Skip to content

Commit 398e768

Browse files
committed
Refine document theme colors and labels
1 parent 32f7b7f commit 398e768

6 files changed

Lines changed: 83 additions & 58 deletions

File tree

src/lib/dc/export-document.ts

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ type DocumentPalette = {
7171
ctaBackground: string;
7272
ctaBorder: string;
7373
ctaText: string;
74+
attribution: string;
7475
};
7576

7677
type RenderContext = {
@@ -107,6 +108,7 @@ function documentPalette(options: DcExportOptions): DocumentPalette {
107108
ctaBackground: "oklch(91.44% 0.064 90.52)",
108109
ctaBorder: "oklch(96.28% 0.022 90.84)",
109110
ctaText: "oklch(13.77% 0.018 87.82)",
111+
attribution: "#787878",
110112
};
111113
}
112114

@@ -130,6 +132,7 @@ function documentPalette(options: DcExportOptions): DocumentPalette {
130132
ctaBackground: "oklch(93.5% 0.044 88.16)",
131133
ctaBorder: "oklch(70.74% 0.08 82.27)",
132134
ctaText: "oklch(26.32% 0.03 80.84)",
135+
attribution: "#c9c1b5",
133136
};
134137
}
135138

@@ -223,57 +226,57 @@ const darkCalloutStyles: Record<
223226
> = {
224227
tip: {
225228
label: "TIP",
226-
background: "oklch(11.88% 0.018 142.78)",
227-
border: "oklch(76.13% 0.153 142.04)",
228-
text: "oklch(91.89% 0.026 143.2)",
229+
background: "oklch(11.52% 0.012 142.78)",
230+
border: "oklch(62.6% 0.082 142.04)",
231+
text: "oklch(90.44% 0.018 143.2)",
229232
},
230233
warning: {
231234
label: "주의",
232-
background: "oklch(12.26% 0.018 58.76)",
233-
border: "oklch(78.46% 0.145 69.41)",
234-
text: "oklch(92.96% 0.03 76.33)",
235+
background: "oklch(11.9% 0.012 58.76)",
236+
border: "oklch(64.8% 0.078 69.41)",
237+
text: "oklch(91.32% 0.02 76.33)",
235238
},
236239
reference: {
237240
label: "REF",
238-
background: "oklch(11.62% 0.021 245.9)",
239-
border: "oklch(72.52% 0.142 232.16)",
240-
text: "oklch(91.87% 0.029 233.82)",
241+
background: "oklch(11.28% 0.014 245.9)",
242+
border: "oklch(60.74% 0.082 232.16)",
243+
text: "oklch(90.58% 0.02 233.82)",
241244
},
242245
emphasis: {
243246
label: "POINT",
244-
background: "oklch(12.04% 0.022 302.17)",
245-
border: "oklch(73.79% 0.151 303.45)",
246-
text: "oklch(93.04% 0.029 303.2)",
247+
background: "oklch(11.68% 0.015 302.17)",
248+
border: "oklch(61.88% 0.086 303.45)",
249+
text: "oklch(91.78% 0.02 303.2)",
247250
},
248251
success: {
249252
label: "성공",
250-
background: "oklch(11.76% 0.02 154.8)",
251-
border: "oklch(76.71% 0.151 154.54)",
252-
text: "oklch(92.34% 0.029 154.17)",
253+
background: "oklch(11.42% 0.013 154.8)",
254+
border: "oklch(62.88% 0.084 154.54)",
255+
text: "oklch(91% 0.02 154.17)",
253256
},
254257
failure: {
255258
label: "실패",
256-
background: "oklch(12.02% 0.021 24.58)",
257-
border: "oklch(75.02% 0.17 24.82)",
258-
text: "oklch(93.14% 0.03 24.92)",
259+
background: "oklch(11.66% 0.014 24.58)",
260+
border: "oklch(62.2% 0.09 24.82)",
261+
text: "oklch(91.88% 0.02 24.92)",
259262
},
260263
experiment: {
261264
label: "실험",
262-
background: "oklch(11.48% 0.022 264.32)",
263-
border: "oklch(73.44% 0.145 264.2)",
264-
text: "oklch(92.52% 0.031 264.14)",
265+
background: "oklch(11.16% 0.014 264.32)",
266+
border: "oklch(61.26% 0.084 264.2)",
267+
text: "oklch(91.16% 0.021 264.14)",
265268
},
266269
conclusion: {
267270
label: "결론",
268-
background: "oklch(12.18% 0.018 91.22)",
269-
border: "oklch(80.18% 0.126 91.43)",
270-
text: "oklch(93.56% 0.027 91.42)",
271+
background: "oklch(11.84% 0.012 91.22)",
272+
border: "oklch(66.4% 0.074 91.43)",
273+
text: "oklch(92.08% 0.018 91.42)",
271274
},
272275
rebuttal: {
273276
label: "반박",
274-
background: "oklch(12.11% 0.023 330.24)",
275-
border: "oklch(75.91% 0.154 330.36)",
276-
text: "oklch(93.11% 0.031 330.24)",
277+
background: "oklch(11.76% 0.015 330.24)",
278+
border: "oklch(62.42% 0.088 330.36)",
279+
text: "oklch(91.82% 0.021 330.24)",
277280
},
278281
};
279282

