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.
@@ -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
- catalogInitialPostCount?: number;
41
- catalogLoadMoreStep?: number;
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
- catalogInitialPostCount: number;
64
- catalogLoadMoreStep: number;
57
+ listingInitialPostCount: number;
58
+ listingLoadMoreStep: number;
65
59
  stylesheetContent?: string;
66
60
  siteTitleConfigured: boolean;
67
61
  siteDescriptionConfigured: boolean;
@@ -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
- catalogInitialPostCount: normalizePositiveInteger(parsedConfig.catalogInitialPostCount, 10),
50
- catalogLoadMoreStep: normalizePositiveInteger(parsedConfig.catalogLoadMoreStep, 10),
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
+ }
@@ -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
- catalogEntries?: ManagedIndexEntry[];
29
- catalogRequestPath?: string;
30
- catalogInitialPostCount?: number;
31
- catalogLoadMoreStep?: number;
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 renderCatalogArticleItems(entries: readonly ManagedIndexEntry[]): string;
34
+ export declare function renderListingArticleItems(entries: readonly ManagedIndexEntry[]): string;
@@ -1,4 +1,4 @@
1
- import { getBuiltInThemeStyles } from './theme.js';
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>${getBuiltInThemeStyles(options.theme)}${options.stylesheetContent ? `\n${options.stylesheetContent}` : ''}</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.template === 'catalog'
88
- ? renderCatalogArticle(options.body, options.catalogEntries ?? [], {
89
- requestPath: options.catalogRequestPath ?? '/',
90
- initialPostCount: options.catalogInitialPostCount ?? 10,
91
- loadMoreStep: options.catalogLoadMoreStep ?? 10,
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
- `<body data-theme="${options.theme}" data-template="${options.template}">`,
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 renderCatalogArticle(body, entries, options) {
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="Catalog">',
174
- directories.length > 0 ? renderCatalogDirectories(directories) : '',
173
+ '<section class="catalog-page" aria-label="Content listing">',
174
+ directories.length > 0 ? renderListingDirectories(directories) : '',
175
175
  articles.length > 0
176
- ? renderCatalogArticles(visibleArticles, {
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 ? renderCatalogLoadMoreScript() : '',
184
+ shouldLoadMore ? renderListingLoadMoreScript() : '',
185
185
  ].join('');
186
186
  }
187
- function renderCatalogDirectories(entries) {
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 renderCatalogArticleItems(entries) {
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 renderCatalogArticles(entries, options) {
203
+ function renderListingArticles(entries, options) {
204
204
  return [
205
- '<div class="catalog-list" data-catalog-articles>',
206
- renderCatalogArticleItems(entries),
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-catalog-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>`
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 renderCatalogLoadMoreScript() {
213
+ function renderListingLoadMoreScript() {
214
214
  return `<script>
215
215
  (() => {
216
- const button = document.querySelector('[data-catalog-load-more]');
217
- const list = document.querySelector('[data-catalog-articles]');
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('catalog-format', 'posts');
237
- url.searchParams.set('catalog-offset', nextOffset);
238
- url.searchParams.set('catalog-limit', loadMoreStep);
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' },
@@ -1,2 +1 @@
1
- export type BuiltInThemeName = 'paper' | 'atlas' | 'gazette';
2
- export declare function getBuiltInThemeStyles(theme: BuiltInThemeName): string;
1
+ export declare function getDefaultThemeStyles(): string;