@riebeckite/plugin-diagnostics 0.0.17 → 0.0.19
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 +1 -1
- package/README_ja.md +1 -1
- package/dist/bin.js +21 -5
- package/dist/index.js +80 -7
- package/package.json +2 -2
package/README.md
CHANGED
package/README_ja.md
CHANGED
package/dist/bin.js
CHANGED
|
@@ -258,7 +258,11 @@ async function scanVault(config) {
|
|
|
258
258
|
const note = {
|
|
259
259
|
relativePath: relative,
|
|
260
260
|
slug,
|
|
261
|
-
language: resolveNoteLanguage(
|
|
261
|
+
language: resolveNoteLanguage(
|
|
262
|
+
relative,
|
|
263
|
+
fm.values.lang,
|
|
264
|
+
config.languages
|
|
265
|
+
),
|
|
262
266
|
markdown,
|
|
263
267
|
fm,
|
|
264
268
|
headings: extractHeadings(markdown),
|
|
@@ -417,11 +421,23 @@ function fragmentExists(note, fragment) {
|
|
|
417
421
|
function normalizeMarkdown(markdown) {
|
|
418
422
|
return markdown.replace(/\r\n/g, "\n");
|
|
419
423
|
}
|
|
420
|
-
function resolveNoteLanguage(relativePath, languages) {
|
|
424
|
+
function resolveNoteLanguage(relativePath, frontmatterLang, languages) {
|
|
421
425
|
if (!languages || languages.length === 0) return void 0;
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
426
|
+
if (typeof frontmatterLang === "string" && frontmatterLang.trim()) {
|
|
427
|
+
const value = frontmatterLang.trim().toLowerCase();
|
|
428
|
+
const match = languages.find(
|
|
429
|
+
(language) => language.toLowerCase() === value
|
|
430
|
+
);
|
|
431
|
+
if (match) return match;
|
|
432
|
+
}
|
|
433
|
+
const filename = relativePath.split("/").at(-1)?.replace(/\.md$/i, "") ?? "";
|
|
434
|
+
const lower = filename.toLowerCase();
|
|
435
|
+
for (const language of languages) {
|
|
436
|
+
const tag = language.toLowerCase();
|
|
437
|
+
if (lower.endsWith(`.${tag}`) || lower.endsWith(`-${tag}`) || lower.endsWith(`_${tag}`))
|
|
438
|
+
return language;
|
|
439
|
+
}
|
|
440
|
+
return void 0;
|
|
425
441
|
}
|
|
426
442
|
function getExtension(filePath) {
|
|
427
443
|
const lastSegment = filePath.split("/").pop() ?? filePath;
|
package/dist/index.js
CHANGED
|
@@ -254,7 +254,11 @@ async function scanVault(config) {
|
|
|
254
254
|
const note = {
|
|
255
255
|
relativePath: relative,
|
|
256
256
|
slug,
|
|
257
|
-
language: resolveNoteLanguage(
|
|
257
|
+
language: resolveNoteLanguage(
|
|
258
|
+
relative,
|
|
259
|
+
fm.values.lang,
|
|
260
|
+
config.languages
|
|
261
|
+
),
|
|
258
262
|
markdown,
|
|
259
263
|
fm,
|
|
260
264
|
headings: extractHeadings(markdown),
|
|
@@ -413,11 +417,23 @@ function fragmentExists(note, fragment) {
|
|
|
413
417
|
function normalizeMarkdown(markdown) {
|
|
414
418
|
return markdown.replace(/\r\n/g, "\n");
|
|
415
419
|
}
|
|
416
|
-
function resolveNoteLanguage(relativePath, languages) {
|
|
420
|
+
function resolveNoteLanguage(relativePath, frontmatterLang, languages) {
|
|
417
421
|
if (!languages || languages.length === 0) return void 0;
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
422
|
+
if (typeof frontmatterLang === "string" && frontmatterLang.trim()) {
|
|
423
|
+
const value = frontmatterLang.trim().toLowerCase();
|
|
424
|
+
const match = languages.find(
|
|
425
|
+
(language) => language.toLowerCase() === value
|
|
426
|
+
);
|
|
427
|
+
if (match) return match;
|
|
428
|
+
}
|
|
429
|
+
const filename = relativePath.split("/").at(-1)?.replace(/\.md$/i, "") ?? "";
|
|
430
|
+
const lower = filename.toLowerCase();
|
|
431
|
+
for (const language of languages) {
|
|
432
|
+
const tag = language.toLowerCase();
|
|
433
|
+
if (lower.endsWith(`.${tag}`) || lower.endsWith(`-${tag}`) || lower.endsWith(`_${tag}`))
|
|
434
|
+
return language;
|
|
435
|
+
}
|
|
436
|
+
return void 0;
|
|
421
437
|
}
|
|
422
438
|
function getExtension(filePath) {
|
|
423
439
|
const lastSegment = filePath.split("/").pop() ?? filePath;
|
|
@@ -991,6 +1007,7 @@ var PLUGIN_NAME2 = "diagnostics";
|
|
|
991
1007
|
var DEFAULT_SEVERITY2 = {
|
|
992
1008
|
"content-integrity:broken-link": "warning",
|
|
993
1009
|
"content-integrity:unresolved-wikilink": "warning",
|
|
1010
|
+
"content-integrity:ambiguous-wikilink": "warning",
|
|
994
1011
|
"content-integrity:broken-asset": "warning",
|
|
995
1012
|
"content-integrity:duplicate-public-location": "error",
|
|
996
1013
|
"content-integrity:redirect-target-missing": "warning",
|
|
@@ -1006,8 +1023,18 @@ function checkSiteIntegrity(manifest, options = {}) {
|
|
|
1006
1023
|
const routeOwners = buildRouteOwners(manifest, diagnostics2, options);
|
|
1007
1024
|
const publicRoutes = new Set(routeOwners.keys());
|
|
1008
1025
|
const assetPaths = buildAssetPaths(manifest);
|
|
1026
|
+
const noteSlugs = new Set(manifest.entries.map((entry) => entry.slug));
|
|
1027
|
+
const ambiguities = manifest.contentIndexAmbiguities ?? /* @__PURE__ */ new Map();
|
|
1009
1028
|
for (const entry of manifest.publicEntries) {
|
|
1010
|
-
checkResolvedLinks(
|
|
1029
|
+
checkResolvedLinks(
|
|
1030
|
+
entry,
|
|
1031
|
+
publicSlugs,
|
|
1032
|
+
assetPaths,
|
|
1033
|
+
noteSlugs,
|
|
1034
|
+
ambiguities,
|
|
1035
|
+
diagnostics2,
|
|
1036
|
+
options
|
|
1037
|
+
);
|
|
1011
1038
|
checkHtmlReferences(entry, publicRoutes, assetPaths, diagnostics2, options);
|
|
1012
1039
|
}
|
|
1013
1040
|
checkRedirectTargets(manifest, diagnostics2, options);
|
|
@@ -1070,9 +1097,24 @@ function reserveRoute(owners, diagnostics2, options, next) {
|
|
|
1070
1097
|
})
|
|
1071
1098
|
);
|
|
1072
1099
|
}
|
|
1073
|
-
function checkResolvedLinks(entry, publicSlugs, assetPaths, diagnostics2, options) {
|
|
1100
|
+
function checkResolvedLinks(entry, publicSlugs, assetPaths, noteSlugs, ambiguities, diagnostics2, options) {
|
|
1074
1101
|
for (const link of entry.links) {
|
|
1075
1102
|
if (link.kind === "unresolved") {
|
|
1103
|
+
const ambiguity = ambiguities.get(link.raw.toLowerCase());
|
|
1104
|
+
if (ambiguity && ambiguity.length > 0) {
|
|
1105
|
+
diagnostics2.push(
|
|
1106
|
+
createAmbiguousWikilinkDiagnostic(
|
|
1107
|
+
entry,
|
|
1108
|
+
link.raw,
|
|
1109
|
+
link.embed,
|
|
1110
|
+
ambiguity,
|
|
1111
|
+
noteSlugs,
|
|
1112
|
+
publicSlugs,
|
|
1113
|
+
options
|
|
1114
|
+
)
|
|
1115
|
+
);
|
|
1116
|
+
continue;
|
|
1117
|
+
}
|
|
1076
1118
|
diagnostics2.push(
|
|
1077
1119
|
diagnostic(options, {
|
|
1078
1120
|
code: "content-integrity:unresolved-wikilink",
|
|
@@ -1118,6 +1160,37 @@ function checkResolvedLinks(entry, publicSlugs, assetPaths, diagnostics2, option
|
|
|
1118
1160
|
}
|
|
1119
1161
|
}
|
|
1120
1162
|
}
|
|
1163
|
+
function createAmbiguousWikilinkDiagnostic(entry, raw, embed, candidates, noteSlugs, publicSlugs, options) {
|
|
1164
|
+
const visible = [];
|
|
1165
|
+
let unpublishedCount = 0;
|
|
1166
|
+
for (const candidate of candidates) {
|
|
1167
|
+
if (!noteSlugs.has(candidate)) {
|
|
1168
|
+
visible.push(candidate);
|
|
1169
|
+
continue;
|
|
1170
|
+
}
|
|
1171
|
+
if (publicSlugs.has(candidate)) visible.push(candidate);
|
|
1172
|
+
else unpublishedCount += 1;
|
|
1173
|
+
}
|
|
1174
|
+
const described = [...visible];
|
|
1175
|
+
if (unpublishedCount > 0)
|
|
1176
|
+
described.push(`${unpublishedCount} unpublished candidate(s)`);
|
|
1177
|
+
const first = visible[0];
|
|
1178
|
+
const suggestion = first ? `Use an explicit path such as [[${first}]].` : "Rename one of the duplicate targets or reference it by a unique path.";
|
|
1179
|
+
return diagnostic(options, {
|
|
1180
|
+
code: "content-integrity:ambiguous-wikilink",
|
|
1181
|
+
slug: entry.slug,
|
|
1182
|
+
filePath: `${entry.slug}.md`,
|
|
1183
|
+
target: raw,
|
|
1184
|
+
message: `WikiLink target "${raw}" matches multiple candidates: ${described.join(", ")}.`,
|
|
1185
|
+
suggestion,
|
|
1186
|
+
meta: {
|
|
1187
|
+
raw,
|
|
1188
|
+
embed,
|
|
1189
|
+
candidates: visible,
|
|
1190
|
+
...unpublishedCount > 0 ? { unpublishedCandidateCount: unpublishedCount } : {}
|
|
1191
|
+
}
|
|
1192
|
+
});
|
|
1193
|
+
}
|
|
1121
1194
|
function checkHtmlReferences(entry, publicRoutes, assetPaths, diagnostics2, options) {
|
|
1122
1195
|
for (const href of extractAttributes(entry.html, "href")) {
|
|
1123
1196
|
if (!isSiteLocalReference(href)) continue;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@riebeckite/plugin-diagnostics",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.19",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"remark-parse": "^11.0.0",
|
|
21
21
|
"unified": "^11.0.5",
|
|
22
22
|
"unist-util-visit": "^5.1.0",
|
|
23
|
-
"@riebeckite/core": "0.0.
|
|
23
|
+
"@riebeckite/core": "0.0.19"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
26
|
"@types/mdast": "^4.0.4",
|