@@ -482,28 +485,25 @@ function compactInheritedProseStyles(html: string, options: DcExportOptions): st
482485
function renderAttributionFooter(options: DcExportOptions): string {
483486
const palette = documentPalette(options);
484487
const isDarkDocument = normalizeDocumentTheme(options.documentTheme) === "darkEditorial";
485-
const mutedColor = isDarkDocument ? "#9a9a9a" : "#d2cbc0";
486-
const linkOpacity = isDarkDocument ? 0.42 : 0.22;
488+
const linkOpacity = isDarkDocument ? 0.34 : 0.18;
487489
const tableStyle = joinStyle({
488-
width: "100%",
489490
margin: "20px 0 0",
490491
"border-collapse": "collapse",
491-
"background-color": palette.articleBackground,
492492
});
493493
const cellStyle = joinStyle({
494494
padding: "8px 0 0",
495495
"text-align": "right",
496-
color: mutedColor,
496+
color: palette.attribution,
497497
"font-size": "12px",
498498
"line-height": 1.4,
499499
});
500500
const linkStyle = joinStyle({
501-
color: mutedColor,
501+
color: palette.attribution,
502502
opacity: linkOpacity,
503503
"text-decoration": "none",
504504
});
505505

506-
return `<table width="100%" cellpadding="0" cellspacing="0" border="0" bgcolor="${palette.fallbackBackground}" style="${tableStyle}"><tbody><tr><td align="right" style="${cellStyle}"><a href="${attributionHref}" target="_blank" rel="noopener noreferrer" style="${linkStyle}">${attributionText}</a></td></tr></tbody></table>`;
506+
return `<table width="100%" style="${tableStyle}"><tbody><tr><td align="right" style="${cellStyle}"><a href="${attributionHref}" target="_blank" rel="noopener noreferrer" style="${linkStyle}">${attributionText}</a></td></tr></tbody></table>`;
507507
}
508508

