@shevky/core 0.0.5 → 0.0.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/lib/contentFile.js +4 -0
- package/lib/contentHeader.js +4 -0
- package/lib/contentSummary.js +5 -0
- package/package.json +1 -1
- package/scripts/build.js +164 -19
- package/scripts/main.js +1 -1
- package/scripts/social.js +4 -0
package/lib/contentFile.js
CHANGED
package/lib/contentHeader.js
CHANGED
package/lib/contentSummary.js
CHANGED
|
@@ -12,6 +12,10 @@ export class ContentSummary {
|
|
|
12
12
|
return this._file.id;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
get fragment() {
|
|
16
|
+
return this._file.fragment;
|
|
17
|
+
}
|
|
18
|
+
|
|
15
19
|
get title() {
|
|
16
20
|
return this._file.title;
|
|
17
21
|
}
|
|
@@ -67,6 +71,7 @@ export class ContentSummary {
|
|
|
67
71
|
toObject() {
|
|
68
72
|
return {
|
|
69
73
|
id: this.id,
|
|
74
|
+
fragment: this.fragment,
|
|
70
75
|
title: this.title,
|
|
71
76
|
slug: this.slug,
|
|
72
77
|
lang: this.lang,
|
package/package.json
CHANGED
package/scripts/build.js
CHANGED
|
@@ -48,6 +48,7 @@ const TEMPLATES_DIR = _prj.templatesDir;
|
|
|
48
48
|
const ASSETS_DIR = _prj.assetsDir;
|
|
49
49
|
const SITE_CONFIG_PATH = _prj.siteConfig;
|
|
50
50
|
const I18N_CONFIG_PATH = _prj.i18nConfig;
|
|
51
|
+
const FRAGMENTS_DIR = "fragments";
|
|
51
52
|
|
|
52
53
|
const pluginRegistry = new PluginRegistry();
|
|
53
54
|
const templateRegistry = new TemplateRegistry();
|
|
@@ -461,6 +462,100 @@ async function renderContentTemplate(
|
|
|
461
462
|
listingOverride,
|
|
462
463
|
) {
|
|
463
464
|
const template = templateRegistry.getTemplate(TYPE_TEMPLATE, templateName);
|
|
465
|
+
const {
|
|
466
|
+
normalizedFront,
|
|
467
|
+
listing,
|
|
468
|
+
collectionFlags,
|
|
469
|
+
site,
|
|
470
|
+
languageFlags,
|
|
471
|
+
resolvedDictionary,
|
|
472
|
+
} = buildContentRenderContext(front, lang, dictionary, listingOverride);
|
|
473
|
+
|
|
474
|
+
return Mustache.render(
|
|
475
|
+
template.content,
|
|
476
|
+
{
|
|
477
|
+
content: { html: decorateHtml(contentHtml, templateName) },
|
|
478
|
+
front: normalizedFront,
|
|
479
|
+
lang,
|
|
480
|
+
listing,
|
|
481
|
+
site,
|
|
482
|
+
locale: languageFlags.locale,
|
|
483
|
+
isEnglish: languageFlags.isEnglish,
|
|
484
|
+
isTurkish: languageFlags.isTurkish,
|
|
485
|
+
i18n: resolvedDictionary,
|
|
486
|
+
...collectionFlags,
|
|
487
|
+
},
|
|
488
|
+
{
|
|
489
|
+
...templateRegistry.getFiles(TYPE_PARTIAL),
|
|
490
|
+
...templateRegistry.getFiles(TYPE_COMPONENT),
|
|
491
|
+
},
|
|
492
|
+
);
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
/**
|
|
496
|
+
* @param {string} contentHtml
|
|
497
|
+
* @param {FrontMatter} front
|
|
498
|
+
* @param {string} lang
|
|
499
|
+
* @param {Record<string, any>} dictionary
|
|
500
|
+
* @param {string} [templateName]
|
|
501
|
+
* @param {any} [listingOverride]
|
|
502
|
+
*/
|
|
503
|
+
async function renderFragmentTemplate(
|
|
504
|
+
contentHtml,
|
|
505
|
+
front,
|
|
506
|
+
lang,
|
|
507
|
+
dictionary,
|
|
508
|
+
templateName,
|
|
509
|
+
listingOverride,
|
|
510
|
+
) {
|
|
511
|
+
const template =
|
|
512
|
+
typeof templateName === "string" && templateName.trim().length > 0
|
|
513
|
+
? templateRegistry.getTemplate(TYPE_TEMPLATE, templateName.trim())
|
|
514
|
+
: null;
|
|
515
|
+
if (templateName && !template) {
|
|
516
|
+
_log.warn(`[build] Fragment template not found: ${templateName}`);
|
|
517
|
+
}
|
|
518
|
+
const {
|
|
519
|
+
normalizedFront,
|
|
520
|
+
listing,
|
|
521
|
+
collectionFlags,
|
|
522
|
+
site,
|
|
523
|
+
languageFlags,
|
|
524
|
+
resolvedDictionary,
|
|
525
|
+
} = buildContentRenderContext(front, lang, dictionary, listingOverride);
|
|
526
|
+
const decorated = decorateHtml(contentHtml, templateName ?? "");
|
|
527
|
+
const templateContent = template?.content ?? "{{{content.html}}}";
|
|
528
|
+
|
|
529
|
+
return Mustache.render(
|
|
530
|
+
templateContent,
|
|
531
|
+
{
|
|
532
|
+
content: { html: decorated },
|
|
533
|
+
contentHtml: decorated,
|
|
534
|
+
contentObject: { html: decorated },
|
|
535
|
+
front: normalizedFront,
|
|
536
|
+
lang,
|
|
537
|
+
listing,
|
|
538
|
+
site,
|
|
539
|
+
locale: languageFlags.locale,
|
|
540
|
+
isEnglish: languageFlags.isEnglish,
|
|
541
|
+
isTurkish: languageFlags.isTurkish,
|
|
542
|
+
i18n: resolvedDictionary,
|
|
543
|
+
...collectionFlags,
|
|
544
|
+
},
|
|
545
|
+
{
|
|
546
|
+
...templateRegistry.getFiles(TYPE_PARTIAL),
|
|
547
|
+
...templateRegistry.getFiles(TYPE_COMPONENT),
|
|
548
|
+
},
|
|
549
|
+
);
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
/**
|
|
553
|
+
* @param {FrontMatter} front
|
|
554
|
+
* @param {string} lang
|
|
555
|
+
* @param {Record<string, any>} dictionary
|
|
556
|
+
* @param {any} [listingOverride]
|
|
557
|
+
*/
|
|
558
|
+
function buildContentRenderContext(front, lang, dictionary, listingOverride) {
|
|
464
559
|
const baseFront = normalizeFrontMatter(front);
|
|
465
560
|
/** @type {string[]} */
|
|
466
561
|
const normalizedTags = Array.isArray(front.tags)
|
|
@@ -513,25 +608,14 @@ async function renderContentTemplate(
|
|
|
513
608
|
const site = metaEngine.buildSiteData(lang);
|
|
514
609
|
const languageFlags = _i18n.flags(lang);
|
|
515
610
|
|
|
516
|
-
return
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
locale: languageFlags.locale,
|
|
525
|
-
isEnglish: languageFlags.isEnglish,
|
|
526
|
-
isTurkish: languageFlags.isTurkish,
|
|
527
|
-
i18n: resolvedDictionary,
|
|
528
|
-
...collectionFlags,
|
|
529
|
-
},
|
|
530
|
-
{
|
|
531
|
-
...templateRegistry.getFiles(TYPE_PARTIAL),
|
|
532
|
-
...templateRegistry.getFiles(TYPE_COMPONENT),
|
|
533
|
-
},
|
|
534
|
-
);
|
|
611
|
+
return {
|
|
612
|
+
normalizedFront,
|
|
613
|
+
listing,
|
|
614
|
+
collectionFlags,
|
|
615
|
+
site,
|
|
616
|
+
languageFlags,
|
|
617
|
+
resolvedDictionary,
|
|
618
|
+
};
|
|
535
619
|
}
|
|
536
620
|
|
|
537
621
|
/**
|
|
@@ -597,6 +681,18 @@ function buildOutputPath(front, lang, slug) {
|
|
|
597
681
|
return _io.path.combine(...segments.filter(Boolean), "index.html");
|
|
598
682
|
}
|
|
599
683
|
|
|
684
|
+
/** @param {unknown} value */
|
|
685
|
+
function resolveFragmentId(value) {
|
|
686
|
+
if (typeof value !== "string") {
|
|
687
|
+
return "";
|
|
688
|
+
}
|
|
689
|
+
const trimmed = value.trim();
|
|
690
|
+
if (!trimmed) {
|
|
691
|
+
return "";
|
|
692
|
+
}
|
|
693
|
+
return trimmed.replace(/[\\/]/g, "-");
|
|
694
|
+
}
|
|
695
|
+
|
|
600
696
|
/** @param {string} value */
|
|
601
697
|
function toPosixPath(value) {
|
|
602
698
|
return value.split(_io.path.separator).join("/");
|
|
@@ -833,6 +929,13 @@ async function buildContentPages() {
|
|
|
833
929
|
markdownHtml ?? "",
|
|
834
930
|
placeholders,
|
|
835
931
|
);
|
|
932
|
+
const rawFront = normalizeFrontMatter(file.header);
|
|
933
|
+
const shouldBuildFragment = _fmt.boolean(rawFront.fragment);
|
|
934
|
+
const fragmentTemplateName =
|
|
935
|
+
typeof rawFront.fragmentTemplate === "string" &&
|
|
936
|
+
rawFront.fragmentTemplate.trim().length > 0
|
|
937
|
+
? rawFront.fragmentTemplate.trim()
|
|
938
|
+
: file.template;
|
|
836
939
|
|
|
837
940
|
if (file.template === "collection" || file.template === "home") {
|
|
838
941
|
await renderEngine.buildPaginatedCollectionPages({
|
|
@@ -918,6 +1021,48 @@ async function buildContentPages() {
|
|
|
918
1021
|
inputBytes: byteLength(file.content),
|
|
919
1022
|
},
|
|
920
1023
|
});
|
|
1024
|
+
|
|
1025
|
+
if (shouldBuildFragment) {
|
|
1026
|
+
const fragmentId = resolveFragmentId(rawFront.id ?? file.id);
|
|
1027
|
+
if (!fragmentId) {
|
|
1028
|
+
_log.warn(
|
|
1029
|
+
`[build] Fragment skipped for ${normalizeLogPath(file.sourcePath)} (missing id).`,
|
|
1030
|
+
);
|
|
1031
|
+
} else {
|
|
1032
|
+
const fragmentHtml = await renderFragmentTemplate(
|
|
1033
|
+
hydratedHtml,
|
|
1034
|
+
file.header,
|
|
1035
|
+
file.lang,
|
|
1036
|
+
dictionary,
|
|
1037
|
+
fragmentTemplateName,
|
|
1038
|
+
);
|
|
1039
|
+
const transformedFragment = await renderEngine.transformHtml(
|
|
1040
|
+
fragmentHtml,
|
|
1041
|
+
{
|
|
1042
|
+
versionToken,
|
|
1043
|
+
minifyHtml,
|
|
1044
|
+
},
|
|
1045
|
+
);
|
|
1046
|
+
const fragmentLang =
|
|
1047
|
+
typeof file.lang === "string" && file.lang.trim().length > 0
|
|
1048
|
+
? file.lang.trim()
|
|
1049
|
+
: _i18n.default;
|
|
1050
|
+
const fragmentPath = _io.path.combine(
|
|
1051
|
+
FRAGMENTS_DIR,
|
|
1052
|
+
fragmentLang,
|
|
1053
|
+
`frag_${fragmentId}.html`,
|
|
1054
|
+
);
|
|
1055
|
+
GENERATED_PAGES.add(toPosixPath(fragmentPath));
|
|
1056
|
+
await writeHtmlFile(fragmentPath, transformedFragment, {
|
|
1057
|
+
action: "BUILD_FRAGMENT",
|
|
1058
|
+
type: "fragment",
|
|
1059
|
+
source: file.sourcePath,
|
|
1060
|
+
lang: file.lang,
|
|
1061
|
+
template: fragmentTemplateName,
|
|
1062
|
+
inputBytes: byteLength(file.content),
|
|
1063
|
+
});
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
921
1066
|
}
|
|
922
1067
|
|
|
923
1068
|
await renderEngine.buildDynamicCollectionPages({
|
package/scripts/main.js
CHANGED