@zeropress/build-core 0.6.4 → 0.6.6

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zeropress/build-core",
3
- "version": "0.6.4",
3
+ "version": "0.6.6",
4
4
  "description": "Shared ZeroPress build core",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -34,8 +34,8 @@
34
34
  },
35
35
  "dependencies": {
36
36
  "@zeropress/slug-policy": "0.1.0",
37
- "@zeropress/preview-data-validator": "0.6.3",
38
- "@zeropress/theme-validator": "0.6.4",
37
+ "@zeropress/preview-data-validator": "0.6.6",
38
+ "@zeropress/theme-validator": "0.6.5",
39
39
  "highlight.js": "11.11.1",
40
40
  "markdown-it": "14.2.0",
41
41
  "markdown-it-anchor": "9.2.0"
@@ -294,6 +294,7 @@ async function renderFrontPage(state, route) {
294
294
  url: currentUrl,
295
295
  title: page.title,
296
296
  description: page.excerpt,
297
+ updatedAt: page.updated_at_iso,
297
298
  includeInFeed: false,
298
299
  includeInSitemap: !isDelistedDocument(page),
299
300
  };
@@ -400,6 +401,7 @@ async function renderPage(state, page) {
400
401
  url: currentUrl,
401
402
  title: page.title,
402
403
  description: page.excerpt,
404
+ updatedAt: page.updated_at_iso,
403
405
  status: page.status,
404
406
  includeInSitemap: page.omit_from_sitemap !== true && !isDelistedDocument(page),
405
407
  });
