Merge pull request #15 from ueberdosis/feature/parse-code-blocks

Add language support to Code Block’s parseDOM function
This commit is contained in:
Philipp Kühn
2020-09-30 19:21:17 +02:00
committed by GitHub
6 changed files with 44 additions and 8 deletions

View File

@@ -3,6 +3,7 @@ module.exports = {
'@babel/preset-env', '@babel/preset-env',
], ],
plugins: [ plugins: [
'@babel/plugin-proposal-nullish-coalescing-operator',
'@babel/plugin-proposal-optional-chaining', '@babel/plugin-proposal-optional-chaining',
], ],
} }

View File

@@ -69,6 +69,16 @@ context('/api/extensions/code-block', () => {
}) })
}) })
it('should parse the language from a HTML code block', () => {
cy.get('.ProseMirror').then(([{ editor }]) => {
editor.setContent('<pre><code class="language-css">body { display: none; }</code></pre>')
cy.get('.ProseMirror')
.find('pre>code.language-css')
.should('have.length', 1)
})
})
it('should make a code block for js', () => { it('should make a code block for js', () => {
cy.get('.ProseMirror').then(([{ editor }]) => { cy.get('.ProseMirror').then(([{ editor }]) => {
editor.clearContent() editor.clearContent()

View File

@@ -17,9 +17,10 @@ yarn add @tiptap/extension-code-block
``` ```
## Settings ## Settings
| Option | Type | Default | Description | | Option | Type | Default | Description |
| ------ | ------ | ------- | -------------------------------------------- | | ------------------- | ------ | --------- | ---------------------------------------------------------------- |
| class | string | | Add a custom class to the rendered HTML tag. | | class | string | | Add a custom class to the rendered HTML tag. |
| languageClassPrefix | string | language- | Adds a prefix to language classes that are applied to code tags. |
## Commands ## Commands
| Command | Options | Description | | Command | Options | Description |

View File

@@ -21,6 +21,7 @@
"reset": "yarn clean:packages && rm -rf ./**/.cache && rm -rf ./**/node_modules && rm -rf ./yarn.lock && yarn install" "reset": "yarn clean:packages && rm -rf ./**/.cache && rm -rf ./**/node_modules && rm -rf ./yarn.lock && yarn install"
}, },
"devDependencies": { "devDependencies": {
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.4",
"@babel/plugin-proposal-optional-chaining": "^7.11.0", "@babel/plugin-proposal-optional-chaining": "^7.11.0",
"@babel/preset-env": "^7.11.5", "@babel/preset-env": "^7.11.5",
"@types/prosemirror-commands": "^1.0.3", "@types/prosemirror-commands": "^1.0.3",

View File

@@ -1,6 +1,10 @@
import { Command, Node } from '@tiptap/core' import { Command, Node } from '@tiptap/core'
import { textblockTypeInputRule } from 'prosemirror-inputrules' import { textblockTypeInputRule } from 'prosemirror-inputrules'
export interface CodeBlockOptions {
languageClassPrefix: string,
}
export type CodeBlockCommand = () => Command export type CodeBlockCommand = () => Command
declare module '@tiptap/core/src/Editor' { declare module '@tiptap/core/src/Editor' {
@@ -11,9 +15,12 @@ declare module '@tiptap/core/src/Editor' {
export const inputRegex = /^```(?<language>[a-z]*)? $/ export const inputRegex = /^```(?<language>[a-z]*)? $/
export default new Node() export default new Node<CodeBlockOptions>()
.name('code_block') .name('code_block')
.schema(() => ({ .defaults({
languageClassPrefix: 'language-',
})
.schema(({ options }) => ({
attrs: { attrs: {
language: { language: {
default: null, default: null,
@@ -26,9 +33,25 @@ export default new Node()
defining: true, defining: true,
draggable: false, draggable: false,
parseDOM: [ parseDOM: [
{ tag: 'pre', preserveWhitespace: 'full' }, {
tag: 'pre',
preserveWhitespace: 'full',
getAttrs(node) {
const classAttribute = (node as Element).firstElementChild?.getAttribute('class')
if (!classAttribute) {
return null
}
const regexLanguageClassPrefix = new RegExp(`^(${options.languageClassPrefix})`)
return { language: classAttribute.replace(regexLanguageClassPrefix, '') }
},
},
], ],
toDOM: node => ['pre', ['code', { class: node.attrs.language && `language-${node.attrs.language}` }, 0]], toDOM: node => ['pre', ['code', {
class: node.attrs.language && options.languageClassPrefix + node.attrs.language,
}, 0]],
})) }))
.commands(({ name }) => ({ .commands(({ name }) => ({
codeBlock: attrs => ({ commands }) => { codeBlock: attrs => ({ commands }) => {

View File

@@ -1,6 +1,6 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "esnext", "target": "es2019",
"module": "esnext", "module": "esnext",
"strict": true, "strict": true,
"jsx": "preserve", "jsx": "preserve",