@limcpf/everything-is-a-markdown 0.4.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/build.ts +4 -1
- package/src/runtime/app.css +23 -13
- package/src/runtime/app.js +38 -5
- package/src/template.ts +24 -19
package/package.json
CHANGED
package/src/build.ts
CHANGED
|
@@ -1042,6 +1042,7 @@ function buildInitialView(doc: DocRecord, docs: DocRecord[], contentHtml: string
|
|
|
1042
1042
|
async function writeShellPages(
|
|
1043
1043
|
context: OutputWriteContext,
|
|
1044
1044
|
docs: DocRecord[],
|
|
1045
|
+
manifest: Manifest,
|
|
1045
1046
|
options: BuildOptions,
|
|
1046
1047
|
runtimeAssets: RuntimeAssets,
|
|
1047
1048
|
contentByDocId: Map<string, string>,
|
|
@@ -1053,6 +1054,7 @@ async function writeShellPages(
|
|
|
1053
1054
|
buildShellMeta("/", null, options),
|
|
1054
1055
|
buildAppShellAssetsForOutput(indexOutputPath, runtimeAssets),
|
|
1055
1056
|
indexInitialView,
|
|
1057
|
+
manifest,
|
|
1056
1058
|
);
|
|
1057
1059
|
await writeOutputIfChanged(context, "_app/index.html", shell);
|
|
1058
1060
|
await writeOutputIfChanged(context, indexOutputPath, shell);
|
|
@@ -1072,6 +1074,7 @@ async function writeShellPages(
|
|
|
1072
1074
|
buildShellMeta(doc.route, doc, options),
|
|
1073
1075
|
buildAppShellAssetsForOutput(routeOutputPath, runtimeAssets),
|
|
1074
1076
|
initialView,
|
|
1077
|
+
manifest,
|
|
1075
1078
|
),
|
|
1076
1079
|
);
|
|
1077
1080
|
}
|
|
@@ -1256,7 +1259,7 @@ export async function buildSite(options: BuildOptions): Promise<BuildResult> {
|
|
|
1256
1259
|
renderedDocs += 1;
|
|
1257
1260
|
}
|
|
1258
1261
|
|
|
1259
|
-
await writeShellPages(outputContext, docs, options, runtimeAssets, contentByDocId);
|
|
1262
|
+
await writeShellPages(outputContext, docs, manifest, options, runtimeAssets, contentByDocId);
|
|
1260
1263
|
await writeSeoArtifacts(outputContext, docs, options);
|
|
1261
1264
|
|
|
1262
1265
|
await writeCache(cachePath, nextCache);
|
package/src/runtime/app.css
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
--latte-crust: #dce0e8;
|
|
6
6
|
--latte-text: #4c4f69;
|
|
7
7
|
--latte-subtext0: #6c6f85;
|
|
8
|
-
--latte-subtext1: #
|
|
9
|
-
--latte-overlay0: #
|
|
8
|
+
--latte-subtext1: #555974;
|
|
9
|
+
--latte-overlay0: #5f637a;
|
|
10
10
|
--latte-surface0: #ccd0da;
|
|
11
11
|
--latte-surface1: #bcc0cc;
|
|
12
12
|
--latte-surface2: #acb0be;
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
--mocha-text: #cdd6f4;
|
|
31
31
|
--mocha-subtext0: #a6adc8;
|
|
32
32
|
--mocha-subtext1: #bac2de;
|
|
33
|
-
--mocha-overlay0: #
|
|
33
|
+
--mocha-overlay0: #a0a7c6;
|
|
34
34
|
--mocha-surface0: #313244;
|
|
35
35
|
--mocha-surface1: #45475a;
|
|
36
36
|
--mocha-surface2: #585b70;
|
|
@@ -121,7 +121,7 @@ body {
|
|
|
121
121
|
body {
|
|
122
122
|
background: var(--latte-base);
|
|
123
123
|
color: var(--latte-text);
|
|
124
|
-
font-family: "
|
|
124
|
+
font-family: "Pretendard Variable", "Pretendard", "Noto Sans KR", "Apple SD Gothic Neo", "Malgun Gothic", "Segoe UI", sans-serif;
|
|
125
125
|
-webkit-font-smoothing: antialiased;
|
|
126
126
|
overflow: hidden;
|
|
127
127
|
}
|
|
@@ -192,11 +192,21 @@ a:hover {
|
|
|
192
192
|
}
|
|
193
193
|
|
|
194
194
|
.material-symbols-outlined {
|
|
195
|
+
font-family: "Material Symbols Outlined", "Material Icons", sans-serif;
|
|
196
|
+
font-style: normal;
|
|
197
|
+
font-weight: 400;
|
|
198
|
+
letter-spacing: normal;
|
|
199
|
+
text-transform: none;
|
|
200
|
+
white-space: nowrap;
|
|
201
|
+
word-wrap: normal;
|
|
202
|
+
direction: ltr;
|
|
203
|
+
font-feature-settings: "liga";
|
|
204
|
+
-webkit-font-feature-settings: "liga";
|
|
195
205
|
display: inline-flex;
|
|
196
206
|
align-items: center;
|
|
197
207
|
justify-content: center;
|
|
198
|
-
width: 1em;
|
|
199
|
-
height: 1em;
|
|
208
|
+
min-width: 1em;
|
|
209
|
+
min-height: 1em;
|
|
200
210
|
flex: 0 0 auto;
|
|
201
211
|
font-size: 20px;
|
|
202
212
|
line-height: 1;
|
|
@@ -571,7 +581,7 @@ a:hover {
|
|
|
571
581
|
}
|
|
572
582
|
|
|
573
583
|
.status-encoding {
|
|
574
|
-
font-family: "
|
|
584
|
+
font-family: ui-monospace, "SFMono-Regular", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
|
575
585
|
color: var(--latte-overlay0);
|
|
576
586
|
}
|
|
577
587
|
|
|
@@ -752,7 +762,7 @@ body.mobile-toggle-left .mobile-menu-toggle {
|
|
|
752
762
|
align-items: center;
|
|
753
763
|
gap: 4px;
|
|
754
764
|
font-size: 0.85rem;
|
|
755
|
-
font-family: "
|
|
765
|
+
font-family: ui-monospace, "SFMono-Regular", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
|
756
766
|
color: var(--latte-overlay0);
|
|
757
767
|
margin-bottom: 24px;
|
|
758
768
|
flex-wrap: nowrap;
|
|
@@ -818,7 +828,7 @@ body.mobile-toggle-left .mobile-menu-toggle {
|
|
|
818
828
|
gap: 16px;
|
|
819
829
|
min-height: 22px;
|
|
820
830
|
font-size: 0.85rem;
|
|
821
|
-
font-family: "
|
|
831
|
+
font-family: ui-monospace, "SFMono-Regular", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
|
822
832
|
color: var(--latte-subtext0);
|
|
823
833
|
}
|
|
824
834
|
|
|
@@ -914,7 +924,7 @@ body.mobile-toggle-left .mobile-menu-toggle {
|
|
|
914
924
|
border: 1px solid var(--latte-surface0);
|
|
915
925
|
border-radius: 4px;
|
|
916
926
|
padding: 2px 6px;
|
|
917
|
-
font-family: "
|
|
927
|
+
font-family: ui-monospace, "SFMono-Regular", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
|
918
928
|
font-size: 0.88em;
|
|
919
929
|
color: var(--latte-mauve);
|
|
920
930
|
}
|
|
@@ -955,7 +965,7 @@ body.mobile-toggle-left .mobile-menu-toggle {
|
|
|
955
965
|
|
|
956
966
|
.code-filename {
|
|
957
967
|
flex: 1;
|
|
958
|
-
font-family: "
|
|
968
|
+
font-family: ui-monospace, "SFMono-Regular", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
|
959
969
|
font-size: 0.75rem;
|
|
960
970
|
color: #aeb7c2;
|
|
961
971
|
text-align: center;
|
|
@@ -1000,7 +1010,7 @@ body.mobile-toggle-left .mobile-menu-toggle {
|
|
|
1000
1010
|
display: block;
|
|
1001
1011
|
padding: 18px 20px;
|
|
1002
1012
|
overflow-x: auto;
|
|
1003
|
-
font-family: "
|
|
1013
|
+
font-family: ui-monospace, "SFMono-Regular", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
|
1004
1014
|
font-size: 0.95rem;
|
|
1005
1015
|
font-weight: 500;
|
|
1006
1016
|
line-height: 1.72;
|
|
@@ -1041,7 +1051,7 @@ body.mobile-toggle-left .mobile-menu-toggle {
|
|
|
1041
1051
|
display: block;
|
|
1042
1052
|
padding: 16px;
|
|
1043
1053
|
overflow-x: auto;
|
|
1044
|
-
font-family: "
|
|
1054
|
+
font-family: ui-monospace, "SFMono-Regular", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
|
1045
1055
|
font-size: 0.875rem;
|
|
1046
1056
|
line-height: 1.6;
|
|
1047
1057
|
}
|
package/src/runtime/app.js
CHANGED
|
@@ -82,6 +82,37 @@ function loadInitialViewData() {
|
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
+
function loadInitialManifestData() {
|
|
86
|
+
const script = document.getElementById("initial-manifest-data");
|
|
87
|
+
if (!(script instanceof HTMLScriptElement)) {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const raw = script.textContent;
|
|
92
|
+
if (!raw) {
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
try {
|
|
97
|
+
const parsed = JSON.parse(raw);
|
|
98
|
+
if (!parsed || typeof parsed !== "object") {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (!Array.isArray(parsed.docs) || !Array.isArray(parsed.tree)) {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (!parsed.routeMap || typeof parsed.routeMap !== "object") {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return parsed;
|
|
111
|
+
} catch {
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
85
116
|
function resolveRouteFromLocation(routeMap) {
|
|
86
117
|
const direct = normalizeRoute(location.pathname);
|
|
87
118
|
if (routeMap[direct]) {
|
|
@@ -1077,12 +1108,14 @@ async function start() {
|
|
|
1077
1108
|
}
|
|
1078
1109
|
});
|
|
1079
1110
|
|
|
1080
|
-
|
|
1081
|
-
if (!
|
|
1082
|
-
|
|
1111
|
+
let manifest = loadInitialManifestData();
|
|
1112
|
+
if (!manifest) {
|
|
1113
|
+
const manifestRes = await fetch("/manifest.json");
|
|
1114
|
+
if (!manifestRes.ok) {
|
|
1115
|
+
throw new Error(`Failed to load manifest: ${manifestRes.status}`);
|
|
1116
|
+
}
|
|
1117
|
+
manifest = await manifestRes.json();
|
|
1083
1118
|
}
|
|
1084
|
-
|
|
1085
|
-
const manifest = await manifestRes.json();
|
|
1086
1119
|
const defaultBranch = normalizeBranch(manifest.defaultBranch) || DEFAULT_BRANCH;
|
|
1087
1120
|
const availableBranchSet = new Set([defaultBranch]);
|
|
1088
1121
|
for (const doc of manifest.docs) {
|
package/src/template.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { escapeHtmlAttribute } from "./seo";
|
|
2
|
+
import type { Manifest } from "./types";
|
|
2
3
|
|
|
3
4
|
const DEFAULT_TITLE = "File-System Blog";
|
|
4
5
|
const DEFAULT_DESCRIPTION = "File-system style static blog with markdown explorer UI.";
|
|
@@ -44,6 +45,8 @@ interface AppShellInitialViewPayload {
|
|
|
44
45
|
title: string;
|
|
45
46
|
}
|
|
46
47
|
|
|
48
|
+
interface AppShellManifestPayload extends Manifest {}
|
|
49
|
+
|
|
47
50
|
const DEFAULT_ASSETS: AppShellAssets = {
|
|
48
51
|
cssHref: "/assets/app.css",
|
|
49
52
|
jsSrc: "/assets/app.js",
|
|
@@ -137,14 +140,6 @@ function renderHeadMeta(meta: AppShellMeta): string {
|
|
|
137
140
|
return headTags.join("\n");
|
|
138
141
|
}
|
|
139
142
|
|
|
140
|
-
function renderDeferredStylesheet(href: string): string {
|
|
141
|
-
return [
|
|
142
|
-
` <link rel="preload" href="${escapeHtmlAttribute(href)}" as="style" />`,
|
|
143
|
-
` <link rel="stylesheet" href="${escapeHtmlAttribute(href)}" media="print" onload="this.media='all'" />`,
|
|
144
|
-
` <noscript><link rel="stylesheet" href="${escapeHtmlAttribute(href)}" /></noscript>`,
|
|
145
|
-
].join("\n");
|
|
146
|
-
}
|
|
147
|
-
|
|
148
143
|
function renderInitialViewScript(initialView: AppShellInitialView | null): string {
|
|
149
144
|
if (!initialView) {
|
|
150
145
|
return "";
|
|
@@ -164,17 +159,30 @@ function renderInitialViewScript(initialView: AppShellInitialView | null): strin
|
|
|
164
159
|
return `\n <script id="initial-view-data" type="application/json">${payload}</script>`;
|
|
165
160
|
}
|
|
166
161
|
|
|
162
|
+
function renderInitialManifestScript(manifest: AppShellManifestPayload | null): string {
|
|
163
|
+
if (!manifest) {
|
|
164
|
+
return "";
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const payload = JSON.stringify(manifest)
|
|
168
|
+
.replaceAll("<", "\\u003c")
|
|
169
|
+
.replaceAll("\u2028", "\\u2028")
|
|
170
|
+
.replaceAll("\u2029", "\\u2029");
|
|
171
|
+
|
|
172
|
+
return `\n <script id="initial-manifest-data" type="application/json">${payload}</script>`;
|
|
173
|
+
}
|
|
174
|
+
|
|
167
175
|
export function renderAppShellHtml(
|
|
168
176
|
meta: AppShellMeta = {},
|
|
169
177
|
assets: AppShellAssets = DEFAULT_ASSETS,
|
|
170
178
|
initialView: AppShellInitialView | null = null,
|
|
179
|
+
manifest: AppShellManifestPayload | null = null,
|
|
171
180
|
): string {
|
|
172
181
|
const headMeta = renderHeadMeta(meta);
|
|
173
182
|
const initialViewScript = renderInitialViewScript(initialView);
|
|
174
|
-
const
|
|
175
|
-
"https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&family=Noto+Sans+KR:wght@400;500;700&display=optional";
|
|
183
|
+
const initialManifestScript = renderInitialManifestScript(manifest);
|
|
176
184
|
const symbolFontStylesheet =
|
|
177
|
-
"https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=
|
|
185
|
+
"https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap";
|
|
178
186
|
const initialTitle = initialView ? escapeHtmlAttribute(initialView.title) : "문서를 선택하세요";
|
|
179
187
|
const initialBreadcrumb = initialView ? initialView.breadcrumbHtml : "";
|
|
180
188
|
const initialMeta = initialView ? initialView.metaHtml : "";
|
|
@@ -191,8 +199,7 @@ export function renderAppShellHtml(
|
|
|
191
199
|
${headMeta}
|
|
192
200
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
193
201
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
194
|
-
${
|
|
195
|
-
${renderDeferredStylesheet(symbolFontStylesheet)}
|
|
202
|
+
<link rel="stylesheet" href="${escapeHtmlAttribute(symbolFontStylesheet)}" />
|
|
196
203
|
<link rel="stylesheet" href="${escapeHtmlAttribute(assets.cssHref)}" />
|
|
197
204
|
</head>
|
|
198
205
|
<body>
|
|
@@ -298,12 +305,13 @@ ${renderDeferredStylesheet(symbolFontStylesheet)}
|
|
|
298
305
|
<div id="viewer-meta" class="viewer-meta">${initialMeta}</div>
|
|
299
306
|
</header>
|
|
300
307
|
<article id="viewer-content" class="viewer-content">${initialContent}</article>
|
|
301
|
-
<nav id="viewer-nav" class="viewer-nav">${initialNav}</nav>
|
|
308
|
+
<nav id="viewer-nav" class="viewer-nav" aria-label="문서 이전/다음 탐색">${initialNav}</nav>
|
|
302
309
|
</div>
|
|
303
310
|
</main>
|
|
304
311
|
</div>
|
|
305
312
|
<div id="tree-label-tooltip" class="tree-label-tooltip" role="tooltip" hidden></div>
|
|
306
313
|
${initialViewScript}
|
|
314
|
+
${initialManifestScript}
|
|
307
315
|
<script type="module" src="${escapeHtmlAttribute(assets.jsSrc)}"></script>
|
|
308
316
|
</body>
|
|
309
317
|
</html>
|
|
@@ -311,10 +319,8 @@ ${initialViewScript}
|
|
|
311
319
|
}
|
|
312
320
|
|
|
313
321
|
export function render404Html(assets: AppShellAssets = DEFAULT_ASSETS): string {
|
|
314
|
-
const textFontStylesheet =
|
|
315
|
-
"https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&family=Noto+Sans+KR:wght@400;500;700&display=optional";
|
|
316
322
|
const symbolFontStylesheet =
|
|
317
|
-
"https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=
|
|
323
|
+
"https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap";
|
|
318
324
|
|
|
319
325
|
return `<!doctype html>
|
|
320
326
|
<html lang="ko">
|
|
@@ -324,8 +330,7 @@ export function render404Html(assets: AppShellAssets = DEFAULT_ASSETS): string {
|
|
|
324
330
|
<title>404 - File-System Blog</title>
|
|
325
331
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
326
332
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
327
|
-
${
|
|
328
|
-
${renderDeferredStylesheet(symbolFontStylesheet)}
|
|
333
|
+
<link rel="stylesheet" href="${escapeHtmlAttribute(symbolFontStylesheet)}" />
|
|
329
334
|
<link rel="stylesheet" href="${escapeHtmlAttribute(assets.cssHref)}" />
|
|
330
335
|
</head>
|
|
331
336
|
<body>
|