@abraca/convert 2.11.0 → 2.13.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/dist/abracadabra-convert.cjs +199 -0
- package/dist/abracadabra-convert.cjs.map +1 -1
- package/dist/abracadabra-convert.esm.js +190 -1
- package/dist/abracadabra-convert.esm.js.map +1 -1
- package/dist/index.d.ts +56 -1
- package/package.json +1 -1
- package/src/code.ts +208 -0
- package/src/file-blocks/manifest.ts +5 -0
- package/src/file-blocks/paths.ts +17 -0
- package/src/index.ts +15 -0
- package/src/markdown-to-yjs.ts +8 -0
- package/src/types.ts +5 -0
- package/src/yjs-to-markdown.ts +5 -0
|
@@ -118,6 +118,12 @@ function parseFrontmatter(markdown) {
|
|
|
118
118
|
if (subtitle) meta.subtitle = subtitle;
|
|
119
119
|
const url = getStr(["url"]);
|
|
120
120
|
if (url) meta.url = url;
|
|
121
|
+
const language = getStr(["language"]);
|
|
122
|
+
if (language) meta.language = language;
|
|
123
|
+
const fileExtension = getStr(["fileExtension"]);
|
|
124
|
+
if (fileExtension) meta.fileExtension = fileExtension;
|
|
125
|
+
const codeTheme = getStr(["codeTheme"]);
|
|
126
|
+
if (codeTheme) meta.codeTheme = codeTheme;
|
|
121
127
|
const ratingRaw = getStr(["rating"]);
|
|
122
128
|
if (ratingRaw !== void 0) {
|
|
123
129
|
const n = Number(ratingRaw);
|
|
@@ -1395,6 +1401,9 @@ function generateFrontmatter(label, meta, type) {
|
|
|
1395
1401
|
4: "urgent"
|
|
1396
1402
|
}[meta.priority] ?? meta.priority}`);
|
|
1397
1403
|
if (meta.checked !== void 0) lines.push(`checked: ${meta.checked}`);
|
|
1404
|
+
if (meta.language) lines.push(`language: ${yamlScalar(meta.language)}`);
|
|
1405
|
+
if (meta.fileExtension) lines.push(`fileExtension: ${yamlScalar(meta.fileExtension)}`);
|
|
1406
|
+
if (meta.codeTheme) lines.push(`codeTheme: ${yamlScalar(meta.codeTheme)}`);
|
|
1398
1407
|
if (meta.dateStart) lines.push(`dateStart: "${escapeYaml(meta.dateStart)}"`);
|
|
1399
1408
|
if (meta.dateEnd) lines.push(`dateEnd: "${escapeYaml(meta.dateEnd)}"`);
|
|
1400
1409
|
if (meta.subtitle) lines.push(`subtitle: "${escapeYaml(meta.subtitle)}"`);
|
|
@@ -1908,6 +1917,174 @@ function appendHtmlToFragment(fragment, html) {
|
|
|
1908
1917
|
});
|
|
1909
1918
|
}
|
|
1910
1919
|
|
|
1920
|
+
//#endregion
|
|
1921
|
+
//#region packages/convert/src/code.ts
|
|
1922
|
+
/** Y.Text key holding a code document's content. */
|
|
1923
|
+
const CODE_TEXT_KEY = "code";
|
|
1924
|
+
/** Read a code document's raw text. Empty string when absent. */
|
|
1925
|
+
function readCodeText(doc) {
|
|
1926
|
+
return doc.getText(CODE_TEXT_KEY).toString();
|
|
1927
|
+
}
|
|
1928
|
+
/**
|
|
1929
|
+
* Replace a code document's full text in a single transaction. `origin`
|
|
1930
|
+
* is forwarded to `transact` so callers (e.g. fs-sync) can tag the write
|
|
1931
|
+
* and skip their own observers.
|
|
1932
|
+
*/
|
|
1933
|
+
function writeCodeText(doc, content, origin) {
|
|
1934
|
+
const ytext = doc.getText(CODE_TEXT_KEY);
|
|
1935
|
+
doc.transact(() => {
|
|
1936
|
+
if (ytext.length > 0) ytext.delete(0, ytext.length);
|
|
1937
|
+
if (content.length > 0) ytext.insert(0, content);
|
|
1938
|
+
}, origin);
|
|
1939
|
+
}
|
|
1940
|
+
const LANGUAGE_BY_EXT = {
|
|
1941
|
+
js: "javascript",
|
|
1942
|
+
mjs: "javascript",
|
|
1943
|
+
cjs: "javascript",
|
|
1944
|
+
jsx: "jsx",
|
|
1945
|
+
ts: "typescript",
|
|
1946
|
+
mts: "typescript",
|
|
1947
|
+
cts: "typescript",
|
|
1948
|
+
tsx: "tsx",
|
|
1949
|
+
html: "html",
|
|
1950
|
+
htm: "html",
|
|
1951
|
+
css: "css",
|
|
1952
|
+
scss: "scss",
|
|
1953
|
+
less: "less",
|
|
1954
|
+
vue: "vue",
|
|
1955
|
+
svelte: "svelte",
|
|
1956
|
+
json: "json",
|
|
1957
|
+
jsonc: "json",
|
|
1958
|
+
json5: "json",
|
|
1959
|
+
yaml: "yaml",
|
|
1960
|
+
yml: "yaml",
|
|
1961
|
+
toml: "toml",
|
|
1962
|
+
xml: "xml",
|
|
1963
|
+
ini: "properties",
|
|
1964
|
+
env: "properties",
|
|
1965
|
+
rs: "rust",
|
|
1966
|
+
go: "go",
|
|
1967
|
+
c: "c",
|
|
1968
|
+
h: "c",
|
|
1969
|
+
cpp: "cpp",
|
|
1970
|
+
cc: "cpp",
|
|
1971
|
+
cxx: "cpp",
|
|
1972
|
+
hpp: "cpp",
|
|
1973
|
+
cs: "csharp",
|
|
1974
|
+
java: "java",
|
|
1975
|
+
kt: "kotlin",
|
|
1976
|
+
kts: "kotlin",
|
|
1977
|
+
swift: "swift",
|
|
1978
|
+
m: "objective-c",
|
|
1979
|
+
mm: "objective-c",
|
|
1980
|
+
py: "python",
|
|
1981
|
+
pyi: "python",
|
|
1982
|
+
rb: "ruby",
|
|
1983
|
+
php: "php",
|
|
1984
|
+
pl: "perl",
|
|
1985
|
+
lua: "lua",
|
|
1986
|
+
r: "r",
|
|
1987
|
+
sh: "shell",
|
|
1988
|
+
bash: "shell",
|
|
1989
|
+
zsh: "shell",
|
|
1990
|
+
fish: "shell",
|
|
1991
|
+
sql: "sql",
|
|
1992
|
+
graphql: "graphql",
|
|
1993
|
+
gql: "graphql",
|
|
1994
|
+
dockerfile: "dockerfile",
|
|
1995
|
+
md: "markdown",
|
|
1996
|
+
markdown: "markdown"
|
|
1997
|
+
};
|
|
1998
|
+
/** Preferred on-disk extension per language (reverse of LANGUAGE_BY_EXT). */
|
|
1999
|
+
const EXT_BY_LANGUAGE = {
|
|
2000
|
+
javascript: "js",
|
|
2001
|
+
jsx: "jsx",
|
|
2002
|
+
typescript: "ts",
|
|
2003
|
+
tsx: "tsx",
|
|
2004
|
+
html: "html",
|
|
2005
|
+
css: "css",
|
|
2006
|
+
scss: "scss",
|
|
2007
|
+
less: "less",
|
|
2008
|
+
vue: "vue",
|
|
2009
|
+
svelte: "svelte",
|
|
2010
|
+
json: "json",
|
|
2011
|
+
yaml: "yaml",
|
|
2012
|
+
toml: "toml",
|
|
2013
|
+
xml: "xml",
|
|
2014
|
+
properties: "ini",
|
|
2015
|
+
rust: "rs",
|
|
2016
|
+
go: "go",
|
|
2017
|
+
c: "c",
|
|
2018
|
+
cpp: "cpp",
|
|
2019
|
+
csharp: "cs",
|
|
2020
|
+
java: "java",
|
|
2021
|
+
kotlin: "kt",
|
|
2022
|
+
swift: "swift",
|
|
2023
|
+
"objective-c": "m",
|
|
2024
|
+
python: "py",
|
|
2025
|
+
ruby: "rb",
|
|
2026
|
+
php: "php",
|
|
2027
|
+
perl: "pl",
|
|
2028
|
+
lua: "lua",
|
|
2029
|
+
r: "r",
|
|
2030
|
+
shell: "sh",
|
|
2031
|
+
sql: "sql",
|
|
2032
|
+
graphql: "graphql",
|
|
2033
|
+
dockerfile: "dockerfile",
|
|
2034
|
+
markdown: "md",
|
|
2035
|
+
plain: "txt"
|
|
2036
|
+
};
|
|
2037
|
+
/** Normalize an extension: strip leading dot(s), lowercase. */
|
|
2038
|
+
function normalizeExtension(ext) {
|
|
2039
|
+
return ext.replace(/^\.+/, "").toLowerCase();
|
|
2040
|
+
}
|
|
2041
|
+
/**
|
|
2042
|
+
* Whether a file extension should import as a `code` page type. Note
|
|
2043
|
+
* `md`/`markdown` are intentionally NOT code extensions here — fs-sync
|
|
2044
|
+
* treats `.md` as the prose/envelope format, so it's excluded from the
|
|
2045
|
+
* code-import gate even though it has a language mapping for in-editor use.
|
|
2046
|
+
*/
|
|
2047
|
+
function isCodeExtension(ext) {
|
|
2048
|
+
const e = normalizeExtension(ext);
|
|
2049
|
+
if (e === "md" || e === "markdown") return false;
|
|
2050
|
+
return e in LANGUAGE_BY_EXT;
|
|
2051
|
+
}
|
|
2052
|
+
/** CodeMirror language id for an extension, or undefined when unknown. */
|
|
2053
|
+
function extToLanguage(ext) {
|
|
2054
|
+
return LANGUAGE_BY_EXT[normalizeExtension(ext)];
|
|
2055
|
+
}
|
|
2056
|
+
/** Preferred on-disk extension (no dot) for a language, or undefined. */
|
|
2057
|
+
function languageToExtension(language) {
|
|
2058
|
+
return EXT_BY_LANGUAGE[language.toLowerCase()];
|
|
2059
|
+
}
|
|
2060
|
+
/**
|
|
2061
|
+
* Derive `{ language, fileExtension }` from a filename for code import.
|
|
2062
|
+
* Returns undefined when the extension is not a recognized code extension
|
|
2063
|
+
* (so callers fall back to the prose/doc path).
|
|
2064
|
+
*/
|
|
2065
|
+
function inferCodeMetaFromFilename(filename) {
|
|
2066
|
+
const dot = filename.lastIndexOf(".");
|
|
2067
|
+
if (dot < 0) return void 0;
|
|
2068
|
+
const ext = normalizeExtension(filename.slice(dot + 1));
|
|
2069
|
+
if (!isCodeExtension(ext)) return void 0;
|
|
2070
|
+
const language = LANGUAGE_BY_EXT[ext];
|
|
2071
|
+
if (!language) return void 0;
|
|
2072
|
+
return {
|
|
2073
|
+
language,
|
|
2074
|
+
fileExtension: ext
|
|
2075
|
+
};
|
|
2076
|
+
}
|
|
2077
|
+
/**
|
|
2078
|
+
* Choose the on-disk extension for a code doc on export. Prefers an
|
|
2079
|
+
* explicit `fileExtension`, then the language's primary extension, then
|
|
2080
|
+
* `txt`.
|
|
2081
|
+
*/
|
|
2082
|
+
function codeFileExtension(meta) {
|
|
2083
|
+
if (meta?.fileExtension) return normalizeExtension(meta.fileExtension);
|
|
2084
|
+
if (meta?.language) return languageToExtension(meta.language) ?? "txt";
|
|
2085
|
+
return "txt";
|
|
2086
|
+
}
|
|
2087
|
+
|
|
1911
2088
|
//#endregion
|
|
1912
2089
|
//#region packages/convert/src/diff.ts
|
|
1913
2090
|
function attrsToJson(el) {
|
|
@@ -3162,6 +3339,18 @@ function buildRelativePath(docId, treeData, manifest) {
|
|
|
3162
3339
|
return `${parentPath}${parentPath ? "/" : ""}${resolvedFilename}.md`;
|
|
3163
3340
|
}
|
|
3164
3341
|
/**
|
|
3342
|
+
* Companion code-file path for a `code` doc, derived from its `.md`
|
|
3343
|
+
* envelope path by swapping the extension. e.g.
|
|
3344
|
+
* `src/main.md` + `rs` -> `src/main.rs`. A code doc never has children,
|
|
3345
|
+
* so the `_index.md` form is not expected here, but is handled defensively.
|
|
3346
|
+
*/
|
|
3347
|
+
function codeCompanionPath(mdRelativePath, fileExtension) {
|
|
3348
|
+
const ext = fileExtension.replace(/^\.+/, "").toLowerCase() || "txt";
|
|
3349
|
+
if (mdRelativePath.endsWith("/_index.md")) return `${mdRelativePath.slice(0, -10)}/_index.${ext}`;
|
|
3350
|
+
if (mdRelativePath.endsWith(".md")) return `${mdRelativePath.slice(0, -3)}.${ext}`;
|
|
3351
|
+
return `${mdRelativePath}.${ext}`;
|
|
3352
|
+
}
|
|
3353
|
+
/**
|
|
3165
3354
|
* Get the directory portion of a relative path for a doc.
|
|
3166
3355
|
* For _index.md docs: returns the directory containing _index.md
|
|
3167
3356
|
* For leaf docs: returns the parent directory
|
|
@@ -3217,6 +3406,7 @@ function nextOrder(treeData, parentId) {
|
|
|
3217
3406
|
}
|
|
3218
3407
|
|
|
3219
3408
|
//#endregion
|
|
3409
|
+
exports.CODE_TEXT_KEY = CODE_TEXT_KEY;
|
|
3220
3410
|
exports.MARK_SPECS = MARK_SPECS;
|
|
3221
3411
|
exports.MARK_SPEC_BY_DELIM = MARK_SPEC_BY_DELIM;
|
|
3222
3412
|
exports.MARK_SPEC_BY_NAME = MARK_SPEC_BY_NAME;
|
|
@@ -3228,18 +3418,24 @@ exports.appendHtmlToFragment = appendHtmlToFragment;
|
|
|
3228
3418
|
exports.buildAliasMap = buildAliasMap;
|
|
3229
3419
|
exports.buildRelativePath = buildRelativePath;
|
|
3230
3420
|
exports.buildReverseLookup = buildReverseLookup;
|
|
3421
|
+
exports.codeCompanionPath = codeCompanionPath;
|
|
3422
|
+
exports.codeFileExtension = codeFileExtension;
|
|
3231
3423
|
exports.conflictsDir = conflictsDir;
|
|
3232
3424
|
exports.createEmptyManifest = createEmptyManifest;
|
|
3233
3425
|
exports.diffJson = diffJson;
|
|
3234
3426
|
exports.diffYjs = diffYjs;
|
|
3427
|
+
exports.extToLanguage = extToLanguage;
|
|
3235
3428
|
exports.filenameToLabel = filenameToLabel;
|
|
3236
3429
|
exports.fsFilenameToLabel = fsFilenameToLabel;
|
|
3237
3430
|
exports.getDocDir = getDocDir;
|
|
3238
3431
|
exports.getFsAdapter = getFsAdapter;
|
|
3239
3432
|
exports.getTreeData = getTreeData;
|
|
3240
3433
|
exports.hasChildren = hasChildren;
|
|
3434
|
+
exports.inferCodeMetaFromFilename = inferCodeMetaFromFilename;
|
|
3435
|
+
exports.isCodeExtension = isCodeExtension;
|
|
3241
3436
|
exports.jsonToYFragment = jsonToYFragment;
|
|
3242
3437
|
exports.labelToFilename = labelToFilename;
|
|
3438
|
+
exports.languageToExtension = languageToExtension;
|
|
3243
3439
|
exports.loadManifest = loadManifest;
|
|
3244
3440
|
exports.lookupByDocId = lookupByDocId;
|
|
3245
3441
|
exports.lookupByHash = lookupByHash;
|
|
@@ -3247,10 +3443,12 @@ exports.lookupByPath = lookupByPath;
|
|
|
3247
3443
|
exports.manifestDir = manifestDir;
|
|
3248
3444
|
exports.mdcTagOf = mdcTagOf;
|
|
3249
3445
|
exports.nextOrder = nextOrder;
|
|
3446
|
+
exports.normalizeExtension = normalizeExtension;
|
|
3250
3447
|
exports.orphansDir = orphansDir;
|
|
3251
3448
|
exports.parseFrontmatter = parseFrontmatter;
|
|
3252
3449
|
exports.populateYDocFromHtml = populateYDocFromHtml;
|
|
3253
3450
|
exports.populateYDocFromMarkdown = populateYDocFromMarkdown;
|
|
3451
|
+
exports.readCodeText = readCodeText;
|
|
3254
3452
|
exports.removeEntry = removeEntry;
|
|
3255
3453
|
exports.resolveParentFromPath = resolveParentFromPath;
|
|
3256
3454
|
exports.saveManifest = saveManifest;
|
|
@@ -3259,6 +3457,7 @@ exports.setFsAdapter = setFsAdapter;
|
|
|
3259
3457
|
exports.simpleHash = simpleHash;
|
|
3260
3458
|
exports.stringifyJsonNode = stringifyJsonNode;
|
|
3261
3459
|
exports.trashDir = trashDir;
|
|
3460
|
+
exports.writeCodeText = writeCodeText;
|
|
3262
3461
|
exports.yfragmentToJson = yfragmentToJson;
|
|
3263
3462
|
exports.yjsToHtml = yjsToHtml;
|
|
3264
3463
|
exports.yjsToMarkdown = yjsToMarkdown;
|