@ox-content/vite-plugin 2.2.0 → 2.4.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.
- package/LICENSE +21 -0
- package/dist/index.cjs +373 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +270 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +270 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +479 -114
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -2
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 ubugeeei
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/index.cjs
CHANGED
|
@@ -14,6 +14,7 @@ let rehype_stringify = require("rehype-stringify");
|
|
|
14
14
|
rehype_stringify = require_chunk.__toESM(rehype_stringify);
|
|
15
15
|
let shiki = require("shiki");
|
|
16
16
|
let node_path = require("node:path");
|
|
17
|
+
node_path = require_chunk.__toESM(node_path);
|
|
17
18
|
let fs = require("fs");
|
|
18
19
|
fs = require_chunk.__toESM(fs);
|
|
19
20
|
let node_crypto = require("node:crypto");
|
|
@@ -22,7 +23,9 @@ fs_promises = require_chunk.__toESM(fs_promises);
|
|
|
22
23
|
let glob = require("glob");
|
|
23
24
|
let crypto = require("crypto");
|
|
24
25
|
crypto = require_chunk.__toESM(crypto);
|
|
26
|
+
let node_module = require("node:module");
|
|
25
27
|
let node_fs_promises = require("node:fs/promises");
|
|
28
|
+
node_fs_promises = require_chunk.__toESM(node_fs_promises);
|
|
26
29
|
//#region src/environment.ts
|
|
27
30
|
/**
|
|
28
31
|
* Creates the Markdown processing environment configuration.
|
|
@@ -7520,11 +7523,22 @@ function renderDetailsControlsHtml(targetSelector) {
|
|
|
7520
7523
|
<button type="button" class="ox-api-controls__button" data-ox-api-toggle="collapse">Close all</button>
|
|
7521
7524
|
</div>`;
|
|
7522
7525
|
}
|
|
7526
|
+
function normalizeDocFilePath(filePath) {
|
|
7527
|
+
const normalized = filePath.replace(/\\/g, "/");
|
|
7528
|
+
return normalized.match(/(?:^|\/)((?:npm|packages|crates|src)\/.+)$/)?.[1] ?? normalized.replace(/^\/+/, "");
|
|
7529
|
+
}
|
|
7523
7530
|
function buildDocsData(docs) {
|
|
7524
7531
|
return {
|
|
7525
7532
|
version: 1,
|
|
7526
7533
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7527
|
-
modules: docs
|
|
7534
|
+
modules: docs.map((doc) => ({
|
|
7535
|
+
...doc,
|
|
7536
|
+
file: normalizeDocFilePath(doc.file),
|
|
7537
|
+
entries: doc.entries.map((entry) => ({
|
|
7538
|
+
...entry,
|
|
7539
|
+
file: normalizeDocFilePath(entry.file)
|
|
7540
|
+
}))
|
|
7541
|
+
}))
|
|
7528
7542
|
};
|
|
7529
7543
|
}
|
|
7530
7544
|
/**
|
|
@@ -8054,7 +8068,7 @@ async function writeDocs(docs, outDir, extractedDocs, options) {
|
|
|
8054
8068
|
* @returns Absolute GitHub URL to source code
|
|
8055
8069
|
*/
|
|
8056
8070
|
function generateSourceHref(filePath, githubUrl, lineNumber, endLineNumber) {
|
|
8057
|
-
return `${githubUrl}/blob/main/${filePath
|
|
8071
|
+
return `${githubUrl}/blob/main/${normalizeDocFilePath(filePath)}${lineNumber ? endLineNumber && endLineNumber > lineNumber ? `#L${lineNumber}-L${endLineNumber}` : `#L${lineNumber}` : ""}`;
|
|
8058
8072
|
}
|
|
8059
8073
|
function generateSourceLink(filePath, githubUrl, lineNumber, endLineNumber) {
|
|
8060
8074
|
return `**[Source](${generateSourceHref(filePath, githubUrl, lineNumber, endLineNumber)})**`;
|
|
@@ -12135,6 +12149,358 @@ function walkDir(dir, pattern, callback) {
|
|
|
12135
12149
|
}
|
|
12136
12150
|
}
|
|
12137
12151
|
//#endregion
|
|
12152
|
+
//#region src/lint.ts
|
|
12153
|
+
const require$1 = (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href);
|
|
12154
|
+
const SUPPORTED_MARKDOWN_LINT_LANGUAGES = [
|
|
12155
|
+
"en",
|
|
12156
|
+
"ja",
|
|
12157
|
+
"zh",
|
|
12158
|
+
"fr",
|
|
12159
|
+
"de",
|
|
12160
|
+
"pl"
|
|
12161
|
+
];
|
|
12162
|
+
const DEFAULT_LANGUAGES = ["en"];
|
|
12163
|
+
const DEFAULT_RULES = {
|
|
12164
|
+
duplicateHeadings: true,
|
|
12165
|
+
headingIncrement: true,
|
|
12166
|
+
maxConsecutiveBlankLines: 1,
|
|
12167
|
+
repeatedPunctuation: true,
|
|
12168
|
+
repeatedWords: true,
|
|
12169
|
+
spellcheck: true,
|
|
12170
|
+
trailingSpaces: true
|
|
12171
|
+
};
|
|
12172
|
+
const DEFAULT_CSPELL_IMPORTS = {
|
|
12173
|
+
de: "@cspell/dict-de-de/cspell-ext.json",
|
|
12174
|
+
en: "@cspell/dict-en_us/cspell-ext.json",
|
|
12175
|
+
fr: "@cspell/dict-fr-fr/cspell-ext.json",
|
|
12176
|
+
pl: "@cspell/dict-pl_pl/cspell-ext.json"
|
|
12177
|
+
};
|
|
12178
|
+
let napiBinding;
|
|
12179
|
+
let cspellLibPromise;
|
|
12180
|
+
/**
|
|
12181
|
+
* Lints Markdown prose with the Rust-backed built-in rule engine.
|
|
12182
|
+
*/
|
|
12183
|
+
function lintMarkdown(source, options = {}) {
|
|
12184
|
+
return lintMarkdownWithNormalizedOptions(source, normalizeLintOptions(options));
|
|
12185
|
+
}
|
|
12186
|
+
/**
|
|
12187
|
+
* Async Markdown linter that supports opt-in standard dictionaries.
|
|
12188
|
+
*/
|
|
12189
|
+
async function lintMarkdownAsync(source, options = {}) {
|
|
12190
|
+
const normalizedOptions = normalizeLintOptions(options);
|
|
12191
|
+
const [result] = await lintMarkdownDocumentsWithNormalizedOptions([source], normalizedOptions);
|
|
12192
|
+
return result ?? createEmptyLintResult$1();
|
|
12193
|
+
}
|
|
12194
|
+
/**
|
|
12195
|
+
* Internal batched Markdown linting entry point used by file-based workflows.
|
|
12196
|
+
*/
|
|
12197
|
+
async function lintMarkdownDocumentsAsync(sources, options = {}) {
|
|
12198
|
+
return lintMarkdownDocumentsWithNormalizedOptions(sources, normalizeLintOptions(options));
|
|
12199
|
+
}
|
|
12200
|
+
function lintMarkdownWithNormalizedOptions(source, normalizedOptions) {
|
|
12201
|
+
if (normalizedOptions.dictionary.standard) throw new Error("[ox-content] lintMarkdownAsync is required when dictionary.standard is enabled.");
|
|
12202
|
+
return stripMaskedDocument(loadNapiBindingSync().lintMarkdown(source, toNapiMarkdownLintOptions(normalizedOptions)));
|
|
12203
|
+
}
|
|
12204
|
+
async function lintMarkdownDocumentsWithNormalizedOptions(sources, normalizedOptions) {
|
|
12205
|
+
if (sources.length === 0) return [];
|
|
12206
|
+
const napi = loadNapiBindingSync();
|
|
12207
|
+
const napiOptions = toNapiMarkdownLintOptions(normalizedOptions, Boolean(normalizedOptions.dictionary.standard));
|
|
12208
|
+
const builtInResults = typeof napi.lintMarkdownDocuments === "function" ? napi.lintMarkdownDocuments(sources, napiOptions) : sources.map((source) => napi.lintMarkdown(source, napiOptions));
|
|
12209
|
+
if (!normalizedOptions.rules.spellcheck || !normalizedOptions.dictionary.standard) return builtInResults.map(stripMaskedDocument);
|
|
12210
|
+
const standardDiagnostics = await runStandardSpellcheckDocuments(builtInResults.map((result) => result.maskedDocument), normalizedOptions);
|
|
12211
|
+
return builtInResults.map((result, index) => summarizeDiagnostics(sortDiagnostics(result.diagnostics.concat(standardDiagnostics[index] ?? []))));
|
|
12212
|
+
}
|
|
12213
|
+
function loadNapiBindingSync() {
|
|
12214
|
+
if (napiBinding) return napiBinding;
|
|
12215
|
+
if (napiBinding === null) throw new Error("[ox-content] @ox-content/napi is required for Markdown linting. Please ensure the NAPI module is built.");
|
|
12216
|
+
try {
|
|
12217
|
+
const loaded = require$1("@ox-content/napi");
|
|
12218
|
+
napiBinding = loaded.default && typeof loaded.default === "object" ? {
|
|
12219
|
+
...loaded.default,
|
|
12220
|
+
...loaded
|
|
12221
|
+
} : loaded;
|
|
12222
|
+
return napiBinding;
|
|
12223
|
+
} catch {
|
|
12224
|
+
napiBinding = null;
|
|
12225
|
+
throw new Error("[ox-content] @ox-content/napi is required for Markdown linting. Please ensure the NAPI module is built.");
|
|
12226
|
+
}
|
|
12227
|
+
}
|
|
12228
|
+
function toNapiMarkdownLintOptions(options, disableBuiltinSpellcheck = false) {
|
|
12229
|
+
return {
|
|
12230
|
+
dictionary: {
|
|
12231
|
+
byLanguage: Object.entries(options.dictionary.byLanguage ?? {}).map(([language, words]) => ({
|
|
12232
|
+
language,
|
|
12233
|
+
words
|
|
12234
|
+
})),
|
|
12235
|
+
ignoredWords: options.dictionary.ignoredWords,
|
|
12236
|
+
words: options.dictionary.words
|
|
12237
|
+
},
|
|
12238
|
+
languages: options.languages,
|
|
12239
|
+
rules: {
|
|
12240
|
+
...options.rules,
|
|
12241
|
+
spellcheck: disableBuiltinSpellcheck ? false : options.rules.spellcheck
|
|
12242
|
+
}
|
|
12243
|
+
};
|
|
12244
|
+
}
|
|
12245
|
+
function stripMaskedDocument(result) {
|
|
12246
|
+
return {
|
|
12247
|
+
diagnostics: result.diagnostics,
|
|
12248
|
+
errorCount: result.errorCount,
|
|
12249
|
+
infoCount: result.infoCount,
|
|
12250
|
+
warningCount: result.warningCount
|
|
12251
|
+
};
|
|
12252
|
+
}
|
|
12253
|
+
function normalizeLintOptions(options) {
|
|
12254
|
+
const languages = options.languages?.filter((language) => SUPPORTED_MARKDOWN_LINT_LANGUAGES.includes(language)) ?? options.dictionary?.standard?.languages?.filter((language) => SUPPORTED_MARKDOWN_LINT_LANGUAGES.includes(language)) ?? [...DEFAULT_LANGUAGES];
|
|
12255
|
+
const standard = normalizeStandardDictionaryOptions(options.dictionary?.standard, languages);
|
|
12256
|
+
return {
|
|
12257
|
+
dictionary: {
|
|
12258
|
+
...options.dictionary,
|
|
12259
|
+
standard
|
|
12260
|
+
},
|
|
12261
|
+
languages: [...new Set(languages)],
|
|
12262
|
+
rules: {
|
|
12263
|
+
duplicateHeadings: options.rules?.duplicateHeadings ?? DEFAULT_RULES.duplicateHeadings,
|
|
12264
|
+
headingIncrement: options.rules?.headingIncrement ?? DEFAULT_RULES.headingIncrement,
|
|
12265
|
+
maxConsecutiveBlankLines: options.rules?.maxConsecutiveBlankLines ?? DEFAULT_RULES.maxConsecutiveBlankLines,
|
|
12266
|
+
repeatedPunctuation: options.rules?.repeatedPunctuation ?? DEFAULT_RULES.repeatedPunctuation,
|
|
12267
|
+
repeatedWords: options.rules?.repeatedWords ?? DEFAULT_RULES.repeatedWords,
|
|
12268
|
+
spellcheck: options.rules?.spellcheck ?? DEFAULT_RULES.spellcheck,
|
|
12269
|
+
trailingSpaces: options.rules?.trailingSpaces ?? DEFAULT_RULES.trailingSpaces
|
|
12270
|
+
}
|
|
12271
|
+
};
|
|
12272
|
+
}
|
|
12273
|
+
function normalizeStandardDictionaryOptions(standard, fallbackLanguages) {
|
|
12274
|
+
if (!standard) return false;
|
|
12275
|
+
const languages = standard.languages?.filter((language) => SUPPORTED_MARKDOWN_LINT_LANGUAGES.includes(language)) ?? fallbackLanguages;
|
|
12276
|
+
const customImports = standard.imports ?? [];
|
|
12277
|
+
const missingPresetLanguages = languages.filter((language) => !DEFAULT_CSPELL_IMPORTS[language]);
|
|
12278
|
+
if (missingPresetLanguages.length > 0 && customImports.length === 0) throw new Error(`[ox-content] No bundled standard dictionary preset exists for ${missingPresetLanguages.join(", ")}. Provide dictionary.standard.imports to enable those languages.`);
|
|
12279
|
+
const imports = [...languages.map((language) => DEFAULT_CSPELL_IMPORTS[language]).filter((value) => Boolean(value)), ...customImports];
|
|
12280
|
+
if (imports.length === 0) throw new Error("[ox-content] dictionary.standard requires at least one bundled preset language or custom import.");
|
|
12281
|
+
return {
|
|
12282
|
+
imports: [...new Set(imports)],
|
|
12283
|
+
languages: [...new Set(languages)],
|
|
12284
|
+
provider: standard.provider ?? "cspell",
|
|
12285
|
+
resolveImportsRelativeTo: standard.resolveImportsRelativeTo ?? new URL(".", require("url").pathToFileURL(__filename).href)
|
|
12286
|
+
};
|
|
12287
|
+
}
|
|
12288
|
+
async function runStandardSpellcheckDocuments(maskedDocuments, options) {
|
|
12289
|
+
const standard = options.dictionary.standard;
|
|
12290
|
+
if (!standard || maskedDocuments.length === 0) return maskedDocuments.map(() => []);
|
|
12291
|
+
try {
|
|
12292
|
+
const { spellCheckDocument } = await loadCspellLib();
|
|
12293
|
+
const locale = standard.languages.join(",");
|
|
12294
|
+
const settings = createStandardSpellcheckSettings(options, locale);
|
|
12295
|
+
return Promise.all(maskedDocuments.map(async (maskedDocument, index) => {
|
|
12296
|
+
if (maskedDocument.trim().length === 0) return [];
|
|
12297
|
+
return (await spellCheckDocument({
|
|
12298
|
+
languageId: "plaintext",
|
|
12299
|
+
locale,
|
|
12300
|
+
text: maskedDocument,
|
|
12301
|
+
uri: `file:///ox-content-lint-${index}.md`
|
|
12302
|
+
}, {
|
|
12303
|
+
generateSuggestions: true,
|
|
12304
|
+
noConfigSearch: true,
|
|
12305
|
+
numSuggestions: 3,
|
|
12306
|
+
resolveImportsRelativeTo: standard.resolveImportsRelativeTo
|
|
12307
|
+
}, settings)).issues.map((issue) => mapStandardIssueToDiagnostic(issue, standard.languages));
|
|
12308
|
+
}));
|
|
12309
|
+
} catch (error) {
|
|
12310
|
+
const imports = standard.imports.join(", ");
|
|
12311
|
+
const message = imports.length > 0 ? `[ox-content] Failed to load standard dictionaries from ${imports}. Verify the imports and install the referenced CSpell packages.` : "[ox-content] Failed to load the configured standard dictionaries.";
|
|
12312
|
+
throw new Error(message, { cause: error });
|
|
12313
|
+
}
|
|
12314
|
+
}
|
|
12315
|
+
function createStandardSpellcheckSettings(options, locale) {
|
|
12316
|
+
return {
|
|
12317
|
+
import: options.dictionary.standard ? options.dictionary.standard.imports : [],
|
|
12318
|
+
ignoreWords: options.dictionary.ignoredWords,
|
|
12319
|
+
language: locale,
|
|
12320
|
+
version: "0.2",
|
|
12321
|
+
words: [...options.dictionary.words ?? [], ...Object.values(options.dictionary.byLanguage ?? {}).flat()]
|
|
12322
|
+
};
|
|
12323
|
+
}
|
|
12324
|
+
async function loadCspellLib() {
|
|
12325
|
+
cspellLibPromise ??= import("cspell-lib");
|
|
12326
|
+
return cspellLibPromise;
|
|
12327
|
+
}
|
|
12328
|
+
function mapStandardIssueToDiagnostic(issue, languages) {
|
|
12329
|
+
const line = issue.line.position.line + 1;
|
|
12330
|
+
const column = issue.offset - issue.line.offset + 1;
|
|
12331
|
+
return {
|
|
12332
|
+
column,
|
|
12333
|
+
endColumn: column + (issue.length ?? issue.text.length),
|
|
12334
|
+
endLine: line,
|
|
12335
|
+
language: inferStandardIssueLanguage(issue.text, languages),
|
|
12336
|
+
line,
|
|
12337
|
+
message: `Unknown word "${issue.text}".`,
|
|
12338
|
+
ruleId: "spellcheck",
|
|
12339
|
+
severity: "warning",
|
|
12340
|
+
suggestions: issue.suggestions?.slice(0, 3)
|
|
12341
|
+
};
|
|
12342
|
+
}
|
|
12343
|
+
function inferStandardIssueLanguage(word, languages) {
|
|
12344
|
+
if (/[\p{Script=Hiragana}\p{Script=Katakana}]/u.test(word) && languages.includes("ja")) return "ja";
|
|
12345
|
+
if (/[\p{Script=Han}]/u.test(word)) {
|
|
12346
|
+
if (languages.includes("zh") && !languages.includes("ja")) return "zh";
|
|
12347
|
+
if (languages.includes("ja") && !languages.includes("zh")) return "ja";
|
|
12348
|
+
}
|
|
12349
|
+
if (/[\p{Script=Latin}]/u.test(word)) {
|
|
12350
|
+
const latinLanguages = languages.filter((language) => language !== "ja" && language !== "zh");
|
|
12351
|
+
if (latinLanguages.length === 1) return latinLanguages[0];
|
|
12352
|
+
return inferLatinLanguageFromCharacters(word, latinLanguages);
|
|
12353
|
+
}
|
|
12354
|
+
}
|
|
12355
|
+
function inferLatinLanguageFromCharacters(word, languages) {
|
|
12356
|
+
if (languages.includes("pl") && /[ąćęłńóśźż]/iu.test(word)) return "pl";
|
|
12357
|
+
if (languages.includes("de") && /[äöüß]/iu.test(word)) return "de";
|
|
12358
|
+
if (languages.includes("fr") && /[àâæçéèêëîïôœùûüÿ]/iu.test(word)) return "fr";
|
|
12359
|
+
}
|
|
12360
|
+
function summarizeDiagnostics(diagnostics) {
|
|
12361
|
+
let errorCount = 0;
|
|
12362
|
+
let warningCount = 0;
|
|
12363
|
+
let infoCount = 0;
|
|
12364
|
+
for (const diagnostic of diagnostics) if (diagnostic.severity === "error") errorCount += 1;
|
|
12365
|
+
else if (diagnostic.severity === "warning") warningCount += 1;
|
|
12366
|
+
else infoCount += 1;
|
|
12367
|
+
return {
|
|
12368
|
+
diagnostics,
|
|
12369
|
+
errorCount,
|
|
12370
|
+
infoCount,
|
|
12371
|
+
warningCount
|
|
12372
|
+
};
|
|
12373
|
+
}
|
|
12374
|
+
function createEmptyLintResult$1() {
|
|
12375
|
+
return summarizeDiagnostics([]);
|
|
12376
|
+
}
|
|
12377
|
+
function sortDiagnostics(diagnostics) {
|
|
12378
|
+
return [...diagnostics].sort((left, right) => {
|
|
12379
|
+
if (left.line !== right.line) return left.line - right.line;
|
|
12380
|
+
if (left.column !== right.column) return left.column - right.column;
|
|
12381
|
+
return left.ruleId.localeCompare(right.ruleId);
|
|
12382
|
+
});
|
|
12383
|
+
}
|
|
12384
|
+
//#endregion
|
|
12385
|
+
//#region src/lint-files.ts
|
|
12386
|
+
const DEFAULT_LINT_FILE_INCLUDE = ["**/*.md", "**/*.markdown"];
|
|
12387
|
+
const DEFAULT_LINT_FILE_EXCLUDE = [
|
|
12388
|
+
"**/node_modules/**",
|
|
12389
|
+
"**/.git/**",
|
|
12390
|
+
"**/dist/**"
|
|
12391
|
+
];
|
|
12392
|
+
/**
|
|
12393
|
+
* Returns true if the file path is included by the configured glob filters.
|
|
12394
|
+
*/
|
|
12395
|
+
function shouldLintMarkdownFile(filePath, options = {}) {
|
|
12396
|
+
const resolvedOptions = resolveMarkdownLintFileOptions(options);
|
|
12397
|
+
return shouldLintAbsoluteFile(node_path.resolve(resolvedOptions.cwd, filePath), resolvedOptions);
|
|
12398
|
+
}
|
|
12399
|
+
/**
|
|
12400
|
+
* Lints a single Markdown file using project-style include/exclude settings.
|
|
12401
|
+
*
|
|
12402
|
+
* If the file is filtered out by `include` / `exclude`, the returned result is
|
|
12403
|
+
* marked as `skipped` and contains no diagnostics.
|
|
12404
|
+
*/
|
|
12405
|
+
async function lintMarkdownFile(filePath, options = {}) {
|
|
12406
|
+
const resolvedOptions = resolveMarkdownLintFileOptions(options);
|
|
12407
|
+
return lintMarkdownFileWithResolvedOptions(node_path.resolve(resolvedOptions.cwd, filePath), resolvedOptions);
|
|
12408
|
+
}
|
|
12409
|
+
/**
|
|
12410
|
+
* Lints all Markdown files matched by the configured include/exclude patterns.
|
|
12411
|
+
*/
|
|
12412
|
+
async function lintMarkdownFiles(options = {}) {
|
|
12413
|
+
const resolvedOptions = resolveMarkdownLintFileOptions(options);
|
|
12414
|
+
const matchedFiles = await collectMarkdownLintFileEntries(resolvedOptions);
|
|
12415
|
+
const results = await lintMarkdownDocumentsAsync(await Promise.all(matchedFiles.map((file) => node_fs_promises.readFile(file.filePath, "utf-8"))), resolvedOptions.lintOptions);
|
|
12416
|
+
const files = matchedFiles.map((file, index) => ({
|
|
12417
|
+
...results[index] ?? createEmptyLintResult(),
|
|
12418
|
+
filePath: file.filePath,
|
|
12419
|
+
relativePath: file.relativePath,
|
|
12420
|
+
skipped: false
|
|
12421
|
+
}));
|
|
12422
|
+
const diagnostics = files.flatMap((fileResult) => fileResult.diagnostics.map((diagnostic) => ({
|
|
12423
|
+
...diagnostic,
|
|
12424
|
+
filePath: fileResult.filePath,
|
|
12425
|
+
relativePath: fileResult.relativePath
|
|
12426
|
+
})));
|
|
12427
|
+
return {
|
|
12428
|
+
checkedFileCount: files.length,
|
|
12429
|
+
diagnostics,
|
|
12430
|
+
errorCount: files.reduce((count, fileResult) => count + fileResult.errorCount, 0),
|
|
12431
|
+
files,
|
|
12432
|
+
infoCount: files.reduce((count, fileResult) => count + fileResult.infoCount, 0),
|
|
12433
|
+
warningCount: files.reduce((count, fileResult) => count + fileResult.warningCount, 0)
|
|
12434
|
+
};
|
|
12435
|
+
}
|
|
12436
|
+
function resolveMarkdownLintFileOptions(options) {
|
|
12437
|
+
return {
|
|
12438
|
+
cwd: node_path.resolve(options.cwd ?? process.cwd()),
|
|
12439
|
+
exclude: [...new Set([...options.exclude ?? DEFAULT_LINT_FILE_EXCLUDE, ...options.ignore ?? []])],
|
|
12440
|
+
include: [...new Set(options.include ?? DEFAULT_LINT_FILE_INCLUDE)],
|
|
12441
|
+
lintOptions: {
|
|
12442
|
+
dictionary: options.dictionary,
|
|
12443
|
+
languages: options.languages,
|
|
12444
|
+
rules: options.rules
|
|
12445
|
+
}
|
|
12446
|
+
};
|
|
12447
|
+
}
|
|
12448
|
+
async function lintMarkdownFileWithResolvedOptions(filePath, options) {
|
|
12449
|
+
const absoluteFilePath = node_path.resolve(filePath);
|
|
12450
|
+
const relativePath = normalizePath(node_path.relative(options.cwd, absoluteFilePath));
|
|
12451
|
+
if (!shouldLintAbsoluteFile(absoluteFilePath, options)) return {
|
|
12452
|
+
...createEmptyLintResult(),
|
|
12453
|
+
filePath: absoluteFilePath,
|
|
12454
|
+
relativePath,
|
|
12455
|
+
skipped: true
|
|
12456
|
+
};
|
|
12457
|
+
return {
|
|
12458
|
+
...await lintMarkdownAsync(await node_fs_promises.readFile(absoluteFilePath, "utf-8"), options.lintOptions),
|
|
12459
|
+
filePath: absoluteFilePath,
|
|
12460
|
+
relativePath,
|
|
12461
|
+
skipped: false
|
|
12462
|
+
};
|
|
12463
|
+
}
|
|
12464
|
+
async function collectMarkdownLintFileEntries(options) {
|
|
12465
|
+
const files = /* @__PURE__ */ new Map();
|
|
12466
|
+
for (const pattern of options.include) {
|
|
12467
|
+
const matches = await (0, glob.glob)(pattern, {
|
|
12468
|
+
absolute: true,
|
|
12469
|
+
cwd: options.cwd,
|
|
12470
|
+
ignore: options.exclude,
|
|
12471
|
+
nodir: true
|
|
12472
|
+
});
|
|
12473
|
+
for (const filePath of matches) {
|
|
12474
|
+
const absoluteFilePath = node_path.resolve(filePath);
|
|
12475
|
+
if (shouldLintAbsoluteFile(absoluteFilePath, options)) files.set(absoluteFilePath, {
|
|
12476
|
+
filePath: absoluteFilePath,
|
|
12477
|
+
relativePath: normalizePath(node_path.relative(options.cwd, absoluteFilePath))
|
|
12478
|
+
});
|
|
12479
|
+
}
|
|
12480
|
+
}
|
|
12481
|
+
return [...files.values()].sort((left, right) => left.filePath.localeCompare(right.filePath));
|
|
12482
|
+
}
|
|
12483
|
+
function shouldLintAbsoluteFile(filePath, options) {
|
|
12484
|
+
const absolutePath = normalizePath(node_path.resolve(filePath));
|
|
12485
|
+
const relativePath = normalizePath(node_path.relative(options.cwd, absolutePath));
|
|
12486
|
+
const matches = (patterns) => patterns.some((pattern) => {
|
|
12487
|
+
const normalizedPattern = normalizePath(pattern);
|
|
12488
|
+
return node_path.matchesGlob(relativePath, normalizedPattern) || node_path.matchesGlob(absolutePath, normalizedPattern);
|
|
12489
|
+
});
|
|
12490
|
+
return matches(options.include) && !matches(options.exclude);
|
|
12491
|
+
}
|
|
12492
|
+
function normalizePath(value) {
|
|
12493
|
+
return value.split(node_path.sep).join("/");
|
|
12494
|
+
}
|
|
12495
|
+
function createEmptyLintResult() {
|
|
12496
|
+
return {
|
|
12497
|
+
diagnostics: [],
|
|
12498
|
+
errorCount: 0,
|
|
12499
|
+
infoCount: 0,
|
|
12500
|
+
warningCount: 0
|
|
12501
|
+
};
|
|
12502
|
+
}
|
|
12503
|
+
//#endregion
|
|
12138
12504
|
//#region src/jsx-runtime.ts
|
|
12139
12505
|
/**
|
|
12140
12506
|
* Custom JSX Runtime for Static HTML Generation
|
|
@@ -12983,6 +13349,10 @@ exports.hasIslands = hasIslands;
|
|
|
12983
13349
|
exports.inferType = inferType;
|
|
12984
13350
|
exports.jsx = jsx;
|
|
12985
13351
|
exports.jsxs = jsxs;
|
|
13352
|
+
exports.lintMarkdown = lintMarkdown;
|
|
13353
|
+
exports.lintMarkdownAsync = lintMarkdownAsync;
|
|
13354
|
+
exports.lintMarkdownFile = lintMarkdownFile;
|
|
13355
|
+
exports.lintMarkdownFiles = lintMarkdownFiles;
|
|
12986
13356
|
exports.mergeThemes = mergeThemes;
|
|
12987
13357
|
exports.mermaidClientScript = require_mermaid.mermaidClientScript;
|
|
12988
13358
|
exports.oxContent = oxContent;
|
|
@@ -12999,6 +13369,7 @@ exports.resolveSearchOptions = resolveSearchOptions;
|
|
|
12999
13369
|
exports.resolveSsgOptions = resolveSsgOptions;
|
|
13000
13370
|
exports.resolveTheme = resolveTheme;
|
|
13001
13371
|
exports.setRenderContext = setRenderContext;
|
|
13372
|
+
exports.shouldLintMarkdownFile = shouldLintMarkdownFile;
|
|
13002
13373
|
exports.transformAllPlugins = transformAllPlugins;
|
|
13003
13374
|
exports.transformGitHub = require_github.transformGitHub;
|
|
13004
13375
|
exports.transformIslands = transformIslands;
|