diff --git a/src/extensions/yfm/YfmHeading/YfmHeadingSpecs/const.ts b/src/extensions/yfm/YfmHeading/YfmHeadingSpecs/const.ts index 9571b1af..1734b247 100644 --- a/src/extensions/yfm/YfmHeading/YfmHeadingSpecs/const.ts +++ b/src/extensions/yfm/YfmHeading/YfmHeadingSpecs/const.ts @@ -7,4 +7,5 @@ export const YfmHeadingAttr = { Level: headingLevelAttr, Id: 'id', DataLine: 'data-line', + Folding: 'folding', } as const; diff --git a/src/extensions/yfm/YfmHeading/YfmHeadingSpecs/index.ts b/src/extensions/yfm/YfmHeading/YfmHeadingSpecs/index.ts index 91aad3ce..51658dc1 100644 --- a/src/extensions/yfm/YfmHeading/YfmHeadingSpecs/index.ts +++ b/src/extensions/yfm/YfmHeading/YfmHeadingSpecs/index.ts @@ -24,6 +24,7 @@ export const YfmHeadingSpecs: ExtensionAuto = (builder, [YfmHeadingAttr.Id]: {default: ''}, [YfmHeadingAttr.Level]: {default: 1}, [YfmHeadingAttr.DataLine]: {default: null}, + [YfmHeadingAttr.Folding]: {default: false}, }, content: '(text | inline)*', group: 'block', @@ -40,11 +41,13 @@ export const YfmHeadingSpecs: ExtensionAuto = (builder, toDOM(node) { const id = node.attrs[YfmHeadingAttr.Id]; const lineNumber = node.attrs[YfmHeadingAttr.DataLine]; + const folding = node.attrs[YfmHeadingAttr.Folding]; return [ 'h' + node.attrs[YfmHeadingAttr.Level], { id: id || null, [YfmHeadingAttr.DataLine]: lineNumber, + [`data-${YfmHeadingAttr.Folding}`]: folding ? '' : null, }, 0, // [ @@ -84,13 +87,17 @@ export const YfmHeadingSpecs: ExtensionAuto = (builder, // attrs have id only if it explicitly specified manually return { [YfmHeadingAttr.Level]: Number(token.tag.slice(1)), + [YfmHeadingAttr.Folding]: token.meta?.folding, ...attrs, }; }, }, }, toMd: (state, node) => { - state.write(state.repeat('#', node.attrs[YfmHeadingAttr.Level]) + ' '); + const folding = node.attrs[YfmHeadingAttr.Folding]; + const level = node.attrs[YfmHeadingAttr.Level]; + + state.write(state.repeat('#', level) + (folding ? '+' : '') + ' '); state.renderInline(node); const anchor = node.attrs[YfmHeadingAttr.Id]; diff --git a/src/extensions/yfm/YfmHeading/YfmHeadingSpecs/utils.ts b/src/extensions/yfm/YfmHeading/YfmHeadingSpecs/utils.ts index 59a61b9c..f026f28d 100644 --- a/src/extensions/yfm/YfmHeading/YfmHeadingSpecs/utils.ts +++ b/src/extensions/yfm/YfmHeading/YfmHeadingSpecs/utils.ts @@ -8,7 +8,8 @@ export const getNodeAttrs = (level: HeadingLevel): TagParseRule['getAttrs'] => (node) => ({ [YfmHeadingAttr.Level]: level, - [YfmHeadingAttr.Id]: (node as Element).getAttribute('id') || '', + [YfmHeadingAttr.Id]: node.getAttribute('id') || '', + [YfmHeadingAttr.Folding]: node.hasAttribute(`data-${YfmHeadingAttr.Folding}`), }); // export const slugify = (str: string) => diff --git a/src/extensions/yfm/YfmHeading/commands.ts b/src/extensions/yfm/YfmHeading/commands.ts index 8d37174e..ab0c4d77 100644 --- a/src/extensions/yfm/YfmHeading/commands.ts +++ b/src/extensions/yfm/YfmHeading/commands.ts @@ -12,16 +12,20 @@ export {resetHeading} from '../../markdown/Heading/commands'; export const toHeading = (level: HeadingLevel): Command => (state, dispatch, view) => { + const attrs: Record = {}; + const parentHeading = findParentNodeOfType(hType(state.schema))(state.selection); - if (parentHeading && parentHeading.node.attrs[headingLevelAttr] === level) { - return toParagraph(state, dispatch, view); + if (parentHeading) { + if (parentHeading.node.attrs[headingLevelAttr] === level) { + return toParagraph(state, dispatch, view); + } + + Object.assign(attrs, parentHeading.node.attrs); } // const text = state.selection.$head.parent.textContent; - const attrs = { - // [YfmHeadingAttr.Id]: slugify(text), - [YfmHeadingAttr.Level]: level, - }; + // attrs[YfmHeadingAttr.Id] = slugify(text); + attrs[YfmHeadingAttr.Level] = level; return setBlockType(hType(state.schema), attrs)(state, dispatch); };