Skip to content

Commit

Permalink
fix(CodeBlock): fixed parsing of language from token.info and added s…
Browse files Browse the repository at this point in the history
…upport for different code_block markup
  • Loading branch information
d3m1d0v committed Mar 1, 2024
1 parent a6d1cec commit 3625f31
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 15 deletions.
12 changes: 7 additions & 5 deletions src/extensions/markdown/CodeBlock/CodeBlock.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ import {createMarkupChecker} from '../../../../tests/sameMarkup';
import {ExtensionsManager} from '../../../core';
import {BaseNode, BaseSpecsPreset} from '../../base/specs';

import {CodeBlockSpecs} from './CodeBlockSpecs';
import {codeBlockLangAttr, codeBlockNodeName} from './const';
import {CodeBlockNodeAttr, CodeBlockSpecs, codeBlockNodeName} from './CodeBlockSpecs';

const {schema, parser, serializer} = new ExtensionsManager({
extensions: (builder) => builder.use(BaseSpecsPreset, {}).use(CodeBlockSpecs, {}),
Expand All @@ -24,7 +23,7 @@ describe('CodeBlock extension', () => {
it('should parse a code block', () =>
same(
'Some code:\n\n```\nHere it is\n```\n\nPara',
doc(p('Some code:'), cb({[codeBlockLangAttr]: ''}, 'Here it is'), p('Para')),
doc(p('Some code:'), cb('Here it is'), p('Para')),
));

it('parses an intended code block', () =>
Expand All @@ -36,14 +35,17 @@ describe('CodeBlock extension', () => {
it('should parse a fenced code block with info string', () =>
same(
'foo\n\n```javascript\n1\n```',
doc(p('foo'), cb({[codeBlockLangAttr]: 'javascript'}, '1')),
doc(p('foo'), cb({[CodeBlockNodeAttr.Lang]: 'javascript'}, '1')),
));

it('should parse a fenced code block with multiple new lines at the end', () =>
same('```\nsome code\n\n\n\n```', doc(cb({[codeBlockLangAttr]: ''}, 'some code\n\n\n'))));
same('```\nsome code\n\n\n\n```', doc(cb('some code\n\n\n'))));

// TODO: parsed: doc(paragraph("code\nblock"))
it.skip('should parse html - pre tag', () => {
parseDOM(schema, '<pre><code>code\nblock</code></pre>', doc(cb('code\nblock')));
});

it('should support different markup', () =>
same('~~~\n123\n~~~', doc(cb({[CodeBlockNodeAttr.Markup]: '~~~'}, '123'))));
});
38 changes: 30 additions & 8 deletions src/extensions/markdown/CodeBlock/CodeBlockSpecs/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import type {ExtensionAuto, YENodeSpec} from '../../../../core';
import {nodeTypeFactory} from '../../../../utils/schema';

export const CodeBlockNodeAttr = {
Lang: 'data-language',
Markup: 'data-markup',
} as const;

export const codeBlockNodeName = 'code_block';
export const codeBlockLangAttr = 'data-language';
/** @deprecated Use __CodeBlockNodeAttr__ instead */
export const codeBlockLangAttr = CodeBlockNodeAttr.Lang;
export const codeBlockType = nodeTypeFactory(codeBlockNodeName);

export type CodeBlockSpecsOptions = {
Expand All @@ -13,7 +19,10 @@ export const CodeBlockSpecs: ExtensionAuto<CodeBlockSpecsOptions> = (builder, op
builder.addNode(codeBlockNodeName, () => ({
view: opts.nodeview,
spec: {
attrs: {[codeBlockLangAttr]: {default: 'text'}},
attrs: {
[CodeBlockNodeAttr.Lang]: {default: ''},
[CodeBlockNodeAttr.Markup]: {default: '```'},
},
content: 'text*',
group: 'block',
code: true,
Expand All @@ -25,13 +34,13 @@ export const CodeBlockSpecs: ExtensionAuto<CodeBlockSpecsOptions> = (builder, op
tag: 'pre',
preserveWhitespace: 'full',
getAttrs: (node) => ({
[codeBlockLangAttr]:
(node as Element).getAttribute(codeBlockLangAttr) || '',
[CodeBlockNodeAttr.Lang]:
(node as Element).getAttribute(CodeBlockNodeAttr.Lang) || '',
}),
},
],
toDOM({attrs}) {
return ['pre', attrs[codeBlockLangAttr] ? attrs : {}, ['code', 0]];
return ['pre', attrs, ['code', 0]];
},
},
fromYfm: {
Expand All @@ -43,11 +52,14 @@ export const CodeBlockSpecs: ExtensionAuto<CodeBlockSpecsOptions> = (builder, op
},
},
toYfm: (state, node) => {
state.write('```' + (node.attrs[codeBlockLangAttr] || '') + '\n');
const lang: string = node.attrs[CodeBlockNodeAttr.Lang];
const markup: string = node.attrs[CodeBlockNodeAttr.Markup];

state.write(markup + lang + '\n');
state.text(node.textContent, false);
// Add a newline to the current content before adding closing marker
state.write('\n');
state.write('```');
state.write(markup);
state.closeBlock(node);
},
}));
Expand All @@ -60,7 +72,17 @@ export const CodeBlockSpecs: ExtensionAuto<CodeBlockSpecsOptions> = (builder, op
name: codeBlockNodeName,
type: 'block',
noCloseToken: true,
getAttrs: (tok) => ({[codeBlockLangAttr]: tok.info || ''}),
getAttrs: (tok) => {
const attrs: Record<string, string> = {
[CodeBlockNodeAttr.Markup]: tok.markup,
};
if (tok.info) {
// like in markdown-it
// https://github.com/markdown-it/markdown-it/blob/d07d585b6b15aaee2bc8f7a54b994526dad4dbc5/lib/renderer.mjs#L36-L37
attrs[CodeBlockNodeAttr.Lang] = tok.info.split(/(\s+)/g)[0];
}
return attrs;
},
prepareContent: removeNewLineAtEnd, // content of fence blocks contains extra \n at the end
},
},
Expand Down
6 changes: 5 additions & 1 deletion src/extensions/markdown/CodeBlock/const.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import {codeBlockType} from './CodeBlockSpecs';

export {codeBlockNodeName, codeBlockLangAttr} from './CodeBlockSpecs';
export {
codeBlockNodeName,
codeBlockLangAttr,
CodeBlockNodeAttr as CodeBlockAttr,
} from './CodeBlockSpecs';
export const cbAction = 'toCodeBlock';
/** @deprecated Use `codeBlockType` instead */
export const cbType = codeBlockType;
7 changes: 6 additions & 1 deletion src/extensions/markdown/CodeBlock/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,12 @@ import {cbAction, cbType} from './const';
import {handlePaste} from './handle-paste';

export {resetCodeblock} from './commands';
export {codeBlockNodeName, codeBlockLangAttr, codeBlockType} from './CodeBlockSpecs';
export {
codeBlockNodeName,
CodeBlockNodeAttr as CodeBlockAttr,
codeBlockLangAttr,
codeBlockType,
} from './CodeBlockSpecs';

export type CodeBlockOptions = CodeBlockSpecsOptions & {
codeBlockKey?: string | null;
Expand Down

0 comments on commit 3625f31

Please sign in to comment.