1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2025-04-14 06:43:15 +00:00

WIP: ast transformers

This commit is contained in:
linonetwo 2025-03-23 20:57:19 +08:00
parent 3d2392dc70
commit 221193a587
2 changed files with 151 additions and 0 deletions

View File

@ -0,0 +1,68 @@
/*\
title: $:/plugins/tiddlywiki/editorjs/ast/wikiAstFromEditorJSAst.js
type: application/javascript
module-type: library
Get the EditorJS AST from a Wiki AST
\*/
/**
* Key is `node.type`, value is node converter function.
*/
const builders = {
// auto parse basic element nodes
// eslint-disable-next-line unicorn/prefer-object-from-entries
...(htmlTags).reduce(
(previousValue, currentValue) => {
previousValue[currentValue] = element;
return previousValue;
},
// eslint-disable-next-line @typescript-eslint/prefer-reduce-type-parameter, @typescript-eslint/consistent-type-assertions
{},
),
[ELEMENT_CODE_BLOCK]: codeblock,
[ELEMENT_LIC]: lic,
text,
widget,
macro: widget,
set,
};
function wikiAstFromEditorJSAst(input) {
return convertNodes(builders, Array.isArray(input) ? input : [input]);
}
exports.wikiAstFromEditorJSAst = wikiAstFromEditorJSAst;
function convertNodes(builders, nodes) {
if (nodes === undefined || nodes.length === 0) {
return [];
}
return nodes.reduce((accumulator, node) => {
return [...accumulator, ...convertWikiAstNode(builders, node)];
}, []);
}
function convertWikiAstNode(builders, node) {
// only text and root node don't have a `type` field, deal with it first
if (isText(node)) {
return [builders.text(builders, node)];
}
if (isElement(node)) {
const builder = builders[node.type];
if (typeof builder === 'function') {
const builtSlateNodeOrNodes = builder(builders, node);
return Array.isArray(builtSlateNodeOrNodes)
? builtSlateNodeOrNodes.map((child) => ({ ...getSlatePlateASTAdditionalProperties(node), ...child }))
: ([{ ...getSlatePlateASTAdditionalProperties(node), ...builtSlateNodeOrNodes }]);
}
}
// it might be a root or pure parent node, reduce it
if ('children' in node) {
return convertNodes(builders, node.children);
}
return [];
}

View File

@ -0,0 +1,83 @@
/*\
title: $:/plugins/tiddlywiki/editorjs/ast/wikiAstToEditorJSAst.js
type: application/javascript
module-type: library
Get the EditorJS AST from a Wiki AST
\*/
function wikiAstToEditorJSAst(node, options) {
return convertNodes({ ...initialContext, ...options }, Array.isArray(node) ? node : [node]);
}
exports.wikiAstToEditorJSAst = wikiAstToEditorJSAst;
const initialContext = {
builders,
marks: {},
};
function convertNodes(context, nodes) {
if (nodes === undefined || nodes.length === 0) {
return [{ text: '' }];
}
return nodes.reduce((accumulator, node) => {
return [...accumulator, ...editorJSNode(context, node)];
}, []);
}
function editorJSNode(context, node) {
const id = context.idCreator?.();
const withId = (nodeToAddId) => (id === undefined ? nodeToAddId : { ...nodeToAddId, id });
if ('rule' in node && node.rule !== undefined && node.rule in context.builders) {
const builder = context.builders[node.rule];
if (typeof builder === 'function') {
// basic elements
const builtEditorJSNodeOrNodes = builder(context, node);
return Array.isArray(builtEditorJSNodeOrNodes)
? builtEditorJSNodeOrNodes.map((child) => withId(child))
: ([withId(builtEditorJSNodeOrNodes)]);
}
} else if ('text' in node) {
// text node
return [withId({ text: node.text })];
} else {
console.warn(`WikiAst get Unknown node type: ${JSON.stringify(node)}`);
return [];
}
return [];
}
const builders = {
element,
text,
};
/** Slate node is compact, we need to filter out some keys from wikiast */
const textLevelKeysToOmit = ['type', 'start', 'end'];
function text(context, text) {
return {
text: '', // provides default text
...omit(text, textLevelKeysToOmit),
...context.marks,
};
}
const elementBuilders = { ul, ol: ul, li, ...marks };
function element(context, node) {
const { tag, children } = node;
if (typeof elementBuilders[tag] === 'function') {
return elementBuilders[tag](context, node);
}
const result = {
type: tag,
children: convertNodes(context, children),
};
if (node.rule) {
result.rule = node.rule;
}
return result;
}