@shevky/core 0.0.6 → 0.0.7
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/contentHeader.js +4 -3
- package/package.json +1 -1
- package/registries/contentRegistry.js +58 -7
- package/scripts/main.js +1 -1
package/lib/contentHeader.js
CHANGED
|
@@ -124,9 +124,10 @@ export class ContentHeader {
|
|
|
124
124
|
|
|
125
125
|
get tags() {
|
|
126
126
|
const tags = _fmt.normalizeStringArray(this._frontMatter.tags);
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
127
|
+
const normalized = tags
|
|
128
|
+
.map((tag) => _fmt.slugify(tag))
|
|
129
|
+
.filter((tag) => tag.length > 0);
|
|
130
|
+
return [...new Set(normalized)];
|
|
130
131
|
}
|
|
131
132
|
|
|
132
133
|
get keywords() {
|
package/package.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { io as _io, config as _cfg } from "@shevky/base";
|
|
1
|
+
import { io as _io, config as _cfg, log as _log } from "@shevky/base";
|
|
2
2
|
import matter from "gray-matter";
|
|
3
3
|
|
|
4
4
|
import { ContentFile } from "../lib/contentFile.js";
|
|
@@ -37,6 +37,7 @@ export class ContentRegistry {
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
const files = await _io.directory.read(path);
|
|
40
|
+
let hasChanges = false;
|
|
40
41
|
for (const entry of files) {
|
|
41
42
|
if (!entry.endsWith(".md")) {
|
|
42
43
|
continue;
|
|
@@ -49,10 +50,14 @@ export class ContentRegistry {
|
|
|
49
50
|
}
|
|
50
51
|
|
|
51
52
|
const contentFile = await this.#_loadFromFile(filePath);
|
|
52
|
-
this.#
|
|
53
|
+
if (this.#_addUniqueContent(contentFile)) {
|
|
54
|
+
hasChanges = true;
|
|
55
|
+
}
|
|
53
56
|
}
|
|
54
57
|
|
|
55
|
-
|
|
58
|
+
if (hasChanges) {
|
|
59
|
+
this.#_resetCaches();
|
|
60
|
+
}
|
|
56
61
|
}
|
|
57
62
|
|
|
58
63
|
get count() {
|
|
@@ -72,8 +77,9 @@ export class ContentRegistry {
|
|
|
72
77
|
}
|
|
73
78
|
|
|
74
79
|
if (input instanceof ContentFile) {
|
|
75
|
-
this.#
|
|
76
|
-
|
|
80
|
+
if (this.#_addUniqueContent(input)) {
|
|
81
|
+
this.#_resetCaches();
|
|
82
|
+
}
|
|
77
83
|
return;
|
|
78
84
|
}
|
|
79
85
|
|
|
@@ -92,8 +98,9 @@ export class ContentRegistry {
|
|
|
92
98
|
const isValid = typeof input.isValid === "boolean" ? input.isValid : true;
|
|
93
99
|
|
|
94
100
|
const contentFile = new ContentFile(header, content, sourcePath, isValid);
|
|
95
|
-
this.#
|
|
96
|
-
|
|
101
|
+
if (this.#_addUniqueContent(contentFile)) {
|
|
102
|
+
this.#_resetCaches();
|
|
103
|
+
}
|
|
97
104
|
}
|
|
98
105
|
|
|
99
106
|
/**
|
|
@@ -325,4 +332,48 @@ export class ContentRegistry {
|
|
|
325
332
|
});
|
|
326
333
|
return sorted;
|
|
327
334
|
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Adds content only if required fields exist and id+lang is unique.
|
|
338
|
+
* @param {ContentFile} contentFile
|
|
339
|
+
*/
|
|
340
|
+
#_addUniqueContent(contentFile) {
|
|
341
|
+
if (!(contentFile instanceof ContentFile)) {
|
|
342
|
+
return false;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
const id = typeof contentFile.id === "string" ? contentFile.id.trim() : "";
|
|
346
|
+
const lang =
|
|
347
|
+
typeof contentFile.lang === "string" ? contentFile.lang.trim() : "";
|
|
348
|
+
const sourcePath =
|
|
349
|
+
typeof contentFile.sourcePath === "string" &&
|
|
350
|
+
contentFile.sourcePath.trim().length > 0
|
|
351
|
+
? contentFile.sourcePath
|
|
352
|
+
: "unknown source";
|
|
353
|
+
|
|
354
|
+
/** @type {string[]} */
|
|
355
|
+
const missingFields = [];
|
|
356
|
+
if (!id) missingFields.push("id");
|
|
357
|
+
if (!lang) missingFields.push("lang");
|
|
358
|
+
if (missingFields.length > 0) {
|
|
359
|
+
_log.warn(
|
|
360
|
+
`[content] Skipped content: missing required field(s): ${missingFields.join(", ")} (${sourcePath})`,
|
|
361
|
+
);
|
|
362
|
+
return false;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
const hasExisting = this.#_cache.some((entry) => {
|
|
366
|
+
const existingId = typeof entry.id === "string" ? entry.id.trim() : "";
|
|
367
|
+
const existingLang =
|
|
368
|
+
typeof entry.lang === "string" ? entry.lang.trim() : "";
|
|
369
|
+
return existingId === id && existingLang === lang;
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
if (hasExisting) {
|
|
373
|
+
return false;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
this.#_cache.push(contentFile);
|
|
377
|
+
return true;
|
|
378
|
+
}
|
|
328
379
|
}
|
package/scripts/main.js
CHANGED