mdorigin 0.1.8 → 0.2.0
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/README.md +12 -0
- package/dist/adapters/cloudflare.d.ts +40 -4
- package/dist/adapters/cloudflare.js +163 -7
- package/dist/adapters/node.js +2 -2
- package/dist/cli/build-cloudflare.js +27 -2
- package/dist/cli/help.js +5 -4
- package/dist/cli/init-cloudflare.js +7 -1
- package/dist/cli/main.js +5 -0
- package/dist/cli/sync-cloudflare-r2.d.ts +1 -0
- package/dist/cli/sync-cloudflare-r2.js +47 -0
- package/dist/cloudflare-runtime.d.ts +1 -1
- package/dist/cloudflare.d.ts +42 -6
- package/dist/cloudflare.js +246 -10
- package/dist/core/content-store.d.ts +1 -0
- package/dist/core/content-store.js +8 -1
- package/dist/core/extensions.d.ts +5 -9
- package/dist/core/markdown.js +6 -2
- package/dist/core/request-handler.js +46 -60
- package/dist/core/site-config.d.ts +4 -10
- package/dist/core/site-config.js +18 -10
- package/dist/html/template.d.ts +5 -9
- package/dist/html/template.js +25 -25
- package/dist/html/theme.d.ts +1 -2
- package/dist/html/theme.js +2 -642
- package/dist/index-builder.js +5 -4
- package/dist/search.js +3 -2
- package/package.json +4 -2
- package/dist/html/template-kind.d.ts +0 -1
- package/dist/html/template-kind.js +0 -1
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import type { ContentStore } from './content-store.js';
|
|
2
2
|
import type { MdoPlugin } from './extensions.js';
|
|
3
|
-
import type { TemplateName } from '../html/template-kind.js';
|
|
4
|
-
import type { BuiltInThemeName } from '../html/theme.js';
|
|
5
3
|
export interface SiteNavItem {
|
|
6
4
|
label: string;
|
|
7
5
|
href: string;
|
|
@@ -29,16 +27,14 @@ export interface SiteConfig {
|
|
|
29
27
|
showDate?: boolean;
|
|
30
28
|
showSummary?: boolean;
|
|
31
29
|
stylesheet?: string;
|
|
32
|
-
theme?: BuiltInThemeName;
|
|
33
|
-
template?: TemplateName;
|
|
34
30
|
topNav?: SiteNavItem[];
|
|
35
31
|
footerNav?: SiteNavItem[];
|
|
36
32
|
footerText?: string;
|
|
37
33
|
socialLinks?: SiteSocialLink[];
|
|
38
34
|
editLink?: EditLinkConfig;
|
|
39
35
|
showHomeIndex?: boolean;
|
|
40
|
-
|
|
41
|
-
|
|
36
|
+
listingInitialPostCount?: number;
|
|
37
|
+
listingLoadMoreStep?: number;
|
|
42
38
|
}
|
|
43
39
|
export interface UserSiteConfig extends SiteConfig {
|
|
44
40
|
plugins?: MdoPlugin[];
|
|
@@ -52,16 +48,14 @@ export interface ResolvedSiteConfig {
|
|
|
52
48
|
logo?: SiteLogo;
|
|
53
49
|
showDate: boolean;
|
|
54
50
|
showSummary: boolean;
|
|
55
|
-
theme: BuiltInThemeName;
|
|
56
|
-
template: TemplateName;
|
|
57
51
|
topNav: SiteNavItem[];
|
|
58
52
|
footerNav: SiteNavItem[];
|
|
59
53
|
footerText?: string;
|
|
60
54
|
socialLinks: SiteSocialLink[];
|
|
61
55
|
editLink?: EditLinkConfig;
|
|
62
56
|
showHomeIndex: boolean;
|
|
63
|
-
|
|
64
|
-
|
|
57
|
+
listingInitialPostCount: number;
|
|
58
|
+
listingLoadMoreStep: number;
|
|
65
59
|
stylesheetContent?: string;
|
|
66
60
|
siteTitleConfigured: boolean;
|
|
67
61
|
siteDescriptionConfigured: boolean;
|
package/dist/core/site-config.js
CHANGED
|
@@ -14,6 +14,7 @@ export async function loadUserSiteConfig(options = {}) {
|
|
|
14
14
|
? path.resolve(cwd, options.configPath)
|
|
15
15
|
: await resolveDefaultConfigPath(cwd, rootDir);
|
|
16
16
|
const parsedConfig = await loadConfigSource(configFilePath);
|
|
17
|
+
const legacyConfig = parsedConfig;
|
|
17
18
|
const stylesheetPath = parsedConfig.stylesheet
|
|
18
19
|
? path.resolve(path.dirname(configFilePath), parsedConfig.stylesheet)
|
|
19
20
|
: null;
|
|
@@ -34,8 +35,6 @@ export async function loadUserSiteConfig(options = {}) {
|
|
|
34
35
|
logo: normalizeLogo(parsedConfig.logo),
|
|
35
36
|
showDate: parsedConfig.showDate ?? true,
|
|
36
37
|
showSummary: parsedConfig.showSummary ?? true,
|
|
37
|
-
theme: isBuiltInThemeName(parsedConfig.theme) ? parsedConfig.theme : 'paper',
|
|
38
|
-
template: isTemplateName(parsedConfig.template) ? parsedConfig.template : 'document',
|
|
39
38
|
topNav: normalizeTopNav(parsedConfig.topNav),
|
|
40
39
|
footerNav: normalizeTopNav(parsedConfig.footerNav),
|
|
41
40
|
footerText: typeof parsedConfig.footerText === 'string' && parsedConfig.footerText !== ''
|
|
@@ -46,13 +45,14 @@ export async function loadUserSiteConfig(options = {}) {
|
|
|
46
45
|
showHomeIndex: typeof parsedConfig.showHomeIndex === 'boolean'
|
|
47
46
|
? parsedConfig.showHomeIndex
|
|
48
47
|
: normalizeTopNav(parsedConfig.topNav).length === 0,
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
listingInitialPostCount: normalizePositiveInteger(parsedConfig.listingInitialPostCount ?? legacyConfig.catalogInitialPostCount, 10),
|
|
49
|
+
listingLoadMoreStep: normalizePositiveInteger(parsedConfig.listingLoadMoreStep ?? legacyConfig.catalogLoadMoreStep, 10),
|
|
51
50
|
stylesheetContent,
|
|
52
51
|
siteTitleConfigured: typeof parsedConfig.siteTitle === 'string' && parsedConfig.siteTitle !== '',
|
|
53
52
|
siteDescriptionConfigured: typeof parsedConfig.siteDescription === 'string' &&
|
|
54
53
|
parsedConfig.siteDescription !== '',
|
|
55
54
|
};
|
|
55
|
+
warnOnLegacyConfig(legacyConfig, configFilePath);
|
|
56
56
|
return {
|
|
57
57
|
siteConfig,
|
|
58
58
|
plugins: Array.isArray(parsedConfig.plugins) ? parsedConfig.plugins : [],
|
|
@@ -93,12 +93,6 @@ async function resolveDefaultConfigPath(cwd, rootDir) {
|
|
|
93
93
|
}
|
|
94
94
|
return (await findConfigPath(cwd)) ?? path.join(cwd, 'mdorigin.config.json');
|
|
95
95
|
}
|
|
96
|
-
function isBuiltInThemeName(value) {
|
|
97
|
-
return value === 'paper' || value === 'atlas' || value === 'gazette';
|
|
98
|
-
}
|
|
99
|
-
function isTemplateName(value) {
|
|
100
|
-
return value === 'document' || value === 'catalog';
|
|
101
|
-
}
|
|
102
96
|
function isNodeNotFound(error) {
|
|
103
97
|
return (typeof error === 'object' &&
|
|
104
98
|
error !== null &&
|
|
@@ -275,3 +269,17 @@ function normalizeSiteHref(value) {
|
|
|
275
269
|
}
|
|
276
270
|
return `/${value.replace(/^\.?\//, '')}`;
|
|
277
271
|
}
|
|
272
|
+
function warnOnLegacyConfig(config, configFilePath) {
|
|
273
|
+
if ('theme' in config) {
|
|
274
|
+
console.warn(`[mdorigin] ${configFilePath}: "theme" is deprecated and ignored. mdorigin now uses a single built-in atlas presentation.`);
|
|
275
|
+
}
|
|
276
|
+
if ('template' in config) {
|
|
277
|
+
console.warn(`[mdorigin] ${configFilePath}: "template" is deprecated and ignored. Listing behavior is now part of the default presentation.`);
|
|
278
|
+
}
|
|
279
|
+
if ('catalogInitialPostCount' in config) {
|
|
280
|
+
console.warn(`[mdorigin] ${configFilePath}: "catalogInitialPostCount" is deprecated. Use "listingInitialPostCount" instead.`);
|
|
281
|
+
}
|
|
282
|
+
if ('catalogLoadMoreStep' in config) {
|
|
283
|
+
console.warn(`[mdorigin] ${configFilePath}: "catalogLoadMoreStep" is deprecated. Use "listingLoadMoreStep" instead.`);
|
|
284
|
+
}
|
|
285
|
+
}
|
package/dist/html/template.d.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import type { SiteLogo, SiteNavItem, SiteSocialLink } from '../core/site-config.js';
|
|
2
2
|
import type { ManagedIndexEntry } from '../core/markdown.js';
|
|
3
|
-
import type { TemplateName } from './template-kind.js';
|
|
4
|
-
import { type BuiltInThemeName } from './theme.js';
|
|
5
3
|
export interface RenderDocumentOptions {
|
|
6
4
|
siteTitle: string;
|
|
7
5
|
siteDescription?: string;
|
|
@@ -15,8 +13,6 @@ export interface RenderDocumentOptions {
|
|
|
15
13
|
date?: string;
|
|
16
14
|
showSummary?: boolean;
|
|
17
15
|
showDate?: boolean;
|
|
18
|
-
theme: BuiltInThemeName;
|
|
19
|
-
template: TemplateName;
|
|
20
16
|
topNav?: SiteNavItem[];
|
|
21
17
|
footerNav?: SiteNavItem[];
|
|
22
18
|
footerText?: string;
|
|
@@ -25,14 +21,14 @@ export interface RenderDocumentOptions {
|
|
|
25
21
|
stylesheetContent?: string;
|
|
26
22
|
canonicalPath?: string;
|
|
27
23
|
alternateMarkdownPath?: string;
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
24
|
+
listingEntries?: ManagedIndexEntry[];
|
|
25
|
+
listingRequestPath?: string;
|
|
26
|
+
listingInitialPostCount?: number;
|
|
27
|
+
listingLoadMoreStep?: number;
|
|
32
28
|
searchEnabled?: boolean;
|
|
33
29
|
headerHtml?: string;
|
|
34
30
|
footerHtml?: string;
|
|
35
31
|
}
|
|
36
32
|
export declare function renderDocument(options: RenderDocumentOptions): string;
|
|
37
33
|
export declare function escapeHtml(value: string): string;
|
|
38
|
-
export declare function
|
|
34
|
+
export declare function renderListingArticleItems(entries: readonly ManagedIndexEntry[]): string;
|
package/dist/html/template.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getDefaultThemeStyles } from './theme.js';
|
|
2
2
|
export function renderDocument(options) {
|
|
3
3
|
const title = escapeHtml(options.title);
|
|
4
4
|
const siteTitle = escapeHtml(options.siteTitle);
|
|
@@ -25,7 +25,7 @@ export function renderDocument(options) {
|
|
|
25
25
|
const alternateMarkdownMeta = options.alternateMarkdownPath
|
|
26
26
|
? `<link rel="alternate" type="text/markdown" href="${escapeHtml(options.alternateMarkdownPath)}">`
|
|
27
27
|
: '';
|
|
28
|
-
const stylesheetBlock = `<style>${
|
|
28
|
+
const stylesheetBlock = `<style>${getDefaultThemeStyles()}${options.stylesheetContent ? `\n${options.stylesheetContent}` : ''}</style>`;
|
|
29
29
|
const navBlock = options.topNav && options.topNav.length > 0
|
|
30
30
|
? `<nav class="site-nav"><ul>${options.topNav
|
|
31
31
|
.map((item) => `<li><a href="${escapeHtml(item.href)}">${escapeHtml(item.label)}</a></li>`)
|
|
@@ -84,11 +84,11 @@ export function renderDocument(options) {
|
|
|
84
84
|
const footerBlock = footerNavBlock || footerTextBlock || footerMetaBlock
|
|
85
85
|
? `<footer class="site-footer"><div class="site-footer__inner">${footerNavBlock}${footerTextBlock}${footerMetaBlock}</div></footer>`
|
|
86
86
|
: '';
|
|
87
|
-
const articleBody = options.
|
|
88
|
-
?
|
|
89
|
-
requestPath: options.
|
|
90
|
-
initialPostCount: options.
|
|
91
|
-
loadMoreStep: options.
|
|
87
|
+
const articleBody = options.listingEntries && options.listingEntries.length > 0
|
|
88
|
+
? renderListingArticle(options.body, options.listingEntries, {
|
|
89
|
+
requestPath: options.listingRequestPath ?? '/',
|
|
90
|
+
initialPostCount: options.listingInitialPostCount ?? 10,
|
|
91
|
+
loadMoreStep: options.listingLoadMoreStep ?? 10,
|
|
92
92
|
})
|
|
93
93
|
: options.body;
|
|
94
94
|
const searchScript = options.searchEnabled ? renderSearchScript() : '';
|
|
@@ -109,7 +109,7 @@ export function renderDocument(options) {
|
|
|
109
109
|
alternateMarkdownMeta,
|
|
110
110
|
stylesheetBlock,
|
|
111
111
|
'</head>',
|
|
112
|
-
|
|
112
|
+
'<body>',
|
|
113
113
|
headerBlock,
|
|
114
114
|
'<main>',
|
|
115
115
|
`<article>${articleBody}</article>`,
|
|
@@ -159,7 +159,7 @@ function renderSocialIcon(icon) {
|
|
|
159
159
|
function iconSvg(pathData) {
|
|
160
160
|
return `<svg viewBox="0 0 24 24" aria-hidden="true"><path d="${pathData}"></path></svg>`;
|
|
161
161
|
}
|
|
162
|
-
function
|
|
162
|
+
function renderListingArticle(body, entries, options) {
|
|
163
163
|
if (entries.length === 0) {
|
|
164
164
|
return body;
|
|
165
165
|
}
|
|
@@ -170,10 +170,10 @@ function renderCatalogArticle(body, entries, options) {
|
|
|
170
170
|
const shouldLoadMore = articles.length > visibleArticles.length;
|
|
171
171
|
return [
|
|
172
172
|
`<div class="catalog-page__body">${body}</div>`,
|
|
173
|
-
'<section class="catalog-page" aria-label="
|
|
174
|
-
directories.length > 0 ?
|
|
173
|
+
'<section class="catalog-page" aria-label="Content listing">',
|
|
174
|
+
directories.length > 0 ? renderListingDirectories(directories) : '',
|
|
175
175
|
articles.length > 0
|
|
176
|
-
?
|
|
176
|
+
? renderListingArticles(visibleArticles, {
|
|
177
177
|
requestPath: options.requestPath,
|
|
178
178
|
nextOffset: visibleArticles.length,
|
|
179
179
|
loadMoreStep: options.loadMoreStep,
|
|
@@ -181,10 +181,10 @@ function renderCatalogArticle(body, entries, options) {
|
|
|
181
181
|
})
|
|
182
182
|
: '',
|
|
183
183
|
'</section>',
|
|
184
|
-
shouldLoadMore ?
|
|
184
|
+
shouldLoadMore ? renderListingLoadMoreScript() : '',
|
|
185
185
|
].join('');
|
|
186
186
|
}
|
|
187
|
-
function
|
|
187
|
+
function renderListingDirectories(entries) {
|
|
188
188
|
return [
|
|
189
189
|
'<div class="catalog-list catalog-list--directories">',
|
|
190
190
|
...entries.map((entry) => `<a class="catalog-item catalog-item--directory" href="${escapeHtml(entry.href)}"><strong class="catalog-item__title">${escapeHtml(entry.title)}</strong>${entry.detail
|
|
@@ -193,28 +193,28 @@ function renderCatalogDirectories(entries) {
|
|
|
193
193
|
'</div>',
|
|
194
194
|
].join('');
|
|
195
195
|
}
|
|
196
|
-
export function
|
|
196
|
+
export function renderListingArticleItems(entries) {
|
|
197
197
|
return entries
|
|
198
198
|
.map((entry) => `<a class="catalog-item" href="${escapeHtml(entry.href)}"><strong class="catalog-item__title">${escapeHtml(entry.title)}</strong>${entry.detail
|
|
199
199
|
? `<span class="catalog-item__detail">${escapeHtml(entry.detail)}</span>`
|
|
200
200
|
: ''}</a>`)
|
|
201
201
|
.join('');
|
|
202
202
|
}
|
|
203
|
-
function
|
|
203
|
+
function renderListingArticles(entries, options) {
|
|
204
204
|
return [
|
|
205
|
-
'<div class="catalog-list" data-
|
|
206
|
-
|
|
205
|
+
'<div class="catalog-list" data-listing-articles>',
|
|
206
|
+
renderListingArticleItems(entries),
|
|
207
207
|
'</div>',
|
|
208
208
|
options.hasMore
|
|
209
|
-
? `<div class="catalog-load-more"><button type="button" class="catalog-load-more__button" data-
|
|
209
|
+
? `<div class="catalog-load-more"><button type="button" class="catalog-load-more__button" data-listing-load-more data-request-path="${escapeHtml(options.requestPath)}" data-next-offset="${escapeHtml(String(options.nextOffset))}" data-load-more-step="${escapeHtml(String(options.loadMoreStep))}">Load more</button></div>`
|
|
210
210
|
: '',
|
|
211
211
|
].join('');
|
|
212
212
|
}
|
|
213
|
-
function
|
|
213
|
+
function renderListingLoadMoreScript() {
|
|
214
214
|
return `<script>
|
|
215
215
|
(() => {
|
|
216
|
-
const button = document.querySelector('[data-
|
|
217
|
-
const list = document.querySelector('[data-
|
|
216
|
+
const button = document.querySelector('[data-listing-load-more]');
|
|
217
|
+
const list = document.querySelector('[data-listing-articles]');
|
|
218
218
|
if (!(button instanceof HTMLButtonElement) || !(list instanceof HTMLElement)) {
|
|
219
219
|
return;
|
|
220
220
|
}
|
|
@@ -233,9 +233,9 @@ function renderCatalogLoadMoreScript() {
|
|
|
233
233
|
|
|
234
234
|
try {
|
|
235
235
|
const url = new URL(requestPath, window.location.origin);
|
|
236
|
-
url.searchParams.set('
|
|
237
|
-
url.searchParams.set('
|
|
238
|
-
url.searchParams.set('
|
|
236
|
+
url.searchParams.set('listing-format', 'posts');
|
|
237
|
+
url.searchParams.set('listing-offset', nextOffset);
|
|
238
|
+
url.searchParams.set('listing-limit', loadMoreStep);
|
|
239
239
|
|
|
240
240
|
const response = await fetch(url.toString(), {
|
|
241
241
|
headers: { Accept: 'application/json' },
|
package/dist/html/theme.d.ts
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
export
|
|
2
|
-
export declare function getBuiltInThemeStyles(theme: BuiltInThemeName): string;
|
|
1
|
+
export declare function getDefaultThemeStyles(): string;
|