@qualcomm-ui/eslint-config-mdx 2.0.0 → 3.0.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/.remarkrc +4 -1
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +29 -0
- package/dist/index.js.map +7 -0
- package/dist/oxfmt-utils.d.ts +6 -0
- package/dist/oxfmt-utils.d.ts.map +1 -0
- package/dist/recommended.d.ts +3 -0
- package/dist/recommended.d.ts.map +1 -0
- package/dist/remark-lint-code-format.d.ts +3 -0
- package/dist/remark-lint-code-format.d.ts.map +1 -0
- package/dist/remark-lint-code-format.js +230 -0
- package/dist/remark-lint-code-format.js.map +7 -0
- package/dist/remark-lint-mdx-jsx-format.d.ts +3 -0
- package/dist/remark-lint-mdx-jsx-format.d.ts.map +1 -0
- package/dist/remark-lint-mdx-jsx-format.js +226 -0
- package/dist/remark-lint-mdx-jsx-format.js.map +7 -0
- package/dist/remark-preserve-alert-markers.d.ts +3 -0
- package/dist/remark-preserve-alert-markers.d.ts.map +1 -0
- package/dist/remark-preserve-alert-markers.js +32 -0
- package/dist/remark-preserve-alert-markers.js.map +7 -0
- package/dist/remark-types.d.ts +27 -0
- package/dist/remark-types.d.ts.map +1 -0
- package/dist/remarkrc.d.ts +12 -0
- package/dist/remarkrc.d.ts.map +1 -0
- package/dist/remarkrc.js +385 -0
- package/dist/remarkrc.js.map +7 -0
- package/package.json +42 -29
- package/index.d.ts +0 -10
- package/index.js +0 -7
- package/recommended.js +0 -19
package/.remarkrc
CHANGED
|
@@ -10,7 +10,10 @@
|
|
|
10
10
|
"remark-lint-no-consecutive-blank-lines",
|
|
11
11
|
"remark-lint-no-duplicate-headings-in-section",
|
|
12
12
|
["remark-lint-no-heading-punctuation", ",.:;"],
|
|
13
|
-
["remark-lint-unordered-list-marker-style", "-"]
|
|
13
|
+
["remark-lint-unordered-list-marker-style", "-"],
|
|
14
|
+
"./dist/remark-lint-code-format.js",
|
|
15
|
+
"./dist/remark-lint-mdx-jsx-format.js",
|
|
16
|
+
"./dist/remark-preserve-alert-markers.js"
|
|
14
17
|
],
|
|
15
18
|
"settings": {
|
|
16
19
|
"bullet": "-",
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,QAAA,MAAM,SAAS;;;;CAId,CAAA;AAED,eAAe,SAAS,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// src/recommended.ts
|
|
2
|
+
import { defineConfig } from "eslint/config";
|
|
3
|
+
import * as mdx from "eslint-plugin-mdx";
|
|
4
|
+
import reactPlugin from "eslint-plugin-react";
|
|
5
|
+
var recommended = defineConfig({
|
|
6
|
+
...mdx.flat,
|
|
7
|
+
plugins: {
|
|
8
|
+
...mdx.flat.plugins,
|
|
9
|
+
react: reactPlugin
|
|
10
|
+
},
|
|
11
|
+
rules: {
|
|
12
|
+
...mdx.flat.rules,
|
|
13
|
+
"mdx/remark": "error",
|
|
14
|
+
"no-unused-expressions": "off"
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
var recommended_default = recommended;
|
|
18
|
+
|
|
19
|
+
// src/index.ts
|
|
20
|
+
var mdxConfig = {
|
|
21
|
+
configs: {
|
|
22
|
+
recommended: recommended_default
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
var index_default = mdxConfig;
|
|
26
|
+
export {
|
|
27
|
+
index_default as default
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/recommended.ts", "../src/index.ts"],
|
|
4
|
+
"sourcesContent": ["// Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.\n// SPDX-License-Identifier: BSD-3-Clause-Clear\n\nimport {defineConfig} from \"eslint/config\"\nimport * as mdx from \"eslint-plugin-mdx\"\nimport reactPlugin from \"eslint-plugin-react\"\n\nconst recommended = defineConfig({\n ...mdx.flat,\n plugins: {\n ...mdx.flat.plugins,\n react: reactPlugin,\n },\n rules: {\n ...mdx.flat.rules,\n \"mdx/remark\": \"error\",\n \"no-unused-expressions\": \"off\",\n },\n})\n\nexport default recommended\n", "// Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.\n// SPDX-License-Identifier: BSD-3-Clause-Clear\n\nimport recommended from \"./recommended.js\"\n\nconst mdxConfig = {\n configs: {\n recommended,\n },\n}\n\nexport default mdxConfig\n"],
|
|
5
|
+
"mappings": ";AAGA,SAAQ,oBAAmB;AAC3B,YAAY,SAAS;AACrB,OAAO,iBAAiB;AAExB,IAAM,cAAc,aAAa;AAAA,EAC/B,GAAO;AAAA,EACP,SAAS;AAAA,IACP,GAAO,SAAK;AAAA,IACZ,OAAO;AAAA,EACT;AAAA,EACA,OAAO;AAAA,IACL,GAAO,SAAK;AAAA,IACZ,cAAc;AAAA,IACd,yBAAyB;AAAA,EAC3B;AACF,CAAC;AAED,IAAO,sBAAQ;;;ACff,IAAM,YAAY;AAAA,EAChB,SAAS;AAAA,IACP;AAAA,EACF;AACF;AAEA,IAAO,gBAAQ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type FormatConfig } from "oxfmt";
|
|
2
|
+
export declare function loadOxfmtConfig(filePath: string | undefined): Promise<FormatConfig>;
|
|
3
|
+
export declare function formatOxfmt(filePath: string, value: string, config: FormatConfig): Promise<null | string>;
|
|
4
|
+
export declare function getAbsolutePath(filePath: string | undefined): string;
|
|
5
|
+
export declare function getErrorMessage(error: unknown): string;
|
|
6
|
+
//# sourceMappingURL=oxfmt-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oxfmt-utils.d.ts","sourceRoot":"","sources":["../src/oxfmt-utils.ts"],"names":[],"mappings":"AAMA,OAAO,EAAuB,KAAK,YAAY,EAAC,MAAM,OAAO,CAAA;AAM7D,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAC3B,OAAO,CAAC,YAAY,CAAC,CAiBvB;AAED,wBAAsB,WAAW,CAC/B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,YAAY,GACnB,OAAO,CAAC,IAAI,GAAG,MAAM,CAAC,CAYxB;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAMpE;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAMtD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recommended.d.ts","sourceRoot":"","sources":["../src/recommended.ts"],"names":[],"mappings":"AAOA,QAAA,MAAM,WAAW,kCAWf,CAAA;AAEF,eAAe,WAAW,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remark-lint-code-format.d.ts","sourceRoot":"","sources":["../src/remark-lint-code-format.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAa,iBAAiB,EAAC,MAAM,mBAAmB,CAAA;AAkBpE,MAAM,CAAC,OAAO,UAAU,oBAAoB,IAAI,iBAAiB,CA2DhE"}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
// src/oxfmt-utils.ts
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
import { dirname, isAbsolute, join, parse, resolve } from "node:path";
|
|
4
|
+
import { pathToFileURL } from "node:url";
|
|
5
|
+
import { format as formatCode } from "oxfmt";
|
|
6
|
+
import { parseConfigFileTextToJson } from "typescript";
|
|
7
|
+
var CONFIG_FILENAMES = [".oxfmtrc.json", ".oxfmtrc.jsonc", "oxfmt.config.ts"];
|
|
8
|
+
var configCache = /* @__PURE__ */ new Map();
|
|
9
|
+
async function loadOxfmtConfig(filePath) {
|
|
10
|
+
const basePath = getAbsolutePath(filePath);
|
|
11
|
+
const startDir = parse(basePath).ext ? dirname(basePath) : basePath;
|
|
12
|
+
const cachedConfig = configCache.get(startDir);
|
|
13
|
+
if (cachedConfig) {
|
|
14
|
+
return cachedConfig;
|
|
15
|
+
}
|
|
16
|
+
const configPromise = findOxfmtConfig(startDir).catch((error) => {
|
|
17
|
+
configCache.delete(startDir);
|
|
18
|
+
throw error;
|
|
19
|
+
});
|
|
20
|
+
configCache.set(startDir, configPromise);
|
|
21
|
+
return configPromise;
|
|
22
|
+
}
|
|
23
|
+
async function formatOxfmt(filePath, value, config) {
|
|
24
|
+
try {
|
|
25
|
+
const result = await formatCode(filePath, value, config);
|
|
26
|
+
if (result.errors.length > 0) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
return removeFinalEol(result.code);
|
|
30
|
+
} catch {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function getAbsolutePath(filePath) {
|
|
35
|
+
if (!filePath) {
|
|
36
|
+
return process.cwd();
|
|
37
|
+
}
|
|
38
|
+
return isAbsolute(filePath) ? filePath : resolve(process.cwd(), filePath);
|
|
39
|
+
}
|
|
40
|
+
function getErrorMessage(error) {
|
|
41
|
+
if (error instanceof Error) {
|
|
42
|
+
return error.message;
|
|
43
|
+
}
|
|
44
|
+
return String(error);
|
|
45
|
+
}
|
|
46
|
+
async function findOxfmtConfig(startDir) {
|
|
47
|
+
let currentDir = startDir;
|
|
48
|
+
while (true) {
|
|
49
|
+
for (const configFilename of CONFIG_FILENAMES) {
|
|
50
|
+
const configPath = join(currentDir, configFilename);
|
|
51
|
+
const config = await readOxfmtConfig(configPath, configFilename);
|
|
52
|
+
if (config) {
|
|
53
|
+
return config;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const parentDir = dirname(currentDir);
|
|
57
|
+
if (parentDir === currentDir) {
|
|
58
|
+
return {};
|
|
59
|
+
}
|
|
60
|
+
currentDir = parentDir;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async function readOxfmtConfig(configPath, configFilename) {
|
|
64
|
+
if (configFilename === "oxfmt.config.ts") {
|
|
65
|
+
return readTypeScriptConfig(configPath);
|
|
66
|
+
}
|
|
67
|
+
const source = await readOptionalFile(configPath);
|
|
68
|
+
if (source === null) {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
if (configFilename.endsWith(".jsonc")) {
|
|
72
|
+
return validateConfig(configPath, readJsoncConfig(configPath, source));
|
|
73
|
+
}
|
|
74
|
+
return validateConfig(configPath, JSON.parse(source));
|
|
75
|
+
}
|
|
76
|
+
async function readTypeScriptConfig(configPath) {
|
|
77
|
+
const source = await readOptionalFile(configPath);
|
|
78
|
+
if (source === null) {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
const url = pathToFileURL(configPath);
|
|
82
|
+
url.searchParams.set("cache", Date.now().toString());
|
|
83
|
+
const module = await import(url.href);
|
|
84
|
+
return validateConfig(configPath, module.default);
|
|
85
|
+
}
|
|
86
|
+
function readJsoncConfig(configPath, source) {
|
|
87
|
+
const result = parseConfigFileTextToJson(configPath, source);
|
|
88
|
+
if (result.error) {
|
|
89
|
+
throw new Error(String(result.error.messageText));
|
|
90
|
+
}
|
|
91
|
+
return result.config;
|
|
92
|
+
}
|
|
93
|
+
function validateConfig(configPath, config) {
|
|
94
|
+
if (!isPlainConfig(config)) {
|
|
95
|
+
throw new Error(`${configPath} must define an object`);
|
|
96
|
+
}
|
|
97
|
+
return config;
|
|
98
|
+
}
|
|
99
|
+
async function readOptionalFile(path) {
|
|
100
|
+
try {
|
|
101
|
+
return await readFile(path, "utf8");
|
|
102
|
+
} catch (error) {
|
|
103
|
+
if (isMissingFileError(error)) {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
throw error;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
function removeFinalEol(value) {
|
|
110
|
+
return value.replace(/\r?\n$/u, "");
|
|
111
|
+
}
|
|
112
|
+
function isPlainConfig(value) {
|
|
113
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
114
|
+
}
|
|
115
|
+
function isMissingFileError(error) {
|
|
116
|
+
if (typeof error !== "object" || error === null || !("code" in error)) {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
const { code } = error;
|
|
120
|
+
return code === "ENOENT" || code === "ENOTDIR";
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// src/remark-lint-code-format.ts
|
|
124
|
+
var LANGUAGE_EXTENSIONS = /* @__PURE__ */ new Map([
|
|
125
|
+
["javascript", ".js"],
|
|
126
|
+
["javascriptreact", ".jsx"],
|
|
127
|
+
["js", ".js"],
|
|
128
|
+
["jsx", ".jsx"],
|
|
129
|
+
["ts", ".ts"],
|
|
130
|
+
["tsx", ".tsx"],
|
|
131
|
+
["typescript", ".ts"],
|
|
132
|
+
["typescriptreact", ".tsx"]
|
|
133
|
+
]);
|
|
134
|
+
function remarkLintCodeFormat() {
|
|
135
|
+
return async function transform(tree, file) {
|
|
136
|
+
let oxfmtConfig;
|
|
137
|
+
try {
|
|
138
|
+
oxfmtConfig = await loadOxfmtConfig(file.path);
|
|
139
|
+
} catch (error) {
|
|
140
|
+
file.message(
|
|
141
|
+
`Unable to load oxfmt config: ${getErrorMessage(error)}`,
|
|
142
|
+
{ column: 1, line: 1 },
|
|
143
|
+
"remark-lint:code-format"
|
|
144
|
+
);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
const codeNodes = [];
|
|
148
|
+
visit(tree, "code", (node) => {
|
|
149
|
+
if (typeof node.value === "string") {
|
|
150
|
+
codeNodes.push(node);
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
for (const [index, node] of codeNodes.entries()) {
|
|
154
|
+
const extension = getExtension(node.lang);
|
|
155
|
+
if (!extension) {
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
const blockFilePath = getBlockFilePath(file.path, index, extension);
|
|
159
|
+
if (isStandaloneJsxSnippet(extension, node.value)) {
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
const formatted = await formatOxfmt(
|
|
163
|
+
blockFilePath,
|
|
164
|
+
node.value,
|
|
165
|
+
oxfmtConfig
|
|
166
|
+
);
|
|
167
|
+
if (formatted === null) {
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
if (formatted !== node.value) {
|
|
171
|
+
file.message(
|
|
172
|
+
"Format code block with oxfmt",
|
|
173
|
+
node,
|
|
174
|
+
"remark-lint:code-format"
|
|
175
|
+
);
|
|
176
|
+
node.value = formatted;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
function getBlockFilePath(filePath, index, extension) {
|
|
182
|
+
return `${getAbsolutePath(filePath)}.${index}${extension}`;
|
|
183
|
+
}
|
|
184
|
+
function getExtension(language) {
|
|
185
|
+
if (!language) {
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
const [name = ""] = language.trim().split(/\s+/u);
|
|
189
|
+
return LANGUAGE_EXTENSIONS.get(name.toLowerCase()) ?? null;
|
|
190
|
+
}
|
|
191
|
+
function isStandaloneJsxSnippet(extension, value) {
|
|
192
|
+
return (extension === ".jsx" || extension === ".tsx") && /^<(?:>|\/?[A-Za-z][\w.:/-]*(?:[\s>/]|$))/u.test(trimLeadingComments(value));
|
|
193
|
+
}
|
|
194
|
+
function trimLeadingComments(value) {
|
|
195
|
+
let source = value.trimStart();
|
|
196
|
+
while (true) {
|
|
197
|
+
if (source.startsWith("//")) {
|
|
198
|
+
const nextLineIndex = source.indexOf("\n");
|
|
199
|
+
if (nextLineIndex === -1) {
|
|
200
|
+
return "";
|
|
201
|
+
}
|
|
202
|
+
source = source.slice(nextLineIndex + 1).trimStart();
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
if (source.startsWith("/*")) {
|
|
206
|
+
const commentEndIndex = source.indexOf("*/");
|
|
207
|
+
if (commentEndIndex === -1) {
|
|
208
|
+
return source;
|
|
209
|
+
}
|
|
210
|
+
source = source.slice(commentEndIndex + 2).trimStart();
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
return source;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
function visit(node, type, callback) {
|
|
217
|
+
if (node.type === type) {
|
|
218
|
+
callback(node);
|
|
219
|
+
}
|
|
220
|
+
if (!Array.isArray(node.children)) {
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
for (const child of node.children) {
|
|
224
|
+
visit(child, type, callback);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
export {
|
|
228
|
+
remarkLintCodeFormat as default
|
|
229
|
+
};
|
|
230
|
+
//# sourceMappingURL=remark-lint-code-format.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/oxfmt-utils.ts", "../src/remark-lint-code-format.ts"],
|
|
4
|
+
"sourcesContent": ["// Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.\n// SPDX-License-Identifier: BSD-3-Clause-Clear\n\nimport {readFile} from \"node:fs/promises\"\nimport {dirname, isAbsolute, join, parse, resolve} from \"node:path\"\nimport {pathToFileURL} from \"node:url\"\nimport {format as formatCode, type FormatConfig} from \"oxfmt\"\nimport {parseConfigFileTextToJson} from \"typescript\"\n\nconst CONFIG_FILENAMES = [\".oxfmtrc.json\", \".oxfmtrc.jsonc\", \"oxfmt.config.ts\"]\nconst configCache = new Map<string, Promise<FormatConfig>>()\n\nexport async function loadOxfmtConfig(\n filePath: string | undefined,\n): Promise<FormatConfig> {\n const basePath = getAbsolutePath(filePath)\n const startDir = parse(basePath).ext ? dirname(basePath) : basePath\n const cachedConfig = configCache.get(startDir)\n\n if (cachedConfig) {\n return cachedConfig\n }\n\n const configPromise = findOxfmtConfig(startDir).catch((error: unknown) => {\n configCache.delete(startDir)\n throw error\n })\n\n configCache.set(startDir, configPromise)\n\n return configPromise\n}\n\nexport async function formatOxfmt(\n filePath: string,\n value: string,\n config: FormatConfig,\n): Promise<null | string> {\n try {\n const result = await formatCode(filePath, value, config)\n\n if (result.errors.length > 0) {\n return null\n }\n\n return removeFinalEol(result.code)\n } catch {\n return null\n }\n}\n\nexport function getAbsolutePath(filePath: string | undefined): string {\n if (!filePath) {\n return process.cwd()\n }\n\n return isAbsolute(filePath) ? filePath : resolve(process.cwd(), filePath)\n}\n\nexport function getErrorMessage(error: unknown): string {\n if (error instanceof Error) {\n return error.message\n }\n\n return String(error)\n}\n\nasync function findOxfmtConfig(startDir: string): Promise<FormatConfig> {\n let currentDir = startDir\n\n while (true) {\n for (const configFilename of CONFIG_FILENAMES) {\n const configPath = join(currentDir, configFilename)\n const config = await readOxfmtConfig(configPath, configFilename)\n\n if (config) {\n return config\n }\n }\n\n const parentDir = dirname(currentDir)\n\n if (parentDir === currentDir) {\n return {}\n }\n\n currentDir = parentDir\n }\n}\n\nasync function readOxfmtConfig(\n configPath: string,\n configFilename: string,\n): Promise<FormatConfig | null> {\n if (configFilename === \"oxfmt.config.ts\") {\n return readTypeScriptConfig(configPath)\n }\n\n const source = await readOptionalFile(configPath)\n\n if (source === null) {\n return null\n }\n\n if (configFilename.endsWith(\".jsonc\")) {\n return validateConfig(configPath, readJsoncConfig(configPath, source))\n }\n\n return validateConfig(configPath, JSON.parse(source))\n}\n\nasync function readTypeScriptConfig(\n configPath: string,\n): Promise<FormatConfig | null> {\n const source = await readOptionalFile(configPath)\n\n if (source === null) {\n return null\n }\n\n const url = pathToFileURL(configPath)\n url.searchParams.set(\"cache\", Date.now().toString())\n\n const module = (await import(url.href)) as {default?: unknown}\n\n return validateConfig(configPath, module.default)\n}\n\nfunction readJsoncConfig(configPath: string, source: string): unknown {\n const result = parseConfigFileTextToJson(configPath, source)\n\n if (result.error) {\n throw new Error(String(result.error.messageText as string))\n }\n\n return result.config\n}\n\nfunction validateConfig(configPath: string, config: unknown): FormatConfig {\n if (!isPlainConfig(config)) {\n throw new Error(`${configPath} must define an object`)\n }\n\n return config as FormatConfig\n}\n\nasync function readOptionalFile(path: string): Promise<null | string> {\n try {\n return await readFile(path, \"utf8\")\n } catch (error) {\n if (isMissingFileError(error)) {\n return null\n }\n\n throw error\n }\n}\n\nfunction removeFinalEol(value: string): string {\n return value.replace(/\\r?\\n$/u, \"\")\n}\n\nfunction isPlainConfig(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n}\n\nfunction isMissingFileError(error: unknown): boolean {\n if (typeof error !== \"object\" || error === null || !(\"code\" in error)) {\n return false\n }\n\n const {code} = error\n\n return code === \"ENOENT\" || code === \"ENOTDIR\"\n}\n", "// Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.\n// SPDX-License-Identifier: BSD-3-Clause-Clear\n\nimport {\n formatOxfmt,\n getAbsolutePath,\n getErrorMessage,\n loadOxfmtConfig,\n} from \"./oxfmt-utils.js\"\nimport type {RemarkNode, RemarkTransformer} from \"./remark-types.js\"\n\ninterface CodeNode extends RemarkNode {\n lang?: string | null\n value: string\n}\n\nconst LANGUAGE_EXTENSIONS = new Map([\n [\"javascript\", \".js\"],\n [\"javascriptreact\", \".jsx\"],\n [\"js\", \".js\"],\n [\"jsx\", \".jsx\"],\n [\"ts\", \".ts\"],\n [\"tsx\", \".tsx\"],\n [\"typescript\", \".ts\"],\n [\"typescriptreact\", \".tsx\"],\n])\n\nexport default function remarkLintCodeFormat(): RemarkTransformer {\n return async function transform(tree, file) {\n let oxfmtConfig\n\n try {\n oxfmtConfig = await loadOxfmtConfig(file.path)\n } catch (error) {\n file.message(\n `Unable to load oxfmt config: ${getErrorMessage(error)}`,\n {column: 1, line: 1},\n \"remark-lint:code-format\",\n )\n return\n }\n\n const codeNodes: CodeNode[] = []\n visit<CodeNode>(tree, \"code\", (node) => {\n if (typeof node.value === \"string\") {\n codeNodes.push(node)\n }\n })\n\n for (const [index, node] of codeNodes.entries()) {\n const extension = getExtension(node.lang)\n\n if (!extension) {\n continue\n }\n\n const blockFilePath = getBlockFilePath(file.path, index, extension)\n\n if (isStandaloneJsxSnippet(extension, node.value)) {\n // Fenced TSX examples are not always complete TSX programs. Many docs\n // use them for JSX fragments, where Oxfmt would add ASI semicolons or\n // reflow comments if we wrapped the snippet. Real MDX JSX nodes are\n // handled separately by remark-lint-mdx-jsx-format.\n continue\n }\n\n const formatted = await formatOxfmt(\n blockFilePath,\n node.value,\n oxfmtConfig,\n )\n\n if (formatted === null) {\n continue\n }\n\n if (formatted !== node.value) {\n file.message(\n \"Format code block with oxfmt\",\n node,\n \"remark-lint:code-format\",\n )\n node.value = formatted\n }\n }\n }\n}\n\nfunction getBlockFilePath(\n filePath: string | undefined,\n index: number,\n extension: string,\n): string {\n return `${getAbsolutePath(filePath)}.${index}${extension}`\n}\n\nfunction getExtension(language: string | null | undefined): null | string {\n if (!language) {\n return null\n }\n\n const [name = \"\"] = language.trim().split(/\\s+/u)\n\n return LANGUAGE_EXTENSIONS.get(name.toLowerCase()) ?? null\n}\n\nfunction isStandaloneJsxSnippet(extension: string, value: string): boolean {\n return (\n (extension === \".jsx\" || extension === \".tsx\") &&\n /^<(?:>|\\/?[A-Za-z][\\w.:/-]*(?:[\\s>/]|$))/u.test(trimLeadingComments(value))\n )\n}\n\nfunction trimLeadingComments(value: string): string {\n let source = value.trimStart()\n\n while (true) {\n if (source.startsWith(\"//\")) {\n const nextLineIndex = source.indexOf(\"\\n\")\n\n if (nextLineIndex === -1) {\n return \"\"\n }\n\n source = source.slice(nextLineIndex + 1).trimStart()\n continue\n }\n\n if (source.startsWith(\"/*\")) {\n const commentEndIndex = source.indexOf(\"*/\")\n\n if (commentEndIndex === -1) {\n return source\n }\n\n source = source.slice(commentEndIndex + 2).trimStart()\n continue\n }\n\n return source\n }\n}\n\nfunction visit<T extends RemarkNode>(\n node: RemarkNode,\n type: string,\n callback: (node: T) => void,\n): void {\n if (node.type === type) {\n callback(node as T)\n }\n\n if (!Array.isArray(node.children)) {\n return\n }\n\n for (const child of node.children) {\n visit(child, type, callback)\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remark-lint-mdx-jsx-format.d.ts","sourceRoot":"","sources":["../src/remark-lint-mdx-jsx-format.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAyB,iBAAiB,EAAC,MAAM,mBAAmB,CAAA;AAEhF,MAAM,CAAC,OAAO,UAAU,sBAAsB,IAAI,iBAAiB,CAwBlE"}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
// src/oxfmt-utils.ts
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
import { dirname, isAbsolute, join, parse, resolve } from "node:path";
|
|
4
|
+
import { pathToFileURL } from "node:url";
|
|
5
|
+
import { format as formatCode } from "oxfmt";
|
|
6
|
+
import { parseConfigFileTextToJson } from "typescript";
|
|
7
|
+
var CONFIG_FILENAMES = [".oxfmtrc.json", ".oxfmtrc.jsonc", "oxfmt.config.ts"];
|
|
8
|
+
var configCache = /* @__PURE__ */ new Map();
|
|
9
|
+
async function loadOxfmtConfig(filePath) {
|
|
10
|
+
const basePath = getAbsolutePath(filePath);
|
|
11
|
+
const startDir = parse(basePath).ext ? dirname(basePath) : basePath;
|
|
12
|
+
const cachedConfig = configCache.get(startDir);
|
|
13
|
+
if (cachedConfig) {
|
|
14
|
+
return cachedConfig;
|
|
15
|
+
}
|
|
16
|
+
const configPromise = findOxfmtConfig(startDir).catch((error) => {
|
|
17
|
+
configCache.delete(startDir);
|
|
18
|
+
throw error;
|
|
19
|
+
});
|
|
20
|
+
configCache.set(startDir, configPromise);
|
|
21
|
+
return configPromise;
|
|
22
|
+
}
|
|
23
|
+
async function formatOxfmt(filePath, value, config) {
|
|
24
|
+
try {
|
|
25
|
+
const result = await formatCode(filePath, value, config);
|
|
26
|
+
if (result.errors.length > 0) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
return removeFinalEol(result.code);
|
|
30
|
+
} catch {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function getAbsolutePath(filePath) {
|
|
35
|
+
if (!filePath) {
|
|
36
|
+
return process.cwd();
|
|
37
|
+
}
|
|
38
|
+
return isAbsolute(filePath) ? filePath : resolve(process.cwd(), filePath);
|
|
39
|
+
}
|
|
40
|
+
function getErrorMessage(error) {
|
|
41
|
+
if (error instanceof Error) {
|
|
42
|
+
return error.message;
|
|
43
|
+
}
|
|
44
|
+
return String(error);
|
|
45
|
+
}
|
|
46
|
+
async function findOxfmtConfig(startDir) {
|
|
47
|
+
let currentDir = startDir;
|
|
48
|
+
while (true) {
|
|
49
|
+
for (const configFilename of CONFIG_FILENAMES) {
|
|
50
|
+
const configPath = join(currentDir, configFilename);
|
|
51
|
+
const config = await readOxfmtConfig(configPath, configFilename);
|
|
52
|
+
if (config) {
|
|
53
|
+
return config;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const parentDir = dirname(currentDir);
|
|
57
|
+
if (parentDir === currentDir) {
|
|
58
|
+
return {};
|
|
59
|
+
}
|
|
60
|
+
currentDir = parentDir;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async function readOxfmtConfig(configPath, configFilename) {
|
|
64
|
+
if (configFilename === "oxfmt.config.ts") {
|
|
65
|
+
return readTypeScriptConfig(configPath);
|
|
66
|
+
}
|
|
67
|
+
const source = await readOptionalFile(configPath);
|
|
68
|
+
if (source === null) {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
if (configFilename.endsWith(".jsonc")) {
|
|
72
|
+
return validateConfig(configPath, readJsoncConfig(configPath, source));
|
|
73
|
+
}
|
|
74
|
+
return validateConfig(configPath, JSON.parse(source));
|
|
75
|
+
}
|
|
76
|
+
async function readTypeScriptConfig(configPath) {
|
|
77
|
+
const source = await readOptionalFile(configPath);
|
|
78
|
+
if (source === null) {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
const url = pathToFileURL(configPath);
|
|
82
|
+
url.searchParams.set("cache", Date.now().toString());
|
|
83
|
+
const module = await import(url.href);
|
|
84
|
+
return validateConfig(configPath, module.default);
|
|
85
|
+
}
|
|
86
|
+
function readJsoncConfig(configPath, source) {
|
|
87
|
+
const result = parseConfigFileTextToJson(configPath, source);
|
|
88
|
+
if (result.error) {
|
|
89
|
+
throw new Error(String(result.error.messageText));
|
|
90
|
+
}
|
|
91
|
+
return result.config;
|
|
92
|
+
}
|
|
93
|
+
function validateConfig(configPath, config) {
|
|
94
|
+
if (!isPlainConfig(config)) {
|
|
95
|
+
throw new Error(`${configPath} must define an object`);
|
|
96
|
+
}
|
|
97
|
+
return config;
|
|
98
|
+
}
|
|
99
|
+
async function readOptionalFile(path) {
|
|
100
|
+
try {
|
|
101
|
+
return await readFile(path, "utf8");
|
|
102
|
+
} catch (error) {
|
|
103
|
+
if (isMissingFileError(error)) {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
throw error;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
function removeFinalEol(value) {
|
|
110
|
+
return value.replace(/\r?\n$/u, "");
|
|
111
|
+
}
|
|
112
|
+
function isPlainConfig(value) {
|
|
113
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
114
|
+
}
|
|
115
|
+
function isMissingFileError(error) {
|
|
116
|
+
if (typeof error !== "object" || error === null || !("code" in error)) {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
const { code } = error;
|
|
120
|
+
return code === "ENOENT" || code === "ENOTDIR";
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// src/remark-lint-mdx-jsx-format.ts
|
|
124
|
+
function remarkLintMdxJsxFormat() {
|
|
125
|
+
return async function transform(tree, file) {
|
|
126
|
+
const source = getFileValue(file);
|
|
127
|
+
if (!source) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
let oxfmtConfig;
|
|
131
|
+
try {
|
|
132
|
+
oxfmtConfig = await loadOxfmtConfig(file.path);
|
|
133
|
+
} catch (error) {
|
|
134
|
+
file.message(
|
|
135
|
+
`Unable to load oxfmt config: ${getErrorMessage(error)}`,
|
|
136
|
+
{ column: 1, line: 1 },
|
|
137
|
+
"remark-lint:mdx-jsx-format"
|
|
138
|
+
);
|
|
139
|
+
await replaceMdxJsxFlowElements(tree, source, file.path, null, file);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
await replaceMdxJsxFlowElements(tree, source, file.path, oxfmtConfig, file);
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
async function replaceMdxJsxFlowElements(node, source, filePath, config, file) {
|
|
146
|
+
if (!Array.isArray(node.children)) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
const children = [];
|
|
150
|
+
for (const child of node.children) {
|
|
151
|
+
if (child.type === "mdxJsxFlowElement") {
|
|
152
|
+
const raw = getSourceSlice(source, child);
|
|
153
|
+
if (raw === null) {
|
|
154
|
+
children.push(child);
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
const formatted = config === null || hasChildren(child) ? raw : await formatMdxJsxBlock(filePath, raw, config);
|
|
158
|
+
if (formatted !== raw) {
|
|
159
|
+
file.message(
|
|
160
|
+
"Format MDX JSX block",
|
|
161
|
+
child,
|
|
162
|
+
"remark-lint:mdx-jsx-format"
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
children.push({
|
|
166
|
+
type: "html",
|
|
167
|
+
value: formatted
|
|
168
|
+
});
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
await replaceMdxJsxFlowElements(child, source, filePath, config, file);
|
|
172
|
+
children.push(child);
|
|
173
|
+
}
|
|
174
|
+
node.children = children;
|
|
175
|
+
}
|
|
176
|
+
async function formatMdxJsxBlock(filePath, value, config) {
|
|
177
|
+
const formatted = await formatOxfmt(
|
|
178
|
+
getBlockFilePath(filePath),
|
|
179
|
+
wrapMdxJsxBlock(value),
|
|
180
|
+
config
|
|
181
|
+
);
|
|
182
|
+
if (formatted === null) {
|
|
183
|
+
return value;
|
|
184
|
+
}
|
|
185
|
+
return unwrapMdxJsxBlock(formatted) ?? value;
|
|
186
|
+
}
|
|
187
|
+
function wrapMdxJsxBlock(value) {
|
|
188
|
+
return `const __mdx = (
|
|
189
|
+
<>
|
|
190
|
+
${value}
|
|
191
|
+
</>
|
|
192
|
+
)
|
|
193
|
+
`;
|
|
194
|
+
}
|
|
195
|
+
function unwrapMdxJsxBlock(value) {
|
|
196
|
+
const lines = value.split(/\r?\n/u);
|
|
197
|
+
const openIndex = lines.findIndex((line) => line.trim() === "<>");
|
|
198
|
+
const closeIndex = lines.findIndex(
|
|
199
|
+
(line, index) => index > openIndex && line.trim() === "</>"
|
|
200
|
+
);
|
|
201
|
+
if (openIndex === -1 || closeIndex === -1 || closeIndex <= openIndex + 1) {
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
return lines.slice(openIndex + 1, closeIndex).map((line) => line.startsWith(" ") ? line.slice(4) : line).join("\n");
|
|
205
|
+
}
|
|
206
|
+
function getSourceSlice(source, node) {
|
|
207
|
+
const start = node.position?.start?.offset;
|
|
208
|
+
const end = node.position?.end?.offset;
|
|
209
|
+
if (typeof start !== "number" || typeof end !== "number") {
|
|
210
|
+
return null;
|
|
211
|
+
}
|
|
212
|
+
return source.slice(start, end);
|
|
213
|
+
}
|
|
214
|
+
function getFileValue(file) {
|
|
215
|
+
return file.value ?? "";
|
|
216
|
+
}
|
|
217
|
+
function getBlockFilePath(filePath) {
|
|
218
|
+
return `${getAbsolutePath(filePath)}.jsx.tsx`;
|
|
219
|
+
}
|
|
220
|
+
function hasChildren(node) {
|
|
221
|
+
return Array.isArray(node.children) && node.children.length > 0;
|
|
222
|
+
}
|
|
223
|
+
export {
|
|
224
|
+
remarkLintMdxJsxFormat as default
|
|
225
|
+
};
|
|
226
|
+
//# sourceMappingURL=remark-lint-mdx-jsx-format.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/oxfmt-utils.ts", "../src/remark-lint-mdx-jsx-format.ts"],
|
|
4
|
+
"sourcesContent": ["// Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.\n// SPDX-License-Identifier: BSD-3-Clause-Clear\n\nimport {readFile} from \"node:fs/promises\"\nimport {dirname, isAbsolute, join, parse, resolve} from \"node:path\"\nimport {pathToFileURL} from \"node:url\"\nimport {format as formatCode, type FormatConfig} from \"oxfmt\"\nimport {parseConfigFileTextToJson} from \"typescript\"\n\nconst CONFIG_FILENAMES = [\".oxfmtrc.json\", \".oxfmtrc.jsonc\", \"oxfmt.config.ts\"]\nconst configCache = new Map<string, Promise<FormatConfig>>()\n\nexport async function loadOxfmtConfig(\n filePath: string | undefined,\n): Promise<FormatConfig> {\n const basePath = getAbsolutePath(filePath)\n const startDir = parse(basePath).ext ? dirname(basePath) : basePath\n const cachedConfig = configCache.get(startDir)\n\n if (cachedConfig) {\n return cachedConfig\n }\n\n const configPromise = findOxfmtConfig(startDir).catch((error: unknown) => {\n configCache.delete(startDir)\n throw error\n })\n\n configCache.set(startDir, configPromise)\n\n return configPromise\n}\n\nexport async function formatOxfmt(\n filePath: string,\n value: string,\n config: FormatConfig,\n): Promise<null | string> {\n try {\n const result = await formatCode(filePath, value, config)\n\n if (result.errors.length > 0) {\n return null\n }\n\n return removeFinalEol(result.code)\n } catch {\n return null\n }\n}\n\nexport function getAbsolutePath(filePath: string | undefined): string {\n if (!filePath) {\n return process.cwd()\n }\n\n return isAbsolute(filePath) ? filePath : resolve(process.cwd(), filePath)\n}\n\nexport function getErrorMessage(error: unknown): string {\n if (error instanceof Error) {\n return error.message\n }\n\n return String(error)\n}\n\nasync function findOxfmtConfig(startDir: string): Promise<FormatConfig> {\n let currentDir = startDir\n\n while (true) {\n for (const configFilename of CONFIG_FILENAMES) {\n const configPath = join(currentDir, configFilename)\n const config = await readOxfmtConfig(configPath, configFilename)\n\n if (config) {\n return config\n }\n }\n\n const parentDir = dirname(currentDir)\n\n if (parentDir === currentDir) {\n return {}\n }\n\n currentDir = parentDir\n }\n}\n\nasync function readOxfmtConfig(\n configPath: string,\n configFilename: string,\n): Promise<FormatConfig | null> {\n if (configFilename === \"oxfmt.config.ts\") {\n return readTypeScriptConfig(configPath)\n }\n\n const source = await readOptionalFile(configPath)\n\n if (source === null) {\n return null\n }\n\n if (configFilename.endsWith(\".jsonc\")) {\n return validateConfig(configPath, readJsoncConfig(configPath, source))\n }\n\n return validateConfig(configPath, JSON.parse(source))\n}\n\nasync function readTypeScriptConfig(\n configPath: string,\n): Promise<FormatConfig | null> {\n const source = await readOptionalFile(configPath)\n\n if (source === null) {\n return null\n }\n\n const url = pathToFileURL(configPath)\n url.searchParams.set(\"cache\", Date.now().toString())\n\n const module = (await import(url.href)) as {default?: unknown}\n\n return validateConfig(configPath, module.default)\n}\n\nfunction readJsoncConfig(configPath: string, source: string): unknown {\n const result = parseConfigFileTextToJson(configPath, source)\n\n if (result.error) {\n throw new Error(String(result.error.messageText as string))\n }\n\n return result.config\n}\n\nfunction validateConfig(configPath: string, config: unknown): FormatConfig {\n if (!isPlainConfig(config)) {\n throw new Error(`${configPath} must define an object`)\n }\n\n return config as FormatConfig\n}\n\nasync function readOptionalFile(path: string): Promise<null | string> {\n try {\n return await readFile(path, \"utf8\")\n } catch (error) {\n if (isMissingFileError(error)) {\n return null\n }\n\n throw error\n }\n}\n\nfunction removeFinalEol(value: string): string {\n return value.replace(/\\r?\\n$/u, \"\")\n}\n\nfunction isPlainConfig(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n}\n\nfunction isMissingFileError(error: unknown): boolean {\n if (typeof error !== \"object\" || error === null || !(\"code\" in error)) {\n return false\n }\n\n const {code} = error\n\n return code === \"ENOENT\" || code === \"ENOTDIR\"\n}\n", "// Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.\n// SPDX-License-Identifier: BSD-3-Clause-Clear\n\nimport type {FormatConfig} from \"oxfmt\"\n\nimport {\n formatOxfmt,\n getAbsolutePath,\n getErrorMessage,\n loadOxfmtConfig,\n} from \"./oxfmt-utils.js\"\nimport type {RemarkFile, RemarkNode, RemarkTransformer} from \"./remark-types.js\"\n\nexport default function remarkLintMdxJsxFormat(): RemarkTransformer {\n return async function transform(tree, file) {\n const source = getFileValue(file)\n\n if (!source) {\n return\n }\n\n let oxfmtConfig\n\n try {\n oxfmtConfig = await loadOxfmtConfig(file.path)\n } catch (error) {\n file.message(\n `Unable to load oxfmt config: ${getErrorMessage(error)}`,\n {column: 1, line: 1},\n \"remark-lint:mdx-jsx-format\",\n )\n await replaceMdxJsxFlowElements(tree, source, file.path, null, file)\n return\n }\n\n await replaceMdxJsxFlowElements(tree, source, file.path, oxfmtConfig, file)\n }\n}\n\nasync function replaceMdxJsxFlowElements(\n node: RemarkNode,\n source: string,\n filePath: string | undefined,\n config: FormatConfig | null,\n file: RemarkFile,\n): Promise<void> {\n if (!Array.isArray(node.children)) {\n return\n }\n\n const children: RemarkNode[] = []\n\n for (const child of node.children) {\n if (child.type === \"mdxJsxFlowElement\") {\n const raw = getSourceSlice(source, child)\n\n if (raw === null) {\n children.push(child)\n continue\n }\n\n const formatted =\n config === null || hasChildren(child)\n ? raw\n : await formatMdxJsxBlock(filePath, raw, config)\n\n if (formatted !== raw) {\n file.message(\n \"Format MDX JSX block\",\n child,\n \"remark-lint:mdx-jsx-format\",\n )\n }\n\n children.push({\n type: \"html\",\n value: formatted,\n })\n continue\n }\n\n await replaceMdxJsxFlowElements(child, source, filePath, config, file)\n children.push(child)\n }\n\n node.children = children\n}\n\nasync function formatMdxJsxBlock(\n filePath: string | undefined,\n value: string,\n config: FormatConfig,\n): Promise<string> {\n const formatted = await formatOxfmt(\n getBlockFilePath(filePath),\n wrapMdxJsxBlock(value),\n config,\n )\n\n if (formatted === null) {\n return value\n }\n\n return unwrapMdxJsxBlock(formatted) ?? value\n}\n\nfunction wrapMdxJsxBlock(value: string): string {\n return `const __mdx = (\n <>\n${value}\n </>\n)\n`\n}\n\nfunction unwrapMdxJsxBlock(value: string): null | string {\n const lines = value.split(/\\r?\\n/u)\n const openIndex = lines.findIndex((line) => line.trim() === \"<>\")\n const closeIndex = lines.findIndex(\n (line, index) => index > openIndex && line.trim() === \"</>\",\n )\n\n if (openIndex === -1 || closeIndex === -1 || closeIndex <= openIndex + 1) {\n return null\n }\n\n return lines\n .slice(openIndex + 1, closeIndex)\n .map((line) => (line.startsWith(\" \") ? line.slice(4) : line))\n .join(\"\\n\")\n}\n\nfunction getSourceSlice(source: string, node: RemarkNode): null | string {\n const start = node.position?.start?.offset\n const end = node.position?.end?.offset\n\n if (typeof start !== \"number\" || typeof end !== \"number\") {\n return null\n }\n\n return source.slice(start, end)\n}\n\nfunction getFileValue(file: RemarkFile): string {\n return (file.value ?? \"\") as string\n}\n\nfunction getBlockFilePath(filePath: string | undefined): string {\n return `${getAbsolutePath(filePath)}.jsx.tsx`\n}\n\nfunction hasChildren(node: RemarkNode): boolean {\n return Array.isArray(node.children) && node.children.length > 0\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remark-preserve-alert-markers.d.ts","sourceRoot":"","sources":["../src/remark-preserve-alert-markers.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,SAAS,CAAA;AA0CtC,MAAM,CAAC,OAAO,UAAU,0BAA0B,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI,CAcxE"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// src/remark-preserve-alert-markers.ts
|
|
2
|
+
var ALERT_MARKER_PATTERN = /^\\?\[!(?:note|tip|success|warning|caution)(?:\/[^\]\n]+)?\]/iu;
|
|
3
|
+
function remarkPreserveAlertMarkers() {
|
|
4
|
+
const extensions = getToMarkdownExtensions(this);
|
|
5
|
+
const data = this.data();
|
|
6
|
+
data.toMarkdownExtensions = [
|
|
7
|
+
...extensions,
|
|
8
|
+
{
|
|
9
|
+
handlers: {
|
|
10
|
+
text: preserveAlertMarkerText
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
];
|
|
14
|
+
}
|
|
15
|
+
function preserveAlertMarkerText(node, parent, state, info) {
|
|
16
|
+
const value = state.safe(node.value, info);
|
|
17
|
+
if (!isAlertMarkerText(node, parent, state)) {
|
|
18
|
+
return value;
|
|
19
|
+
}
|
|
20
|
+
return value.replace(/^\\(?=\[!)/u, "");
|
|
21
|
+
}
|
|
22
|
+
function isAlertMarkerText(node, parent, state) {
|
|
23
|
+
return parent?.type === "paragraph" && parent.children?.[0] === node && state.stack.includes("blockquote") && ALERT_MARKER_PATTERN.test(node.value);
|
|
24
|
+
}
|
|
25
|
+
function getToMarkdownExtensions(processor) {
|
|
26
|
+
const { toMarkdownExtensions } = processor.data();
|
|
27
|
+
return Array.isArray(toMarkdownExtensions) ? toMarkdownExtensions : [];
|
|
28
|
+
}
|
|
29
|
+
export {
|
|
30
|
+
remarkPreserveAlertMarkers as default
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=remark-preserve-alert-markers.js.map
|