509509
function renderDcTableBlock({

src/lib/editor/callout-palette.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,11 @@ export function createCalloutColorPalette(
9898
const accent = normalizeCalloutToneColor(value, kind);
9999

100100
if (mode === "dark") {
101-
const background = mixHex(accent, "#050505", 0.2);
102-
const inlineCodeBackground = mixHex(accent, "#0f172a", 0.62);
101+
const background = mixHex(accent, "#050505", 0.14);
102+
const inlineCodeBackground = mixHex(accent, "#0f172a", 0.48);
103103

104104
return {
105-
border: mixHex(accent, "#ffffff", 0.82),
105+
border: mixHex(accent, "#b8b8b8", 0.54),
106106
background,
107107
fallbackBackground: background,
108108
text: readableTextFor(background),

src/lib/highlighter/shiki-client.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -290,8 +290,8 @@ function highlightedLineDecorations(
290290
border: "oklch(73.05% 0.141 83.41)",
291291
}
292292
: {
293-
background: "oklch(31.14% 0.076 83.12 / 0.82)",
294-
border: "oklch(79.43% 0.129 84.28)",
293+
background: "oklch(25.8% 0.042 83.12 / 0.72)",
294+
border: "oklch(66.8% 0.082 84.28)",
295295
};
296296

297297
return lines.map((_, index) =>

src/routes/+page.svelte

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -151,8 +151,8 @@
151151
const previewRenderDebounceMs = 90;
152152
const draftPersistDebounceMs = 450;
153153
const documentThemes: { label: string; value: DcDocumentTheme }[] = [
154-
{ label: "라이트", value: "lightLecture" },
155-
{ label: "다크", value: "darkEditorial" },
154+
{ label: "밝은 글", value: "lightLecture" },
155+
{ label: "어두운 글", value: "darkEditorial" },
156156
];
157157
const editorThemeColorSafety = {
158158
lightLecture: {
@@ -275,7 +275,7 @@
275275
);
276276
const documentThemeLabel = $derived(
277277
documentThemes.find((item) => item.value === documentTheme)?.label ??
278-
"라이트",
278+
"밝은 글",
279279
);
280280
const presetStateLabel = $derived(
281281
presetState === "saved"
@@ -477,8 +477,8 @@
477477
function draftHistorySummary(snapshot: DraftHistorySnapshot) {
478478
const themeLabel =
479479
snapshot.preferences.documentTheme === "darkEditorial"
480-
? "다크"
481-
: "라이트";
480+
? "어두운 글"
481+
: "밝은 글";
482482
const textLength = countDocumentText(
483483
snapshot.document,
484484
).toLocaleString();
@@ -3092,8 +3092,12 @@
30923092
{#if activeToolPanel === "style"}
30933093
<div id="style-tools" class="tool-group tool-panel tool-group-wide typography-group">
30943094
<label>
3095-
<span><Paintbrush size={15} /> 문서</span>
3096-
<select bind:value={documentTheme} aria-label="문서 테마">
3095+
<span><Paintbrush size={15} /> 글 배경</span>
3096+
<select
3097+
bind:value={documentTheme}
3098+
aria-label="복사될 글 배경"
3099+
title="DC 야간모드와 별개로 복사될 글의 배경을 고릅니다"
3100+
>
30973101
{#each documentThemes as item}
30983102
<option value={item.value}>{item.label}</option>
30993103
{/each}
@@ -3219,8 +3223,8 @@
32193223
>{preset.preferences
32203224
.documentTheme ===
32213225
"darkEditorial"
3222-
? "다크"
3223-
: "라이트"} · {presetDateLabel(
3226+
? "어두운 글"
3227+
: "밝은 글"} · {presetDateLabel(
32243228
preset.updatedAt,
32253229
)}</small
32263230
>
@@ -3440,7 +3444,7 @@
34403444
</div>
34413445
<div class="preview-tools">
34423446
<span class="status-pill" aria-label="현재 복붙 구조">DC 테이블</span>
3443-
<span class="status-pill" aria-label="현재 문서 테마"
3447+
<span class="status-pill" aria-label="현재 글 배경"
34443448
>{documentThemeLabel}</span
34453449
>
34463450
<div class="mode-switch" aria-label="미리보기 형식">

tests/e2e/paste-preview.spec.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ test("renders the paste tool", async ({ page }) => {
7878
await expect(page.getByLabel("코드 글자 크기")).toHaveValue("15px");
7979
await expect(page.getByLabel("코드 테마")).toHaveValue("catppuccin-mocha");
8080
await expect(page.getByLabel("줄번호")).toBeVisible();
81-
await expect(page.getByLabel("문서 테마", { exact: true })).toHaveCount(0);
81+
await expect(page.getByLabel("복사될 글 배경", { exact: true })).toHaveCount(0);
8282
await page
8383
.locator(".article-editor pre")
8484
.first()
@@ -181,12 +181,12 @@ test("renders the paste tool", async ({ page }) => {
181181

182182
await expect(page.getByText("글쓰기")).toBeVisible();
183183
await expect(page.getByLabel("현재 복붙 구조")).toHaveText("DC 테이블");
184-
await expect(page.getByLabel("현재 문서 테마")).toHaveText("라이트");
185-
if ((await page.getByLabel("문서 테마", { exact: true }).count()) === 0) {
184+
await expect(page.getByLabel("현재 글 배경")).toHaveText("밝은 글");
185+
if ((await page.getByLabel("복사될 글 배경", { exact: true }).count()) === 0) {
186186
await page.getByRole("button", { name: "스타일 도구" }).click();
187187
}
188-
await page.getByLabel("문서 테마", { exact: true }).selectOption("darkEditorial");
189-
await expect(page.getByLabel("현재 문서 테마")).toHaveText("다크");
188+
await page.getByLabel("복사될 글 배경", { exact: true }).selectOption("darkEditorial");
189+
await expect(page.getByLabel("현재 글 배경")).toHaveText("어두운 글");
190190
await expect(page.locator(".preview-surface")).toHaveClass(/preview-surface-dark/);
191191
const darkEditorCtaColors = await page.locator(".editor-surface").evaluate((surface) => {
192192
const cta = surface.querySelector<HTMLElement>(".dc-cta-button");
@@ -201,8 +201,8 @@ test("renders the paste tool", async ({ page }) => {
201201
};
202202
});
203203
expect(darkEditorCtaColors.ctaColor).not.toBe(darkEditorCtaColors.ctaBackground);
204-
await page.getByLabel("문서 테마", { exact: true }).selectOption("lightLecture");
205-
await expect(page.getByLabel("현재 문서 테마")).toHaveText("라이트");
204+
await page.getByLabel("복사될 글 배경", { exact: true }).selectOption("lightLecture");
205+
await expect(page.getByLabel("현재 글 배경")).toHaveText("밝은 글");
206206
await expect(page.locator(".preview-surface")).not.toHaveClass(/preview-surface-dark/);
207207
await page.getByRole("button", { name: "저장함" }).click();
208208
await expect(page.getByRole("button", { name: "저장함" })).toHaveAttribute(

tests/unit/export-document.test.ts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,32 @@ describe("exportDocumentToDcHtml", () => {
4747
expect(html).toContain('rel="noopener noreferrer"');
4848
expect(html).toContain('align="right"');
4949
expect(html).toContain("text-align:right");
50-
expect(html).toContain("color:#d2cbc0");
51-
expect(html).toContain("opacity:0.22");
50+
expect(html).toContain("color:#c9c1b5");
51+
expect(html).toContain("opacity:0.18");
5252
expect(html.slice(footerStart - 200, footerStart + 120)).not.toContain("font-family:");
5353
});
5454

55+
it("keeps the attribution footer quieter on dark documents", async () => {
56+
const document: JSONContent = {
57+
type: "doc",
58+
content: [
59+
{
60+
type: "paragraph",
61+
content: [{ type: "text", text: "다크 문서" }],
62+
},
63+
],
64+
};
65+
66+
const html = await exportDocumentToDcHtml(document, {
67+
...exportOptions,
68+
documentTheme: "darkEditorial",
69+
});
70+
71+
expect(html).toContain("Created with dc-code-paste");
72+
expect(html).toContain("color:#787878");
73+
expect(html).toContain("opacity:0.34");
74+
});
75+
5576
it("renders prose, links, callouts, and code blocks as inline-style DC HTML", async () => {
5677
const document: JSONContent = {
5778
type: "doc",

0 commit comments

Comments
 (0)