@@ -508,6 +510,7 @@ function normalizePreviewData(previewData, options = {}) {
508
510
  const featuredMedia = deriveManagedMedia(featuredImage, mediaRegistry, normalizedSite);
509
511
  return {
510
512
  ...page,
513
+ ...(page.updated_at_iso ? { updated_at_iso: normalizeIsoTimestamp(page.updated_at_iso) } : {}),
511
514
  discoverability: normalizeDiscoverability(page.discoverability),
512
515
  featured_image: featuredImage,
513
516
  ...(featuredMedia ? { featured_media: featuredMedia } : {}),
@@ -995,6 +998,8 @@ function buildCollectionPageSummary(page, frontPage) {
995
998
  url: frontPage?.type === 'page' && frontPage.page_slug === page.slug ? '/' : page.url,
996
999
  excerpt: page.excerpt || '',
997
1000
  featured_image: page.featured_image || '',
1001
+ updated_at: page.updated_at || '',
1002
+ updated_at_iso: page.updated_at_iso || '',
998
1003
  ...(page.featured_media ? { featured_media: { ...page.featured_media } } : {}),
999
1004
  meta: page.meta,
1000
1005
  data: page.data,
@@ -1057,6 +1062,8 @@ function buildCollectionCursorItemSummary(item) {
1057
1062
  url: item.url,
1058
1063
  excerpt: item.excerpt || '',
1059
1064
  featured_image: item.featured_image || '',
1065
+ updated_at: item.updated_at || '',
1066
+ updated_at_iso: item.updated_at_iso || '',
1060
1067
  meta: item.meta,
1061
1068
  data: item.data,
1062
1069
  };
@@ -1389,6 +1396,7 @@ function preparePage(page, site) {
1389
1396
  document_type: documentType,
1390
1397
  html: renderedDocument.html,
1391
1398
  toc: renderedDocument.toc,
1399
+ updated_at: page.updated_at_iso ? formatTimestamp(page.updated_at_iso, site) : '',
1392
1400
  };
1393
1401
  }
1394
1402
 
@@ -2633,7 +2641,7 @@ function buildSearchPageItem(page, url) {
2633
2641
  categories: [],
2634
2642
  tags: [],
2635
2643
  published_at_iso: '',
2636
- updated_at_iso: '',
2644
+ updated_at_iso: normalizeIsoTimestamp(page.updated_at_iso),
2637
2645
  content_text: htmlToSearchText(page.html),
2638
2646
  };
2639
2647
  }
@@ -3073,6 +3081,7 @@ function buildSitemapXml(site, emitted, generatedAt, stylesheetHref = '') {
3073
3081
  ...(emitted.frontPage && emitted.frontPage.includeInSitemap !== false
3074
3082
  ? [{
3075
3083
  url: emitted.frontPage.url,
3084
+ ...(emitted.frontPage.updatedAt ? { lastmod: toDate(emitted.frontPage.updatedAt) } : {}),
3076
3085
  changefreq: 'daily',
3077
3086
  priority: 1.0,
3078
3087
  }]
@@ -3094,6 +3103,7 @@ function buildSitemapXml(site, emitted, generatedAt, stylesheetHref = '') {
3094
3103
  .filter((page) => page.includeInSitemap !== false)
3095
3104
  .map((page) => ({
3096
3105
  url: page.url,
3106
+ ...(page.updatedAt ? { lastmod: toDate(page.updatedAt) } : {}),
3097
3107
  changefreq: 'monthly',
3098
3108
  priority: 0.7,
3099
3109
  })),
@@ -49,7 +49,7 @@ function renderMarkdownDocument(content) {
49
49
  function createMarkdownRenderer(toc) {
50
50
  const markdown = new MarkdownIt({
51
51
  html: true,
52
- linkify: true,
52
+ linkify: false,
53
53
  typographer: true,
54
54
  breaks: true,
55
55
  highlight(value, language) {
@@ -71,6 +71,7 @@ function createMarkdownRenderer(toc) {
71
71
 
72
72
  markdown.use(markdownTaskLists);
73
73
  markdown.use(markdownAlerts);
74
+ markdown.use(markdownTableAlignmentClasses);
74
75
  markdown.use(anchor, {
75
76
  slugify: slugify,
76
77
  callback(token, { slug, title }) {
@@ -91,6 +92,25 @@ function createMarkdownRenderer(toc) {
91
92
  return markdown;
92
93
  }
93
94
 
95
+ function markdownTableAlignmentClasses(markdown) {
96
+ for (const tokenName of ['th_open', 'td_open']) {
97
+ markdown.renderer.rules[tokenName] = (tokens, index, options, env, self) => {
98
+ const token = tokens[index];
99
+ const styleIndex = token.attrIndex('style');
100
+ if (styleIndex >= 0) {
101
+ const styleValue = token.attrs[styleIndex][1] || '';
102
+ const match = /(?:^|;)\s*text-align\s*:\s*(left|center|right)\s*;?\s*$/i.exec(styleValue);
103
+ if (match) {
104
+ token.attrs.splice(styleIndex, 1);
105
+ addTokenClass(token, `zp-align-${match[1].toLowerCase()}`);
106
+ }
107
+ }
108
+
109
+ return self.renderToken(tokens, index, options);
110
+ };
111
+ }
112
+ }
113
+
94
114
  function markdownTaskLists(markdown) {
95
115
  markdown.core.ruler.after('inline', 'zeropress_task_lists', (state) => {
96
116
  const listStack = [];
@@ -142,8 +162,10 @@ function markdownTaskLists(markdown) {
142
162
  addTokenClass(listItemToken, 'task-list-item');
143
163
 
144
164
  const checkboxToken = new state.Token('html_inline', '', 0);
145
- const checked = markerMatch[1].toLowerCase() === 'x' ? ' checked' : '';
146
- checkboxToken.content = `<input class="task-list-item-checkbox" type="checkbox"${checked} disabled> `;
165
+ const isChecked = markerMatch[1].toLowerCase() === 'x';
166
+ const checked = isChecked ? ' checked' : '';
167
+ const label = isChecked ? 'Completed task' : 'Incomplete task';
168
+ checkboxToken.content = `<input class="task-list-item-checkbox" type="checkbox"${checked} disabled aria-label="${label}"> `;
147
169
 
148
170
  const strippedContent = token.content.slice(markerMatch[0].length);
149
171
  token.content = strippedContent;
@@ -317,7 +339,7 @@ function sanitizeHtml(html) {
317
339
  aside: new Set(['role', 'class', 'id']),
318
340
  img: new Set(['src', 'srcset', 'sizes', 'alt', 'title', 'class', 'id', 'width', 'height', 'loading', 'decoding']),
319
341
  iframe: new Set(['src', 'width', 'height', 'frameborder', 'allowfullscreen', 'class']),
320
- input: new Set(['type', 'checked', 'disabled', 'class', 'id']),
342
+ input: new Set(['type', 'checked', 'disabled', 'class', 'id', 'aria-label']),
321
343
  source: new Set(['src', 'srcset', 'sizes', 'type', 'media', 'width', 'height', 'class', 'id']),
322
344
  '*': new Set(['class', 'id']),
323
345
  };
@@ -370,10 +370,11 @@ export class ControlFlowRenderer {
370
370
  let alternate = [];
371
371
  let nextIndex = startIndex;
372
372
  let currentBranch = initialBranch;
373
- const elseIfTag = `else_${tagName}`;
373
+ const comparisonStopTags = new Set(['else', 'if', tagName, ...COMPARISON_ELSE_IF_TAGS]);
374
+ const comparisonCloseTags = new Set(['if', tagName]);
374
375
 
375
376
  while (true) {
376
- const branchResult = this.parseNodes(source, nextIndex, new Set(['else', elseIfTag, tagName]), partialArgScope);
377
+ const branchResult = this.parseNodes(source, nextIndex, comparisonStopTags, partialArgScope);
377
378
  branches.push({
378
379
  operator: currentBranch.operator,
379
380
  left: currentBranch.left,
@@ -382,8 +383,8 @@ export class ControlFlowRenderer {
382
383
  });
383
384
 
384
385
  if (branchResult.stopTag === 'else') {
385
- const elseResult = this.parseNodes(source, branchResult.nextIndex, new Set([tagName]), partialArgScope);
386
- if (elseResult.stopTag !== tagName) {
386
+ const elseResult = this.parseNodes(source, branchResult.nextIndex, comparisonCloseTags, partialArgScope);
387
+ if (!comparisonCloseTags.has(elseResult.stopTag)) {
387
388
  throw new Error(`Unclosed ${tagName} block after else`);
388
389
  }
389
390
  alternate = elseResult.nodes;
@@ -391,16 +392,19 @@ export class ControlFlowRenderer {
391
392
  break;
392
393
  }
393
394
 
394
- if (typeof branchResult.stopTag === 'string' && branchResult.stopTag.startsWith(`#${elseIfTag} `)) {
395
+ const comparisonElseIfTag = typeof branchResult.stopTag === 'string'
396
+ ? getComparisonElseIfTag(branchResult.stopTag)
397
+ : '';
398
+ if (comparisonElseIfTag) {
395
399
  currentBranch = this.parseComparisonBranchExpression(
396
- branchResult.stopTag.slice(`#${elseIfTag} `.length).trim(),
397
- elseIfTag,
400
+ branchResult.stopTag.slice(`#${comparisonElseIfTag} `.length).trim(),
401
+ comparisonElseIfTag,
398
402
  );
399
403
  nextIndex = branchResult.nextIndex;
400
404
  continue;
401
405
  }
402
406
 
403
- if (branchResult.stopTag === tagName) {
407
+ if (comparisonCloseTags.has(branchResult.stopTag)) {
404
408
  nextIndex = branchResult.nextIndex;
405
409
  break;
406
410
  }