@init-kz/editorjs-code-highlight
Version:
A micro code-editor for awesome web pages
1 lines • 14.6 kB
Source Map (JSON)
{"version":3,"sources":["../src/index.ts","../src/icon.ts"],"sourcesContent":["import { icon } from \"./icon\";\nimport \"./style.css\";\n\nimport { API, BlockTool, SanitizerConfig } from \"@editorjs/editorjs\";\nimport {\n BlockToolConstructorOptions,\n MenuConfig,\n} from \"@editorjs/editorjs/types/tools\";\n\nimport HighlightCode from \"@init-kz/init-code-highlight-ts\";\n\ntype EditorJsCodeHighlightData = {\n code?: string;\n language?: string;\n showlinenumbers?: boolean;\n showCopyButton?: boolean;\n};\n\ntype EditorJsCodeHighlightConfig = {\n placeholder?: string;\n preserveBlank?: boolean;\n};\n\ntype EditorJsCodeHighlightOptions = BlockToolConstructorOptions<\n EditorJsCodeHighlightData,\n EditorJsCodeHighlightConfig\n>;\n\nexport default class EditorJsCodeHighlight implements BlockTool {\n sanitize?: SanitizerConfig | undefined;\n\n /**\n * Editor.js API instance\n */\n private api: API;\n\n /**\n * Stores current block data internally\n */\n private _data: EditorJsCodeHighlightData;\n\n private readOnly: boolean;\n\n private _CSS: Record<string, string> = {};\n\n private _element: HTMLElement | null = null;\n\n private editorInstance: HighlightCode | null = null;\n\n constructor({ api, data, readOnly }: EditorJsCodeHighlightOptions) {\n this.api = api;\n this._data = {\n code: data?.code || EditorJsCodeHighlight.DEFAULT_PLACEHOLDER,\n language: data?.language || \"html\",\n showlinenumbers: data?.showlinenumbers ?? true,\n showCopyButton: data?.showCopyButton ?? true,\n };\n\n this._CSS = {\n block: this.api.styles.block,\n wrapper: \"ce-EditorJsCodeHighlight\",\n settingsButton: this.api.styles.settingsButton,\n settingsButtonActive: this.api.styles.settingsButtonActive,\n };\n\n this.readOnly = readOnly;\n this.data = data;\n }\n\n /**\n * Return Tool data\n */\n private get data(): EditorJsCodeHighlightData {\n return this._data;\n }\n\n /**\n * Return Tool data\n */\n private set data(data: EditorJsCodeHighlightData) {\n this._data = data;\n }\n\n /**\n * Icon and title for displaying at the Toolbox\n *\n * @return {{icon: string, title: string}}\n */\n static get toolbox() {\n return {\n icon: icon,\n title: \"Code\",\n };\n }\n\n /**\n * Returns true to notify the core that read-only mode is supported\n *\n * @return {boolean}\n */\n static get isReadOnlySupported() {\n return true;\n }\n\n /**\n * Check if text content is empty and set empty string to inner html.\n * We need this because some browsers (e.g. Safari) insert <br> into empty contenteditanle elements\n *\n * @param {KeyboardEvent} e - key up event\n */\n protected onKeyUp(e: KeyboardEvent) {\n if (e.code !== \"Backspace\" && e.code !== \"Delete\") {\n return;\n }\n\n if (this._element) {\n const { textContent } = this._element;\n\n if (textContent === \"\") {\n this._element.innerHTML = \"\";\n }\n }\n }\n\n protected _updateEditorHeight(length: number) {\n let _height = Math.min(length, 100) * 20 + 24;\n\n if (this._element) this._element.style.height = _height + \"px\";\n }\n\n _debounce(func: Function, timeout = 500) {\n let timer: ReturnType<typeof setTimeout>;\n\n return (...args: any[]) => {\n clearTimeout(timer);\n timer = setTimeout(() => {\n func.apply(this, args);\n }, timeout);\n };\n }\n\n private _toggleLineNumbers = () => {\n this.data.showlinenumbers = !this.data.showlinenumbers;\n\n this.editorInstance?.toggleLineNumbers();\n };\n\n private _updateLanguage = (lang: string) => {\n this.data.language = lang;\n\n const langDisplay = this._element?.querySelector(\n \".editorjs-code-highlight_LangDisplay\"\n );\n\n if (langDisplay) {\n langDisplay.textContent = this.data.language;\n }\n\n this.editorInstance?.updateLanguage(this.data.language);\n };\n\n save(_: HTMLElement) {\n let resp = {\n code:\n this.editorInstance?.getCode() ||\n EditorJsCodeHighlight.DEFAULT_PLACEHOLDER,\n language: this.data.language,\n showlinenumbers: this.data.showlinenumbers,\n showCopyButton: this.data.showCopyButton,\n };\n\n return resp;\n }\n\n renderSettings(): HTMLElement | MenuConfig {\n const settingsContainer = document.createElement(\"div\");\n\n const toggleButton = document.createElement(\"div\");\n const toggleButtonInner = document.createElement(\"div\");\n toggleButton.classList.add(\"ce-popover-item\");\n toggleButtonInner.classList.add(\"ce-popover-item__title\");\n\n if (this.data.showlinenumbers) {\n toggleButtonInner.innerHTML = this.api.i18n.t(\"Hide Numbers\");\n } else {\n toggleButtonInner.innerHTML = this.api.i18n.t(\"Show Numbers\");\n }\n\n let string = `<div class=\"ce-popover-item__icon ce-popover-item__icon--tool\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 256 256\"><rect width=\"256\" height=\"256\" fill=\"none\"/><line x1=\"48\" y1=\"40\" x2=\"208\" y2=\"216\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"16\"/><path d=\"M154.91,157.6a40,40,0,0,1-53.82-59.2\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"16\"/><path d=\"M135.53,88.71a40,40,0,0,1,32.3,35.53\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"16\"/><path d=\"M208.61,169.1C230.41,149.58,240,128,240,128S208,56,128,56a126,126,0,0,0-20.68,1.68\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"16\"/><path d=\"M74,68.6C33.23,89.24,16,128,16,128s32,72,112,72a118.05,118.05,0,0,0,54-12.6\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"16\"/></svg>\n </div>`;\n toggleButton.innerHTML = string;\n\n toggleButton.appendChild(toggleButtonInner);\n\n toggleButton.addEventListener(\"click\", (e) => {\n (e.target as HTMLElement).classList.toggle(\n this._CSS.settingsButtonActive\n );\n this._toggleLineNumbers();\n if (this.data.showlinenumbers) {\n toggleButtonInner.innerHTML = this.api.i18n.t(\"Hide Numbers\");\n } else {\n toggleButtonInner.innerHTML = this.api.i18n.t(\"Show Numbers\");\n }\n });\n\n const languageEntryInputContainer = document.createElement(\"div\");\n languageEntryInputContainer.classList.add(\n \"editorjs-code-highlight_inputContainer\"\n );\n\n let languageEntryInput = document.createElement(\"div\");\n languageEntryInput.classList.add(\"editorjs-code-highlight_input\");\n languageEntryInput.setAttribute(\"contenteditable\", \"true\");\n languageEntryInput.setAttribute(\n \"data-placeholder\",\n this.api.i18n.t(\"Enter a language...\")\n );\n\n let languageEntryInputButton = document.createElement(\"div\");\n let string2 = `<div class=\"ce-popover-item__icon ce-popover-item__icon--tool\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 256 256\"><rect width=\"256\" height=\"256\" fill=\"none\"/><path d=\"M136,136a8,8,0,0,1,8,8,16,16,0,0,1-16,16,24,24,0,0,1-24-24,32,32,0,0,1,32-32,40,40,0,0,1,40,40,48,48,0,0,1-48,48,56,56,0,0,1-56-56,64,64,0,0,1,64-64,72,72,0,0,1,72,72,80,80,0,0,1-80,80,88,88,0,0,1-88-88,96,96,0,0,1,96-96A104,104,0,0,1,240,144\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"16\"/></svg>\n </div>`;\n languageEntryInputButton.innerHTML = string2;\n languageEntryInputButton.classList.add(\n \"editorjs-code-highlight_inputButton\"\n );\n languageEntryInputButton.addEventListener(\"click\", (event) => {\n let lang = languageEntryInput.textContent;\n if (lang && lang != \"\") {\n this._updateLanguage(lang);\n }\n });\n\n languageEntryInputContainer.appendChild(languageEntryInput);\n languageEntryInputContainer.appendChild(languageEntryInputButton);\n\n settingsContainer.appendChild(toggleButton);\n // settingsContainer.appendChild(languageSelectButton);\n settingsContainer.appendChild(languageEntryInputContainer);\n\n return settingsContainer;\n }\n\n render(): HTMLElement | Promise<HTMLElement> {\n this._element = document.createElement(\"div\");\n this._element.classList.add(\"editorjs-code-highlight_Wrapper\");\n let editorElem = document.createElement(\"div\");\n editorElem.classList.add(\"editorjs-code-highlight_Editor\");\n let langdisplay = document.createElement(\"div\");\n langdisplay.classList.add(\"editorjs-code-highlight_LangDisplay\");\n\n langdisplay.innerHTML = this.data.language || \"html\";\n\n this._element.appendChild(editorElem);\n this._element.appendChild(langdisplay);\n\n this.editorInstance = new HighlightCode(editorElem, {\n language: this.data.language,\n lineNumbers: this.data.showlinenumbers,\n readonly: this.readOnly,\n copyButton: this.data.showCopyButton,\n });\n\n this.editorInstance.onUpdate((code) => {\n let _length = code.split(\"\\n\").length;\n this._updateEditorHeight(_length);\n // this._debounce(() => this._updateEditorHeight(_length));\n });\n\n this.editorInstance.updateCode(\n this.data.code || EditorJsCodeHighlight.DEFAULT_PLACEHOLDER\n );\n\n return this._element;\n }\n\n static get DEFAULT_PLACEHOLDER() {\n return \"// Hello\";\n }\n\n static get enableLineBreaks() {\n return true;\n }\n}\n","export const icon = `\n<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" style=\"width: 16px !important; height: 16px !important\" x=\"0\" y=\"0\" viewBox=\"0 0 24 24\" style=\"enable-background:new 0 0 512 512\" xml:space=\"preserve\" class=\"\"><g><path d=\"M1.5 12a.5.5 0 0 1 .5-.5A2.503 2.503 0 0 0 4.5 9V6A2.503 2.503 0 0 1 7 3.5h2a.5.5 0 0 1 0 1H7A1.502 1.502 0 0 0 5.5 6v3a3.5 3.5 0 0 1-1.7 3 3.5 3.5 0 0 1 1.7 3v3A1.502 1.502 0 0 0 7 19.5h2a.5.5 0 0 1 0 1H7A2.503 2.503 0 0 1 4.5 18v-3A2.503 2.503 0 0 0 2 12.5a.5.5 0 0 1-.5-.5zm20.5-.5A2.503 2.503 0 0 1 19.5 9V6A2.503 2.503 0 0 0 17 3.5h-2a.5.5 0 0 0 0 1h2A1.502 1.502 0 0 1 18.5 6v3a3.5 3.5 0 0 0 1.7 3 3.5 3.5 0 0 0-1.7 3v3a1.502 1.502 0 0 1-1.5 1.5h-2a.5.5 0 0 0 0 1h2a2.503 2.503 0 0 0 2.5-2.5v-3a2.503 2.503 0 0 1 2.5-2.5.5.5 0 0 0 0-1z\" fill=\"#000000\" opacity=\"1\" data-original=\"#000000\"></path></g></svg>\n`;\n"],"mappings":"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","names":["HighlightCode"]}