UNPKG

@atlaskit/editor-core

Version:

A package contains Atlassian editor core functionality

105 lines (97 loc) 3.5 kB
import { NodeSpec, browser } from '../../prosemirror'; import { Definition as Text } from './text'; import { NoMark } from './doc'; /** * @name codeBlock_node */ export interface Definition { type: 'codeBlock'; content?: Array<Text & NoMark>; attrs?: { language?: 'abap' | 'actionscript' | 'ada' | 'arduino' | 'autoit' | 'c' | 'c++' | 'clojure' | 'coffeescript' | 'csharp' | 'css' | 'cuda' | 'd' | 'dart' | 'delphi' | 'elixir' | 'erlang' | 'fortran' | 'foxpro' | 'go' | 'groovy' | 'haskell' | 'haxe' | 'html' | 'java' | 'javascript' | 'julia' | 'kotlin' | 'latex' | 'livescript' | 'lua' | 'mathematica' | 'matlab' | 'objective-c' | 'objective-j' | 'objectpascal' | 'ocaml' | 'octave' | 'perl' | 'php' | 'powershell' | 'prolog' | 'puppet' | 'python' | 'qml' | 'r' | 'racket' | 'restructuredtext' | 'ruby' | 'rust' | 'sass' | 'scala' | 'scheme' | 'shell' | 'smalltalk' | 'sql' | 'standardml' | 'swift' | 'tcl' | 'tex' | 'typescript' | 'vala' | 'vbnet' | 'verilog' | 'vhdl' | 'xml' | 'xquery'; }; } const getLanguageFromEditorStyle = (dom: HTMLElement): string | undefined => { return dom.dataset['language']; }; // example of BB style: // <div class="codehilite language-javascript"><pre><span>hello world</span><span>\n</span></pre></div> const getLanguageFromBitbucketStyle = (dom: HTMLElement): string | undefined => { if (dom && dom.classList.contains('codehilite')) { // code block html from Bitbucket always contains an extra new line return extractLanguageFromClass(dom.className); } }; const extractLanguageFromClass = (className: string): string | undefined => { const languageRegex = /(?:^|\s)language-([^\s]+)/; const result = languageRegex.exec(className); if (result && result[1]) { return result[1]; } }; const removeLastNewLine = (dom: HTMLElement): HTMLElement => { const parent = dom && dom.parentElement; if (parent && parent.classList.contains('codehilite')) { dom.textContent = dom.textContent!.replace(/\n$/, ''); } return dom; }; export const codeBlock: NodeSpec = { attrs: { language: { default: null }, uniqueId: { default: null } }, content: 'text*', group: 'block', code: true, defining: true, parseDOM: [{ tag: 'pre', preserveWhitespace: 'full', getAttrs: (dom: HTMLElement) => { const language = ( getLanguageFromBitbucketStyle(dom.parentElement!) || getLanguageFromEditorStyle(dom.parentElement!) || dom.getAttribute('data-language')! ); dom = removeLastNewLine(dom); return { language }; } }, // Handle VSCode paste, it wraps copied content with // <div style="...white-space: pre;..."> { tag: 'div[style]', preserveWhitespace: 'full', getAttrs: (dom: HTMLElement) => { if ( dom.style.whiteSpace === 'pre' || dom.style.whiteSpace === 'pre-wrap' || (dom.style.fontFamily && dom.style.fontFamily.toLowerCase().indexOf('monospace') > -1) ) { return {}; } return false; } }, // Handle GitHub/Gist paste { tag: 'table[style]', preserveWhitespace: 'full', getAttrs: (dom: HTMLElement) => { if (dom.querySelector('td[class*="blob-code"]')) { return {}; } return false; } }], toDOM(node): [string, any, number] { const className = browser.ie && browser.ie_version <= 11 ? 'ie11' : ''; return ['pre', { 'data-language': node.attrs.language, 'class': className }, 0]; } };