diff --git a/packages/vue-prism-editor/dist/Editor.d.ts b/packages/vue-prism-editor/dist/Editor.d.ts index 5214ba3..d0a4cef 100644 --- a/packages/vue-prism-editor/dist/Editor.d.ts +++ b/packages/vue-prism-editor/dist/Editor.d.ts @@ -22,12 +22,22 @@ export interface History { }>; offset: number; } +interface AutocompleteEntry { + text: string; + overlap: number; + label?: string; +} export declare const PrismEditor: import("vue/types/vue").ExtendedVue; +export {}; diff --git a/packages/vue-prism-editor/dist/prismeditor.cjs.development.js b/packages/vue-prism-editor/dist/prismeditor.cjs.development.js index b209c90..101ed01 100644 --- a/packages/vue-prism-editor/dist/prismeditor.cjs.development.js +++ b/packages/vue-prism-editor/dist/prismeditor.cjs.development.js @@ -79,6 +79,12 @@ var PrismEditor = /*#__PURE__*/Vue.extend({ placeholder: { type: String, "default": '' + }, + autocomplete: { + type: Function, + "default": function _default() { + return []; + } } }, data: function data() { @@ -89,7 +95,10 @@ var PrismEditor = /*#__PURE__*/Vue.extend({ offset: -1 }, lineNumbersHeight: '20px', - codeData: '' + codeData: '', + autocompleteOpen: false, + autocompleteIndex: 0, + autocompleteData: [] }; }, watch: { @@ -123,6 +132,17 @@ var PrismEditor = /*#__PURE__*/Vue.extend({ _this2.setLineNumbersHeight(); }); + }, + autocompleteIndex: function autocompleteIndex() { + var _this3 = this; + + Vue.nextTick(function () { + var node = _this3.$el.querySelector('ul.prism-editor__autocomplete > li.selected'); + + if (node) node.scrollIntoView({ + block: 'nearest' + }); + }); } }, computed: { @@ -137,6 +157,16 @@ var PrismEditor = /*#__PURE__*/Vue.extend({ lineNumbersCount: function lineNumbersCount() { var totalLines = this.codeData.split(/\r\n|\n/).length; return totalLines; + }, + cursorOffset: function cursorOffset() { + var text = this.codeData; + var input = this.$refs.textarea; + var wrapper = this.$refs.wrapper; + var lines = text.substring(0, input.selectionEnd || 0).split(/\r\n|\n/); + var font_size = parseFloat(getComputedStyle(input).getPropertyValue('font-size')); + var line = lines.length; + var column = lines[lines.length - 1].length; + return [Math.min(column * 8.85 * (font_size / 16) - wrapper.scrollLeft, wrapper.clientWidth - Math.min(240, wrapper.clientWidth)), line * 24.0 * (font_size / 16) + 2 - wrapper.scrollTop]; } }, mounted: function mounted() { @@ -145,6 +175,53 @@ var PrismEditor = /*#__PURE__*/Vue.extend({ this.styleLineNumbers(); }, methods: { + updateAutocompleteData: function updateAutocompleteData() { + var _this$autocompleteDat; + + var input = this.$refs.textarea; + var data = typeof this.autocomplete == 'function' ? this.autocomplete(this.codeData, input.selectionEnd) : []; + var old_length = this.autocompleteData.length; + + (_this$autocompleteDat = this.autocompleteData).splice.apply(_this$autocompleteDat, [0, Infinity].concat(data)); + + this.autocompleteOpen = true; + this.autocompleteIndex = Math.max(0, Math.min(this.autocompleteIndex, this.autocompleteData.length - 1)); + if (old_length > this.autocompleteData.length) this.autocompleteIndex = 0; + }, + acceptAutocomplete: function acceptAutocomplete(event, option) { + var _this4 = this; + + event.preventDefault(); + if (option == undefined) option = this.autocompleteIndex; + var input = this.$refs.textarea; + var wrapper = this.$refs.wrapper; + var suggestion = this.autocompleteData[option] || this.autocompleteData[0]; + if (!suggestion) return; + var overlap = suggestion.overlap || 0; + var new_text = [this.codeData.substr(0, input.selectionEnd - overlap), suggestion.text, this.codeData.substring(input.selectionEnd)]; + var result = new_text.join(''); + var cursor_pos = input.selectionEnd - overlap + suggestion.text.length + (suggestion.text.endsWith(')') ? -1 : 0); + input.selectionStart = input.selectionEnd = cursor_pos; + + this._applyEdits({ + value: result, + selectionStart: cursor_pos, + selectionEnd: cursor_pos + }); + + var inserted_characters = suggestion.text.length - suggestion.overlap; + Vue.nextTick(function () { + wrapper.scrollLeft += inserted_characters * 8.85; + }); + + if (suggestion.text.endsWith('.')) { + setTimeout(function () { + _this4.updateAutocompleteData(); + }, 1); + } else { + this.autocompleteOpen = false; + } + }, setLineNumbersHeight: function setLineNumbersHeight() { this.lineNumbersHeight = getComputedStyle(this.$refs.pre).height; }, @@ -318,6 +395,8 @@ var PrismEditor = /*#__PURE__*/Vue.extend({ } }, handleKeyDown: function handleKeyDown(e) { + var _this5 = this; + // console.log(navigator.platform); var tabSize = this.tabSize, insertSpaces = this.insertSpaces, @@ -332,6 +411,36 @@ var PrismEditor = /*#__PURE__*/Vue.extend({ } } + if (e.keyCode === 9 && this.autocompleteData.length && this.autocompleteOpen) { + this.acceptAutocomplete(e); + e.preventDefault(); + e.stopPropagation(); + return; + } + + if (e.keyCode === 27) { + // Escape + if (this.autocompleteData.length && this.autocompleteOpen) { + e.preventDefault(); + this.autocompleteOpen = false; + return; + } + } else if (e.keyCode === 38) { + // Up + if (this.autocompleteData.length && this.autocompleteOpen) { + e.preventDefault(); + this.autocompleteIndex = (this.autocompleteIndex ? this.autocompleteIndex : this.autocompleteData.length) - 1; + return; + } + } else if (e.keyCode === 40) { + // Down + if (this.autocompleteData.length && this.autocompleteOpen) { + e.preventDefault(); + this.autocompleteIndex = (this.autocompleteIndex + 1) % this.autocompleteData.length; + return; + } + } + if (e.keyCode === KEYCODE_ESCAPE) { e.target.blur(); this.$emit('blur', e); @@ -427,8 +536,9 @@ var PrismEditor = /*#__PURE__*/Vue.extend({ }); } } else if (e.keyCode === KEYCODE_ENTER) { - // Ignore selections - if (selectionStart === selectionEnd) { + if (this.autocompleteData.length && this.autocompleteOpen) { + this.acceptAutocomplete(e); + } else if (selectionStart === selectionEnd) { // Get the current line var line = this._getLines(value, selectionStart).pop(); @@ -480,10 +590,16 @@ var PrismEditor = /*#__PURE__*/Vue.extend({ this.capture = !this.capture; } + + if (e.keyCode !== 13 && e.keyCode !== 9) { + setTimeout(function () { + _this5.updateAutocompleteData(); + }, 1); + } } }, render: function render(h) { - var _this3 = this; + var _this6 = this; var lineNumberWidthCalculator = h('div', { attrs: { @@ -506,24 +622,47 @@ var PrismEditor = /*#__PURE__*/Vue.extend({ } }, "" + ++index); })]); + var autocompleteList = this.autocompleteOpen && this.autocompleteData.length ? h('ul', { + staticClass: 'prism-editor__autocomplete', + style: { + left: this.cursorOffset[0] + 'px', + top: this.cursorOffset[1] + 'px' + } + }, this.autocompleteData.map(function (data, i) { + return h('li', { + key: data.text, + "class": { + selected: i == _this6.autocompleteIndex + }, + on: { + mousedown: function mousedown($event) { + _this6.acceptAutocomplete($event, i); + } + } + }, [data.label || data.text]); + })) : undefined; var textarea = h('textarea', { ref: 'textarea', on: { input: this.handleChange, keydown: this.handleKeyDown, click: function click($event) { - _this3.$emit('click', $event); + _this6.autocompleteOpen = false; + + _this6.$emit('click', $event); }, keyup: function keyup($event) { - _this3.$emit('keyup', $event); + _this6.$emit('keyup', $event); }, focus: function focus($event) { - _this3._recordStateIfChange(); + _this6._recordStateIfChange(); - _this3.$emit('focus', $event); + _this6.$emit('focus', $event); }, blur: function blur($event) { - _this3.$emit('blur', $event); + _this6.autocompleteOpen = false; + + _this6.$emit('blur', $event); } }, staticClass: 'prism-editor__textarea', @@ -557,9 +696,13 @@ var PrismEditor = /*#__PURE__*/Vue.extend({ var editorContainer = h('div', { staticClass: 'prism-editor__container' }, [textarea, preview]); - return h('div', { - staticClass: 'prism-editor-wrapper' + var wrapper = h('div', { + staticClass: 'prism-editor-wrapper', + ref: 'wrapper' }, [this.lineNumbers && lineNumbers, editorContainer]); + return h('div', { + staticClass: 'prism-editor-component' + }, [wrapper, autocompleteList]); } }); diff --git a/packages/vue-prism-editor/dist/prismeditor.cjs.development.js.map b/packages/vue-prism-editor/dist/prismeditor.cjs.development.js.map index f4cda03..b5c0a31 100644 --- a/packages/vue-prism-editor/dist/prismeditor.cjs.development.js.map +++ b/packages/vue-prism-editor/dist/prismeditor.cjs.development.js.map @@ -1 +1 @@ -{"version":3,"file":"prismeditor.cjs.development.js","sources":["../src/Editor.ts"],"sourcesContent":["import Vue, { VNode } from 'vue';\r\n\r\nimport './styles.css';\r\nconst KEYCODE_ENTER = 13;\r\nconst KEYCODE_TAB = 9;\r\nconst KEYCODE_BACKSPACE = 8;\r\nconst KEYCODE_Y = 89;\r\nconst KEYCODE_Z = 90;\r\nconst KEYCODE_M = 77;\r\nconst KEYCODE_ESCAPE = 27;\r\n\r\nconst BRACKET_PAIRS: {[opening: string]: string} = {\r\n '(':')',\r\n '{':'}',\r\n '[':']',\r\n '\"':'\"',\r\n \"'\":\"'\",\r\n};\r\n\r\nconst HISTORY_LIMIT = 100;\r\nconst HISTORY_TIME_GAP = 3000;\r\n\r\nconst isWindows = 'navigator' in global && /Win/i.test(navigator.platform);\r\nconst isMacLike = 'navigator' in global && /(Mac|iPhone|iPod|iPad)/i.test(navigator.platform);\r\n\r\nexport interface EditorProps {\r\n lineNumbers: boolean;\r\n autoStyleLineNumbers: boolean;\r\n readonly: boolean;\r\n value: string;\r\n highlight: () => string;\r\n tabSize: number;\r\n insertSpaces: boolean;\r\n ignoreTabKey: boolean;\r\n placeholder: string;\r\n}\r\nexport interface Record {\r\n value: string;\r\n selectionStart: number;\r\n selectionEnd: number;\r\n}\r\n\r\nexport interface History {\r\n stack: Array;\r\n offset: number;\r\n}\r\n\r\nexport const PrismEditor = Vue.extend({\r\n props: {\r\n lineNumbers: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n autoStyleLineNumbers: {\r\n type: Boolean,\r\n default: true,\r\n },\r\n readonly: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n value: {\r\n type: String,\r\n default: '',\r\n },\r\n highlight: {\r\n type: Function,\r\n required: true,\r\n },\r\n tabSize: {\r\n type: Number,\r\n default: 2,\r\n },\r\n insertSpaces: {\r\n type: Boolean,\r\n default: true,\r\n },\r\n ignoreTabKey: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n placeholder: {\r\n type: String,\r\n default: '',\r\n },\r\n },\r\n data() {\r\n return {\r\n capture: true,\r\n history: {\r\n stack: [],\r\n offset: -1,\r\n } as History,\r\n lineNumbersHeight: '20px',\r\n codeData: '',\r\n };\r\n },\r\n watch: {\r\n value: {\r\n immediate: true,\r\n handler(newVal: string): void {\r\n if (!newVal) {\r\n this.codeData = '';\r\n } else {\r\n this.codeData = newVal;\r\n }\r\n },\r\n },\r\n content: {\r\n immediate: true,\r\n handler(): void {\r\n if (this.lineNumbers) {\r\n this.$nextTick(() => {\r\n this.setLineNumbersHeight();\r\n });\r\n }\r\n },\r\n },\r\n lineNumbers(): void {\r\n this.$nextTick(() => {\r\n this.styleLineNumbers();\r\n this.setLineNumbersHeight();\r\n });\r\n },\r\n },\r\n computed: {\r\n isEmpty(): boolean {\r\n return this.codeData.length === 0;\r\n },\r\n content(): string {\r\n const result = this.highlight(this.codeData) + '
';\r\n // todo: VNode support?\r\n return result;\r\n },\r\n lineNumbersCount(): number {\r\n const totalLines = this.codeData.split(/\\r\\n|\\n/).length;\r\n return totalLines;\r\n },\r\n },\r\n mounted() {\r\n this._recordCurrentState();\r\n this.styleLineNumbers();\r\n },\r\n\r\n methods: {\r\n setLineNumbersHeight(): void {\r\n this.lineNumbersHeight = getComputedStyle(this.$refs.pre as HTMLTextAreaElement).height;\r\n },\r\n styleLineNumbers(): void {\r\n if (!this.lineNumbers || !this.autoStyleLineNumbers) return;\r\n\r\n const $editor = this.$refs.pre as HTMLTextAreaElement;\r\n const $lineNumbers: HTMLDivElement | null = this.$el.querySelector('.prism-editor__line-numbers');\r\n const editorStyles = window.getComputedStyle($editor);\r\n\r\n this.$nextTick(() => {\r\n const btlr: any = 'border-top-left-radius';\r\n const bblr: any = 'border-bottom-left-radius';\r\n if (!$lineNumbers) return;\r\n $lineNumbers.style[btlr] = editorStyles[btlr];\r\n $lineNumbers.style[bblr] = editorStyles[bblr];\r\n $editor.style[btlr] = '0';\r\n $editor.style[bblr] = '0';\r\n\r\n const stylesList = ['background-color', 'margin-top', 'padding-top', 'font-family', 'font-size', 'line-height'];\r\n stylesList.forEach((style: any) => {\r\n $lineNumbers.style[style] = editorStyles[style];\r\n });\r\n $lineNumbers.style['margin-bottom' as any] = '-' + editorStyles['padding-top' as any];\r\n });\r\n },\r\n _recordCurrentState(): void {\r\n const input = this.$refs.textarea as HTMLTextAreaElement;\r\n\r\n if (!input) return;\r\n // Save current state of the input\r\n const { value, selectionStart, selectionEnd } = input;\r\n\r\n this._recordChange({\r\n value,\r\n selectionStart,\r\n selectionEnd,\r\n });\r\n },\r\n _getLines(text: string, position: number): Array {\r\n return text.substring(0, position).split('\\n');\r\n },\r\n _recordStateIfChange(): void {\r\n if (this.history.stack[this.history.offset].value != this.codeData) {\r\n this._recordChange({\r\n value: this.codeData,\r\n selectionStart: this.codeData.length,\r\n selectionEnd: this.codeData.length,\r\n });\r\n }\r\n },\r\n _applyEdits(record: Record): void {\r\n // Save last selection state\r\n const input = this.$refs.textarea as HTMLTextAreaElement;\r\n const last = this.history.stack[this.history.offset];\r\n\r\n if (last && input) {\r\n this.history.stack[this.history.offset] = {\r\n ...last,\r\n selectionStart: input.selectionStart,\r\n selectionEnd: input.selectionEnd,\r\n };\r\n }\r\n\r\n // Save the changes\r\n this._recordChange(record);\r\n this._updateInput(record);\r\n },\r\n _recordChange(record: Record, overwrite = false): void {\r\n const { stack, offset } = this.history;\r\n\r\n if (stack.length && offset > -1) {\r\n // When something updates, drop the redo operations\r\n this.history.stack = stack.slice(0, offset + 1);\r\n\r\n // Limit the number of operations to 100\r\n const count = this.history.stack.length;\r\n\r\n if (count > HISTORY_LIMIT) {\r\n const extras = count - HISTORY_LIMIT;\r\n\r\n this.history.stack = stack.slice(extras, count);\r\n this.history.offset = Math.max(this.history.offset - extras, 0);\r\n }\r\n }\r\n\r\n const timestamp = Date.now();\r\n\r\n if (overwrite) {\r\n const last = this.history.stack[this.history.offset];\r\n\r\n if (last && timestamp - last.timestamp < HISTORY_TIME_GAP) {\r\n // A previous entry exists and was in short interval\r\n\r\n // Match the last word in the line\r\n const re = /[^a-z0-9]([a-z0-9]+)$/i;\r\n\r\n // Get the previous line\r\n const previous = this._getLines(last.value, last.selectionStart).pop()?.match(re);\r\n\r\n // Get the current line\r\n const current = this._getLines(record.value, record.selectionStart).pop()?.match(re);\r\n\r\n if (previous && current && current[1].startsWith(previous[1])) {\r\n // The last word of the previous line and current line match\r\n // Overwrite previous entry so that undo will remove whole word\r\n this.history.stack[this.history.offset] = {\r\n ...record,\r\n timestamp,\r\n };\r\n\r\n return;\r\n }\r\n }\r\n }\r\n\r\n // Add the new operation to the stack\r\n this.history.stack.push({ ...record, timestamp });\r\n this.history.offset++;\r\n },\r\n\r\n _updateInput(record: Record): void {\r\n const input = this.$refs.textarea as HTMLTextAreaElement;\r\n\r\n if (!input) return;\r\n\r\n // Update values and selection state\r\n input.value = record.value;\r\n input.selectionStart = record.selectionStart;\r\n input.selectionEnd = record.selectionEnd;\r\n\r\n this.$emit('input', record.value);\r\n // this.props.onValueChange(record.value);\r\n },\r\n handleChange(e: KeyboardEvent): void {\r\n const { value, selectionStart, selectionEnd } = e.target as HTMLTextAreaElement;\r\n\r\n this._recordChange(\r\n {\r\n value,\r\n selectionStart,\r\n selectionEnd,\r\n },\r\n true\r\n );\r\n this.$emit('input', value);\r\n // this.props.onValueChange(value);\r\n },\r\n _undoEdit(): void {\r\n const { stack, offset } = this.history;\r\n\r\n // Get the previous edit\r\n const record = stack[offset - 1];\r\n\r\n if (record) {\r\n // Apply the changes and update the offset\r\n this._updateInput(record);\r\n this.history.offset = Math.max(offset - 1, 0);\r\n }\r\n },\r\n _redoEdit(): void {\r\n const { stack, offset } = this.history;\r\n\r\n // Get the next edit\r\n const record = stack[offset + 1];\r\n\r\n if (record) {\r\n // Apply the changes and update the offset\r\n this._updateInput(record);\r\n this.history.offset = Math.min(offset + 1, stack.length - 1);\r\n }\r\n },\r\n handleKeyDown(e: KeyboardEvent): void {\r\n // console.log(navigator.platform);\r\n const { tabSize, insertSpaces, ignoreTabKey } = this;\r\n\r\n if (this.$listeners.keydown) {\r\n // onKeyDown(e);\r\n this.$emit('keydown', e);\r\n\r\n if (e.defaultPrevented) {\r\n return;\r\n }\r\n }\r\n\r\n if (e.keyCode === KEYCODE_ESCAPE) {\r\n (e.target).blur();\r\n this.$emit('blur', e);\r\n }\r\n\r\n const { value, selectionStart, selectionEnd } = e.target as HTMLTextAreaElement;\r\n\r\n const tabCharacter = (insertSpaces ? ' ' : '\\t').repeat(tabSize);\r\n\r\n if (e.keyCode === KEYCODE_TAB && !ignoreTabKey && this.capture) {\r\n // Prevent focus change\r\n e.preventDefault();\r\n\r\n if (e.shiftKey) {\r\n // Unindent selected lines\r\n const linesBeforeCaret = this._getLines(value, selectionStart);\r\n const startLine = linesBeforeCaret.length - 1;\r\n const endLine = this._getLines(value, selectionEnd).length - 1;\r\n const nextValue = value\r\n .split('\\n')\r\n .map((line, i) => {\r\n if (i >= startLine && i <= endLine && line.startsWith(tabCharacter)) {\r\n return line.substring(tabCharacter.length);\r\n }\r\n\r\n return line;\r\n })\r\n .join('\\n');\r\n\r\n if (value !== nextValue) {\r\n const startLineText = linesBeforeCaret[startLine];\r\n\r\n this._applyEdits({\r\n value: nextValue,\r\n // Move the start cursor if first line in selection was modified\r\n // It was modified only if it started with a tab\r\n selectionStart: startLineText.startsWith(tabCharacter)\r\n ? selectionStart - tabCharacter.length\r\n : selectionStart,\r\n // Move the end cursor by total number of characters removed\r\n selectionEnd: selectionEnd - (value.length - nextValue.length),\r\n });\r\n }\r\n } else if (selectionStart !== selectionEnd) {\r\n // Indent selected lines\r\n const linesBeforeCaret = this._getLines(value, selectionStart);\r\n const startLine = linesBeforeCaret.length - 1;\r\n const endLine = this._getLines(value, selectionEnd).length - 1;\r\n const startLineText = linesBeforeCaret[startLine];\r\n\r\n this._applyEdits({\r\n value: value\r\n .split('\\n')\r\n .map((line, i) => {\r\n if (i >= startLine && i <= endLine) {\r\n return tabCharacter + line;\r\n }\r\n\r\n return line;\r\n })\r\n .join('\\n'),\r\n // Move the start cursor by number of characters added in first line of selection\r\n // Don't move it if it there was no text before cursor\r\n selectionStart: /\\S/.test(startLineText) ? selectionStart + tabCharacter.length : selectionStart,\r\n // Move the end cursor by total number of characters added\r\n selectionEnd: selectionEnd + tabCharacter.length * (endLine - startLine + 1),\r\n });\r\n } else {\r\n const updatedSelection = selectionStart + tabCharacter.length;\r\n\r\n this._applyEdits({\r\n // Insert tab character at caret\r\n value: value.substring(0, selectionStart) + tabCharacter + value.substring(selectionEnd),\r\n // Update caret position\r\n selectionStart: updatedSelection,\r\n selectionEnd: updatedSelection,\r\n });\r\n }\r\n } else if (e.keyCode === KEYCODE_BACKSPACE) {\r\n const hasSelection = selectionStart !== selectionEnd;\r\n const textBeforeCaret = value.substring(0, selectionStart);\r\n\r\n if (textBeforeCaret.endsWith(tabCharacter) && !hasSelection) {\r\n // Prevent default delete behaviour\r\n e.preventDefault();\r\n\r\n const updatedSelection = selectionStart - tabCharacter.length;\r\n\r\n this._applyEdits({\r\n // Remove tab character at caret\r\n value: value.substring(0, selectionStart - tabCharacter.length) + value.substring(selectionEnd),\r\n // Update caret position\r\n selectionStart: updatedSelection,\r\n selectionEnd: updatedSelection,\r\n });\r\n }\r\n } else if (e.keyCode === KEYCODE_ENTER) {\r\n // Ignore selections\r\n if (selectionStart === selectionEnd) {\r\n // Get the current line\r\n const line = this._getLines(value, selectionStart).pop();\r\n const matches = line?.match(/^\\s+/);\r\n\r\n if (matches && matches[0]) {\r\n e.preventDefault();\r\n\r\n // Preserve indentation on inserting a new line\r\n const indent = '\\n' + matches[0];\r\n const updatedSelection = selectionStart + indent.length;\r\n\r\n this._applyEdits({\r\n // Insert indentation character at caret\r\n value: value.substring(0, selectionStart) + indent + value.substring(selectionEnd),\r\n // Update caret position\r\n selectionStart: updatedSelection,\r\n selectionEnd: updatedSelection,\r\n });\r\n }\r\n }\r\n } else if (BRACKET_PAIRS[e.key]) {\r\n // If text is selected, wrap them in the characters\r\n if (selectionStart !== selectionEnd) {\r\n e.preventDefault();\r\n\r\n this._applyEdits({\r\n value:\r\n value.substring(0, selectionStart) +\r\n e.key +\r\n value.substring(selectionStart, selectionEnd) +\r\n BRACKET_PAIRS[e.key] +\r\n value.substring(selectionEnd),\r\n // Update caret position\r\n selectionStart: selectionStart + 1,\r\n selectionEnd: selectionEnd + 1,\r\n });\r\n }\r\n } else if (\r\n (isMacLike\r\n ? // Trigger undo with ⌘+Z on Mac\r\n e.metaKey && e.keyCode === KEYCODE_Z\r\n : // Trigger undo with Ctrl+Z on other platforms\r\n e.ctrlKey && e.keyCode === KEYCODE_Z) &&\r\n !e.shiftKey &&\r\n !e.altKey\r\n ) {\r\n e.preventDefault();\r\n\r\n this._undoEdit();\r\n } else if (\r\n (isMacLike\r\n ? // Trigger redo with ⌘+Shift+Z on Mac\r\n e.metaKey && e.keyCode === KEYCODE_Z && e.shiftKey\r\n : isWindows\r\n ? // Trigger redo with Ctrl+Y on Windows\r\n e.ctrlKey && e.keyCode === KEYCODE_Y\r\n : // Trigger redo with Ctrl+Shift+Z on other platforms\r\n e.ctrlKey && e.keyCode === KEYCODE_Z && e.shiftKey) &&\r\n !e.altKey\r\n ) {\r\n e.preventDefault();\r\n\r\n this._redoEdit();\r\n } else if (e.keyCode === KEYCODE_M && e.ctrlKey && (isMacLike ? e.shiftKey : true)) {\r\n e.preventDefault();\r\n\r\n // Toggle capturing tab key so users can focus away\r\n this.capture = !this.capture;\r\n }\r\n },\r\n },\r\n render(h): VNode {\r\n const lineNumberWidthCalculator = h(\r\n 'div',\r\n {\r\n attrs: {\r\n class: 'prism-editor__line-width-calc',\r\n style: 'height: 0px; visibility: hidden; pointer-events: none;',\r\n },\r\n },\r\n '999'\r\n );\r\n const lineNumbers = h(\r\n 'div',\r\n {\r\n staticClass: 'prism-editor__line-numbers',\r\n style: {\r\n 'min-height': this.lineNumbersHeight,\r\n },\r\n attrs: {\r\n 'aria-hidden': 'true',\r\n },\r\n },\r\n [\r\n lineNumberWidthCalculator,\r\n Array.from(Array(this.lineNumbersCount).keys()).map((_, index) => {\r\n return h('div', { attrs: { class: 'prism-editor__line-number token comment' } }, `${++index}`);\r\n }),\r\n ]\r\n );\r\n\r\n const textarea = h('textarea', {\r\n ref: 'textarea',\r\n on: {\r\n input: this.handleChange,\r\n keydown: this.handleKeyDown,\r\n click: ($event: MouseEvent) => {\r\n this.$emit('click', $event);\r\n },\r\n keyup: ($event: KeyboardEvent) => {\r\n this.$emit('keyup', $event);\r\n },\r\n focus: ($event: FocusEvent) => {\r\n this._recordStateIfChange();\r\n this.$emit('focus', $event);\r\n },\r\n blur: ($event: FocusEvent) => {\r\n this.$emit('blur', $event);\r\n },\r\n },\r\n staticClass: 'prism-editor__textarea',\r\n class: {\r\n 'prism-editor__textarea--empty': this.isEmpty,\r\n },\r\n attrs: {\r\n spellCheck: 'false',\r\n autocapitalize: 'off',\r\n autocomplete: 'off',\r\n autocorrect: 'off',\r\n 'data-gramm': 'false',\r\n placeholder: this.placeholder,\r\n 'data-testid': 'textarea',\r\n readonly: this.readonly,\r\n },\r\n domProps: {\r\n value: this.codeData,\r\n },\r\n });\r\n const preview = h('pre', {\r\n ref: 'pre',\r\n staticClass: 'prism-editor__editor',\r\n attrs: {\r\n 'data-testid': 'preview',\r\n },\r\n domProps: {\r\n innerHTML: this.content,\r\n },\r\n });\r\n const editorContainer = h('div', { staticClass: 'prism-editor__container' }, [textarea, preview]);\r\n return h('div', { staticClass: 'prism-editor-wrapper' }, [this.lineNumbers && lineNumbers, editorContainer]);\r\n },\r\n});\r\n"],"names":["KEYCODE_ENTER","KEYCODE_TAB","KEYCODE_BACKSPACE","KEYCODE_Y","KEYCODE_Z","KEYCODE_M","KEYCODE_ESCAPE","BRACKET_PAIRS","HISTORY_LIMIT","HISTORY_TIME_GAP","isWindows","global","test","navigator","platform","isMacLike","PrismEditor","Vue","extend","props","lineNumbers","type","Boolean","autoStyleLineNumbers","readonly","value","String","highlight","Function","required","tabSize","Number","insertSpaces","ignoreTabKey","placeholder","data","capture","history","stack","offset","lineNumbersHeight","codeData","watch","immediate","handler","newVal","content","$nextTick","setLineNumbersHeight","styleLineNumbers","computed","isEmpty","length","result","lineNumbersCount","totalLines","split","mounted","_recordCurrentState","methods","getComputedStyle","$refs","pre","height","$editor","$lineNumbers","$el","querySelector","editorStyles","window","btlr","bblr","style","stylesList","forEach","input","textarea","selectionStart","selectionEnd","_recordChange","_getLines","text","position","substring","_recordStateIfChange","_applyEdits","record","last","_updateInput","overwrite","slice","count","extras","Math","max","timestamp","Date","now","re","previous","pop","match","current","startsWith","push","$emit","handleChange","e","target","_undoEdit","_redoEdit","min","handleKeyDown","$listeners","keydown","defaultPrevented","keyCode","blur","tabCharacter","repeat","preventDefault","shiftKey","linesBeforeCaret","startLine","endLine","nextValue","map","line","i","join","startLineText","updatedSelection","hasSelection","textBeforeCaret","endsWith","matches","indent","key","metaKey","ctrlKey","altKey","render","h","lineNumberWidthCalculator","attrs","staticClass","Array","from","keys","_","index","ref","on","click","$event","keyup","focus","spellCheck","autocapitalize","autocomplete","autocorrect","domProps","preview","innerHTML","editorContainer"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"prismeditor.cjs.development.js","sources":["../src/Editor.ts"],"sourcesContent":["import Vue, { VNode } from 'vue';\r\n\r\nimport './styles.css';\r\nconst KEYCODE_ENTER = 13;\r\nconst KEYCODE_TAB = 9;\r\nconst KEYCODE_BACKSPACE = 8;\r\nconst KEYCODE_Y = 89;\r\nconst KEYCODE_Z = 90;\r\nconst KEYCODE_M = 77;\r\nconst KEYCODE_ESCAPE = 27;\r\n\r\nconst BRACKET_PAIRS: {[opening: string]: string} = {\r\n '(':')',\r\n '{':'}',\r\n '[':']',\r\n '\"':'\"',\r\n \"'\":\"'\",\r\n};\r\n\r\nconst HISTORY_LIMIT = 100;\r\nconst HISTORY_TIME_GAP = 3000;\r\n\r\nconst isWindows = 'navigator' in global && /Win/i.test(navigator.platform);\r\nconst isMacLike = 'navigator' in global && /(Mac|iPhone|iPod|iPad)/i.test(navigator.platform);\r\n\r\nexport interface EditorProps {\r\n lineNumbers: boolean;\r\n autoStyleLineNumbers: boolean;\r\n readonly: boolean;\r\n value: string;\r\n highlight: () => string;\r\n tabSize: number;\r\n insertSpaces: boolean;\r\n ignoreTabKey: boolean;\r\n placeholder: string;\r\n}\r\nexport interface Record {\r\n value: string;\r\n selectionStart: number;\r\n selectionEnd: number;\r\n}\r\n\r\nexport interface History {\r\n stack: Array;\r\n offset: number;\r\n}\r\ninterface AutocompleteEntry {\r\n text: string\r\n overlap: number\r\n label?: string\r\n}\r\n\r\nexport const PrismEditor = Vue.extend({\r\n props: {\r\n lineNumbers: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n autoStyleLineNumbers: {\r\n type: Boolean,\r\n default: true,\r\n },\r\n readonly: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n value: {\r\n type: String,\r\n default: '',\r\n },\r\n highlight: {\r\n type: Function,\r\n required: true,\r\n },\r\n tabSize: {\r\n type: Number,\r\n default: 2,\r\n },\r\n insertSpaces: {\r\n type: Boolean,\r\n default: true,\r\n },\r\n ignoreTabKey: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n placeholder: {\r\n type: String,\r\n default: '',\r\n },\r\n autocomplete: {\r\n type: Function,\r\n default() {\r\n return []\r\n }\r\n }\r\n },\r\n data() {\r\n return {\r\n capture: true,\r\n history: {\r\n stack: [],\r\n offset: -1,\r\n } as History,\r\n lineNumbersHeight: '20px',\r\n codeData: '',\r\n\r\n autocompleteOpen: false,\r\n autocompleteIndex: 0,\r\n autocompleteData: [] as AutocompleteEntry[]\r\n };\r\n },\r\n watch: {\r\n value: {\r\n immediate: true,\r\n handler(newVal: string): void {\r\n if (!newVal) {\r\n this.codeData = '';\r\n } else {\r\n this.codeData = newVal;\r\n }\r\n },\r\n },\r\n content: {\r\n immediate: true,\r\n handler(): void {\r\n if (this.lineNumbers) {\r\n this.$nextTick(() => {\r\n this.setLineNumbersHeight();\r\n });\r\n }\r\n },\r\n },\r\n lineNumbers(): void {\r\n this.$nextTick(() => {\r\n this.styleLineNumbers();\r\n this.setLineNumbersHeight();\r\n });\r\n },\r\n autocompleteIndex() {\r\n Vue.nextTick(() => {\r\n let node = this.$el.querySelector('ul.prism-editor__autocomplete > li.selected');\r\n if (node) node.scrollIntoView({block: 'nearest'});\r\n })\r\n },\r\n },\r\n computed: {\r\n isEmpty(): boolean {\r\n return this.codeData.length === 0;\r\n },\r\n content(): string {\r\n const result = this.highlight(this.codeData) + '
';\r\n // todo: VNode support?\r\n return result;\r\n },\r\n lineNumbersCount(): number {\r\n const totalLines = this.codeData.split(/\\r\\n|\\n/).length;\r\n return totalLines;\r\n },\r\n cursorOffset() {\r\n let text: string = this.codeData;\r\n let input = this.$refs.textarea as HTMLTextAreaElement;\r\n let wrapper = this.$refs.wrapper as HTMLDivElement;\r\n let lines = text.substring(0, input.selectionEnd || 0).split(/\\r\\n|\\n/);\r\n let font_size = parseFloat(getComputedStyle(input).getPropertyValue('font-size'));\r\n let line = lines.length;\r\n let column = lines[lines.length-1].length;\r\n return [\r\n Math.min((column * 8.85 * (font_size / 16)) - wrapper.scrollLeft, wrapper.clientWidth - Math.min(240, wrapper.clientWidth)),\r\n (line * 24.0 * (font_size / 16)) + 2 - wrapper.scrollTop,\r\n ]\r\n },\r\n },\r\n mounted() {\r\n this._recordCurrentState();\r\n this.styleLineNumbers();\r\n },\r\n\r\n methods: {\r\n updateAutocompleteData() {\r\n let input = this.$refs.textarea as HTMLTextAreaElement;\r\n let data: AutocompleteEntry[] = typeof this.autocomplete == 'function' ? this.autocomplete(this.codeData, input.selectionEnd) : [];\r\n let old_length = this.autocompleteData.length;\r\n this.autocompleteData.splice(0, Infinity, ...data);\r\n this.autocompleteOpen = true;\r\n this.autocompleteIndex = Math.max(0, Math.min(this.autocompleteIndex, this.autocompleteData.length-1));\r\n if (old_length > this.autocompleteData.length) this.autocompleteIndex = 0;\r\n },\r\n acceptAutocomplete(event: Event, option?: number) {\r\n event.preventDefault()\r\n if (option == undefined) option = this.autocompleteIndex;\r\n\r\n let input = this.$refs.textarea as HTMLTextAreaElement;\r\n let wrapper = this.$refs.wrapper as HTMLDivElement;\r\n let suggestion = this.autocompleteData[option] || this.autocompleteData[0];\r\n if (!suggestion) return;\r\n \r\n let overlap = suggestion.overlap || 0;\r\n let new_text = [\r\n this.codeData.substr(0, input.selectionEnd - overlap),\r\n suggestion.text,\r\n this.codeData.substring(input.selectionEnd),\r\n ]\r\n let result: string = new_text.join('');\r\n let cursor_pos = input.selectionEnd - overlap + suggestion.text.length + (suggestion.text.endsWith(')') ? -1 : 0);\r\n input.selectionStart = input.selectionEnd = cursor_pos;\r\n\r\n this._applyEdits({\r\n value: result,\r\n selectionStart: cursor_pos,\r\n selectionEnd: cursor_pos,\r\n });\r\n let inserted_characters = suggestion.text.length - suggestion.overlap;\r\n Vue.nextTick(() => {\r\n wrapper.scrollLeft += inserted_characters * 8.85;\r\n })\r\n\r\n if (suggestion.text.endsWith('.')) {\r\n setTimeout(() => {\r\n this.updateAutocompleteData();\r\n }, 1);\r\n } else {\r\n this.autocompleteOpen = false;\r\n }\r\n },\r\n setLineNumbersHeight(): void {\r\n this.lineNumbersHeight = getComputedStyle(this.$refs.pre as HTMLTextAreaElement).height;\r\n },\r\n styleLineNumbers(): void {\r\n if (!this.lineNumbers || !this.autoStyleLineNumbers) return;\r\n\r\n const $editor = this.$refs.pre as HTMLTextAreaElement;\r\n const $lineNumbers: HTMLDivElement | null = this.$el.querySelector('.prism-editor__line-numbers');\r\n const editorStyles = window.getComputedStyle($editor);\r\n\r\n this.$nextTick(() => {\r\n const btlr: any = 'border-top-left-radius';\r\n const bblr: any = 'border-bottom-left-radius';\r\n if (!$lineNumbers) return;\r\n $lineNumbers.style[btlr] = editorStyles[btlr];\r\n $lineNumbers.style[bblr] = editorStyles[bblr];\r\n $editor.style[btlr] = '0';\r\n $editor.style[bblr] = '0';\r\n\r\n const stylesList = ['background-color', 'margin-top', 'padding-top', 'font-family', 'font-size', 'line-height'];\r\n stylesList.forEach((style: any) => {\r\n $lineNumbers.style[style] = editorStyles[style];\r\n });\r\n $lineNumbers.style['margin-bottom' as any] = '-' + editorStyles['padding-top' as any];\r\n });\r\n },\r\n _recordCurrentState(): void {\r\n const input = this.$refs.textarea as HTMLTextAreaElement;\r\n\r\n if (!input) return;\r\n // Save current state of the input\r\n const { value, selectionStart, selectionEnd } = input;\r\n\r\n this._recordChange({\r\n value,\r\n selectionStart,\r\n selectionEnd,\r\n });\r\n },\r\n _getLines(text: string, position: number): Array {\r\n return text.substring(0, position).split('\\n');\r\n },\r\n _recordStateIfChange(): void {\r\n if (this.history.stack[this.history.offset].value != this.codeData) {\r\n this._recordChange({\r\n value: this.codeData,\r\n selectionStart: this.codeData.length,\r\n selectionEnd: this.codeData.length,\r\n });\r\n }\r\n },\r\n _applyEdits(record: Record): void {\r\n // Save last selection state\r\n const input = this.$refs.textarea as HTMLTextAreaElement;\r\n const last = this.history.stack[this.history.offset];\r\n\r\n if (last && input) {\r\n this.history.stack[this.history.offset] = {\r\n ...last,\r\n selectionStart: input.selectionStart,\r\n selectionEnd: input.selectionEnd,\r\n };\r\n }\r\n\r\n // Save the changes\r\n this._recordChange(record);\r\n this._updateInput(record);\r\n },\r\n _recordChange(record: Record, overwrite = false): void {\r\n const { stack, offset } = this.history;\r\n\r\n if (stack.length && offset > -1) {\r\n // When something updates, drop the redo operations\r\n this.history.stack = stack.slice(0, offset + 1);\r\n\r\n // Limit the number of operations to 100\r\n const count = this.history.stack.length;\r\n\r\n if (count > HISTORY_LIMIT) {\r\n const extras = count - HISTORY_LIMIT;\r\n\r\n this.history.stack = stack.slice(extras, count);\r\n this.history.offset = Math.max(this.history.offset - extras, 0);\r\n }\r\n }\r\n\r\n const timestamp = Date.now();\r\n\r\n if (overwrite) {\r\n const last = this.history.stack[this.history.offset];\r\n\r\n if (last && timestamp - last.timestamp < HISTORY_TIME_GAP) {\r\n // A previous entry exists and was in short interval\r\n\r\n // Match the last word in the line\r\n const re = /[^a-z0-9]([a-z0-9]+)$/i;\r\n\r\n // Get the previous line\r\n const previous = this._getLines(last.value, last.selectionStart).pop()?.match(re);\r\n\r\n // Get the current line\r\n const current = this._getLines(record.value, record.selectionStart).pop()?.match(re);\r\n\r\n if (previous && current && current[1].startsWith(previous[1])) {\r\n // The last word of the previous line and current line match\r\n // Overwrite previous entry so that undo will remove whole word\r\n this.history.stack[this.history.offset] = {\r\n ...record,\r\n timestamp,\r\n };\r\n\r\n return;\r\n }\r\n }\r\n }\r\n\r\n // Add the new operation to the stack\r\n this.history.stack.push({ ...record, timestamp });\r\n this.history.offset++;\r\n },\r\n\r\n _updateInput(record: Record): void {\r\n const input = this.$refs.textarea as HTMLTextAreaElement;\r\n\r\n if (!input) return;\r\n\r\n // Update values and selection state\r\n input.value = record.value;\r\n input.selectionStart = record.selectionStart;\r\n input.selectionEnd = record.selectionEnd;\r\n\r\n this.$emit('input', record.value);\r\n // this.props.onValueChange(record.value);\r\n },\r\n handleChange(e: KeyboardEvent): void {\r\n const { value, selectionStart, selectionEnd } = e.target as HTMLTextAreaElement;\r\n\r\n this._recordChange(\r\n {\r\n value,\r\n selectionStart,\r\n selectionEnd,\r\n },\r\n true\r\n );\r\n this.$emit('input', value);\r\n // this.props.onValueChange(value);\r\n },\r\n _undoEdit(): void {\r\n const { stack, offset } = this.history;\r\n\r\n // Get the previous edit\r\n const record = stack[offset - 1];\r\n\r\n if (record) {\r\n // Apply the changes and update the offset\r\n this._updateInput(record);\r\n this.history.offset = Math.max(offset - 1, 0);\r\n }\r\n },\r\n _redoEdit(): void {\r\n const { stack, offset } = this.history;\r\n\r\n // Get the next edit\r\n const record = stack[offset + 1];\r\n\r\n if (record) {\r\n // Apply the changes and update the offset\r\n this._updateInput(record);\r\n this.history.offset = Math.min(offset + 1, stack.length - 1);\r\n }\r\n },\r\n handleKeyDown(e: KeyboardEvent): void {\r\n // console.log(navigator.platform);\r\n const { tabSize, insertSpaces, ignoreTabKey } = this;\r\n\r\n if (this.$listeners.keydown) {\r\n // onKeyDown(e);\r\n this.$emit('keydown', e);\r\n\r\n if (e.defaultPrevented) {\r\n return;\r\n }\r\n }\r\n\r\n if (e.keyCode === 9 && this.autocompleteData.length && this.autocompleteOpen) {\r\n this.acceptAutocomplete(e);\r\n e.preventDefault();\r\n e.stopPropagation();\r\n return;\r\n }\r\n if (e.keyCode === 27) {\r\n // Escape\r\n if (this.autocompleteData.length && this.autocompleteOpen) {\r\n e.preventDefault();\r\n this.autocompleteOpen = false;\r\n return;\r\n }\r\n } else if (e.keyCode === 38) {\r\n // Up\r\n if (this.autocompleteData.length && this.autocompleteOpen) {\r\n e.preventDefault();\r\n this.autocompleteIndex = (this.autocompleteIndex ? this.autocompleteIndex : this.autocompleteData.length) - 1;\r\n return;\r\n }\r\n } else if (e.keyCode === 40) {\r\n // Down\r\n if (this.autocompleteData.length && this.autocompleteOpen) {\r\n e.preventDefault();\r\n this.autocompleteIndex = (this.autocompleteIndex + 1) % this.autocompleteData.length;\r\n return;\r\n }\r\n }\r\n\r\n if (e.keyCode === KEYCODE_ESCAPE) {\r\n (e.target).blur();\r\n this.$emit('blur', e);\r\n }\r\n\r\n const { value, selectionStart, selectionEnd } = e.target as HTMLTextAreaElement;\r\n\r\n const tabCharacter = (insertSpaces ? ' ' : '\\t').repeat(tabSize);\r\n\r\n if (e.keyCode === KEYCODE_TAB && !ignoreTabKey && this.capture) {\r\n // Prevent focus change\r\n e.preventDefault();\r\n\r\n if (e.shiftKey) {\r\n // Unindent selected lines\r\n const linesBeforeCaret = this._getLines(value, selectionStart);\r\n const startLine = linesBeforeCaret.length - 1;\r\n const endLine = this._getLines(value, selectionEnd).length - 1;\r\n const nextValue = value\r\n .split('\\n')\r\n .map((line, i) => {\r\n if (i >= startLine && i <= endLine && line.startsWith(tabCharacter)) {\r\n return line.substring(tabCharacter.length);\r\n }\r\n\r\n return line;\r\n })\r\n .join('\\n');\r\n\r\n if (value !== nextValue) {\r\n const startLineText = linesBeforeCaret[startLine];\r\n\r\n this._applyEdits({\r\n value: nextValue,\r\n // Move the start cursor if first line in selection was modified\r\n // It was modified only if it started with a tab\r\n selectionStart: startLineText.startsWith(tabCharacter)\r\n ? selectionStart - tabCharacter.length\r\n : selectionStart,\r\n // Move the end cursor by total number of characters removed\r\n selectionEnd: selectionEnd - (value.length - nextValue.length),\r\n });\r\n }\r\n } else if (selectionStart !== selectionEnd) {\r\n // Indent selected lines\r\n const linesBeforeCaret = this._getLines(value, selectionStart);\r\n const startLine = linesBeforeCaret.length - 1;\r\n const endLine = this._getLines(value, selectionEnd).length - 1;\r\n const startLineText = linesBeforeCaret[startLine];\r\n\r\n this._applyEdits({\r\n value: value\r\n .split('\\n')\r\n .map((line, i) => {\r\n if (i >= startLine && i <= endLine) {\r\n return tabCharacter + line;\r\n }\r\n\r\n return line;\r\n })\r\n .join('\\n'),\r\n // Move the start cursor by number of characters added in first line of selection\r\n // Don't move it if it there was no text before cursor\r\n selectionStart: /\\S/.test(startLineText) ? selectionStart + tabCharacter.length : selectionStart,\r\n // Move the end cursor by total number of characters added\r\n selectionEnd: selectionEnd + tabCharacter.length * (endLine - startLine + 1),\r\n });\r\n } else {\r\n const updatedSelection = selectionStart + tabCharacter.length;\r\n\r\n this._applyEdits({\r\n // Insert tab character at caret\r\n value: value.substring(0, selectionStart) + tabCharacter + value.substring(selectionEnd),\r\n // Update caret position\r\n selectionStart: updatedSelection,\r\n selectionEnd: updatedSelection,\r\n });\r\n }\r\n } else if (e.keyCode === KEYCODE_BACKSPACE) {\r\n const hasSelection = selectionStart !== selectionEnd;\r\n const textBeforeCaret = value.substring(0, selectionStart);\r\n\r\n if (textBeforeCaret.endsWith(tabCharacter) && !hasSelection) {\r\n // Prevent default delete behaviour\r\n e.preventDefault();\r\n\r\n const updatedSelection = selectionStart - tabCharacter.length;\r\n\r\n this._applyEdits({\r\n // Remove tab character at caret\r\n value: value.substring(0, selectionStart - tabCharacter.length) + value.substring(selectionEnd),\r\n // Update caret position\r\n selectionStart: updatedSelection,\r\n selectionEnd: updatedSelection,\r\n });\r\n }\r\n } else if (e.keyCode === KEYCODE_ENTER) {\r\n \r\n if (this.autocompleteData.length && this.autocompleteOpen) {\r\n this.acceptAutocomplete(e);\r\n\r\n } else if (selectionStart === selectionEnd) {\r\n // Get the current line\r\n const line = this._getLines(value, selectionStart).pop();\r\n const matches = line?.match(/^\\s+/);\r\n\r\n if (matches && matches[0]) {\r\n e.preventDefault();\r\n\r\n // Preserve indentation on inserting a new line\r\n const indent = '\\n' + matches[0];\r\n const updatedSelection = selectionStart + indent.length;\r\n\r\n this._applyEdits({\r\n // Insert indentation character at caret\r\n value: value.substring(0, selectionStart) + indent + value.substring(selectionEnd),\r\n // Update caret position\r\n selectionStart: updatedSelection,\r\n selectionEnd: updatedSelection,\r\n });\r\n }\r\n }\r\n } else if (BRACKET_PAIRS[e.key]) {\r\n // If text is selected, wrap them in the characters\r\n if (selectionStart !== selectionEnd) {\r\n e.preventDefault();\r\n\r\n this._applyEdits({\r\n value:\r\n value.substring(0, selectionStart) +\r\n e.key +\r\n value.substring(selectionStart, selectionEnd) +\r\n BRACKET_PAIRS[e.key] +\r\n value.substring(selectionEnd),\r\n // Update caret position\r\n selectionStart: selectionStart + 1,\r\n selectionEnd: selectionEnd + 1,\r\n });\r\n }\r\n } else if (\r\n (isMacLike\r\n ? // Trigger undo with ⌘+Z on Mac\r\n e.metaKey && e.keyCode === KEYCODE_Z\r\n : // Trigger undo with Ctrl+Z on other platforms\r\n e.ctrlKey && e.keyCode === KEYCODE_Z) &&\r\n !e.shiftKey &&\r\n !e.altKey\r\n ) {\r\n e.preventDefault();\r\n\r\n this._undoEdit();\r\n } else if (\r\n (isMacLike\r\n ? // Trigger redo with ⌘+Shift+Z on Mac\r\n e.metaKey && e.keyCode === KEYCODE_Z && e.shiftKey\r\n : isWindows\r\n ? // Trigger redo with Ctrl+Y on Windows\r\n e.ctrlKey && e.keyCode === KEYCODE_Y\r\n : // Trigger redo with Ctrl+Shift+Z on other platforms\r\n e.ctrlKey && e.keyCode === KEYCODE_Z && e.shiftKey) &&\r\n !e.altKey\r\n ) {\r\n e.preventDefault();\r\n\r\n this._redoEdit();\r\n } else if (e.keyCode === KEYCODE_M && e.ctrlKey && (isMacLike ? e.shiftKey : true)) {\r\n e.preventDefault();\r\n\r\n // Toggle capturing tab key so users can focus away\r\n this.capture = !this.capture;\r\n }\r\n if (e.keyCode !== 13 && e.keyCode !== 9) {\r\n setTimeout(() => {\r\n this.updateAutocompleteData();\r\n }, 1);\r\n }\r\n },\r\n },\r\n render(h): VNode {\r\n const lineNumberWidthCalculator = h(\r\n 'div',\r\n {\r\n attrs: {\r\n class: 'prism-editor__line-width-calc',\r\n style: 'height: 0px; visibility: hidden; pointer-events: none;',\r\n },\r\n },\r\n '999'\r\n );\r\n const lineNumbers = h(\r\n 'div',\r\n {\r\n staticClass: 'prism-editor__line-numbers',\r\n style: {\r\n 'min-height': this.lineNumbersHeight,\r\n },\r\n attrs: {\r\n 'aria-hidden': 'true',\r\n },\r\n },\r\n [\r\n lineNumberWidthCalculator,\r\n Array.from(Array(this.lineNumbersCount).keys()).map((_, index) => {\r\n return h('div', { attrs: { class: 'prism-editor__line-number token comment' } }, `${++index}`);\r\n }),\r\n ]\r\n );\r\n\r\n const autocompleteList = (this.autocompleteOpen && this.autocompleteData.length) ? h(\r\n 'ul',\r\n {\r\n staticClass: 'prism-editor__autocomplete',\r\n style: {left: this.cursorOffset[0] + 'px', top: this.cursorOffset[1] + 'px'}\r\n },\r\n this.autocompleteData.map((data: AutocompleteEntry, i) => {\r\n return h('li', {\r\n key: data.text,\r\n class: {selected: i == this.autocompleteIndex},\r\n on: {\r\n mousedown: ($event: MouseEvent) => {\r\n this.acceptAutocomplete($event, i);\r\n }\r\n }\r\n }, [data.label || data.text]);\r\n })\r\n ) : undefined;\r\n\r\n const textarea = h('textarea', {\r\n ref: 'textarea',\r\n on: {\r\n input: this.handleChange,\r\n keydown: this.handleKeyDown,\r\n click: ($event: MouseEvent) => {\r\n this.autocompleteOpen = false;\r\n this.$emit('click', $event);\r\n },\r\n keyup: ($event: KeyboardEvent) => {\r\n this.$emit('keyup', $event);\r\n },\r\n focus: ($event: FocusEvent) => {\r\n this._recordStateIfChange();\r\n this.$emit('focus', $event);\r\n },\r\n blur: ($event: FocusEvent) => {\r\n this.autocompleteOpen = false;\r\n this.$emit('blur', $event);\r\n },\r\n },\r\n staticClass: 'prism-editor__textarea',\r\n class: {\r\n 'prism-editor__textarea--empty': this.isEmpty,\r\n },\r\n attrs: {\r\n spellCheck: 'false',\r\n autocapitalize: 'off',\r\n autocomplete: 'off',\r\n autocorrect: 'off',\r\n 'data-gramm': 'false',\r\n placeholder: this.placeholder,\r\n 'data-testid': 'textarea',\r\n readonly: this.readonly,\r\n },\r\n domProps: {\r\n value: this.codeData,\r\n },\r\n });\r\n const preview = h('pre', {\r\n ref: 'pre',\r\n staticClass: 'prism-editor__editor',\r\n attrs: {\r\n 'data-testid': 'preview',\r\n },\r\n domProps: {\r\n innerHTML: this.content,\r\n },\r\n });\r\n const editorContainer = h('div', { staticClass: 'prism-editor__container' }, [textarea, preview]);\r\n const wrapper = h('div', { staticClass: 'prism-editor-wrapper', ref: 'wrapper' }, [this.lineNumbers && lineNumbers, editorContainer]);\r\n return h('div', { staticClass: 'prism-editor-component' }, [wrapper, autocompleteList]);\r\n },\r\n});\r\n"],"names":["KEYCODE_ENTER","KEYCODE_TAB","KEYCODE_BACKSPACE","KEYCODE_Y","KEYCODE_Z","KEYCODE_M","KEYCODE_ESCAPE","BRACKET_PAIRS","HISTORY_LIMIT","HISTORY_TIME_GAP","isWindows","global","test","navigator","platform","isMacLike","PrismEditor","Vue","extend","props","lineNumbers","type","Boolean","autoStyleLineNumbers","readonly","value","String","highlight","Function","required","tabSize","Number","insertSpaces","ignoreTabKey","placeholder","autocomplete","data","capture","history","stack","offset","lineNumbersHeight","codeData","autocompleteOpen","autocompleteIndex","autocompleteData","watch","immediate","handler","newVal","content","$nextTick","setLineNumbersHeight","styleLineNumbers","nextTick","node","$el","querySelector","scrollIntoView","block","computed","isEmpty","length","result","lineNumbersCount","totalLines","split","cursorOffset","text","input","$refs","textarea","wrapper","lines","substring","selectionEnd","font_size","parseFloat","getComputedStyle","getPropertyValue","line","column","Math","min","scrollLeft","clientWidth","scrollTop","mounted","_recordCurrentState","methods","updateAutocompleteData","old_length","splice","Infinity","max","acceptAutocomplete","event","option","preventDefault","undefined","suggestion","overlap","new_text","substr","join","cursor_pos","endsWith","selectionStart","_applyEdits","inserted_characters","setTimeout","pre","height","$editor","$lineNumbers","editorStyles","window","btlr","bblr","style","stylesList","forEach","_recordChange","_getLines","position","_recordStateIfChange","record","last","_updateInput","overwrite","slice","count","extras","timestamp","Date","now","re","previous","pop","match","current","startsWith","push","$emit","handleChange","e","target","_undoEdit","_redoEdit","handleKeyDown","$listeners","keydown","defaultPrevented","keyCode","stopPropagation","blur","tabCharacter","repeat","shiftKey","linesBeforeCaret","startLine","endLine","nextValue","map","i","startLineText","updatedSelection","hasSelection","textBeforeCaret","matches","indent","key","metaKey","ctrlKey","altKey","render","h","lineNumberWidthCalculator","attrs","staticClass","Array","from","keys","_","index","autocompleteList","left","top","selected","on","mousedown","$event","label","ref","click","keyup","focus","spellCheck","autocapitalize","autocorrect","domProps","preview","innerHTML","editorContainer"],"mappings":"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"} \ No newline at end of file diff --git a/packages/vue-prism-editor/dist/prismeditor.cjs.production.min.js b/packages/vue-prism-editor/dist/prismeditor.cjs.production.min.js index cff05a4..f4e4dd6 100644 --- a/packages/vue-prism-editor/dist/prismeditor.cjs.production.min.js +++ b/packages/vue-prism-editor/dist/prismeditor.cjs.production.min.js @@ -1,2 +1,2 @@ -"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var t,e=(t=require("vue"))&&"object"==typeof t&&"default"in t?t.default:t;function i(){return(i=Object.assign||function(t){for(var e=1;e"},lineNumbersCount:function(){return this.codeData.split(/\r\n|\n/).length}},mounted:function(){this._recordCurrentState(),this.styleLineNumbers()},methods:{setLineNumbersHeight:function(){this.lineNumbersHeight=getComputedStyle(this.$refs.pre).height},styleLineNumbers:function(){if(this.lineNumbers&&this.autoStyleLineNumbers){var t=this.$refs.pre,e=this.$el.querySelector(".prism-editor__line-numbers"),i=window.getComputedStyle(t);this.$nextTick((function(){var s="border-top-left-radius",n="border-bottom-left-radius";e&&(e.style[s]=i[s],e.style[n]=i[n],t.style[s]="0",t.style[n]="0",["background-color","margin-top","padding-top","font-family","font-size","line-height"].forEach((function(t){e.style[t]=i[t]})),e.style["margin-bottom"]="-"+i["padding-top"])}))}},_recordCurrentState:function(){var t=this.$refs.textarea;t&&this._recordChange({value:t.value,selectionStart:t.selectionStart,selectionEnd:t.selectionEnd})},_getLines:function(t,e){return t.substring(0,e).split("\n")},_recordStateIfChange:function(){this.history.stack[this.history.offset].value!=this.codeData&&this._recordChange({value:this.codeData,selectionStart:this.codeData.length,selectionEnd:this.codeData.length})},_applyEdits:function(t){var e=this.$refs.textarea,s=this.history.stack[this.history.offset];s&&e&&(this.history.stack[this.history.offset]=i({},s,{selectionStart:e.selectionStart,selectionEnd:e.selectionEnd})),this._recordChange(t),this._updateInput(t)},_recordChange:function(t,e){void 0===e&&(e=!1);var s=this.history,n=s.stack,r=s.offset;if(n.length&&r>-1){this.history.stack=n.slice(0,r+1);var a=this.history.stack.length;if(a>100){var o=a-100;this.history.stack=n.slice(o,a),this.history.offset=Math.max(this.history.offset-o,0)}}var l=Date.now();if(e){var h=this.history.stack[this.history.offset];if(h&&l-h.timestamp<3e3){var u,c,d=/[^a-z0-9]([a-z0-9]+)$/i,f=null===(u=this._getLines(h.value,h.selectionStart).pop())||void 0===u?void 0:u.match(d),p=null===(c=this._getLines(t.value,t.selectionStart).pop())||void 0===c?void 0:c.match(d);if(f&&p&&p[1].startsWith(f[1]))return void(this.history.stack[this.history.offset]=i({},t,{timestamp:l}))}}this.history.stack.push(i({},t,{timestamp:l})),this.history.offset++},_updateInput:function(t){var e=this.$refs.textarea;e&&(e.value=t.value,e.selectionStart=t.selectionStart,e.selectionEnd=t.selectionEnd,this.$emit("input",t.value))},handleChange:function(t){var e=t.target,i=e.value;this._recordChange({value:i,selectionStart:e.selectionStart,selectionEnd:e.selectionEnd},!0),this.$emit("input",i)},_undoEdit:function(){var t=this.history,e=t.offset,i=t.stack[e-1];i&&(this._updateInput(i),this.history.offset=Math.max(e-1,0))},_redoEdit:function(){var t=this.history,e=t.stack,i=t.offset,s=e[i+1];s&&(this._updateInput(s),this.history.offset=Math.min(i+1,e.length-1))},handleKeyDown:function(t){var e=this.tabSize,i=this.insertSpaces,a=this.ignoreTabKey;if(!this.$listeners.keydown||(this.$emit("keydown",t),!t.defaultPrevented)){27===t.keyCode&&(t.target.blur(),this.$emit("blur",t));var o=t.target,l=o.value,h=o.selectionStart,u=o.selectionEnd,c=(i?" ":"\t").repeat(e);if(9===t.keyCode&&!a&&this.capture)if(t.preventDefault(),t.shiftKey){var d=this._getLines(l,h),f=d.length-1,p=this._getLines(l,u).length-1,y=l.split("\n").map((function(t,e){return e>=f&&e<=p&&t.startsWith(c)?t.substring(c.length):t})).join("\n");l!==y&&this._applyEdits({value:y,selectionStart:d[f].startsWith(c)?h-c.length:h,selectionEnd:u-(l.length-y.length)})}else if(h!==u){var g=this._getLines(l,h),m=g.length-1,v=this._getLines(l,u).length-1,b=g[m];this._applyEdits({value:l.split("\n").map((function(t,e){return e>=m&&e<=v?c+t:t})).join("\n"),selectionStart:/\S/.test(b)?h+c.length:h,selectionEnd:u+c.length*(v-m+1)})}else{var _=h+c.length;this._applyEdits({value:l.substring(0,h)+c+l.substring(u),selectionStart:_,selectionEnd:_})}else if(8===t.keyCode){var k=h!==u;if(l.substring(0,h).endsWith(c)&&!k){t.preventDefault();var S=h-c.length;this._applyEdits({value:l.substring(0,h-c.length)+l.substring(u),selectionStart:S,selectionEnd:S})}}else if(13===t.keyCode){if(h===u){var C=this._getLines(l,h).pop(),E=null==C?void 0:C.match(/^\s+/);if(E&&E[0]){t.preventDefault();var D="\n"+E[0],N=h+D.length;this._applyEdits({value:l.substring(0,h)+D+l.substring(u),selectionStart:N,selectionEnd:N})}}}else s[t.key]?h!==u&&(t.preventDefault(),this._applyEdits({value:l.substring(0,h)+t.key+l.substring(h,u)+s[t.key]+l.substring(u),selectionStart:h+1,selectionEnd:u+1})):!(r?t.metaKey&&90===t.keyCode:t.ctrlKey&&90===t.keyCode)||t.shiftKey||t.altKey?(r?t.metaKey&&90===t.keyCode&&t.shiftKey:n?t.ctrlKey&&89===t.keyCode:t.ctrlKey&&90===t.keyCode&&t.shiftKey)&&!t.altKey?(t.preventDefault(),this._redoEdit()):77!==t.keyCode||!t.ctrlKey||r&&!t.shiftKey||(t.preventDefault(),this.capture=!this.capture):(t.preventDefault(),this._undoEdit())}}},render:function(t){var e=this,i=t("div",{attrs:{class:"prism-editor__line-width-calc",style:"height: 0px; visibility: hidden; pointer-events: none;"}},"999"),s=t("div",{staticClass:"prism-editor__line-numbers",style:{"min-height":this.lineNumbersHeight},attrs:{"aria-hidden":"true"}},[i,Array.from(Array(this.lineNumbersCount).keys()).map((function(e,i){return t("div",{attrs:{class:"prism-editor__line-number token comment"}},""+ ++i)}))]),n=t("textarea",{ref:"textarea",on:{input:this.handleChange,keydown:this.handleKeyDown,click:function(t){e.$emit("click",t)},keyup:function(t){e.$emit("keyup",t)},focus:function(t){e._recordStateIfChange(),e.$emit("focus",t)},blur:function(t){e.$emit("blur",t)}},staticClass:"prism-editor__textarea",class:{"prism-editor__textarea--empty":this.isEmpty},attrs:{spellCheck:"false",autocapitalize:"off",autocomplete:"off",autocorrect:"off","data-gramm":"false",placeholder:this.placeholder,"data-testid":"textarea",readonly:this.readonly},domProps:{value:this.codeData}}),r=t("pre",{ref:"pre",staticClass:"prism-editor__editor",attrs:{"data-testid":"preview"},domProps:{innerHTML:this.content}}),a=t("div",{staticClass:"prism-editor__container"},[n,r]);return t("div",{staticClass:"prism-editor-wrapper"},[this.lineNumbers&&s,a])}});exports.PrismEditor=a; +"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var t,e=(t=require("vue"))&&"object"==typeof t&&"default"in t?t.default:t;function i(){return(i=Object.assign||function(t){for(var e=1;e li.selected");e&&e.scrollIntoView({block:"nearest"})}))}},computed:{isEmpty:function(){return 0===this.codeData.length},content:function(){return this.highlight(this.codeData)+"
"},lineNumbersCount:function(){return this.codeData.split(/\r\n|\n/).length},cursorOffset:function(){var t=this.$refs.textarea,e=this.$refs.wrapper,i=this.codeData.substring(0,t.selectionEnd||0).split(/\r\n|\n/),s=parseFloat(getComputedStyle(t).getPropertyValue("font-size")),n=i.length;return[Math.min(8.85*i[i.length-1].length*(s/16)-e.scrollLeft,e.clientWidth-Math.min(240,e.clientWidth)),24*n*(s/16)+2-e.scrollTop]}},mounted:function(){this._recordCurrentState(),this.styleLineNumbers()},methods:{updateAutocompleteData:function(){var t,e="function"==typeof this.autocomplete?this.autocomplete(this.codeData,this.$refs.textarea.selectionEnd):[],i=this.autocompleteData.length;(t=this.autocompleteData).splice.apply(t,[0,Infinity].concat(e)),this.autocompleteOpen=!0,this.autocompleteIndex=Math.max(0,Math.min(this.autocompleteIndex,this.autocompleteData.length-1)),i>this.autocompleteData.length&&(this.autocompleteIndex=0)},acceptAutocomplete:function(t,i){var s=this;t.preventDefault(),null==i&&(i=this.autocompleteIndex);var n=this.$refs.textarea,a=this.$refs.wrapper,o=this.autocompleteData[i]||this.autocompleteData[0];if(o){var r=o.overlap||0,l=[this.codeData.substr(0,n.selectionEnd-r),o.text,this.codeData.substring(n.selectionEnd)].join(""),h=n.selectionEnd-r+o.text.length+(o.text.endsWith(")")?-1:0);n.selectionStart=n.selectionEnd=h,this._applyEdits({value:l,selectionStart:h,selectionEnd:h});var u=o.text.length-o.overlap;e.nextTick((function(){a.scrollLeft+=8.85*u})),o.text.endsWith(".")?setTimeout((function(){s.updateAutocompleteData()}),1):this.autocompleteOpen=!1}},setLineNumbersHeight:function(){this.lineNumbersHeight=getComputedStyle(this.$refs.pre).height},styleLineNumbers:function(){if(this.lineNumbers&&this.autoStyleLineNumbers){var t=this.$refs.pre,e=this.$el.querySelector(".prism-editor__line-numbers"),i=window.getComputedStyle(t);this.$nextTick((function(){var s="border-top-left-radius",n="border-bottom-left-radius";e&&(e.style[s]=i[s],e.style[n]=i[n],t.style[s]="0",t.style[n]="0",["background-color","margin-top","padding-top","font-family","font-size","line-height"].forEach((function(t){e.style[t]=i[t]})),e.style["margin-bottom"]="-"+i["padding-top"])}))}},_recordCurrentState:function(){var t=this.$refs.textarea;t&&this._recordChange({value:t.value,selectionStart:t.selectionStart,selectionEnd:t.selectionEnd})},_getLines:function(t,e){return t.substring(0,e).split("\n")},_recordStateIfChange:function(){this.history.stack[this.history.offset].value!=this.codeData&&this._recordChange({value:this.codeData,selectionStart:this.codeData.length,selectionEnd:this.codeData.length})},_applyEdits:function(t){var e=this.$refs.textarea,s=this.history.stack[this.history.offset];s&&e&&(this.history.stack[this.history.offset]=i({},s,{selectionStart:e.selectionStart,selectionEnd:e.selectionEnd})),this._recordChange(t),this._updateInput(t)},_recordChange:function(t,e){void 0===e&&(e=!1);var s=this.history,n=s.stack,a=s.offset;if(n.length&&a>-1){this.history.stack=n.slice(0,a+1);var o=this.history.stack.length;if(o>100){var r=o-100;this.history.stack=n.slice(r,o),this.history.offset=Math.max(this.history.offset-r,0)}}var l=Date.now();if(e){var h=this.history.stack[this.history.offset];if(h&&l-h.timestamp<3e3){var u,c,p=/[^a-z0-9]([a-z0-9]+)$/i,d=null===(u=this._getLines(h.value,h.selectionStart).pop())||void 0===u?void 0:u.match(p),f=null===(c=this._getLines(t.value,t.selectionStart).pop())||void 0===c?void 0:c.match(p);if(d&&f&&f[1].startsWith(d[1]))return void(this.history.stack[this.history.offset]=i({},t,{timestamp:l}))}}this.history.stack.push(i({},t,{timestamp:l})),this.history.offset++},_updateInput:function(t){var e=this.$refs.textarea;e&&(e.value=t.value,e.selectionStart=t.selectionStart,e.selectionEnd=t.selectionEnd,this.$emit("input",t.value))},handleChange:function(t){var e=t.target,i=e.value;this._recordChange({value:i,selectionStart:e.selectionStart,selectionEnd:e.selectionEnd},!0),this.$emit("input",i)},_undoEdit:function(){var t=this.history,e=t.offset,i=t.stack[e-1];i&&(this._updateInput(i),this.history.offset=Math.max(e-1,0))},_redoEdit:function(){var t=this.history,e=t.stack,i=t.offset,s=e[i+1];s&&(this._updateInput(s),this.history.offset=Math.min(i+1,e.length-1))},handleKeyDown:function(t){var e=this,i=this.tabSize,o=this.insertSpaces,r=this.ignoreTabKey;if(!this.$listeners.keydown||(this.$emit("keydown",t),!t.defaultPrevented)){if(9===t.keyCode&&this.autocompleteData.length&&this.autocompleteOpen)return this.acceptAutocomplete(t),t.preventDefault(),void t.stopPropagation();if(27===t.keyCode){if(this.autocompleteData.length&&this.autocompleteOpen)return t.preventDefault(),void(this.autocompleteOpen=!1)}else if(38===t.keyCode){if(this.autocompleteData.length&&this.autocompleteOpen)return t.preventDefault(),void(this.autocompleteIndex=(this.autocompleteIndex?this.autocompleteIndex:this.autocompleteData.length)-1)}else if(40===t.keyCode&&this.autocompleteData.length&&this.autocompleteOpen)return t.preventDefault(),void(this.autocompleteIndex=(this.autocompleteIndex+1)%this.autocompleteData.length);27===t.keyCode&&(t.target.blur(),this.$emit("blur",t));var l=t.target,h=l.value,u=l.selectionStart,c=l.selectionEnd,p=(o?" ":"\t").repeat(i);if(9===t.keyCode&&!r&&this.capture)if(t.preventDefault(),t.shiftKey){var d=this._getLines(h,u),f=d.length-1,m=this._getLines(h,c).length-1,y=h.split("\n").map((function(t,e){return e>=f&&e<=m&&t.startsWith(p)?t.substring(p.length):t})).join("\n");h!==y&&this._applyEdits({value:y,selectionStart:d[f].startsWith(p)?u-p.length:u,selectionEnd:c-(h.length-y.length)})}else if(u!==c){var g=this._getLines(h,u),v=g.length-1,b=this._getLines(h,c).length-1,_=g[v];this._applyEdits({value:h.split("\n").map((function(t,e){return e>=v&&e<=b?p+t:t})).join("\n"),selectionStart:/\S/.test(_)?u+p.length:u,selectionEnd:c+p.length*(b-v+1)})}else{var k=u+p.length;this._applyEdits({value:h.substring(0,u)+p+h.substring(c),selectionStart:k,selectionEnd:k})}else if(8===t.keyCode){var D=u!==c;if(h.substring(0,u).endsWith(p)&&!D){t.preventDefault();var x=u-p.length;this._applyEdits({value:h.substring(0,u-p.length)+h.substring(c),selectionStart:x,selectionEnd:x})}}else if(13===t.keyCode){if(this.autocompleteData.length&&this.autocompleteOpen)this.acceptAutocomplete(t);else if(u===c){var C=this._getLines(h,u).pop(),E=null==C?void 0:C.match(/^\s+/);if(E&&E[0]){t.preventDefault();var S="\n"+E[0],$=u+S.length;this._applyEdits({value:h.substring(0,u)+S+h.substring(c),selectionStart:$,selectionEnd:$})}}}else s[t.key]?u!==c&&(t.preventDefault(),this._applyEdits({value:h.substring(0,u)+t.key+h.substring(u,c)+s[t.key]+h.substring(c),selectionStart:u+1,selectionEnd:c+1})):!(a?t.metaKey&&90===t.keyCode:t.ctrlKey&&90===t.keyCode)||t.shiftKey||t.altKey?(a?t.metaKey&&90===t.keyCode&&t.shiftKey:n?t.ctrlKey&&89===t.keyCode:t.ctrlKey&&90===t.keyCode&&t.shiftKey)&&!t.altKey?(t.preventDefault(),this._redoEdit()):77!==t.keyCode||!t.ctrlKey||a&&!t.shiftKey||(t.preventDefault(),this.capture=!this.capture):(t.preventDefault(),this._undoEdit());13!==t.keyCode&&9!==t.keyCode&&setTimeout((function(){e.updateAutocompleteData()}),1)}}},render:function(t){var e=this,i=t("div",{attrs:{class:"prism-editor__line-width-calc",style:"height: 0px; visibility: hidden; pointer-events: none;"}},"999"),s=t("div",{staticClass:"prism-editor__line-numbers",style:{"min-height":this.lineNumbersHeight},attrs:{"aria-hidden":"true"}},[i,Array.from(Array(this.lineNumbersCount).keys()).map((function(e,i){return t("div",{attrs:{class:"prism-editor__line-number token comment"}},""+ ++i)}))]),n=this.autocompleteOpen&&this.autocompleteData.length?t("ul",{staticClass:"prism-editor__autocomplete",style:{left:this.cursorOffset[0]+"px",top:this.cursorOffset[1]+"px"}},this.autocompleteData.map((function(i,s){return t("li",{key:i.text,class:{selected:s==e.autocompleteIndex},on:{mousedown:function(t){e.acceptAutocomplete(t,s)}}},[i.label||i.text])}))):void 0,a=t("textarea",{ref:"textarea",on:{input:this.handleChange,keydown:this.handleKeyDown,click:function(t){e.autocompleteOpen=!1,e.$emit("click",t)},keyup:function(t){e.$emit("keyup",t)},focus:function(t){e._recordStateIfChange(),e.$emit("focus",t)},blur:function(t){e.autocompleteOpen=!1,e.$emit("blur",t)}},staticClass:"prism-editor__textarea",class:{"prism-editor__textarea--empty":this.isEmpty},attrs:{spellCheck:"false",autocapitalize:"off",autocomplete:"off",autocorrect:"off","data-gramm":"false",placeholder:this.placeholder,"data-testid":"textarea",readonly:this.readonly},domProps:{value:this.codeData}}),o=t("pre",{ref:"pre",staticClass:"prism-editor__editor",attrs:{"data-testid":"preview"},domProps:{innerHTML:this.content}}),r=t("div",{staticClass:"prism-editor__container"},[a,o]),l=t("div",{staticClass:"prism-editor-wrapper",ref:"wrapper"},[this.lineNumbers&&s,r]);return t("div",{staticClass:"prism-editor-component"},[l,n])}});exports.PrismEditor=o; //# sourceMappingURL=prismeditor.cjs.production.min.js.map diff --git a/packages/vue-prism-editor/dist/prismeditor.cjs.production.min.js.map b/packages/vue-prism-editor/dist/prismeditor.cjs.production.min.js.map index c06c8c4..18fabe7 100644 --- a/packages/vue-prism-editor/dist/prismeditor.cjs.production.min.js.map +++ b/packages/vue-prism-editor/dist/prismeditor.cjs.production.min.js.map @@ -1 +1 @@ -{"version":3,"file":"prismeditor.cjs.production.min.js","sources":["../src/Editor.ts"],"sourcesContent":["import Vue, { VNode } from 'vue';\r\n\r\nimport './styles.css';\r\nconst KEYCODE_ENTER = 13;\r\nconst KEYCODE_TAB = 9;\r\nconst KEYCODE_BACKSPACE = 8;\r\nconst KEYCODE_Y = 89;\r\nconst KEYCODE_Z = 90;\r\nconst KEYCODE_M = 77;\r\nconst KEYCODE_ESCAPE = 27;\r\n\r\nconst BRACKET_PAIRS: {[opening: string]: string} = {\r\n '(':')',\r\n '{':'}',\r\n '[':']',\r\n '\"':'\"',\r\n \"'\":\"'\",\r\n};\r\n\r\nconst HISTORY_LIMIT = 100;\r\nconst HISTORY_TIME_GAP = 3000;\r\n\r\nconst isWindows = 'navigator' in global && /Win/i.test(navigator.platform);\r\nconst isMacLike = 'navigator' in global && /(Mac|iPhone|iPod|iPad)/i.test(navigator.platform);\r\n\r\nexport interface EditorProps {\r\n lineNumbers: boolean;\r\n autoStyleLineNumbers: boolean;\r\n readonly: boolean;\r\n value: string;\r\n highlight: () => string;\r\n tabSize: number;\r\n insertSpaces: boolean;\r\n ignoreTabKey: boolean;\r\n placeholder: string;\r\n}\r\nexport interface Record {\r\n value: string;\r\n selectionStart: number;\r\n selectionEnd: number;\r\n}\r\n\r\nexport interface History {\r\n stack: Array;\r\n offset: number;\r\n}\r\n\r\nexport const PrismEditor = Vue.extend({\r\n props: {\r\n lineNumbers: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n autoStyleLineNumbers: {\r\n type: Boolean,\r\n default: true,\r\n },\r\n readonly: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n value: {\r\n type: String,\r\n default: '',\r\n },\r\n highlight: {\r\n type: Function,\r\n required: true,\r\n },\r\n tabSize: {\r\n type: Number,\r\n default: 2,\r\n },\r\n insertSpaces: {\r\n type: Boolean,\r\n default: true,\r\n },\r\n ignoreTabKey: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n placeholder: {\r\n type: String,\r\n default: '',\r\n },\r\n },\r\n data() {\r\n return {\r\n capture: true,\r\n history: {\r\n stack: [],\r\n offset: -1,\r\n } as History,\r\n lineNumbersHeight: '20px',\r\n codeData: '',\r\n };\r\n },\r\n watch: {\r\n value: {\r\n immediate: true,\r\n handler(newVal: string): void {\r\n if (!newVal) {\r\n this.codeData = '';\r\n } else {\r\n this.codeData = newVal;\r\n }\r\n },\r\n },\r\n content: {\r\n immediate: true,\r\n handler(): void {\r\n if (this.lineNumbers) {\r\n this.$nextTick(() => {\r\n this.setLineNumbersHeight();\r\n });\r\n }\r\n },\r\n },\r\n lineNumbers(): void {\r\n this.$nextTick(() => {\r\n this.styleLineNumbers();\r\n this.setLineNumbersHeight();\r\n });\r\n },\r\n },\r\n computed: {\r\n isEmpty(): boolean {\r\n return this.codeData.length === 0;\r\n },\r\n content(): string {\r\n const result = this.highlight(this.codeData) + '
';\r\n // todo: VNode support?\r\n return result;\r\n },\r\n lineNumbersCount(): number {\r\n const totalLines = this.codeData.split(/\\r\\n|\\n/).length;\r\n return totalLines;\r\n },\r\n },\r\n mounted() {\r\n this._recordCurrentState();\r\n this.styleLineNumbers();\r\n },\r\n\r\n methods: {\r\n setLineNumbersHeight(): void {\r\n this.lineNumbersHeight = getComputedStyle(this.$refs.pre as HTMLTextAreaElement).height;\r\n },\r\n styleLineNumbers(): void {\r\n if (!this.lineNumbers || !this.autoStyleLineNumbers) return;\r\n\r\n const $editor = this.$refs.pre as HTMLTextAreaElement;\r\n const $lineNumbers: HTMLDivElement | null = this.$el.querySelector('.prism-editor__line-numbers');\r\n const editorStyles = window.getComputedStyle($editor);\r\n\r\n this.$nextTick(() => {\r\n const btlr: any = 'border-top-left-radius';\r\n const bblr: any = 'border-bottom-left-radius';\r\n if (!$lineNumbers) return;\r\n $lineNumbers.style[btlr] = editorStyles[btlr];\r\n $lineNumbers.style[bblr] = editorStyles[bblr];\r\n $editor.style[btlr] = '0';\r\n $editor.style[bblr] = '0';\r\n\r\n const stylesList = ['background-color', 'margin-top', 'padding-top', 'font-family', 'font-size', 'line-height'];\r\n stylesList.forEach((style: any) => {\r\n $lineNumbers.style[style] = editorStyles[style];\r\n });\r\n $lineNumbers.style['margin-bottom' as any] = '-' + editorStyles['padding-top' as any];\r\n });\r\n },\r\n _recordCurrentState(): void {\r\n const input = this.$refs.textarea as HTMLTextAreaElement;\r\n\r\n if (!input) return;\r\n // Save current state of the input\r\n const { value, selectionStart, selectionEnd } = input;\r\n\r\n this._recordChange({\r\n value,\r\n selectionStart,\r\n selectionEnd,\r\n });\r\n },\r\n _getLines(text: string, position: number): Array {\r\n return text.substring(0, position).split('\\n');\r\n },\r\n _recordStateIfChange(): void {\r\n if (this.history.stack[this.history.offset].value != this.codeData) {\r\n this._recordChange({\r\n value: this.codeData,\r\n selectionStart: this.codeData.length,\r\n selectionEnd: this.codeData.length,\r\n });\r\n }\r\n },\r\n _applyEdits(record: Record): void {\r\n // Save last selection state\r\n const input = this.$refs.textarea as HTMLTextAreaElement;\r\n const last = this.history.stack[this.history.offset];\r\n\r\n if (last && input) {\r\n this.history.stack[this.history.offset] = {\r\n ...last,\r\n selectionStart: input.selectionStart,\r\n selectionEnd: input.selectionEnd,\r\n };\r\n }\r\n\r\n // Save the changes\r\n this._recordChange(record);\r\n this._updateInput(record);\r\n },\r\n _recordChange(record: Record, overwrite = false): void {\r\n const { stack, offset } = this.history;\r\n\r\n if (stack.length && offset > -1) {\r\n // When something updates, drop the redo operations\r\n this.history.stack = stack.slice(0, offset + 1);\r\n\r\n // Limit the number of operations to 100\r\n const count = this.history.stack.length;\r\n\r\n if (count > HISTORY_LIMIT) {\r\n const extras = count - HISTORY_LIMIT;\r\n\r\n this.history.stack = stack.slice(extras, count);\r\n this.history.offset = Math.max(this.history.offset - extras, 0);\r\n }\r\n }\r\n\r\n const timestamp = Date.now();\r\n\r\n if (overwrite) {\r\n const last = this.history.stack[this.history.offset];\r\n\r\n if (last && timestamp - last.timestamp < HISTORY_TIME_GAP) {\r\n // A previous entry exists and was in short interval\r\n\r\n // Match the last word in the line\r\n const re = /[^a-z0-9]([a-z0-9]+)$/i;\r\n\r\n // Get the previous line\r\n const previous = this._getLines(last.value, last.selectionStart).pop()?.match(re);\r\n\r\n // Get the current line\r\n const current = this._getLines(record.value, record.selectionStart).pop()?.match(re);\r\n\r\n if (previous && current && current[1].startsWith(previous[1])) {\r\n // The last word of the previous line and current line match\r\n // Overwrite previous entry so that undo will remove whole word\r\n this.history.stack[this.history.offset] = {\r\n ...record,\r\n timestamp,\r\n };\r\n\r\n return;\r\n }\r\n }\r\n }\r\n\r\n // Add the new operation to the stack\r\n this.history.stack.push({ ...record, timestamp });\r\n this.history.offset++;\r\n },\r\n\r\n _updateInput(record: Record): void {\r\n const input = this.$refs.textarea as HTMLTextAreaElement;\r\n\r\n if (!input) return;\r\n\r\n // Update values and selection state\r\n input.value = record.value;\r\n input.selectionStart = record.selectionStart;\r\n input.selectionEnd = record.selectionEnd;\r\n\r\n this.$emit('input', record.value);\r\n // this.props.onValueChange(record.value);\r\n },\r\n handleChange(e: KeyboardEvent): void {\r\n const { value, selectionStart, selectionEnd } = e.target as HTMLTextAreaElement;\r\n\r\n this._recordChange(\r\n {\r\n value,\r\n selectionStart,\r\n selectionEnd,\r\n },\r\n true\r\n );\r\n this.$emit('input', value);\r\n // this.props.onValueChange(value);\r\n },\r\n _undoEdit(): void {\r\n const { stack, offset } = this.history;\r\n\r\n // Get the previous edit\r\n const record = stack[offset - 1];\r\n\r\n if (record) {\r\n // Apply the changes and update the offset\r\n this._updateInput(record);\r\n this.history.offset = Math.max(offset - 1, 0);\r\n }\r\n },\r\n _redoEdit(): void {\r\n const { stack, offset } = this.history;\r\n\r\n // Get the next edit\r\n const record = stack[offset + 1];\r\n\r\n if (record) {\r\n // Apply the changes and update the offset\r\n this._updateInput(record);\r\n this.history.offset = Math.min(offset + 1, stack.length - 1);\r\n }\r\n },\r\n handleKeyDown(e: KeyboardEvent): void {\r\n // console.log(navigator.platform);\r\n const { tabSize, insertSpaces, ignoreTabKey } = this;\r\n\r\n if (this.$listeners.keydown) {\r\n // onKeyDown(e);\r\n this.$emit('keydown', e);\r\n\r\n if (e.defaultPrevented) {\r\n return;\r\n }\r\n }\r\n\r\n if (e.keyCode === KEYCODE_ESCAPE) {\r\n (e.target).blur();\r\n this.$emit('blur', e);\r\n }\r\n\r\n const { value, selectionStart, selectionEnd } = e.target as HTMLTextAreaElement;\r\n\r\n const tabCharacter = (insertSpaces ? ' ' : '\\t').repeat(tabSize);\r\n\r\n if (e.keyCode === KEYCODE_TAB && !ignoreTabKey && this.capture) {\r\n // Prevent focus change\r\n e.preventDefault();\r\n\r\n if (e.shiftKey) {\r\n // Unindent selected lines\r\n const linesBeforeCaret = this._getLines(value, selectionStart);\r\n const startLine = linesBeforeCaret.length - 1;\r\n const endLine = this._getLines(value, selectionEnd).length - 1;\r\n const nextValue = value\r\n .split('\\n')\r\n .map((line, i) => {\r\n if (i >= startLine && i <= endLine && line.startsWith(tabCharacter)) {\r\n return line.substring(tabCharacter.length);\r\n }\r\n\r\n return line;\r\n })\r\n .join('\\n');\r\n\r\n if (value !== nextValue) {\r\n const startLineText = linesBeforeCaret[startLine];\r\n\r\n this._applyEdits({\r\n value: nextValue,\r\n // Move the start cursor if first line in selection was modified\r\n // It was modified only if it started with a tab\r\n selectionStart: startLineText.startsWith(tabCharacter)\r\n ? selectionStart - tabCharacter.length\r\n : selectionStart,\r\n // Move the end cursor by total number of characters removed\r\n selectionEnd: selectionEnd - (value.length - nextValue.length),\r\n });\r\n }\r\n } else if (selectionStart !== selectionEnd) {\r\n // Indent selected lines\r\n const linesBeforeCaret = this._getLines(value, selectionStart);\r\n const startLine = linesBeforeCaret.length - 1;\r\n const endLine = this._getLines(value, selectionEnd).length - 1;\r\n const startLineText = linesBeforeCaret[startLine];\r\n\r\n this._applyEdits({\r\n value: value\r\n .split('\\n')\r\n .map((line, i) => {\r\n if (i >= startLine && i <= endLine) {\r\n return tabCharacter + line;\r\n }\r\n\r\n return line;\r\n })\r\n .join('\\n'),\r\n // Move the start cursor by number of characters added in first line of selection\r\n // Don't move it if it there was no text before cursor\r\n selectionStart: /\\S/.test(startLineText) ? selectionStart + tabCharacter.length : selectionStart,\r\n // Move the end cursor by total number of characters added\r\n selectionEnd: selectionEnd + tabCharacter.length * (endLine - startLine + 1),\r\n });\r\n } else {\r\n const updatedSelection = selectionStart + tabCharacter.length;\r\n\r\n this._applyEdits({\r\n // Insert tab character at caret\r\n value: value.substring(0, selectionStart) + tabCharacter + value.substring(selectionEnd),\r\n // Update caret position\r\n selectionStart: updatedSelection,\r\n selectionEnd: updatedSelection,\r\n });\r\n }\r\n } else if (e.keyCode === KEYCODE_BACKSPACE) {\r\n const hasSelection = selectionStart !== selectionEnd;\r\n const textBeforeCaret = value.substring(0, selectionStart);\r\n\r\n if (textBeforeCaret.endsWith(tabCharacter) && !hasSelection) {\r\n // Prevent default delete behaviour\r\n e.preventDefault();\r\n\r\n const updatedSelection = selectionStart - tabCharacter.length;\r\n\r\n this._applyEdits({\r\n // Remove tab character at caret\r\n value: value.substring(0, selectionStart - tabCharacter.length) + value.substring(selectionEnd),\r\n // Update caret position\r\n selectionStart: updatedSelection,\r\n selectionEnd: updatedSelection,\r\n });\r\n }\r\n } else if (e.keyCode === KEYCODE_ENTER) {\r\n // Ignore selections\r\n if (selectionStart === selectionEnd) {\r\n // Get the current line\r\n const line = this._getLines(value, selectionStart).pop();\r\n const matches = line?.match(/^\\s+/);\r\n\r\n if (matches && matches[0]) {\r\n e.preventDefault();\r\n\r\n // Preserve indentation on inserting a new line\r\n const indent = '\\n' + matches[0];\r\n const updatedSelection = selectionStart + indent.length;\r\n\r\n this._applyEdits({\r\n // Insert indentation character at caret\r\n value: value.substring(0, selectionStart) + indent + value.substring(selectionEnd),\r\n // Update caret position\r\n selectionStart: updatedSelection,\r\n selectionEnd: updatedSelection,\r\n });\r\n }\r\n }\r\n } else if (BRACKET_PAIRS[e.key]) {\r\n // If text is selected, wrap them in the characters\r\n if (selectionStart !== selectionEnd) {\r\n e.preventDefault();\r\n\r\n this._applyEdits({\r\n value:\r\n value.substring(0, selectionStart) +\r\n e.key +\r\n value.substring(selectionStart, selectionEnd) +\r\n BRACKET_PAIRS[e.key] +\r\n value.substring(selectionEnd),\r\n // Update caret position\r\n selectionStart: selectionStart + 1,\r\n selectionEnd: selectionEnd + 1,\r\n });\r\n }\r\n } else if (\r\n (isMacLike\r\n ? // Trigger undo with ⌘+Z on Mac\r\n e.metaKey && e.keyCode === KEYCODE_Z\r\n : // Trigger undo with Ctrl+Z on other platforms\r\n e.ctrlKey && e.keyCode === KEYCODE_Z) &&\r\n !e.shiftKey &&\r\n !e.altKey\r\n ) {\r\n e.preventDefault();\r\n\r\n this._undoEdit();\r\n } else if (\r\n (isMacLike\r\n ? // Trigger redo with ⌘+Shift+Z on Mac\r\n e.metaKey && e.keyCode === KEYCODE_Z && e.shiftKey\r\n : isWindows\r\n ? // Trigger redo with Ctrl+Y on Windows\r\n e.ctrlKey && e.keyCode === KEYCODE_Y\r\n : // Trigger redo with Ctrl+Shift+Z on other platforms\r\n e.ctrlKey && e.keyCode === KEYCODE_Z && e.shiftKey) &&\r\n !e.altKey\r\n ) {\r\n e.preventDefault();\r\n\r\n this._redoEdit();\r\n } else if (e.keyCode === KEYCODE_M && e.ctrlKey && (isMacLike ? e.shiftKey : true)) {\r\n e.preventDefault();\r\n\r\n // Toggle capturing tab key so users can focus away\r\n this.capture = !this.capture;\r\n }\r\n },\r\n },\r\n render(h): VNode {\r\n const lineNumberWidthCalculator = h(\r\n 'div',\r\n {\r\n attrs: {\r\n class: 'prism-editor__line-width-calc',\r\n style: 'height: 0px; visibility: hidden; pointer-events: none;',\r\n },\r\n },\r\n '999'\r\n );\r\n const lineNumbers = h(\r\n 'div',\r\n {\r\n staticClass: 'prism-editor__line-numbers',\r\n style: {\r\n 'min-height': this.lineNumbersHeight,\r\n },\r\n attrs: {\r\n 'aria-hidden': 'true',\r\n },\r\n },\r\n [\r\n lineNumberWidthCalculator,\r\n Array.from(Array(this.lineNumbersCount).keys()).map((_, index) => {\r\n return h('div', { attrs: { class: 'prism-editor__line-number token comment' } }, `${++index}`);\r\n }),\r\n ]\r\n );\r\n\r\n const textarea = h('textarea', {\r\n ref: 'textarea',\r\n on: {\r\n input: this.handleChange,\r\n keydown: this.handleKeyDown,\r\n click: ($event: MouseEvent) => {\r\n this.$emit('click', $event);\r\n },\r\n keyup: ($event: KeyboardEvent) => {\r\n this.$emit('keyup', $event);\r\n },\r\n focus: ($event: FocusEvent) => {\r\n this._recordStateIfChange();\r\n this.$emit('focus', $event);\r\n },\r\n blur: ($event: FocusEvent) => {\r\n this.$emit('blur', $event);\r\n },\r\n },\r\n staticClass: 'prism-editor__textarea',\r\n class: {\r\n 'prism-editor__textarea--empty': this.isEmpty,\r\n },\r\n attrs: {\r\n spellCheck: 'false',\r\n autocapitalize: 'off',\r\n autocomplete: 'off',\r\n autocorrect: 'off',\r\n 'data-gramm': 'false',\r\n placeholder: this.placeholder,\r\n 'data-testid': 'textarea',\r\n readonly: this.readonly,\r\n },\r\n domProps: {\r\n value: this.codeData,\r\n },\r\n });\r\n const preview = h('pre', {\r\n ref: 'pre',\r\n staticClass: 'prism-editor__editor',\r\n attrs: {\r\n 'data-testid': 'preview',\r\n },\r\n domProps: {\r\n innerHTML: this.content,\r\n },\r\n });\r\n const editorContainer = h('div', { staticClass: 'prism-editor__container' }, [textarea, preview]);\r\n return h('div', { staticClass: 'prism-editor-wrapper' }, [this.lineNumbers && lineNumbers, editorContainer]);\r\n },\r\n});\r\n"],"names":["BRACKET_PAIRS","isWindows","global","test","navigator","platform","isMacLike","PrismEditor","Vue","extend","props","lineNumbers","type","Boolean","autoStyleLineNumbers","readonly","value","String","highlight","Function","required","tabSize","Number","insertSpaces","ignoreTabKey","placeholder","data","capture","history","stack","offset","lineNumbersHeight","codeData","watch","immediate","handler","newVal","content","this","$nextTick","_this","setLineNumbersHeight","_this2","styleLineNumbers","computed","isEmpty","length","lineNumbersCount","split","mounted","_recordCurrentState","methods","getComputedStyle","$refs","pre","height","$editor","$lineNumbers","$el","querySelector","editorStyles","window","btlr","bblr","style","forEach","input","textarea","_recordChange","selectionStart","selectionEnd","_getLines","text","position","substring","_recordStateIfChange","_applyEdits","record","last","_updateInput","overwrite","slice","count","extras","Math","max","timestamp","Date","now","re","previous","pop","_this$_getLines$pop","match","current","_this$_getLines$pop2","startsWith","push","$emit","handleChange","e","target","_undoEdit","_redoEdit","min","handleKeyDown","$listeners","keydown","defaultPrevented","keyCode","blur","tabCharacter","repeat","preventDefault","shiftKey","linesBeforeCaret","startLine","endLine","nextValue","map","line","i","join","startLineText","updatedSelection","hasSelection","endsWith","matches","indent","key","metaKey","ctrlKey","altKey","render","h","lineNumberWidthCalculator","attrs","staticClass","Array","from","keys","_","index","ref","on","click","$event","_this3","keyup","focus","spellCheck","autocapitalize","autocomplete","autocorrect","domProps","preview","innerHTML","editorContainer"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"prismeditor.cjs.production.min.js","sources":["../src/Editor.ts"],"sourcesContent":["import Vue, { VNode } from 'vue';\r\n\r\nimport './styles.css';\r\nconst KEYCODE_ENTER = 13;\r\nconst KEYCODE_TAB = 9;\r\nconst KEYCODE_BACKSPACE = 8;\r\nconst KEYCODE_Y = 89;\r\nconst KEYCODE_Z = 90;\r\nconst KEYCODE_M = 77;\r\nconst KEYCODE_ESCAPE = 27;\r\n\r\nconst BRACKET_PAIRS: {[opening: string]: string} = {\r\n '(':')',\r\n '{':'}',\r\n '[':']',\r\n '\"':'\"',\r\n \"'\":\"'\",\r\n};\r\n\r\nconst HISTORY_LIMIT = 100;\r\nconst HISTORY_TIME_GAP = 3000;\r\n\r\nconst isWindows = 'navigator' in global && /Win/i.test(navigator.platform);\r\nconst isMacLike = 'navigator' in global && /(Mac|iPhone|iPod|iPad)/i.test(navigator.platform);\r\n\r\nexport interface EditorProps {\r\n lineNumbers: boolean;\r\n autoStyleLineNumbers: boolean;\r\n readonly: boolean;\r\n value: string;\r\n highlight: () => string;\r\n tabSize: number;\r\n insertSpaces: boolean;\r\n ignoreTabKey: boolean;\r\n placeholder: string;\r\n}\r\nexport interface Record {\r\n value: string;\r\n selectionStart: number;\r\n selectionEnd: number;\r\n}\r\n\r\nexport interface History {\r\n stack: Array;\r\n offset: number;\r\n}\r\ninterface AutocompleteEntry {\r\n text: string\r\n overlap: number\r\n label?: string\r\n}\r\n\r\nexport const PrismEditor = Vue.extend({\r\n props: {\r\n lineNumbers: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n autoStyleLineNumbers: {\r\n type: Boolean,\r\n default: true,\r\n },\r\n readonly: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n value: {\r\n type: String,\r\n default: '',\r\n },\r\n highlight: {\r\n type: Function,\r\n required: true,\r\n },\r\n tabSize: {\r\n type: Number,\r\n default: 2,\r\n },\r\n insertSpaces: {\r\n type: Boolean,\r\n default: true,\r\n },\r\n ignoreTabKey: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n placeholder: {\r\n type: String,\r\n default: '',\r\n },\r\n autocomplete: {\r\n type: Function,\r\n default() {\r\n return []\r\n }\r\n }\r\n },\r\n data() {\r\n return {\r\n capture: true,\r\n history: {\r\n stack: [],\r\n offset: -1,\r\n } as History,\r\n lineNumbersHeight: '20px',\r\n codeData: '',\r\n\r\n autocompleteOpen: false,\r\n autocompleteIndex: 0,\r\n autocompleteData: [] as AutocompleteEntry[]\r\n };\r\n },\r\n watch: {\r\n value: {\r\n immediate: true,\r\n handler(newVal: string): void {\r\n if (!newVal) {\r\n this.codeData = '';\r\n } else {\r\n this.codeData = newVal;\r\n }\r\n },\r\n },\r\n content: {\r\n immediate: true,\r\n handler(): void {\r\n if (this.lineNumbers) {\r\n this.$nextTick(() => {\r\n this.setLineNumbersHeight();\r\n });\r\n }\r\n },\r\n },\r\n lineNumbers(): void {\r\n this.$nextTick(() => {\r\n this.styleLineNumbers();\r\n this.setLineNumbersHeight();\r\n });\r\n },\r\n autocompleteIndex() {\r\n Vue.nextTick(() => {\r\n let node = this.$el.querySelector('ul.prism-editor__autocomplete > li.selected');\r\n if (node) node.scrollIntoView({block: 'nearest'});\r\n })\r\n },\r\n },\r\n computed: {\r\n isEmpty(): boolean {\r\n return this.codeData.length === 0;\r\n },\r\n content(): string {\r\n const result = this.highlight(this.codeData) + '
';\r\n // todo: VNode support?\r\n return result;\r\n },\r\n lineNumbersCount(): number {\r\n const totalLines = this.codeData.split(/\\r\\n|\\n/).length;\r\n return totalLines;\r\n },\r\n cursorOffset() {\r\n let text: string = this.codeData;\r\n let input = this.$refs.textarea as HTMLTextAreaElement;\r\n let wrapper = this.$refs.wrapper as HTMLDivElement;\r\n let lines = text.substring(0, input.selectionEnd || 0).split(/\\r\\n|\\n/);\r\n let font_size = parseFloat(getComputedStyle(input).getPropertyValue('font-size'));\r\n let line = lines.length;\r\n let column = lines[lines.length-1].length;\r\n return [\r\n Math.min((column * 8.85 * (font_size / 16)) - wrapper.scrollLeft, wrapper.clientWidth - Math.min(240, wrapper.clientWidth)),\r\n (line * 24.0 * (font_size / 16)) + 2 - wrapper.scrollTop,\r\n ]\r\n },\r\n },\r\n mounted() {\r\n this._recordCurrentState();\r\n this.styleLineNumbers();\r\n },\r\n\r\n methods: {\r\n updateAutocompleteData() {\r\n let input = this.$refs.textarea as HTMLTextAreaElement;\r\n let data: AutocompleteEntry[] = typeof this.autocomplete == 'function' ? this.autocomplete(this.codeData, input.selectionEnd) : [];\r\n let old_length = this.autocompleteData.length;\r\n this.autocompleteData.splice(0, Infinity, ...data);\r\n this.autocompleteOpen = true;\r\n this.autocompleteIndex = Math.max(0, Math.min(this.autocompleteIndex, this.autocompleteData.length-1));\r\n if (old_length > this.autocompleteData.length) this.autocompleteIndex = 0;\r\n },\r\n acceptAutocomplete(event: Event, option?: number) {\r\n event.preventDefault()\r\n if (option == undefined) option = this.autocompleteIndex;\r\n\r\n let input = this.$refs.textarea as HTMLTextAreaElement;\r\n let wrapper = this.$refs.wrapper as HTMLDivElement;\r\n let suggestion = this.autocompleteData[option] || this.autocompleteData[0];\r\n if (!suggestion) return;\r\n \r\n let overlap = suggestion.overlap || 0;\r\n let new_text = [\r\n this.codeData.substr(0, input.selectionEnd - overlap),\r\n suggestion.text,\r\n this.codeData.substring(input.selectionEnd),\r\n ]\r\n let result: string = new_text.join('');\r\n let cursor_pos = input.selectionEnd - overlap + suggestion.text.length + (suggestion.text.endsWith(')') ? -1 : 0);\r\n input.selectionStart = input.selectionEnd = cursor_pos;\r\n\r\n this._applyEdits({\r\n value: result,\r\n selectionStart: cursor_pos,\r\n selectionEnd: cursor_pos,\r\n });\r\n let inserted_characters = suggestion.text.length - suggestion.overlap;\r\n Vue.nextTick(() => {\r\n wrapper.scrollLeft += inserted_characters * 8.85;\r\n })\r\n\r\n if (suggestion.text.endsWith('.')) {\r\n setTimeout(() => {\r\n this.updateAutocompleteData();\r\n }, 1);\r\n } else {\r\n this.autocompleteOpen = false;\r\n }\r\n },\r\n setLineNumbersHeight(): void {\r\n this.lineNumbersHeight = getComputedStyle(this.$refs.pre as HTMLTextAreaElement).height;\r\n },\r\n styleLineNumbers(): void {\r\n if (!this.lineNumbers || !this.autoStyleLineNumbers) return;\r\n\r\n const $editor = this.$refs.pre as HTMLTextAreaElement;\r\n const $lineNumbers: HTMLDivElement | null = this.$el.querySelector('.prism-editor__line-numbers');\r\n const editorStyles = window.getComputedStyle($editor);\r\n\r\n this.$nextTick(() => {\r\n const btlr: any = 'border-top-left-radius';\r\n const bblr: any = 'border-bottom-left-radius';\r\n if (!$lineNumbers) return;\r\n $lineNumbers.style[btlr] = editorStyles[btlr];\r\n $lineNumbers.style[bblr] = editorStyles[bblr];\r\n $editor.style[btlr] = '0';\r\n $editor.style[bblr] = '0';\r\n\r\n const stylesList = ['background-color', 'margin-top', 'padding-top', 'font-family', 'font-size', 'line-height'];\r\n stylesList.forEach((style: any) => {\r\n $lineNumbers.style[style] = editorStyles[style];\r\n });\r\n $lineNumbers.style['margin-bottom' as any] = '-' + editorStyles['padding-top' as any];\r\n });\r\n },\r\n _recordCurrentState(): void {\r\n const input = this.$refs.textarea as HTMLTextAreaElement;\r\n\r\n if (!input) return;\r\n // Save current state of the input\r\n const { value, selectionStart, selectionEnd } = input;\r\n\r\n this._recordChange({\r\n value,\r\n selectionStart,\r\n selectionEnd,\r\n });\r\n },\r\n _getLines(text: string, position: number): Array {\r\n return text.substring(0, position).split('\\n');\r\n },\r\n _recordStateIfChange(): void {\r\n if (this.history.stack[this.history.offset].value != this.codeData) {\r\n this._recordChange({\r\n value: this.codeData,\r\n selectionStart: this.codeData.length,\r\n selectionEnd: this.codeData.length,\r\n });\r\n }\r\n },\r\n _applyEdits(record: Record): void {\r\n // Save last selection state\r\n const input = this.$refs.textarea as HTMLTextAreaElement;\r\n const last = this.history.stack[this.history.offset];\r\n\r\n if (last && input) {\r\n this.history.stack[this.history.offset] = {\r\n ...last,\r\n selectionStart: input.selectionStart,\r\n selectionEnd: input.selectionEnd,\r\n };\r\n }\r\n\r\n // Save the changes\r\n this._recordChange(record);\r\n this._updateInput(record);\r\n },\r\n _recordChange(record: Record, overwrite = false): void {\r\n const { stack, offset } = this.history;\r\n\r\n if (stack.length && offset > -1) {\r\n // When something updates, drop the redo operations\r\n this.history.stack = stack.slice(0, offset + 1);\r\n\r\n // Limit the number of operations to 100\r\n const count = this.history.stack.length;\r\n\r\n if (count > HISTORY_LIMIT) {\r\n const extras = count - HISTORY_LIMIT;\r\n\r\n this.history.stack = stack.slice(extras, count);\r\n this.history.offset = Math.max(this.history.offset - extras, 0);\r\n }\r\n }\r\n\r\n const timestamp = Date.now();\r\n\r\n if (overwrite) {\r\n const last = this.history.stack[this.history.offset];\r\n\r\n if (last && timestamp - last.timestamp < HISTORY_TIME_GAP) {\r\n // A previous entry exists and was in short interval\r\n\r\n // Match the last word in the line\r\n const re = /[^a-z0-9]([a-z0-9]+)$/i;\r\n\r\n // Get the previous line\r\n const previous = this._getLines(last.value, last.selectionStart).pop()?.match(re);\r\n\r\n // Get the current line\r\n const current = this._getLines(record.value, record.selectionStart).pop()?.match(re);\r\n\r\n if (previous && current && current[1].startsWith(previous[1])) {\r\n // The last word of the previous line and current line match\r\n // Overwrite previous entry so that undo will remove whole word\r\n this.history.stack[this.history.offset] = {\r\n ...record,\r\n timestamp,\r\n };\r\n\r\n return;\r\n }\r\n }\r\n }\r\n\r\n // Add the new operation to the stack\r\n this.history.stack.push({ ...record, timestamp });\r\n this.history.offset++;\r\n },\r\n\r\n _updateInput(record: Record): void {\r\n const input = this.$refs.textarea as HTMLTextAreaElement;\r\n\r\n if (!input) return;\r\n\r\n // Update values and selection state\r\n input.value = record.value;\r\n input.selectionStart = record.selectionStart;\r\n input.selectionEnd = record.selectionEnd;\r\n\r\n this.$emit('input', record.value);\r\n // this.props.onValueChange(record.value);\r\n },\r\n handleChange(e: KeyboardEvent): void {\r\n const { value, selectionStart, selectionEnd } = e.target as HTMLTextAreaElement;\r\n\r\n this._recordChange(\r\n {\r\n value,\r\n selectionStart,\r\n selectionEnd,\r\n },\r\n true\r\n );\r\n this.$emit('input', value);\r\n // this.props.onValueChange(value);\r\n },\r\n _undoEdit(): void {\r\n const { stack, offset } = this.history;\r\n\r\n // Get the previous edit\r\n const record = stack[offset - 1];\r\n\r\n if (record) {\r\n // Apply the changes and update the offset\r\n this._updateInput(record);\r\n this.history.offset = Math.max(offset - 1, 0);\r\n }\r\n },\r\n _redoEdit(): void {\r\n const { stack, offset } = this.history;\r\n\r\n // Get the next edit\r\n const record = stack[offset + 1];\r\n\r\n if (record) {\r\n // Apply the changes and update the offset\r\n this._updateInput(record);\r\n this.history.offset = Math.min(offset + 1, stack.length - 1);\r\n }\r\n },\r\n handleKeyDown(e: KeyboardEvent): void {\r\n // console.log(navigator.platform);\r\n const { tabSize, insertSpaces, ignoreTabKey } = this;\r\n\r\n if (this.$listeners.keydown) {\r\n // onKeyDown(e);\r\n this.$emit('keydown', e);\r\n\r\n if (e.defaultPrevented) {\r\n return;\r\n }\r\n }\r\n\r\n if (e.keyCode === 9 && this.autocompleteData.length && this.autocompleteOpen) {\r\n this.acceptAutocomplete(e);\r\n e.preventDefault();\r\n e.stopPropagation();\r\n return;\r\n }\r\n if (e.keyCode === 27) {\r\n // Escape\r\n if (this.autocompleteData.length && this.autocompleteOpen) {\r\n e.preventDefault();\r\n this.autocompleteOpen = false;\r\n return;\r\n }\r\n } else if (e.keyCode === 38) {\r\n // Up\r\n if (this.autocompleteData.length && this.autocompleteOpen) {\r\n e.preventDefault();\r\n this.autocompleteIndex = (this.autocompleteIndex ? this.autocompleteIndex : this.autocompleteData.length) - 1;\r\n return;\r\n }\r\n } else if (e.keyCode === 40) {\r\n // Down\r\n if (this.autocompleteData.length && this.autocompleteOpen) {\r\n e.preventDefault();\r\n this.autocompleteIndex = (this.autocompleteIndex + 1) % this.autocompleteData.length;\r\n return;\r\n }\r\n }\r\n\r\n if (e.keyCode === KEYCODE_ESCAPE) {\r\n (e.target).blur();\r\n this.$emit('blur', e);\r\n }\r\n\r\n const { value, selectionStart, selectionEnd } = e.target as HTMLTextAreaElement;\r\n\r\n const tabCharacter = (insertSpaces ? ' ' : '\\t').repeat(tabSize);\r\n\r\n if (e.keyCode === KEYCODE_TAB && !ignoreTabKey && this.capture) {\r\n // Prevent focus change\r\n e.preventDefault();\r\n\r\n if (e.shiftKey) {\r\n // Unindent selected lines\r\n const linesBeforeCaret = this._getLines(value, selectionStart);\r\n const startLine = linesBeforeCaret.length - 1;\r\n const endLine = this._getLines(value, selectionEnd).length - 1;\r\n const nextValue = value\r\n .split('\\n')\r\n .map((line, i) => {\r\n if (i >= startLine && i <= endLine && line.startsWith(tabCharacter)) {\r\n return line.substring(tabCharacter.length);\r\n }\r\n\r\n return line;\r\n })\r\n .join('\\n');\r\n\r\n if (value !== nextValue) {\r\n const startLineText = linesBeforeCaret[startLine];\r\n\r\n this._applyEdits({\r\n value: nextValue,\r\n // Move the start cursor if first line in selection was modified\r\n // It was modified only if it started with a tab\r\n selectionStart: startLineText.startsWith(tabCharacter)\r\n ? selectionStart - tabCharacter.length\r\n : selectionStart,\r\n // Move the end cursor by total number of characters removed\r\n selectionEnd: selectionEnd - (value.length - nextValue.length),\r\n });\r\n }\r\n } else if (selectionStart !== selectionEnd) {\r\n // Indent selected lines\r\n const linesBeforeCaret = this._getLines(value, selectionStart);\r\n const startLine = linesBeforeCaret.length - 1;\r\n const endLine = this._getLines(value, selectionEnd).length - 1;\r\n const startLineText = linesBeforeCaret[startLine];\r\n\r\n this._applyEdits({\r\n value: value\r\n .split('\\n')\r\n .map((line, i) => {\r\n if (i >= startLine && i <= endLine) {\r\n return tabCharacter + line;\r\n }\r\n\r\n return line;\r\n })\r\n .join('\\n'),\r\n // Move the start cursor by number of characters added in first line of selection\r\n // Don't move it if it there was no text before cursor\r\n selectionStart: /\\S/.test(startLineText) ? selectionStart + tabCharacter.length : selectionStart,\r\n // Move the end cursor by total number of characters added\r\n selectionEnd: selectionEnd + tabCharacter.length * (endLine - startLine + 1),\r\n });\r\n } else {\r\n const updatedSelection = selectionStart + tabCharacter.length;\r\n\r\n this._applyEdits({\r\n // Insert tab character at caret\r\n value: value.substring(0, selectionStart) + tabCharacter + value.substring(selectionEnd),\r\n // Update caret position\r\n selectionStart: updatedSelection,\r\n selectionEnd: updatedSelection,\r\n });\r\n }\r\n } else if (e.keyCode === KEYCODE_BACKSPACE) {\r\n const hasSelection = selectionStart !== selectionEnd;\r\n const textBeforeCaret = value.substring(0, selectionStart);\r\n\r\n if (textBeforeCaret.endsWith(tabCharacter) && !hasSelection) {\r\n // Prevent default delete behaviour\r\n e.preventDefault();\r\n\r\n const updatedSelection = selectionStart - tabCharacter.length;\r\n\r\n this._applyEdits({\r\n // Remove tab character at caret\r\n value: value.substring(0, selectionStart - tabCharacter.length) + value.substring(selectionEnd),\r\n // Update caret position\r\n selectionStart: updatedSelection,\r\n selectionEnd: updatedSelection,\r\n });\r\n }\r\n } else if (e.keyCode === KEYCODE_ENTER) {\r\n \r\n if (this.autocompleteData.length && this.autocompleteOpen) {\r\n this.acceptAutocomplete(e);\r\n\r\n } else if (selectionStart === selectionEnd) {\r\n // Get the current line\r\n const line = this._getLines(value, selectionStart).pop();\r\n const matches = line?.match(/^\\s+/);\r\n\r\n if (matches && matches[0]) {\r\n e.preventDefault();\r\n\r\n // Preserve indentation on inserting a new line\r\n const indent = '\\n' + matches[0];\r\n const updatedSelection = selectionStart + indent.length;\r\n\r\n this._applyEdits({\r\n // Insert indentation character at caret\r\n value: value.substring(0, selectionStart) + indent + value.substring(selectionEnd),\r\n // Update caret position\r\n selectionStart: updatedSelection,\r\n selectionEnd: updatedSelection,\r\n });\r\n }\r\n }\r\n } else if (BRACKET_PAIRS[e.key]) {\r\n // If text is selected, wrap them in the characters\r\n if (selectionStart !== selectionEnd) {\r\n e.preventDefault();\r\n\r\n this._applyEdits({\r\n value:\r\n value.substring(0, selectionStart) +\r\n e.key +\r\n value.substring(selectionStart, selectionEnd) +\r\n BRACKET_PAIRS[e.key] +\r\n value.substring(selectionEnd),\r\n // Update caret position\r\n selectionStart: selectionStart + 1,\r\n selectionEnd: selectionEnd + 1,\r\n });\r\n }\r\n } else if (\r\n (isMacLike\r\n ? // Trigger undo with ⌘+Z on Mac\r\n e.metaKey && e.keyCode === KEYCODE_Z\r\n : // Trigger undo with Ctrl+Z on other platforms\r\n e.ctrlKey && e.keyCode === KEYCODE_Z) &&\r\n !e.shiftKey &&\r\n !e.altKey\r\n ) {\r\n e.preventDefault();\r\n\r\n this._undoEdit();\r\n } else if (\r\n (isMacLike\r\n ? // Trigger redo with ⌘+Shift+Z on Mac\r\n e.metaKey && e.keyCode === KEYCODE_Z && e.shiftKey\r\n : isWindows\r\n ? // Trigger redo with Ctrl+Y on Windows\r\n e.ctrlKey && e.keyCode === KEYCODE_Y\r\n : // Trigger redo with Ctrl+Shift+Z on other platforms\r\n e.ctrlKey && e.keyCode === KEYCODE_Z && e.shiftKey) &&\r\n !e.altKey\r\n ) {\r\n e.preventDefault();\r\n\r\n this._redoEdit();\r\n } else if (e.keyCode === KEYCODE_M && e.ctrlKey && (isMacLike ? e.shiftKey : true)) {\r\n e.preventDefault();\r\n\r\n // Toggle capturing tab key so users can focus away\r\n this.capture = !this.capture;\r\n }\r\n if (e.keyCode !== 13 && e.keyCode !== 9) {\r\n setTimeout(() => {\r\n this.updateAutocompleteData();\r\n }, 1);\r\n }\r\n },\r\n },\r\n render(h): VNode {\r\n const lineNumberWidthCalculator = h(\r\n 'div',\r\n {\r\n attrs: {\r\n class: 'prism-editor__line-width-calc',\r\n style: 'height: 0px; visibility: hidden; pointer-events: none;',\r\n },\r\n },\r\n '999'\r\n );\r\n const lineNumbers = h(\r\n 'div',\r\n {\r\n staticClass: 'prism-editor__line-numbers',\r\n style: {\r\n 'min-height': this.lineNumbersHeight,\r\n },\r\n attrs: {\r\n 'aria-hidden': 'true',\r\n },\r\n },\r\n [\r\n lineNumberWidthCalculator,\r\n Array.from(Array(this.lineNumbersCount).keys()).map((_, index) => {\r\n return h('div', { attrs: { class: 'prism-editor__line-number token comment' } }, `${++index}`);\r\n }),\r\n ]\r\n );\r\n\r\n const autocompleteList = (this.autocompleteOpen && this.autocompleteData.length) ? h(\r\n 'ul',\r\n {\r\n staticClass: 'prism-editor__autocomplete',\r\n style: {left: this.cursorOffset[0] + 'px', top: this.cursorOffset[1] + 'px'}\r\n },\r\n this.autocompleteData.map((data: AutocompleteEntry, i) => {\r\n return h('li', {\r\n key: data.text,\r\n class: {selected: i == this.autocompleteIndex},\r\n on: {\r\n mousedown: ($event: MouseEvent) => {\r\n this.acceptAutocomplete($event, i);\r\n }\r\n }\r\n }, [data.label || data.text]);\r\n })\r\n ) : undefined;\r\n\r\n const textarea = h('textarea', {\r\n ref: 'textarea',\r\n on: {\r\n input: this.handleChange,\r\n keydown: this.handleKeyDown,\r\n click: ($event: MouseEvent) => {\r\n this.autocompleteOpen = false;\r\n this.$emit('click', $event);\r\n },\r\n keyup: ($event: KeyboardEvent) => {\r\n this.$emit('keyup', $event);\r\n },\r\n focus: ($event: FocusEvent) => {\r\n this._recordStateIfChange();\r\n this.$emit('focus', $event);\r\n },\r\n blur: ($event: FocusEvent) => {\r\n this.autocompleteOpen = false;\r\n this.$emit('blur', $event);\r\n },\r\n },\r\n staticClass: 'prism-editor__textarea',\r\n class: {\r\n 'prism-editor__textarea--empty': this.isEmpty,\r\n },\r\n attrs: {\r\n spellCheck: 'false',\r\n autocapitalize: 'off',\r\n autocomplete: 'off',\r\n autocorrect: 'off',\r\n 'data-gramm': 'false',\r\n placeholder: this.placeholder,\r\n 'data-testid': 'textarea',\r\n readonly: this.readonly,\r\n },\r\n domProps: {\r\n value: this.codeData,\r\n },\r\n });\r\n const preview = h('pre', {\r\n ref: 'pre',\r\n staticClass: 'prism-editor__editor',\r\n attrs: {\r\n 'data-testid': 'preview',\r\n },\r\n domProps: {\r\n innerHTML: this.content,\r\n },\r\n });\r\n const editorContainer = h('div', { staticClass: 'prism-editor__container' }, [textarea, preview]);\r\n const wrapper = h('div', { staticClass: 'prism-editor-wrapper', ref: 'wrapper' }, [this.lineNumbers && lineNumbers, editorContainer]);\r\n return h('div', { staticClass: 'prism-editor-component' }, [wrapper, autocompleteList]);\r\n },\r\n});\r\n"],"names":["BRACKET_PAIRS","isWindows","global","test","navigator","platform","isMacLike","PrismEditor","Vue","extend","props","lineNumbers","type","Boolean","autoStyleLineNumbers","readonly","value","String","highlight","Function","required","tabSize","Number","insertSpaces","ignoreTabKey","placeholder","autocomplete","data","capture","history","stack","offset","lineNumbersHeight","codeData","autocompleteOpen","autocompleteIndex","autocompleteData","watch","immediate","handler","newVal","content","this","$nextTick","_this","setLineNumbersHeight","_this2","styleLineNumbers","nextTick","node","_this3","$el","querySelector","scrollIntoView","block","computed","isEmpty","length","lineNumbersCount","split","cursorOffset","input","$refs","textarea","wrapper","lines","substring","selectionEnd","font_size","parseFloat","getComputedStyle","getPropertyValue","line","Math","min","scrollLeft","clientWidth","scrollTop","mounted","_recordCurrentState","methods","updateAutocompleteData","old_length","splice","Infinity","max","acceptAutocomplete","event","option","preventDefault","undefined","suggestion","overlap","result","substr","text","join","cursor_pos","endsWith","selectionStart","_applyEdits","inserted_characters","setTimeout","_this4","pre","height","$editor","$lineNumbers","editorStyles","window","btlr","bblr","style","forEach","_recordChange","_getLines","position","_recordStateIfChange","record","last","_updateInput","overwrite","slice","count","extras","timestamp","Date","now","re","previous","pop","_this$_getLines$pop","match","current","_this$_getLines$pop2","startsWith","push","$emit","handleChange","e","target","_undoEdit","_redoEdit","handleKeyDown","$listeners","keydown","defaultPrevented","keyCode","stopPropagation","blur","tabCharacter","repeat","shiftKey","linesBeforeCaret","startLine","endLine","nextValue","map","i","startLineText","updatedSelection","hasSelection","matches","indent","key","metaKey","ctrlKey","altKey","_this5","render","h","lineNumberWidthCalculator","attrs","staticClass","Array","from","keys","_","index","autocompleteList","left","top","selected","_this6","on","mousedown","$event","label","ref","click","keyup","focus","spellCheck","autocapitalize","autocorrect","domProps","preview","innerHTML","editorContainer"],"mappings":"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"} \ No newline at end of file diff --git a/packages/vue-prism-editor/dist/prismeditor.esm.js b/packages/vue-prism-editor/dist/prismeditor.esm.js index ec7682f..0f87c75 100644 --- a/packages/vue-prism-editor/dist/prismeditor.esm.js +++ b/packages/vue-prism-editor/dist/prismeditor.esm.js @@ -73,6 +73,12 @@ var PrismEditor = /*#__PURE__*/Vue.extend({ placeholder: { type: String, "default": '' + }, + autocomplete: { + type: Function, + "default": function _default() { + return []; + } } }, data: function data() { @@ -83,7 +89,10 @@ var PrismEditor = /*#__PURE__*/Vue.extend({ offset: -1 }, lineNumbersHeight: '20px', - codeData: '' + codeData: '', + autocompleteOpen: false, + autocompleteIndex: 0, + autocompleteData: [] }; }, watch: { @@ -117,6 +126,17 @@ var PrismEditor = /*#__PURE__*/Vue.extend({ _this2.setLineNumbersHeight(); }); + }, + autocompleteIndex: function autocompleteIndex() { + var _this3 = this; + + Vue.nextTick(function () { + var node = _this3.$el.querySelector('ul.prism-editor__autocomplete > li.selected'); + + if (node) node.scrollIntoView({ + block: 'nearest' + }); + }); } }, computed: { @@ -131,6 +151,16 @@ var PrismEditor = /*#__PURE__*/Vue.extend({ lineNumbersCount: function lineNumbersCount() { var totalLines = this.codeData.split(/\r\n|\n/).length; return totalLines; + }, + cursorOffset: function cursorOffset() { + var text = this.codeData; + var input = this.$refs.textarea; + var wrapper = this.$refs.wrapper; + var lines = text.substring(0, input.selectionEnd || 0).split(/\r\n|\n/); + var font_size = parseFloat(getComputedStyle(input).getPropertyValue('font-size')); + var line = lines.length; + var column = lines[lines.length - 1].length; + return [Math.min(column * 8.85 * (font_size / 16) - wrapper.scrollLeft, wrapper.clientWidth - Math.min(240, wrapper.clientWidth)), line * 24.0 * (font_size / 16) + 2 - wrapper.scrollTop]; } }, mounted: function mounted() { @@ -139,6 +169,53 @@ var PrismEditor = /*#__PURE__*/Vue.extend({ this.styleLineNumbers(); }, methods: { + updateAutocompleteData: function updateAutocompleteData() { + var _this$autocompleteDat; + + var input = this.$refs.textarea; + var data = typeof this.autocomplete == 'function' ? this.autocomplete(this.codeData, input.selectionEnd) : []; + var old_length = this.autocompleteData.length; + + (_this$autocompleteDat = this.autocompleteData).splice.apply(_this$autocompleteDat, [0, Infinity].concat(data)); + + this.autocompleteOpen = true; + this.autocompleteIndex = Math.max(0, Math.min(this.autocompleteIndex, this.autocompleteData.length - 1)); + if (old_length > this.autocompleteData.length) this.autocompleteIndex = 0; + }, + acceptAutocomplete: function acceptAutocomplete(event, option) { + var _this4 = this; + + event.preventDefault(); + if (option == undefined) option = this.autocompleteIndex; + var input = this.$refs.textarea; + var wrapper = this.$refs.wrapper; + var suggestion = this.autocompleteData[option] || this.autocompleteData[0]; + if (!suggestion) return; + var overlap = suggestion.overlap || 0; + var new_text = [this.codeData.substr(0, input.selectionEnd - overlap), suggestion.text, this.codeData.substring(input.selectionEnd)]; + var result = new_text.join(''); + var cursor_pos = input.selectionEnd - overlap + suggestion.text.length + (suggestion.text.endsWith(')') ? -1 : 0); + input.selectionStart = input.selectionEnd = cursor_pos; + + this._applyEdits({ + value: result, + selectionStart: cursor_pos, + selectionEnd: cursor_pos + }); + + var inserted_characters = suggestion.text.length - suggestion.overlap; + Vue.nextTick(function () { + wrapper.scrollLeft += inserted_characters * 8.85; + }); + + if (suggestion.text.endsWith('.')) { + setTimeout(function () { + _this4.updateAutocompleteData(); + }, 1); + } else { + this.autocompleteOpen = false; + } + }, setLineNumbersHeight: function setLineNumbersHeight() { this.lineNumbersHeight = getComputedStyle(this.$refs.pre).height; }, @@ -312,6 +389,8 @@ var PrismEditor = /*#__PURE__*/Vue.extend({ } }, handleKeyDown: function handleKeyDown(e) { + var _this5 = this; + // console.log(navigator.platform); var tabSize = this.tabSize, insertSpaces = this.insertSpaces, @@ -326,6 +405,36 @@ var PrismEditor = /*#__PURE__*/Vue.extend({ } } + if (e.keyCode === 9 && this.autocompleteData.length && this.autocompleteOpen) { + this.acceptAutocomplete(e); + e.preventDefault(); + e.stopPropagation(); + return; + } + + if (e.keyCode === 27) { + // Escape + if (this.autocompleteData.length && this.autocompleteOpen) { + e.preventDefault(); + this.autocompleteOpen = false; + return; + } + } else if (e.keyCode === 38) { + // Up + if (this.autocompleteData.length && this.autocompleteOpen) { + e.preventDefault(); + this.autocompleteIndex = (this.autocompleteIndex ? this.autocompleteIndex : this.autocompleteData.length) - 1; + return; + } + } else if (e.keyCode === 40) { + // Down + if (this.autocompleteData.length && this.autocompleteOpen) { + e.preventDefault(); + this.autocompleteIndex = (this.autocompleteIndex + 1) % this.autocompleteData.length; + return; + } + } + if (e.keyCode === KEYCODE_ESCAPE) { e.target.blur(); this.$emit('blur', e); @@ -421,8 +530,9 @@ var PrismEditor = /*#__PURE__*/Vue.extend({ }); } } else if (e.keyCode === KEYCODE_ENTER) { - // Ignore selections - if (selectionStart === selectionEnd) { + if (this.autocompleteData.length && this.autocompleteOpen) { + this.acceptAutocomplete(e); + } else if (selectionStart === selectionEnd) { // Get the current line var line = this._getLines(value, selectionStart).pop(); @@ -474,10 +584,16 @@ var PrismEditor = /*#__PURE__*/Vue.extend({ this.capture = !this.capture; } + + if (e.keyCode !== 13 && e.keyCode !== 9) { + setTimeout(function () { + _this5.updateAutocompleteData(); + }, 1); + } } }, render: function render(h) { - var _this3 = this; + var _this6 = this; var lineNumberWidthCalculator = h('div', { attrs: { @@ -500,24 +616,47 @@ var PrismEditor = /*#__PURE__*/Vue.extend({ } }, "" + ++index); })]); + var autocompleteList = this.autocompleteOpen && this.autocompleteData.length ? h('ul', { + staticClass: 'prism-editor__autocomplete', + style: { + left: this.cursorOffset[0] + 'px', + top: this.cursorOffset[1] + 'px' + } + }, this.autocompleteData.map(function (data, i) { + return h('li', { + key: data.text, + "class": { + selected: i == _this6.autocompleteIndex + }, + on: { + mousedown: function mousedown($event) { + _this6.acceptAutocomplete($event, i); + } + } + }, [data.label || data.text]); + })) : undefined; var textarea = h('textarea', { ref: 'textarea', on: { input: this.handleChange, keydown: this.handleKeyDown, click: function click($event) { - _this3.$emit('click', $event); + _this6.autocompleteOpen = false; + + _this6.$emit('click', $event); }, keyup: function keyup($event) { - _this3.$emit('keyup', $event); + _this6.$emit('keyup', $event); }, focus: function focus($event) { - _this3._recordStateIfChange(); + _this6._recordStateIfChange(); - _this3.$emit('focus', $event); + _this6.$emit('focus', $event); }, blur: function blur($event) { - _this3.$emit('blur', $event); + _this6.autocompleteOpen = false; + + _this6.$emit('blur', $event); } }, staticClass: 'prism-editor__textarea', @@ -551,9 +690,13 @@ var PrismEditor = /*#__PURE__*/Vue.extend({ var editorContainer = h('div', { staticClass: 'prism-editor__container' }, [textarea, preview]); - return h('div', { - staticClass: 'prism-editor-wrapper' + var wrapper = h('div', { + staticClass: 'prism-editor-wrapper', + ref: 'wrapper' }, [this.lineNumbers && lineNumbers, editorContainer]); + return h('div', { + staticClass: 'prism-editor-component' + }, [wrapper, autocompleteList]); } }); diff --git a/packages/vue-prism-editor/dist/prismeditor.esm.js.map b/packages/vue-prism-editor/dist/prismeditor.esm.js.map index 2300e6c..8646ae4 100644 --- a/packages/vue-prism-editor/dist/prismeditor.esm.js.map +++ b/packages/vue-prism-editor/dist/prismeditor.esm.js.map @@ -1 +1 @@ -{"version":3,"file":"prismeditor.esm.js","sources":["../src/Editor.ts"],"sourcesContent":["import Vue, { VNode } from 'vue';\r\n\r\nimport './styles.css';\r\nconst KEYCODE_ENTER = 13;\r\nconst KEYCODE_TAB = 9;\r\nconst KEYCODE_BACKSPACE = 8;\r\nconst KEYCODE_Y = 89;\r\nconst KEYCODE_Z = 90;\r\nconst KEYCODE_M = 77;\r\nconst KEYCODE_ESCAPE = 27;\r\n\r\nconst BRACKET_PAIRS: {[opening: string]: string} = {\r\n '(':')',\r\n '{':'}',\r\n '[':']',\r\n '\"':'\"',\r\n \"'\":\"'\",\r\n};\r\n\r\nconst HISTORY_LIMIT = 100;\r\nconst HISTORY_TIME_GAP = 3000;\r\n\r\nconst isWindows = 'navigator' in global && /Win/i.test(navigator.platform);\r\nconst isMacLike = 'navigator' in global && /(Mac|iPhone|iPod|iPad)/i.test(navigator.platform);\r\n\r\nexport interface EditorProps {\r\n lineNumbers: boolean;\r\n autoStyleLineNumbers: boolean;\r\n readonly: boolean;\r\n value: string;\r\n highlight: () => string;\r\n tabSize: number;\r\n insertSpaces: boolean;\r\n ignoreTabKey: boolean;\r\n placeholder: string;\r\n}\r\nexport interface Record {\r\n value: string;\r\n selectionStart: number;\r\n selectionEnd: number;\r\n}\r\n\r\nexport interface History {\r\n stack: Array;\r\n offset: number;\r\n}\r\n\r\nexport const PrismEditor = Vue.extend({\r\n props: {\r\n lineNumbers: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n autoStyleLineNumbers: {\r\n type: Boolean,\r\n default: true,\r\n },\r\n readonly: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n value: {\r\n type: String,\r\n default: '',\r\n },\r\n highlight: {\r\n type: Function,\r\n required: true,\r\n },\r\n tabSize: {\r\n type: Number,\r\n default: 2,\r\n },\r\n insertSpaces: {\r\n type: Boolean,\r\n default: true,\r\n },\r\n ignoreTabKey: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n placeholder: {\r\n type: String,\r\n default: '',\r\n },\r\n },\r\n data() {\r\n return {\r\n capture: true,\r\n history: {\r\n stack: [],\r\n offset: -1,\r\n } as History,\r\n lineNumbersHeight: '20px',\r\n codeData: '',\r\n };\r\n },\r\n watch: {\r\n value: {\r\n immediate: true,\r\n handler(newVal: string): void {\r\n if (!newVal) {\r\n this.codeData = '';\r\n } else {\r\n this.codeData = newVal;\r\n }\r\n },\r\n },\r\n content: {\r\n immediate: true,\r\n handler(): void {\r\n if (this.lineNumbers) {\r\n this.$nextTick(() => {\r\n this.setLineNumbersHeight();\r\n });\r\n }\r\n },\r\n },\r\n lineNumbers(): void {\r\n this.$nextTick(() => {\r\n this.styleLineNumbers();\r\n this.setLineNumbersHeight();\r\n });\r\n },\r\n },\r\n computed: {\r\n isEmpty(): boolean {\r\n return this.codeData.length === 0;\r\n },\r\n content(): string {\r\n const result = this.highlight(this.codeData) + '
';\r\n // todo: VNode support?\r\n return result;\r\n },\r\n lineNumbersCount(): number {\r\n const totalLines = this.codeData.split(/\\r\\n|\\n/).length;\r\n return totalLines;\r\n },\r\n },\r\n mounted() {\r\n this._recordCurrentState();\r\n this.styleLineNumbers();\r\n },\r\n\r\n methods: {\r\n setLineNumbersHeight(): void {\r\n this.lineNumbersHeight = getComputedStyle(this.$refs.pre as HTMLTextAreaElement).height;\r\n },\r\n styleLineNumbers(): void {\r\n if (!this.lineNumbers || !this.autoStyleLineNumbers) return;\r\n\r\n const $editor = this.$refs.pre as HTMLTextAreaElement;\r\n const $lineNumbers: HTMLDivElement | null = this.$el.querySelector('.prism-editor__line-numbers');\r\n const editorStyles = window.getComputedStyle($editor);\r\n\r\n this.$nextTick(() => {\r\n const btlr: any = 'border-top-left-radius';\r\n const bblr: any = 'border-bottom-left-radius';\r\n if (!$lineNumbers) return;\r\n $lineNumbers.style[btlr] = editorStyles[btlr];\r\n $lineNumbers.style[bblr] = editorStyles[bblr];\r\n $editor.style[btlr] = '0';\r\n $editor.style[bblr] = '0';\r\n\r\n const stylesList = ['background-color', 'margin-top', 'padding-top', 'font-family', 'font-size', 'line-height'];\r\n stylesList.forEach((style: any) => {\r\n $lineNumbers.style[style] = editorStyles[style];\r\n });\r\n $lineNumbers.style['margin-bottom' as any] = '-' + editorStyles['padding-top' as any];\r\n });\r\n },\r\n _recordCurrentState(): void {\r\n const input = this.$refs.textarea as HTMLTextAreaElement;\r\n\r\n if (!input) return;\r\n // Save current state of the input\r\n const { value, selectionStart, selectionEnd } = input;\r\n\r\n this._recordChange({\r\n value,\r\n selectionStart,\r\n selectionEnd,\r\n });\r\n },\r\n _getLines(text: string, position: number): Array {\r\n return text.substring(0, position).split('\\n');\r\n },\r\n _recordStateIfChange(): void {\r\n if (this.history.stack[this.history.offset].value != this.codeData) {\r\n this._recordChange({\r\n value: this.codeData,\r\n selectionStart: this.codeData.length,\r\n selectionEnd: this.codeData.length,\r\n });\r\n }\r\n },\r\n _applyEdits(record: Record): void {\r\n // Save last selection state\r\n const input = this.$refs.textarea as HTMLTextAreaElement;\r\n const last = this.history.stack[this.history.offset];\r\n\r\n if (last && input) {\r\n this.history.stack[this.history.offset] = {\r\n ...last,\r\n selectionStart: input.selectionStart,\r\n selectionEnd: input.selectionEnd,\r\n };\r\n }\r\n\r\n // Save the changes\r\n this._recordChange(record);\r\n this._updateInput(record);\r\n },\r\n _recordChange(record: Record, overwrite = false): void {\r\n const { stack, offset } = this.history;\r\n\r\n if (stack.length && offset > -1) {\r\n // When something updates, drop the redo operations\r\n this.history.stack = stack.slice(0, offset + 1);\r\n\r\n // Limit the number of operations to 100\r\n const count = this.history.stack.length;\r\n\r\n if (count > HISTORY_LIMIT) {\r\n const extras = count - HISTORY_LIMIT;\r\n\r\n this.history.stack = stack.slice(extras, count);\r\n this.history.offset = Math.max(this.history.offset - extras, 0);\r\n }\r\n }\r\n\r\n const timestamp = Date.now();\r\n\r\n if (overwrite) {\r\n const last = this.history.stack[this.history.offset];\r\n\r\n if (last && timestamp - last.timestamp < HISTORY_TIME_GAP) {\r\n // A previous entry exists and was in short interval\r\n\r\n // Match the last word in the line\r\n const re = /[^a-z0-9]([a-z0-9]+)$/i;\r\n\r\n // Get the previous line\r\n const previous = this._getLines(last.value, last.selectionStart).pop()?.match(re);\r\n\r\n // Get the current line\r\n const current = this._getLines(record.value, record.selectionStart).pop()?.match(re);\r\n\r\n if (previous && current && current[1].startsWith(previous[1])) {\r\n // The last word of the previous line and current line match\r\n // Overwrite previous entry so that undo will remove whole word\r\n this.history.stack[this.history.offset] = {\r\n ...record,\r\n timestamp,\r\n };\r\n\r\n return;\r\n }\r\n }\r\n }\r\n\r\n // Add the new operation to the stack\r\n this.history.stack.push({ ...record, timestamp });\r\n this.history.offset++;\r\n },\r\n\r\n _updateInput(record: Record): void {\r\n const input = this.$refs.textarea as HTMLTextAreaElement;\r\n\r\n if (!input) return;\r\n\r\n // Update values and selection state\r\n input.value = record.value;\r\n input.selectionStart = record.selectionStart;\r\n input.selectionEnd = record.selectionEnd;\r\n\r\n this.$emit('input', record.value);\r\n // this.props.onValueChange(record.value);\r\n },\r\n handleChange(e: KeyboardEvent): void {\r\n const { value, selectionStart, selectionEnd } = e.target as HTMLTextAreaElement;\r\n\r\n this._recordChange(\r\n {\r\n value,\r\n selectionStart,\r\n selectionEnd,\r\n },\r\n true\r\n );\r\n this.$emit('input', value);\r\n // this.props.onValueChange(value);\r\n },\r\n _undoEdit(): void {\r\n const { stack, offset } = this.history;\r\n\r\n // Get the previous edit\r\n const record = stack[offset - 1];\r\n\r\n if (record) {\r\n // Apply the changes and update the offset\r\n this._updateInput(record);\r\n this.history.offset = Math.max(offset - 1, 0);\r\n }\r\n },\r\n _redoEdit(): void {\r\n const { stack, offset } = this.history;\r\n\r\n // Get the next edit\r\n const record = stack[offset + 1];\r\n\r\n if (record) {\r\n // Apply the changes and update the offset\r\n this._updateInput(record);\r\n this.history.offset = Math.min(offset + 1, stack.length - 1);\r\n }\r\n },\r\n handleKeyDown(e: KeyboardEvent): void {\r\n // console.log(navigator.platform);\r\n const { tabSize, insertSpaces, ignoreTabKey } = this;\r\n\r\n if (this.$listeners.keydown) {\r\n // onKeyDown(e);\r\n this.$emit('keydown', e);\r\n\r\n if (e.defaultPrevented) {\r\n return;\r\n }\r\n }\r\n\r\n if (e.keyCode === KEYCODE_ESCAPE) {\r\n (e.target).blur();\r\n this.$emit('blur', e);\r\n }\r\n\r\n const { value, selectionStart, selectionEnd } = e.target as HTMLTextAreaElement;\r\n\r\n const tabCharacter = (insertSpaces ? ' ' : '\\t').repeat(tabSize);\r\n\r\n if (e.keyCode === KEYCODE_TAB && !ignoreTabKey && this.capture) {\r\n // Prevent focus change\r\n e.preventDefault();\r\n\r\n if (e.shiftKey) {\r\n // Unindent selected lines\r\n const linesBeforeCaret = this._getLines(value, selectionStart);\r\n const startLine = linesBeforeCaret.length - 1;\r\n const endLine = this._getLines(value, selectionEnd).length - 1;\r\n const nextValue = value\r\n .split('\\n')\r\n .map((line, i) => {\r\n if (i >= startLine && i <= endLine && line.startsWith(tabCharacter)) {\r\n return line.substring(tabCharacter.length);\r\n }\r\n\r\n return line;\r\n })\r\n .join('\\n');\r\n\r\n if (value !== nextValue) {\r\n const startLineText = linesBeforeCaret[startLine];\r\n\r\n this._applyEdits({\r\n value: nextValue,\r\n // Move the start cursor if first line in selection was modified\r\n // It was modified only if it started with a tab\r\n selectionStart: startLineText.startsWith(tabCharacter)\r\n ? selectionStart - tabCharacter.length\r\n : selectionStart,\r\n // Move the end cursor by total number of characters removed\r\n selectionEnd: selectionEnd - (value.length - nextValue.length),\r\n });\r\n }\r\n } else if (selectionStart !== selectionEnd) {\r\n // Indent selected lines\r\n const linesBeforeCaret = this._getLines(value, selectionStart);\r\n const startLine = linesBeforeCaret.length - 1;\r\n const endLine = this._getLines(value, selectionEnd).length - 1;\r\n const startLineText = linesBeforeCaret[startLine];\r\n\r\n this._applyEdits({\r\n value: value\r\n .split('\\n')\r\n .map((line, i) => {\r\n if (i >= startLine && i <= endLine) {\r\n return tabCharacter + line;\r\n }\r\n\r\n return line;\r\n })\r\n .join('\\n'),\r\n // Move the start cursor by number of characters added in first line of selection\r\n // Don't move it if it there was no text before cursor\r\n selectionStart: /\\S/.test(startLineText) ? selectionStart + tabCharacter.length : selectionStart,\r\n // Move the end cursor by total number of characters added\r\n selectionEnd: selectionEnd + tabCharacter.length * (endLine - startLine + 1),\r\n });\r\n } else {\r\n const updatedSelection = selectionStart + tabCharacter.length;\r\n\r\n this._applyEdits({\r\n // Insert tab character at caret\r\n value: value.substring(0, selectionStart) + tabCharacter + value.substring(selectionEnd),\r\n // Update caret position\r\n selectionStart: updatedSelection,\r\n selectionEnd: updatedSelection,\r\n });\r\n }\r\n } else if (e.keyCode === KEYCODE_BACKSPACE) {\r\n const hasSelection = selectionStart !== selectionEnd;\r\n const textBeforeCaret = value.substring(0, selectionStart);\r\n\r\n if (textBeforeCaret.endsWith(tabCharacter) && !hasSelection) {\r\n // Prevent default delete behaviour\r\n e.preventDefault();\r\n\r\n const updatedSelection = selectionStart - tabCharacter.length;\r\n\r\n this._applyEdits({\r\n // Remove tab character at caret\r\n value: value.substring(0, selectionStart - tabCharacter.length) + value.substring(selectionEnd),\r\n // Update caret position\r\n selectionStart: updatedSelection,\r\n selectionEnd: updatedSelection,\r\n });\r\n }\r\n } else if (e.keyCode === KEYCODE_ENTER) {\r\n // Ignore selections\r\n if (selectionStart === selectionEnd) {\r\n // Get the current line\r\n const line = this._getLines(value, selectionStart).pop();\r\n const matches = line?.match(/^\\s+/);\r\n\r\n if (matches && matches[0]) {\r\n e.preventDefault();\r\n\r\n // Preserve indentation on inserting a new line\r\n const indent = '\\n' + matches[0];\r\n const updatedSelection = selectionStart + indent.length;\r\n\r\n this._applyEdits({\r\n // Insert indentation character at caret\r\n value: value.substring(0, selectionStart) + indent + value.substring(selectionEnd),\r\n // Update caret position\r\n selectionStart: updatedSelection,\r\n selectionEnd: updatedSelection,\r\n });\r\n }\r\n }\r\n } else if (BRACKET_PAIRS[e.key]) {\r\n // If text is selected, wrap them in the characters\r\n if (selectionStart !== selectionEnd) {\r\n e.preventDefault();\r\n\r\n this._applyEdits({\r\n value:\r\n value.substring(0, selectionStart) +\r\n e.key +\r\n value.substring(selectionStart, selectionEnd) +\r\n BRACKET_PAIRS[e.key] +\r\n value.substring(selectionEnd),\r\n // Update caret position\r\n selectionStart: selectionStart + 1,\r\n selectionEnd: selectionEnd + 1,\r\n });\r\n }\r\n } else if (\r\n (isMacLike\r\n ? // Trigger undo with ⌘+Z on Mac\r\n e.metaKey && e.keyCode === KEYCODE_Z\r\n : // Trigger undo with Ctrl+Z on other platforms\r\n e.ctrlKey && e.keyCode === KEYCODE_Z) &&\r\n !e.shiftKey &&\r\n !e.altKey\r\n ) {\r\n e.preventDefault();\r\n\r\n this._undoEdit();\r\n } else if (\r\n (isMacLike\r\n ? // Trigger redo with ⌘+Shift+Z on Mac\r\n e.metaKey && e.keyCode === KEYCODE_Z && e.shiftKey\r\n : isWindows\r\n ? // Trigger redo with Ctrl+Y on Windows\r\n e.ctrlKey && e.keyCode === KEYCODE_Y\r\n : // Trigger redo with Ctrl+Shift+Z on other platforms\r\n e.ctrlKey && e.keyCode === KEYCODE_Z && e.shiftKey) &&\r\n !e.altKey\r\n ) {\r\n e.preventDefault();\r\n\r\n this._redoEdit();\r\n } else if (e.keyCode === KEYCODE_M && e.ctrlKey && (isMacLike ? e.shiftKey : true)) {\r\n e.preventDefault();\r\n\r\n // Toggle capturing tab key so users can focus away\r\n this.capture = !this.capture;\r\n }\r\n },\r\n },\r\n render(h): VNode {\r\n const lineNumberWidthCalculator = h(\r\n 'div',\r\n {\r\n attrs: {\r\n class: 'prism-editor__line-width-calc',\r\n style: 'height: 0px; visibility: hidden; pointer-events: none;',\r\n },\r\n },\r\n '999'\r\n );\r\n const lineNumbers = h(\r\n 'div',\r\n {\r\n staticClass: 'prism-editor__line-numbers',\r\n style: {\r\n 'min-height': this.lineNumbersHeight,\r\n },\r\n attrs: {\r\n 'aria-hidden': 'true',\r\n },\r\n },\r\n [\r\n lineNumberWidthCalculator,\r\n Array.from(Array(this.lineNumbersCount).keys()).map((_, index) => {\r\n return h('div', { attrs: { class: 'prism-editor__line-number token comment' } }, `${++index}`);\r\n }),\r\n ]\r\n );\r\n\r\n const textarea = h('textarea', {\r\n ref: 'textarea',\r\n on: {\r\n input: this.handleChange,\r\n keydown: this.handleKeyDown,\r\n click: ($event: MouseEvent) => {\r\n this.$emit('click', $event);\r\n },\r\n keyup: ($event: KeyboardEvent) => {\r\n this.$emit('keyup', $event);\r\n },\r\n focus: ($event: FocusEvent) => {\r\n this._recordStateIfChange();\r\n this.$emit('focus', $event);\r\n },\r\n blur: ($event: FocusEvent) => {\r\n this.$emit('blur', $event);\r\n },\r\n },\r\n staticClass: 'prism-editor__textarea',\r\n class: {\r\n 'prism-editor__textarea--empty': this.isEmpty,\r\n },\r\n attrs: {\r\n spellCheck: 'false',\r\n autocapitalize: 'off',\r\n autocomplete: 'off',\r\n autocorrect: 'off',\r\n 'data-gramm': 'false',\r\n placeholder: this.placeholder,\r\n 'data-testid': 'textarea',\r\n readonly: this.readonly,\r\n },\r\n domProps: {\r\n value: this.codeData,\r\n },\r\n });\r\n const preview = h('pre', {\r\n ref: 'pre',\r\n staticClass: 'prism-editor__editor',\r\n attrs: {\r\n 'data-testid': 'preview',\r\n },\r\n domProps: {\r\n innerHTML: this.content,\r\n },\r\n });\r\n const editorContainer = h('div', { staticClass: 'prism-editor__container' }, [textarea, preview]);\r\n return h('div', { staticClass: 'prism-editor-wrapper' }, [this.lineNumbers && lineNumbers, editorContainer]);\r\n },\r\n});\r\n"],"names":["KEYCODE_ENTER","KEYCODE_TAB","KEYCODE_BACKSPACE","KEYCODE_Y","KEYCODE_Z","KEYCODE_M","KEYCODE_ESCAPE","BRACKET_PAIRS","HISTORY_LIMIT","HISTORY_TIME_GAP","isWindows","global","test","navigator","platform","isMacLike","PrismEditor","Vue","extend","props","lineNumbers","type","Boolean","autoStyleLineNumbers","readonly","value","String","highlight","Function","required","tabSize","Number","insertSpaces","ignoreTabKey","placeholder","data","capture","history","stack","offset","lineNumbersHeight","codeData","watch","immediate","handler","newVal","content","$nextTick","setLineNumbersHeight","styleLineNumbers","computed","isEmpty","length","result","lineNumbersCount","totalLines","split","mounted","_recordCurrentState","methods","getComputedStyle","$refs","pre","height","$editor","$lineNumbers","$el","querySelector","editorStyles","window","btlr","bblr","style","stylesList","forEach","input","textarea","selectionStart","selectionEnd","_recordChange","_getLines","text","position","substring","_recordStateIfChange","_applyEdits","record","last","_updateInput","overwrite","slice","count","extras","Math","max","timestamp","Date","now","re","previous","pop","match","current","startsWith","push","$emit","handleChange","e","target","_undoEdit","_redoEdit","min","handleKeyDown","$listeners","keydown","defaultPrevented","keyCode","blur","tabCharacter","repeat","preventDefault","shiftKey","linesBeforeCaret","startLine","endLine","nextValue","map","line","i","join","startLineText","updatedSelection","hasSelection","textBeforeCaret","endsWith","matches","indent","key","metaKey","ctrlKey","altKey","render","h","lineNumberWidthCalculator","attrs","staticClass","Array","from","keys","_","index","ref","on","click","$event","keyup","focus","spellCheck","autocapitalize","autocomplete","autocorrect","domProps","preview","innerHTML","editorContainer"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"prismeditor.esm.js","sources":["../src/Editor.ts"],"sourcesContent":["import Vue, { VNode } from 'vue';\r\n\r\nimport './styles.css';\r\nconst KEYCODE_ENTER = 13;\r\nconst KEYCODE_TAB = 9;\r\nconst KEYCODE_BACKSPACE = 8;\r\nconst KEYCODE_Y = 89;\r\nconst KEYCODE_Z = 90;\r\nconst KEYCODE_M = 77;\r\nconst KEYCODE_ESCAPE = 27;\r\n\r\nconst BRACKET_PAIRS: {[opening: string]: string} = {\r\n '(':')',\r\n '{':'}',\r\n '[':']',\r\n '\"':'\"',\r\n \"'\":\"'\",\r\n};\r\n\r\nconst HISTORY_LIMIT = 100;\r\nconst HISTORY_TIME_GAP = 3000;\r\n\r\nconst isWindows = 'navigator' in global && /Win/i.test(navigator.platform);\r\nconst isMacLike = 'navigator' in global && /(Mac|iPhone|iPod|iPad)/i.test(navigator.platform);\r\n\r\nexport interface EditorProps {\r\n lineNumbers: boolean;\r\n autoStyleLineNumbers: boolean;\r\n readonly: boolean;\r\n value: string;\r\n highlight: () => string;\r\n tabSize: number;\r\n insertSpaces: boolean;\r\n ignoreTabKey: boolean;\r\n placeholder: string;\r\n}\r\nexport interface Record {\r\n value: string;\r\n selectionStart: number;\r\n selectionEnd: number;\r\n}\r\n\r\nexport interface History {\r\n stack: Array;\r\n offset: number;\r\n}\r\ninterface AutocompleteEntry {\r\n text: string\r\n overlap: number\r\n label?: string\r\n}\r\n\r\nexport const PrismEditor = Vue.extend({\r\n props: {\r\n lineNumbers: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n autoStyleLineNumbers: {\r\n type: Boolean,\r\n default: true,\r\n },\r\n readonly: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n value: {\r\n type: String,\r\n default: '',\r\n },\r\n highlight: {\r\n type: Function,\r\n required: true,\r\n },\r\n tabSize: {\r\n type: Number,\r\n default: 2,\r\n },\r\n insertSpaces: {\r\n type: Boolean,\r\n default: true,\r\n },\r\n ignoreTabKey: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n placeholder: {\r\n type: String,\r\n default: '',\r\n },\r\n autocomplete: {\r\n type: Function,\r\n default() {\r\n return []\r\n }\r\n }\r\n },\r\n data() {\r\n return {\r\n capture: true,\r\n history: {\r\n stack: [],\r\n offset: -1,\r\n } as History,\r\n lineNumbersHeight: '20px',\r\n codeData: '',\r\n\r\n autocompleteOpen: false,\r\n autocompleteIndex: 0,\r\n autocompleteData: [] as AutocompleteEntry[]\r\n };\r\n },\r\n watch: {\r\n value: {\r\n immediate: true,\r\n handler(newVal: string): void {\r\n if (!newVal) {\r\n this.codeData = '';\r\n } else {\r\n this.codeData = newVal;\r\n }\r\n },\r\n },\r\n content: {\r\n immediate: true,\r\n handler(): void {\r\n if (this.lineNumbers) {\r\n this.$nextTick(() => {\r\n this.setLineNumbersHeight();\r\n });\r\n }\r\n },\r\n },\r\n lineNumbers(): void {\r\n this.$nextTick(() => {\r\n this.styleLineNumbers();\r\n this.setLineNumbersHeight();\r\n });\r\n },\r\n autocompleteIndex() {\r\n Vue.nextTick(() => {\r\n let node = this.$el.querySelector('ul.prism-editor__autocomplete > li.selected');\r\n if (node) node.scrollIntoView({block: 'nearest'});\r\n })\r\n },\r\n },\r\n computed: {\r\n isEmpty(): boolean {\r\n return this.codeData.length === 0;\r\n },\r\n content(): string {\r\n const result = this.highlight(this.codeData) + '
';\r\n // todo: VNode support?\r\n return result;\r\n },\r\n lineNumbersCount(): number {\r\n const totalLines = this.codeData.split(/\\r\\n|\\n/).length;\r\n return totalLines;\r\n },\r\n cursorOffset() {\r\n let text: string = this.codeData;\r\n let input = this.$refs.textarea as HTMLTextAreaElement;\r\n let wrapper = this.$refs.wrapper as HTMLDivElement;\r\n let lines = text.substring(0, input.selectionEnd || 0).split(/\\r\\n|\\n/);\r\n let font_size = parseFloat(getComputedStyle(input).getPropertyValue('font-size'));\r\n let line = lines.length;\r\n let column = lines[lines.length-1].length;\r\n return [\r\n Math.min((column * 8.85 * (font_size / 16)) - wrapper.scrollLeft, wrapper.clientWidth - Math.min(240, wrapper.clientWidth)),\r\n (line * 24.0 * (font_size / 16)) + 2 - wrapper.scrollTop,\r\n ]\r\n },\r\n },\r\n mounted() {\r\n this._recordCurrentState();\r\n this.styleLineNumbers();\r\n },\r\n\r\n methods: {\r\n updateAutocompleteData() {\r\n let input = this.$refs.textarea as HTMLTextAreaElement;\r\n let data: AutocompleteEntry[] = typeof this.autocomplete == 'function' ? this.autocomplete(this.codeData, input.selectionEnd) : [];\r\n let old_length = this.autocompleteData.length;\r\n this.autocompleteData.splice(0, Infinity, ...data);\r\n this.autocompleteOpen = true;\r\n this.autocompleteIndex = Math.max(0, Math.min(this.autocompleteIndex, this.autocompleteData.length-1));\r\n if (old_length > this.autocompleteData.length) this.autocompleteIndex = 0;\r\n },\r\n acceptAutocomplete(event: Event, option?: number) {\r\n event.preventDefault()\r\n if (option == undefined) option = this.autocompleteIndex;\r\n\r\n let input = this.$refs.textarea as HTMLTextAreaElement;\r\n let wrapper = this.$refs.wrapper as HTMLDivElement;\r\n let suggestion = this.autocompleteData[option] || this.autocompleteData[0];\r\n if (!suggestion) return;\r\n \r\n let overlap = suggestion.overlap || 0;\r\n let new_text = [\r\n this.codeData.substr(0, input.selectionEnd - overlap),\r\n suggestion.text,\r\n this.codeData.substring(input.selectionEnd),\r\n ]\r\n let result: string = new_text.join('');\r\n let cursor_pos = input.selectionEnd - overlap + suggestion.text.length + (suggestion.text.endsWith(')') ? -1 : 0);\r\n input.selectionStart = input.selectionEnd = cursor_pos;\r\n\r\n this._applyEdits({\r\n value: result,\r\n selectionStart: cursor_pos,\r\n selectionEnd: cursor_pos,\r\n });\r\n let inserted_characters = suggestion.text.length - suggestion.overlap;\r\n Vue.nextTick(() => {\r\n wrapper.scrollLeft += inserted_characters * 8.85;\r\n })\r\n\r\n if (suggestion.text.endsWith('.')) {\r\n setTimeout(() => {\r\n this.updateAutocompleteData();\r\n }, 1);\r\n } else {\r\n this.autocompleteOpen = false;\r\n }\r\n },\r\n setLineNumbersHeight(): void {\r\n this.lineNumbersHeight = getComputedStyle(this.$refs.pre as HTMLTextAreaElement).height;\r\n },\r\n styleLineNumbers(): void {\r\n if (!this.lineNumbers || !this.autoStyleLineNumbers) return;\r\n\r\n const $editor = this.$refs.pre as HTMLTextAreaElement;\r\n const $lineNumbers: HTMLDivElement | null = this.$el.querySelector('.prism-editor__line-numbers');\r\n const editorStyles = window.getComputedStyle($editor);\r\n\r\n this.$nextTick(() => {\r\n const btlr: any = 'border-top-left-radius';\r\n const bblr: any = 'border-bottom-left-radius';\r\n if (!$lineNumbers) return;\r\n $lineNumbers.style[btlr] = editorStyles[btlr];\r\n $lineNumbers.style[bblr] = editorStyles[bblr];\r\n $editor.style[btlr] = '0';\r\n $editor.style[bblr] = '0';\r\n\r\n const stylesList = ['background-color', 'margin-top', 'padding-top', 'font-family', 'font-size', 'line-height'];\r\n stylesList.forEach((style: any) => {\r\n $lineNumbers.style[style] = editorStyles[style];\r\n });\r\n $lineNumbers.style['margin-bottom' as any] = '-' + editorStyles['padding-top' as any];\r\n });\r\n },\r\n _recordCurrentState(): void {\r\n const input = this.$refs.textarea as HTMLTextAreaElement;\r\n\r\n if (!input) return;\r\n // Save current state of the input\r\n const { value, selectionStart, selectionEnd } = input;\r\n\r\n this._recordChange({\r\n value,\r\n selectionStart,\r\n selectionEnd,\r\n });\r\n },\r\n _getLines(text: string, position: number): Array {\r\n return text.substring(0, position).split('\\n');\r\n },\r\n _recordStateIfChange(): void {\r\n if (this.history.stack[this.history.offset].value != this.codeData) {\r\n this._recordChange({\r\n value: this.codeData,\r\n selectionStart: this.codeData.length,\r\n selectionEnd: this.codeData.length,\r\n });\r\n }\r\n },\r\n _applyEdits(record: Record): void {\r\n // Save last selection state\r\n const input = this.$refs.textarea as HTMLTextAreaElement;\r\n const last = this.history.stack[this.history.offset];\r\n\r\n if (last && input) {\r\n this.history.stack[this.history.offset] = {\r\n ...last,\r\n selectionStart: input.selectionStart,\r\n selectionEnd: input.selectionEnd,\r\n };\r\n }\r\n\r\n // Save the changes\r\n this._recordChange(record);\r\n this._updateInput(record);\r\n },\r\n _recordChange(record: Record, overwrite = false): void {\r\n const { stack, offset } = this.history;\r\n\r\n if (stack.length && offset > -1) {\r\n // When something updates, drop the redo operations\r\n this.history.stack = stack.slice(0, offset + 1);\r\n\r\n // Limit the number of operations to 100\r\n const count = this.history.stack.length;\r\n\r\n if (count > HISTORY_LIMIT) {\r\n const extras = count - HISTORY_LIMIT;\r\n\r\n this.history.stack = stack.slice(extras, count);\r\n this.history.offset = Math.max(this.history.offset - extras, 0);\r\n }\r\n }\r\n\r\n const timestamp = Date.now();\r\n\r\n if (overwrite) {\r\n const last = this.history.stack[this.history.offset];\r\n\r\n if (last && timestamp - last.timestamp < HISTORY_TIME_GAP) {\r\n // A previous entry exists and was in short interval\r\n\r\n // Match the last word in the line\r\n const re = /[^a-z0-9]([a-z0-9]+)$/i;\r\n\r\n // Get the previous line\r\n const previous = this._getLines(last.value, last.selectionStart).pop()?.match(re);\r\n\r\n // Get the current line\r\n const current = this._getLines(record.value, record.selectionStart).pop()?.match(re);\r\n\r\n if (previous && current && current[1].startsWith(previous[1])) {\r\n // The last word of the previous line and current line match\r\n // Overwrite previous entry so that undo will remove whole word\r\n this.history.stack[this.history.offset] = {\r\n ...record,\r\n timestamp,\r\n };\r\n\r\n return;\r\n }\r\n }\r\n }\r\n\r\n // Add the new operation to the stack\r\n this.history.stack.push({ ...record, timestamp });\r\n this.history.offset++;\r\n },\r\n\r\n _updateInput(record: Record): void {\r\n const input = this.$refs.textarea as HTMLTextAreaElement;\r\n\r\n if (!input) return;\r\n\r\n // Update values and selection state\r\n input.value = record.value;\r\n input.selectionStart = record.selectionStart;\r\n input.selectionEnd = record.selectionEnd;\r\n\r\n this.$emit('input', record.value);\r\n // this.props.onValueChange(record.value);\r\n },\r\n handleChange(e: KeyboardEvent): void {\r\n const { value, selectionStart, selectionEnd } = e.target as HTMLTextAreaElement;\r\n\r\n this._recordChange(\r\n {\r\n value,\r\n selectionStart,\r\n selectionEnd,\r\n },\r\n true\r\n );\r\n this.$emit('input', value);\r\n // this.props.onValueChange(value);\r\n },\r\n _undoEdit(): void {\r\n const { stack, offset } = this.history;\r\n\r\n // Get the previous edit\r\n const record = stack[offset - 1];\r\n\r\n if (record) {\r\n // Apply the changes and update the offset\r\n this._updateInput(record);\r\n this.history.offset = Math.max(offset - 1, 0);\r\n }\r\n },\r\n _redoEdit(): void {\r\n const { stack, offset } = this.history;\r\n\r\n // Get the next edit\r\n const record = stack[offset + 1];\r\n\r\n if (record) {\r\n // Apply the changes and update the offset\r\n this._updateInput(record);\r\n this.history.offset = Math.min(offset + 1, stack.length - 1);\r\n }\r\n },\r\n handleKeyDown(e: KeyboardEvent): void {\r\n // console.log(navigator.platform);\r\n const { tabSize, insertSpaces, ignoreTabKey } = this;\r\n\r\n if (this.$listeners.keydown) {\r\n // onKeyDown(e);\r\n this.$emit('keydown', e);\r\n\r\n if (e.defaultPrevented) {\r\n return;\r\n }\r\n }\r\n\r\n if (e.keyCode === 9 && this.autocompleteData.length && this.autocompleteOpen) {\r\n this.acceptAutocomplete(e);\r\n e.preventDefault();\r\n e.stopPropagation();\r\n return;\r\n }\r\n if (e.keyCode === 27) {\r\n // Escape\r\n if (this.autocompleteData.length && this.autocompleteOpen) {\r\n e.preventDefault();\r\n this.autocompleteOpen = false;\r\n return;\r\n }\r\n } else if (e.keyCode === 38) {\r\n // Up\r\n if (this.autocompleteData.length && this.autocompleteOpen) {\r\n e.preventDefault();\r\n this.autocompleteIndex = (this.autocompleteIndex ? this.autocompleteIndex : this.autocompleteData.length) - 1;\r\n return;\r\n }\r\n } else if (e.keyCode === 40) {\r\n // Down\r\n if (this.autocompleteData.length && this.autocompleteOpen) {\r\n e.preventDefault();\r\n this.autocompleteIndex = (this.autocompleteIndex + 1) % this.autocompleteData.length;\r\n return;\r\n }\r\n }\r\n\r\n if (e.keyCode === KEYCODE_ESCAPE) {\r\n (e.target).blur();\r\n this.$emit('blur', e);\r\n }\r\n\r\n const { value, selectionStart, selectionEnd } = e.target as HTMLTextAreaElement;\r\n\r\n const tabCharacter = (insertSpaces ? ' ' : '\\t').repeat(tabSize);\r\n\r\n if (e.keyCode === KEYCODE_TAB && !ignoreTabKey && this.capture) {\r\n // Prevent focus change\r\n e.preventDefault();\r\n\r\n if (e.shiftKey) {\r\n // Unindent selected lines\r\n const linesBeforeCaret = this._getLines(value, selectionStart);\r\n const startLine = linesBeforeCaret.length - 1;\r\n const endLine = this._getLines(value, selectionEnd).length - 1;\r\n const nextValue = value\r\n .split('\\n')\r\n .map((line, i) => {\r\n if (i >= startLine && i <= endLine && line.startsWith(tabCharacter)) {\r\n return line.substring(tabCharacter.length);\r\n }\r\n\r\n return line;\r\n })\r\n .join('\\n');\r\n\r\n if (value !== nextValue) {\r\n const startLineText = linesBeforeCaret[startLine];\r\n\r\n this._applyEdits({\r\n value: nextValue,\r\n // Move the start cursor if first line in selection was modified\r\n // It was modified only if it started with a tab\r\n selectionStart: startLineText.startsWith(tabCharacter)\r\n ? selectionStart - tabCharacter.length\r\n : selectionStart,\r\n // Move the end cursor by total number of characters removed\r\n selectionEnd: selectionEnd - (value.length - nextValue.length),\r\n });\r\n }\r\n } else if (selectionStart !== selectionEnd) {\r\n // Indent selected lines\r\n const linesBeforeCaret = this._getLines(value, selectionStart);\r\n const startLine = linesBeforeCaret.length - 1;\r\n const endLine = this._getLines(value, selectionEnd).length - 1;\r\n const startLineText = linesBeforeCaret[startLine];\r\n\r\n this._applyEdits({\r\n value: value\r\n .split('\\n')\r\n .map((line, i) => {\r\n if (i >= startLine && i <= endLine) {\r\n return tabCharacter + line;\r\n }\r\n\r\n return line;\r\n })\r\n .join('\\n'),\r\n // Move the start cursor by number of characters added in first line of selection\r\n // Don't move it if it there was no text before cursor\r\n selectionStart: /\\S/.test(startLineText) ? selectionStart + tabCharacter.length : selectionStart,\r\n // Move the end cursor by total number of characters added\r\n selectionEnd: selectionEnd + tabCharacter.length * (endLine - startLine + 1),\r\n });\r\n } else {\r\n const updatedSelection = selectionStart + tabCharacter.length;\r\n\r\n this._applyEdits({\r\n // Insert tab character at caret\r\n value: value.substring(0, selectionStart) + tabCharacter + value.substring(selectionEnd),\r\n // Update caret position\r\n selectionStart: updatedSelection,\r\n selectionEnd: updatedSelection,\r\n });\r\n }\r\n } else if (e.keyCode === KEYCODE_BACKSPACE) {\r\n const hasSelection = selectionStart !== selectionEnd;\r\n const textBeforeCaret = value.substring(0, selectionStart);\r\n\r\n if (textBeforeCaret.endsWith(tabCharacter) && !hasSelection) {\r\n // Prevent default delete behaviour\r\n e.preventDefault();\r\n\r\n const updatedSelection = selectionStart - tabCharacter.length;\r\n\r\n this._applyEdits({\r\n // Remove tab character at caret\r\n value: value.substring(0, selectionStart - tabCharacter.length) + value.substring(selectionEnd),\r\n // Update caret position\r\n selectionStart: updatedSelection,\r\n selectionEnd: updatedSelection,\r\n });\r\n }\r\n } else if (e.keyCode === KEYCODE_ENTER) {\r\n \r\n if (this.autocompleteData.length && this.autocompleteOpen) {\r\n this.acceptAutocomplete(e);\r\n\r\n } else if (selectionStart === selectionEnd) {\r\n // Get the current line\r\n const line = this._getLines(value, selectionStart).pop();\r\n const matches = line?.match(/^\\s+/);\r\n\r\n if (matches && matches[0]) {\r\n e.preventDefault();\r\n\r\n // Preserve indentation on inserting a new line\r\n const indent = '\\n' + matches[0];\r\n const updatedSelection = selectionStart + indent.length;\r\n\r\n this._applyEdits({\r\n // Insert indentation character at caret\r\n value: value.substring(0, selectionStart) + indent + value.substring(selectionEnd),\r\n // Update caret position\r\n selectionStart: updatedSelection,\r\n selectionEnd: updatedSelection,\r\n });\r\n }\r\n }\r\n } else if (BRACKET_PAIRS[e.key]) {\r\n // If text is selected, wrap them in the characters\r\n if (selectionStart !== selectionEnd) {\r\n e.preventDefault();\r\n\r\n this._applyEdits({\r\n value:\r\n value.substring(0, selectionStart) +\r\n e.key +\r\n value.substring(selectionStart, selectionEnd) +\r\n BRACKET_PAIRS[e.key] +\r\n value.substring(selectionEnd),\r\n // Update caret position\r\n selectionStart: selectionStart + 1,\r\n selectionEnd: selectionEnd + 1,\r\n });\r\n }\r\n } else if (\r\n (isMacLike\r\n ? // Trigger undo with ⌘+Z on Mac\r\n e.metaKey && e.keyCode === KEYCODE_Z\r\n : // Trigger undo with Ctrl+Z on other platforms\r\n e.ctrlKey && e.keyCode === KEYCODE_Z) &&\r\n !e.shiftKey &&\r\n !e.altKey\r\n ) {\r\n e.preventDefault();\r\n\r\n this._undoEdit();\r\n } else if (\r\n (isMacLike\r\n ? // Trigger redo with ⌘+Shift+Z on Mac\r\n e.metaKey && e.keyCode === KEYCODE_Z && e.shiftKey\r\n : isWindows\r\n ? // Trigger redo with Ctrl+Y on Windows\r\n e.ctrlKey && e.keyCode === KEYCODE_Y\r\n : // Trigger redo with Ctrl+Shift+Z on other platforms\r\n e.ctrlKey && e.keyCode === KEYCODE_Z && e.shiftKey) &&\r\n !e.altKey\r\n ) {\r\n e.preventDefault();\r\n\r\n this._redoEdit();\r\n } else if (e.keyCode === KEYCODE_M && e.ctrlKey && (isMacLike ? e.shiftKey : true)) {\r\n e.preventDefault();\r\n\r\n // Toggle capturing tab key so users can focus away\r\n this.capture = !this.capture;\r\n }\r\n if (e.keyCode !== 13 && e.keyCode !== 9) {\r\n setTimeout(() => {\r\n this.updateAutocompleteData();\r\n }, 1);\r\n }\r\n },\r\n },\r\n render(h): VNode {\r\n const lineNumberWidthCalculator = h(\r\n 'div',\r\n {\r\n attrs: {\r\n class: 'prism-editor__line-width-calc',\r\n style: 'height: 0px; visibility: hidden; pointer-events: none;',\r\n },\r\n },\r\n '999'\r\n );\r\n const lineNumbers = h(\r\n 'div',\r\n {\r\n staticClass: 'prism-editor__line-numbers',\r\n style: {\r\n 'min-height': this.lineNumbersHeight,\r\n },\r\n attrs: {\r\n 'aria-hidden': 'true',\r\n },\r\n },\r\n [\r\n lineNumberWidthCalculator,\r\n Array.from(Array(this.lineNumbersCount).keys()).map((_, index) => {\r\n return h('div', { attrs: { class: 'prism-editor__line-number token comment' } }, `${++index}`);\r\n }),\r\n ]\r\n );\r\n\r\n const autocompleteList = (this.autocompleteOpen && this.autocompleteData.length) ? h(\r\n 'ul',\r\n {\r\n staticClass: 'prism-editor__autocomplete',\r\n style: {left: this.cursorOffset[0] + 'px', top: this.cursorOffset[1] + 'px'}\r\n },\r\n this.autocompleteData.map((data: AutocompleteEntry, i) => {\r\n return h('li', {\r\n key: data.text,\r\n class: {selected: i == this.autocompleteIndex},\r\n on: {\r\n mousedown: ($event: MouseEvent) => {\r\n this.acceptAutocomplete($event, i);\r\n }\r\n }\r\n }, [data.label || data.text]);\r\n })\r\n ) : undefined;\r\n\r\n const textarea = h('textarea', {\r\n ref: 'textarea',\r\n on: {\r\n input: this.handleChange,\r\n keydown: this.handleKeyDown,\r\n click: ($event: MouseEvent) => {\r\n this.autocompleteOpen = false;\r\n this.$emit('click', $event);\r\n },\r\n keyup: ($event: KeyboardEvent) => {\r\n this.$emit('keyup', $event);\r\n },\r\n focus: ($event: FocusEvent) => {\r\n this._recordStateIfChange();\r\n this.$emit('focus', $event);\r\n },\r\n blur: ($event: FocusEvent) => {\r\n this.autocompleteOpen = false;\r\n this.$emit('blur', $event);\r\n },\r\n },\r\n staticClass: 'prism-editor__textarea',\r\n class: {\r\n 'prism-editor__textarea--empty': this.isEmpty,\r\n },\r\n attrs: {\r\n spellCheck: 'false',\r\n autocapitalize: 'off',\r\n autocomplete: 'off',\r\n autocorrect: 'off',\r\n 'data-gramm': 'false',\r\n placeholder: this.placeholder,\r\n 'data-testid': 'textarea',\r\n readonly: this.readonly,\r\n },\r\n domProps: {\r\n value: this.codeData,\r\n },\r\n });\r\n const preview = h('pre', {\r\n ref: 'pre',\r\n staticClass: 'prism-editor__editor',\r\n attrs: {\r\n 'data-testid': 'preview',\r\n },\r\n domProps: {\r\n innerHTML: this.content,\r\n },\r\n });\r\n const editorContainer = h('div', { staticClass: 'prism-editor__container' }, [textarea, preview]);\r\n const wrapper = h('div', { staticClass: 'prism-editor-wrapper', ref: 'wrapper' }, [this.lineNumbers && lineNumbers, editorContainer]);\r\n return h('div', { staticClass: 'prism-editor-component' }, [wrapper, autocompleteList]);\r\n },\r\n});\r\n"],"names":["KEYCODE_ENTER","KEYCODE_TAB","KEYCODE_BACKSPACE","KEYCODE_Y","KEYCODE_Z","KEYCODE_M","KEYCODE_ESCAPE","BRACKET_PAIRS","HISTORY_LIMIT","HISTORY_TIME_GAP","isWindows","global","test","navigator","platform","isMacLike","PrismEditor","Vue","extend","props","lineNumbers","type","Boolean","autoStyleLineNumbers","readonly","value","String","highlight","Function","required","tabSize","Number","insertSpaces","ignoreTabKey","placeholder","autocomplete","data","capture","history","stack","offset","lineNumbersHeight","codeData","autocompleteOpen","autocompleteIndex","autocompleteData","watch","immediate","handler","newVal","content","$nextTick","setLineNumbersHeight","styleLineNumbers","nextTick","node","$el","querySelector","scrollIntoView","block","computed","isEmpty","length","result","lineNumbersCount","totalLines","split","cursorOffset","text","input","$refs","textarea","wrapper","lines","substring","selectionEnd","font_size","parseFloat","getComputedStyle","getPropertyValue","line","column","Math","min","scrollLeft","clientWidth","scrollTop","mounted","_recordCurrentState","methods","updateAutocompleteData","old_length","splice","Infinity","max","acceptAutocomplete","event","option","preventDefault","undefined","suggestion","overlap","new_text","substr","join","cursor_pos","endsWith","selectionStart","_applyEdits","inserted_characters","setTimeout","pre","height","$editor","$lineNumbers","editorStyles","window","btlr","bblr","style","stylesList","forEach","_recordChange","_getLines","position","_recordStateIfChange","record","last","_updateInput","overwrite","slice","count","extras","timestamp","Date","now","re","previous","pop","match","current","startsWith","push","$emit","handleChange","e","target","_undoEdit","_redoEdit","handleKeyDown","$listeners","keydown","defaultPrevented","keyCode","stopPropagation","blur","tabCharacter","repeat","shiftKey","linesBeforeCaret","startLine","endLine","nextValue","map","i","startLineText","updatedSelection","hasSelection","textBeforeCaret","matches","indent","key","metaKey","ctrlKey","altKey","render","h","lineNumberWidthCalculator","attrs","staticClass","Array","from","keys","_","index","autocompleteList","left","top","selected","on","mousedown","$event","label","ref","click","keyup","focus","spellCheck","autocapitalize","autocorrect","domProps","preview","innerHTML","editorContainer"],"mappings":"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"} \ No newline at end of file diff --git a/packages/vue-prism-editor/dist/prismeditor.min.css b/packages/vue-prism-editor/dist/prismeditor.min.css index 7cc9ec1..e4c579c 100644 --- a/packages/vue-prism-editor/dist/prismeditor.min.css +++ b/packages/vue-prism-editor/dist/prismeditor.min.css @@ -1 +1 @@ -.prism-editor-wrapper{align-items:flex-start;display:flex;height:100%;overflow:auto;-o-tab-size:1.5em;tab-size:1.5em;-moz-tab-size:1.5em;width:100%}@media (-ms-high-contrast:active),(-ms-high-contrast:none){.prism-editor-wrapper .prism-editor__textarea{color:transparent!important}.prism-editor-wrapper .prism-editor__textarea::-moz-selection{background-color:#accef7!important;color:transparent!important}.prism-editor-wrapper .prism-editor__textarea::selection{background-color:#accef7!important;color:transparent!important}}.prism-editor-wrapper .prism-editor__container{box-sizing:border-box;overflow:hidden;padding:0;position:relative;text-align:left;width:100%}.prism-editor-wrapper .prism-editor__line-numbers{flex-shrink:0;height:100%;margin-right:10px;margin-top:0;overflow:hidden;padding-top:4px}.prism-editor-wrapper .prism-editor__line-number{text-align:right;white-space:nowrap}.prism-editor-wrapper .prism-editor__textarea{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;-webkit-text-fill-color:transparent;color:inherit;height:100%;left:0;overflow:hidden;position:absolute;resize:none;top:0;width:100%}.prism-editor-wrapper .prism-editor__editor,.prism-editor-wrapper .prism-editor__textarea{text-rendering:inherit;word-wrap:keep-all;background:none;border:0;box-sizing:inherit;display:inherit;font-family:inherit;font-size:inherit;font-style:inherit;font-variant-ligatures:inherit;font-weight:inherit;letter-spacing:inherit;line-height:inherit;margin:0;overflow-wrap:break-word;padding:0;-moz-tab-size:inherit;-o-tab-size:inherit;tab-size:inherit;text-indent:inherit;text-transform:inherit;white-space:pre-wrap}.prism-editor-wrapper .prism-editor__textarea--empty{-webkit-text-fill-color:inherit!important}.prism-editor-wrapper .prism-editor__editor{pointer-events:none;position:relative} \ No newline at end of file +.prism-editor-component{align-items:flex-start;display:flex;height:auto;max-height:100%;position:relative;width:100%}.prism-editor-wrapper{display:block;height:100%;overflow:auto;-o-tab-size:1.5em;tab-size:1.5em;-moz-tab-size:1.5em;width:100%}@media (-ms-high-contrast:active),(-ms-high-contrast:none){.prism-editor__textarea{color:transparent!important}.prism-editor__textarea::-moz-selection{background-color:#accef7!important;color:transparent!important}.prism-editor__textarea::selection{background-color:#accef7!important;color:transparent!important}}.prism-editor__autocomplete{max-height:180px;max-width:250px;min-height:12px;min-width:100px;overflow-y:auto;position:absolute;top:25px;width:100%;z-index:4}.prism-editor__autocomplete li{cursor:pointer;overflow:hidden;padding:1px 5px;white-space:nowrap}.prism-editor__container{box-sizing:border-box;min-width:100%;padding:0;position:relative;text-align:left;width:-webkit-max-content;width:-moz-max-content;width:max-content}.prism-editor__line-numbers{flex-shrink:0;height:100%;margin-right:10px;margin-top:0;overflow:hidden;padding-top:4px}.prism-editor__line-number{text-align:right;white-space:nowrap}.prism-editor__textarea{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;-webkit-text-fill-color:transparent;color:inherit;height:100%;left:0;overflow:hidden;position:absolute;resize:none;top:0;width:100%}.prism-editor__editor,.prism-editor__textarea{text-rendering:inherit;word-wrap:keep-all;background:none;border:0;box-sizing:inherit;display:inherit;font-family:inherit;font-size:inherit;font-style:inherit;font-variant-ligatures:inherit;font-weight:inherit;letter-spacing:inherit;line-height:inherit;margin:0;overflow-wrap:break-word;padding:0;-moz-tab-size:inherit;-o-tab-size:inherit;tab-size:inherit;text-indent:inherit;text-transform:inherit;white-space:pre-wrap}.prism-editor__textarea--empty{-webkit-text-fill-color:inherit!important}.prism-editor__editor{overflow:visible;pointer-events:none;position:relative} \ No newline at end of file diff --git a/packages/vue-prism-editor/dist/prismeditor.umd.development.js b/packages/vue-prism-editor/dist/prismeditor.umd.development.js index 35bef19..5e92d0c 100644 --- a/packages/vue-prism-editor/dist/prismeditor.umd.development.js +++ b/packages/vue-prism-editor/dist/prismeditor.umd.development.js @@ -81,6 +81,12 @@ placeholder: { type: String, "default": '' + }, + autocomplete: { + type: Function, + "default": function _default() { + return []; + } } }, data: function data() { @@ -91,7 +97,10 @@ offset: -1 }, lineNumbersHeight: '20px', - codeData: '' + codeData: '', + autocompleteOpen: false, + autocompleteIndex: 0, + autocompleteData: [] }; }, watch: { @@ -125,6 +134,17 @@ _this2.setLineNumbersHeight(); }); + }, + autocompleteIndex: function autocompleteIndex() { + var _this3 = this; + + Vue.nextTick(function () { + var node = _this3.$el.querySelector('ul.prism-editor__autocomplete > li.selected'); + + if (node) node.scrollIntoView({ + block: 'nearest' + }); + }); } }, computed: { @@ -139,6 +159,16 @@ lineNumbersCount: function lineNumbersCount() { var totalLines = this.codeData.split(/\r\n|\n/).length; return totalLines; + }, + cursorOffset: function cursorOffset() { + var text = this.codeData; + var input = this.$refs.textarea; + var wrapper = this.$refs.wrapper; + var lines = text.substring(0, input.selectionEnd || 0).split(/\r\n|\n/); + var font_size = parseFloat(getComputedStyle(input).getPropertyValue('font-size')); + var line = lines.length; + var column = lines[lines.length - 1].length; + return [Math.min(column * 8.85 * (font_size / 16) - wrapper.scrollLeft, wrapper.clientWidth - Math.min(240, wrapper.clientWidth)), line * 24.0 * (font_size / 16) + 2 - wrapper.scrollTop]; } }, mounted: function mounted() { @@ -147,6 +177,53 @@ this.styleLineNumbers(); }, methods: { + updateAutocompleteData: function updateAutocompleteData() { + var _this$autocompleteDat; + + var input = this.$refs.textarea; + var data = typeof this.autocomplete == 'function' ? this.autocomplete(this.codeData, input.selectionEnd) : []; + var old_length = this.autocompleteData.length; + + (_this$autocompleteDat = this.autocompleteData).splice.apply(_this$autocompleteDat, [0, Infinity].concat(data)); + + this.autocompleteOpen = true; + this.autocompleteIndex = Math.max(0, Math.min(this.autocompleteIndex, this.autocompleteData.length - 1)); + if (old_length > this.autocompleteData.length) this.autocompleteIndex = 0; + }, + acceptAutocomplete: function acceptAutocomplete(event, option) { + var _this4 = this; + + event.preventDefault(); + if (option == undefined) option = this.autocompleteIndex; + var input = this.$refs.textarea; + var wrapper = this.$refs.wrapper; + var suggestion = this.autocompleteData[option] || this.autocompleteData[0]; + if (!suggestion) return; + var overlap = suggestion.overlap || 0; + var new_text = [this.codeData.substr(0, input.selectionEnd - overlap), suggestion.text, this.codeData.substring(input.selectionEnd)]; + var result = new_text.join(''); + var cursor_pos = input.selectionEnd - overlap + suggestion.text.length + (suggestion.text.endsWith(')') ? -1 : 0); + input.selectionStart = input.selectionEnd = cursor_pos; + + this._applyEdits({ + value: result, + selectionStart: cursor_pos, + selectionEnd: cursor_pos + }); + + var inserted_characters = suggestion.text.length - suggestion.overlap; + Vue.nextTick(function () { + wrapper.scrollLeft += inserted_characters * 8.85; + }); + + if (suggestion.text.endsWith('.')) { + setTimeout(function () { + _this4.updateAutocompleteData(); + }, 1); + } else { + this.autocompleteOpen = false; + } + }, setLineNumbersHeight: function setLineNumbersHeight() { this.lineNumbersHeight = getComputedStyle(this.$refs.pre).height; }, @@ -320,6 +397,8 @@ } }, handleKeyDown: function handleKeyDown(e) { + var _this5 = this; + // console.log(navigator.platform); var tabSize = this.tabSize, insertSpaces = this.insertSpaces, @@ -334,6 +413,36 @@ } } + if (e.keyCode === 9 && this.autocompleteData.length && this.autocompleteOpen) { + this.acceptAutocomplete(e); + e.preventDefault(); + e.stopPropagation(); + return; + } + + if (e.keyCode === 27) { + // Escape + if (this.autocompleteData.length && this.autocompleteOpen) { + e.preventDefault(); + this.autocompleteOpen = false; + return; + } + } else if (e.keyCode === 38) { + // Up + if (this.autocompleteData.length && this.autocompleteOpen) { + e.preventDefault(); + this.autocompleteIndex = (this.autocompleteIndex ? this.autocompleteIndex : this.autocompleteData.length) - 1; + return; + } + } else if (e.keyCode === 40) { + // Down + if (this.autocompleteData.length && this.autocompleteOpen) { + e.preventDefault(); + this.autocompleteIndex = (this.autocompleteIndex + 1) % this.autocompleteData.length; + return; + } + } + if (e.keyCode === KEYCODE_ESCAPE) { e.target.blur(); this.$emit('blur', e); @@ -429,8 +538,9 @@ }); } } else if (e.keyCode === KEYCODE_ENTER) { - // Ignore selections - if (selectionStart === selectionEnd) { + if (this.autocompleteData.length && this.autocompleteOpen) { + this.acceptAutocomplete(e); + } else if (selectionStart === selectionEnd) { // Get the current line var line = this._getLines(value, selectionStart).pop(); @@ -482,10 +592,16 @@ this.capture = !this.capture; } + + if (e.keyCode !== 13 && e.keyCode !== 9) { + setTimeout(function () { + _this5.updateAutocompleteData(); + }, 1); + } } }, render: function render(h) { - var _this3 = this; + var _this6 = this; var lineNumberWidthCalculator = h('div', { attrs: { @@ -508,24 +624,47 @@ } }, "" + ++index); })]); + var autocompleteList = this.autocompleteOpen && this.autocompleteData.length ? h('ul', { + staticClass: 'prism-editor__autocomplete', + style: { + left: this.cursorOffset[0] + 'px', + top: this.cursorOffset[1] + 'px' + } + }, this.autocompleteData.map(function (data, i) { + return h('li', { + key: data.text, + "class": { + selected: i == _this6.autocompleteIndex + }, + on: { + mousedown: function mousedown($event) { + _this6.acceptAutocomplete($event, i); + } + } + }, [data.label || data.text]); + })) : undefined; var textarea = h('textarea', { ref: 'textarea', on: { input: this.handleChange, keydown: this.handleKeyDown, click: function click($event) { - _this3.$emit('click', $event); + _this6.autocompleteOpen = false; + + _this6.$emit('click', $event); }, keyup: function keyup($event) { - _this3.$emit('keyup', $event); + _this6.$emit('keyup', $event); }, focus: function focus($event) { - _this3._recordStateIfChange(); + _this6._recordStateIfChange(); - _this3.$emit('focus', $event); + _this6.$emit('focus', $event); }, blur: function blur($event) { - _this3.$emit('blur', $event); + _this6.autocompleteOpen = false; + + _this6.$emit('blur', $event); } }, staticClass: 'prism-editor__textarea', @@ -559,9 +698,13 @@ var editorContainer = h('div', { staticClass: 'prism-editor__container' }, [textarea, preview]); - return h('div', { - staticClass: 'prism-editor-wrapper' + var wrapper = h('div', { + staticClass: 'prism-editor-wrapper', + ref: 'wrapper' }, [this.lineNumbers && lineNumbers, editorContainer]); + return h('div', { + staticClass: 'prism-editor-component' + }, [wrapper, autocompleteList]); } }); diff --git a/packages/vue-prism-editor/dist/prismeditor.umd.development.js.map b/packages/vue-prism-editor/dist/prismeditor.umd.development.js.map index a57671b..aa40f79 100644 --- a/packages/vue-prism-editor/dist/prismeditor.umd.development.js.map +++ b/packages/vue-prism-editor/dist/prismeditor.umd.development.js.map @@ -1 +1 @@ -{"version":3,"file":"prismeditor.umd.development.js","sources":["../src/Editor.ts"],"sourcesContent":["import Vue, { VNode } from 'vue';\r\n\r\nimport './styles.css';\r\nconst KEYCODE_ENTER = 13;\r\nconst KEYCODE_TAB = 9;\r\nconst KEYCODE_BACKSPACE = 8;\r\nconst KEYCODE_Y = 89;\r\nconst KEYCODE_Z = 90;\r\nconst KEYCODE_M = 77;\r\nconst KEYCODE_ESCAPE = 27;\r\n\r\nconst BRACKET_PAIRS: {[opening: string]: string} = {\r\n '(':')',\r\n '{':'}',\r\n '[':']',\r\n '\"':'\"',\r\n \"'\":\"'\",\r\n};\r\n\r\nconst HISTORY_LIMIT = 100;\r\nconst HISTORY_TIME_GAP = 3000;\r\n\r\nconst isWindows = 'navigator' in global && /Win/i.test(navigator.platform);\r\nconst isMacLike = 'navigator' in global && /(Mac|iPhone|iPod|iPad)/i.test(navigator.platform);\r\n\r\nexport interface EditorProps {\r\n lineNumbers: boolean;\r\n autoStyleLineNumbers: boolean;\r\n readonly: boolean;\r\n value: string;\r\n highlight: () => string;\r\n tabSize: number;\r\n insertSpaces: boolean;\r\n ignoreTabKey: boolean;\r\n placeholder: string;\r\n}\r\nexport interface Record {\r\n value: string;\r\n selectionStart: number;\r\n selectionEnd: number;\r\n}\r\n\r\nexport interface History {\r\n stack: Array;\r\n offset: number;\r\n}\r\n\r\nexport const PrismEditor = Vue.extend({\r\n props: {\r\n lineNumbers: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n autoStyleLineNumbers: {\r\n type: Boolean,\r\n default: true,\r\n },\r\n readonly: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n value: {\r\n type: String,\r\n default: '',\r\n },\r\n highlight: {\r\n type: Function,\r\n required: true,\r\n },\r\n tabSize: {\r\n type: Number,\r\n default: 2,\r\n },\r\n insertSpaces: {\r\n type: Boolean,\r\n default: true,\r\n },\r\n ignoreTabKey: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n placeholder: {\r\n type: String,\r\n default: '',\r\n },\r\n },\r\n data() {\r\n return {\r\n capture: true,\r\n history: {\r\n stack: [],\r\n offset: -1,\r\n } as History,\r\n lineNumbersHeight: '20px',\r\n codeData: '',\r\n };\r\n },\r\n watch: {\r\n value: {\r\n immediate: true,\r\n handler(newVal: string): void {\r\n if (!newVal) {\r\n this.codeData = '';\r\n } else {\r\n this.codeData = newVal;\r\n }\r\n },\r\n },\r\n content: {\r\n immediate: true,\r\n handler(): void {\r\n if (this.lineNumbers) {\r\n this.$nextTick(() => {\r\n this.setLineNumbersHeight();\r\n });\r\n }\r\n },\r\n },\r\n lineNumbers(): void {\r\n this.$nextTick(() => {\r\n this.styleLineNumbers();\r\n this.setLineNumbersHeight();\r\n });\r\n },\r\n },\r\n computed: {\r\n isEmpty(): boolean {\r\n return this.codeData.length === 0;\r\n },\r\n content(): string {\r\n const result = this.highlight(this.codeData) + '
';\r\n // todo: VNode support?\r\n return result;\r\n },\r\n lineNumbersCount(): number {\r\n const totalLines = this.codeData.split(/\\r\\n|\\n/).length;\r\n return totalLines;\r\n },\r\n },\r\n mounted() {\r\n this._recordCurrentState();\r\n this.styleLineNumbers();\r\n },\r\n\r\n methods: {\r\n setLineNumbersHeight(): void {\r\n this.lineNumbersHeight = getComputedStyle(this.$refs.pre as HTMLTextAreaElement).height;\r\n },\r\n styleLineNumbers(): void {\r\n if (!this.lineNumbers || !this.autoStyleLineNumbers) return;\r\n\r\n const $editor = this.$refs.pre as HTMLTextAreaElement;\r\n const $lineNumbers: HTMLDivElement | null = this.$el.querySelector('.prism-editor__line-numbers');\r\n const editorStyles = window.getComputedStyle($editor);\r\n\r\n this.$nextTick(() => {\r\n const btlr: any = 'border-top-left-radius';\r\n const bblr: any = 'border-bottom-left-radius';\r\n if (!$lineNumbers) return;\r\n $lineNumbers.style[btlr] = editorStyles[btlr];\r\n $lineNumbers.style[bblr] = editorStyles[bblr];\r\n $editor.style[btlr] = '0';\r\n $editor.style[bblr] = '0';\r\n\r\n const stylesList = ['background-color', 'margin-top', 'padding-top', 'font-family', 'font-size', 'line-height'];\r\n stylesList.forEach((style: any) => {\r\n $lineNumbers.style[style] = editorStyles[style];\r\n });\r\n $lineNumbers.style['margin-bottom' as any] = '-' + editorStyles['padding-top' as any];\r\n });\r\n },\r\n _recordCurrentState(): void {\r\n const input = this.$refs.textarea as HTMLTextAreaElement;\r\n\r\n if (!input) return;\r\n // Save current state of the input\r\n const { value, selectionStart, selectionEnd } = input;\r\n\r\n this._recordChange({\r\n value,\r\n selectionStart,\r\n selectionEnd,\r\n });\r\n },\r\n _getLines(text: string, position: number): Array {\r\n return text.substring(0, position).split('\\n');\r\n },\r\n _recordStateIfChange(): void {\r\n if (this.history.stack[this.history.offset].value != this.codeData) {\r\n this._recordChange({\r\n value: this.codeData,\r\n selectionStart: this.codeData.length,\r\n selectionEnd: this.codeData.length,\r\n });\r\n }\r\n },\r\n _applyEdits(record: Record): void {\r\n // Save last selection state\r\n const input = this.$refs.textarea as HTMLTextAreaElement;\r\n const last = this.history.stack[this.history.offset];\r\n\r\n if (last && input) {\r\n this.history.stack[this.history.offset] = {\r\n ...last,\r\n selectionStart: input.selectionStart,\r\n selectionEnd: input.selectionEnd,\r\n };\r\n }\r\n\r\n // Save the changes\r\n this._recordChange(record);\r\n this._updateInput(record);\r\n },\r\n _recordChange(record: Record, overwrite = false): void {\r\n const { stack, offset } = this.history;\r\n\r\n if (stack.length && offset > -1) {\r\n // When something updates, drop the redo operations\r\n this.history.stack = stack.slice(0, offset + 1);\r\n\r\n // Limit the number of operations to 100\r\n const count = this.history.stack.length;\r\n\r\n if (count > HISTORY_LIMIT) {\r\n const extras = count - HISTORY_LIMIT;\r\n\r\n this.history.stack = stack.slice(extras, count);\r\n this.history.offset = Math.max(this.history.offset - extras, 0);\r\n }\r\n }\r\n\r\n const timestamp = Date.now();\r\n\r\n if (overwrite) {\r\n const last = this.history.stack[this.history.offset];\r\n\r\n if (last && timestamp - last.timestamp < HISTORY_TIME_GAP) {\r\n // A previous entry exists and was in short interval\r\n\r\n // Match the last word in the line\r\n const re = /[^a-z0-9]([a-z0-9]+)$/i;\r\n\r\n // Get the previous line\r\n const previous = this._getLines(last.value, last.selectionStart).pop()?.match(re);\r\n\r\n // Get the current line\r\n const current = this._getLines(record.value, record.selectionStart).pop()?.match(re);\r\n\r\n if (previous && current && current[1].startsWith(previous[1])) {\r\n // The last word of the previous line and current line match\r\n // Overwrite previous entry so that undo will remove whole word\r\n this.history.stack[this.history.offset] = {\r\n ...record,\r\n timestamp,\r\n };\r\n\r\n return;\r\n }\r\n }\r\n }\r\n\r\n // Add the new operation to the stack\r\n this.history.stack.push({ ...record, timestamp });\r\n this.history.offset++;\r\n },\r\n\r\n _updateInput(record: Record): void {\r\n const input = this.$refs.textarea as HTMLTextAreaElement;\r\n\r\n if (!input) return;\r\n\r\n // Update values and selection state\r\n input.value = record.value;\r\n input.selectionStart = record.selectionStart;\r\n input.selectionEnd = record.selectionEnd;\r\n\r\n this.$emit('input', record.value);\r\n // this.props.onValueChange(record.value);\r\n },\r\n handleChange(e: KeyboardEvent): void {\r\n const { value, selectionStart, selectionEnd } = e.target as HTMLTextAreaElement;\r\n\r\n this._recordChange(\r\n {\r\n value,\r\n selectionStart,\r\n selectionEnd,\r\n },\r\n true\r\n );\r\n this.$emit('input', value);\r\n // this.props.onValueChange(value);\r\n },\r\n _undoEdit(): void {\r\n const { stack, offset } = this.history;\r\n\r\n // Get the previous edit\r\n const record = stack[offset - 1];\r\n\r\n if (record) {\r\n // Apply the changes and update the offset\r\n this._updateInput(record);\r\n this.history.offset = Math.max(offset - 1, 0);\r\n }\r\n },\r\n _redoEdit(): void {\r\n const { stack, offset } = this.history;\r\n\r\n // Get the next edit\r\n const record = stack[offset + 1];\r\n\r\n if (record) {\r\n // Apply the changes and update the offset\r\n this._updateInput(record);\r\n this.history.offset = Math.min(offset + 1, stack.length - 1);\r\n }\r\n },\r\n handleKeyDown(e: KeyboardEvent): void {\r\n // console.log(navigator.platform);\r\n const { tabSize, insertSpaces, ignoreTabKey } = this;\r\n\r\n if (this.$listeners.keydown) {\r\n // onKeyDown(e);\r\n this.$emit('keydown', e);\r\n\r\n if (e.defaultPrevented) {\r\n return;\r\n }\r\n }\r\n\r\n if (e.keyCode === KEYCODE_ESCAPE) {\r\n (e.target).blur();\r\n this.$emit('blur', e);\r\n }\r\n\r\n const { value, selectionStart, selectionEnd } = e.target as HTMLTextAreaElement;\r\n\r\n const tabCharacter = (insertSpaces ? ' ' : '\\t').repeat(tabSize);\r\n\r\n if (e.keyCode === KEYCODE_TAB && !ignoreTabKey && this.capture) {\r\n // Prevent focus change\r\n e.preventDefault();\r\n\r\n if (e.shiftKey) {\r\n // Unindent selected lines\r\n const linesBeforeCaret = this._getLines(value, selectionStart);\r\n const startLine = linesBeforeCaret.length - 1;\r\n const endLine = this._getLines(value, selectionEnd).length - 1;\r\n const nextValue = value\r\n .split('\\n')\r\n .map((line, i) => {\r\n if (i >= startLine && i <= endLine && line.startsWith(tabCharacter)) {\r\n return line.substring(tabCharacter.length);\r\n }\r\n\r\n return line;\r\n })\r\n .join('\\n');\r\n\r\n if (value !== nextValue) {\r\n const startLineText = linesBeforeCaret[startLine];\r\n\r\n this._applyEdits({\r\n value: nextValue,\r\n // Move the start cursor if first line in selection was modified\r\n // It was modified only if it started with a tab\r\n selectionStart: startLineText.startsWith(tabCharacter)\r\n ? selectionStart - tabCharacter.length\r\n : selectionStart,\r\n // Move the end cursor by total number of characters removed\r\n selectionEnd: selectionEnd - (value.length - nextValue.length),\r\n });\r\n }\r\n } else if (selectionStart !== selectionEnd) {\r\n // Indent selected lines\r\n const linesBeforeCaret = this._getLines(value, selectionStart);\r\n const startLine = linesBeforeCaret.length - 1;\r\n const endLine = this._getLines(value, selectionEnd).length - 1;\r\n const startLineText = linesBeforeCaret[startLine];\r\n\r\n this._applyEdits({\r\n value: value\r\n .split('\\n')\r\n .map((line, i) => {\r\n if (i >= startLine && i <= endLine) {\r\n return tabCharacter + line;\r\n }\r\n\r\n return line;\r\n })\r\n .join('\\n'),\r\n // Move the start cursor by number of characters added in first line of selection\r\n // Don't move it if it there was no text before cursor\r\n selectionStart: /\\S/.test(startLineText) ? selectionStart + tabCharacter.length : selectionStart,\r\n // Move the end cursor by total number of characters added\r\n selectionEnd: selectionEnd + tabCharacter.length * (endLine - startLine + 1),\r\n });\r\n } else {\r\n const updatedSelection = selectionStart + tabCharacter.length;\r\n\r\n this._applyEdits({\r\n // Insert tab character at caret\r\n value: value.substring(0, selectionStart) + tabCharacter + value.substring(selectionEnd),\r\n // Update caret position\r\n selectionStart: updatedSelection,\r\n selectionEnd: updatedSelection,\r\n });\r\n }\r\n } else if (e.keyCode === KEYCODE_BACKSPACE) {\r\n const hasSelection = selectionStart !== selectionEnd;\r\n const textBeforeCaret = value.substring(0, selectionStart);\r\n\r\n if (textBeforeCaret.endsWith(tabCharacter) && !hasSelection) {\r\n // Prevent default delete behaviour\r\n e.preventDefault();\r\n\r\n const updatedSelection = selectionStart - tabCharacter.length;\r\n\r\n this._applyEdits({\r\n // Remove tab character at caret\r\n value: value.substring(0, selectionStart - tabCharacter.length) + value.substring(selectionEnd),\r\n // Update caret position\r\n selectionStart: updatedSelection,\r\n selectionEnd: updatedSelection,\r\n });\r\n }\r\n } else if (e.keyCode === KEYCODE_ENTER) {\r\n // Ignore selections\r\n if (selectionStart === selectionEnd) {\r\n // Get the current line\r\n const line = this._getLines(value, selectionStart).pop();\r\n const matches = line?.match(/^\\s+/);\r\n\r\n if (matches && matches[0]) {\r\n e.preventDefault();\r\n\r\n // Preserve indentation on inserting a new line\r\n const indent = '\\n' + matches[0];\r\n const updatedSelection = selectionStart + indent.length;\r\n\r\n this._applyEdits({\r\n // Insert indentation character at caret\r\n value: value.substring(0, selectionStart) + indent + value.substring(selectionEnd),\r\n // Update caret position\r\n selectionStart: updatedSelection,\r\n selectionEnd: updatedSelection,\r\n });\r\n }\r\n }\r\n } else if (BRACKET_PAIRS[e.key]) {\r\n // If text is selected, wrap them in the characters\r\n if (selectionStart !== selectionEnd) {\r\n e.preventDefault();\r\n\r\n this._applyEdits({\r\n value:\r\n value.substring(0, selectionStart) +\r\n e.key +\r\n value.substring(selectionStart, selectionEnd) +\r\n BRACKET_PAIRS[e.key] +\r\n value.substring(selectionEnd),\r\n // Update caret position\r\n selectionStart: selectionStart + 1,\r\n selectionEnd: selectionEnd + 1,\r\n });\r\n }\r\n } else if (\r\n (isMacLike\r\n ? // Trigger undo with ⌘+Z on Mac\r\n e.metaKey && e.keyCode === KEYCODE_Z\r\n : // Trigger undo with Ctrl+Z on other platforms\r\n e.ctrlKey && e.keyCode === KEYCODE_Z) &&\r\n !e.shiftKey &&\r\n !e.altKey\r\n ) {\r\n e.preventDefault();\r\n\r\n this._undoEdit();\r\n } else if (\r\n (isMacLike\r\n ? // Trigger redo with ⌘+Shift+Z on Mac\r\n e.metaKey && e.keyCode === KEYCODE_Z && e.shiftKey\r\n : isWindows\r\n ? // Trigger redo with Ctrl+Y on Windows\r\n e.ctrlKey && e.keyCode === KEYCODE_Y\r\n : // Trigger redo with Ctrl+Shift+Z on other platforms\r\n e.ctrlKey && e.keyCode === KEYCODE_Z && e.shiftKey) &&\r\n !e.altKey\r\n ) {\r\n e.preventDefault();\r\n\r\n this._redoEdit();\r\n } else if (e.keyCode === KEYCODE_M && e.ctrlKey && (isMacLike ? e.shiftKey : true)) {\r\n e.preventDefault();\r\n\r\n // Toggle capturing tab key so users can focus away\r\n this.capture = !this.capture;\r\n }\r\n },\r\n },\r\n render(h): VNode {\r\n const lineNumberWidthCalculator = h(\r\n 'div',\r\n {\r\n attrs: {\r\n class: 'prism-editor__line-width-calc',\r\n style: 'height: 0px; visibility: hidden; pointer-events: none;',\r\n },\r\n },\r\n '999'\r\n );\r\n const lineNumbers = h(\r\n 'div',\r\n {\r\n staticClass: 'prism-editor__line-numbers',\r\n style: {\r\n 'min-height': this.lineNumbersHeight,\r\n },\r\n attrs: {\r\n 'aria-hidden': 'true',\r\n },\r\n },\r\n [\r\n lineNumberWidthCalculator,\r\n Array.from(Array(this.lineNumbersCount).keys()).map((_, index) => {\r\n return h('div', { attrs: { class: 'prism-editor__line-number token comment' } }, `${++index}`);\r\n }),\r\n ]\r\n );\r\n\r\n const textarea = h('textarea', {\r\n ref: 'textarea',\r\n on: {\r\n input: this.handleChange,\r\n keydown: this.handleKeyDown,\r\n click: ($event: MouseEvent) => {\r\n this.$emit('click', $event);\r\n },\r\n keyup: ($event: KeyboardEvent) => {\r\n this.$emit('keyup', $event);\r\n },\r\n focus: ($event: FocusEvent) => {\r\n this._recordStateIfChange();\r\n this.$emit('focus', $event);\r\n },\r\n blur: ($event: FocusEvent) => {\r\n this.$emit('blur', $event);\r\n },\r\n },\r\n staticClass: 'prism-editor__textarea',\r\n class: {\r\n 'prism-editor__textarea--empty': this.isEmpty,\r\n },\r\n attrs: {\r\n spellCheck: 'false',\r\n autocapitalize: 'off',\r\n autocomplete: 'off',\r\n autocorrect: 'off',\r\n 'data-gramm': 'false',\r\n placeholder: this.placeholder,\r\n 'data-testid': 'textarea',\r\n readonly: this.readonly,\r\n },\r\n domProps: {\r\n value: this.codeData,\r\n },\r\n });\r\n const preview = h('pre', {\r\n ref: 'pre',\r\n staticClass: 'prism-editor__editor',\r\n attrs: {\r\n 'data-testid': 'preview',\r\n },\r\n domProps: {\r\n innerHTML: this.content,\r\n },\r\n });\r\n const editorContainer = h('div', { staticClass: 'prism-editor__container' }, [textarea, preview]);\r\n return h('div', { staticClass: 'prism-editor-wrapper' }, [this.lineNumbers && lineNumbers, editorContainer]);\r\n },\r\n});\r\n"],"names":["KEYCODE_ENTER","KEYCODE_TAB","KEYCODE_BACKSPACE","KEYCODE_Y","KEYCODE_Z","KEYCODE_M","KEYCODE_ESCAPE","BRACKET_PAIRS","HISTORY_LIMIT","HISTORY_TIME_GAP","isWindows","global","test","navigator","platform","isMacLike","PrismEditor","Vue","extend","props","lineNumbers","type","Boolean","autoStyleLineNumbers","readonly","value","String","highlight","Function","required","tabSize","Number","insertSpaces","ignoreTabKey","placeholder","data","capture","history","stack","offset","lineNumbersHeight","codeData","watch","immediate","handler","newVal","content","$nextTick","setLineNumbersHeight","styleLineNumbers","computed","isEmpty","length","result","lineNumbersCount","totalLines","split","mounted","_recordCurrentState","methods","getComputedStyle","$refs","pre","height","$editor","$lineNumbers","$el","querySelector","editorStyles","window","btlr","bblr","style","stylesList","forEach","input","textarea","selectionStart","selectionEnd","_recordChange","_getLines","text","position","substring","_recordStateIfChange","_applyEdits","record","last","_updateInput","overwrite","slice","count","extras","Math","max","timestamp","Date","now","re","previous","pop","match","current","startsWith","push","$emit","handleChange","e","target","_undoEdit","_redoEdit","min","handleKeyDown","$listeners","keydown","defaultPrevented","keyCode","blur","tabCharacter","repeat","preventDefault","shiftKey","linesBeforeCaret","startLine","endLine","nextValue","map","line","i","join","startLineText","updatedSelection","hasSelection","textBeforeCaret","endsWith","matches","indent","key","metaKey","ctrlKey","altKey","render","h","lineNumberWidthCalculator","attrs","staticClass","Array","from","keys","_","index","ref","on","click","$event","keyup","focus","spellCheck","autocapitalize","autocomplete","autocorrect","domProps","preview","innerHTML","editorContainer"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"prismeditor.umd.development.js","sources":["../src/Editor.ts"],"sourcesContent":["import Vue, { VNode } from 'vue';\r\n\r\nimport './styles.css';\r\nconst KEYCODE_ENTER = 13;\r\nconst KEYCODE_TAB = 9;\r\nconst KEYCODE_BACKSPACE = 8;\r\nconst KEYCODE_Y = 89;\r\nconst KEYCODE_Z = 90;\r\nconst KEYCODE_M = 77;\r\nconst KEYCODE_ESCAPE = 27;\r\n\r\nconst BRACKET_PAIRS: {[opening: string]: string} = {\r\n '(':')',\r\n '{':'}',\r\n '[':']',\r\n '\"':'\"',\r\n \"'\":\"'\",\r\n};\r\n\r\nconst HISTORY_LIMIT = 100;\r\nconst HISTORY_TIME_GAP = 3000;\r\n\r\nconst isWindows = 'navigator' in global && /Win/i.test(navigator.platform);\r\nconst isMacLike = 'navigator' in global && /(Mac|iPhone|iPod|iPad)/i.test(navigator.platform);\r\n\r\nexport interface EditorProps {\r\n lineNumbers: boolean;\r\n autoStyleLineNumbers: boolean;\r\n readonly: boolean;\r\n value: string;\r\n highlight: () => string;\r\n tabSize: number;\r\n insertSpaces: boolean;\r\n ignoreTabKey: boolean;\r\n placeholder: string;\r\n}\r\nexport interface Record {\r\n value: string;\r\n selectionStart: number;\r\n selectionEnd: number;\r\n}\r\n\r\nexport interface History {\r\n stack: Array;\r\n offset: number;\r\n}\r\ninterface AutocompleteEntry {\r\n text: string\r\n overlap: number\r\n label?: string\r\n}\r\n\r\nexport const PrismEditor = Vue.extend({\r\n props: {\r\n lineNumbers: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n autoStyleLineNumbers: {\r\n type: Boolean,\r\n default: true,\r\n },\r\n readonly: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n value: {\r\n type: String,\r\n default: '',\r\n },\r\n highlight: {\r\n type: Function,\r\n required: true,\r\n },\r\n tabSize: {\r\n type: Number,\r\n default: 2,\r\n },\r\n insertSpaces: {\r\n type: Boolean,\r\n default: true,\r\n },\r\n ignoreTabKey: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n placeholder: {\r\n type: String,\r\n default: '',\r\n },\r\n autocomplete: {\r\n type: Function,\r\n default() {\r\n return []\r\n }\r\n }\r\n },\r\n data() {\r\n return {\r\n capture: true,\r\n history: {\r\n stack: [],\r\n offset: -1,\r\n } as History,\r\n lineNumbersHeight: '20px',\r\n codeData: '',\r\n\r\n autocompleteOpen: false,\r\n autocompleteIndex: 0,\r\n autocompleteData: [] as AutocompleteEntry[]\r\n };\r\n },\r\n watch: {\r\n value: {\r\n immediate: true,\r\n handler(newVal: string): void {\r\n if (!newVal) {\r\n this.codeData = '';\r\n } else {\r\n this.codeData = newVal;\r\n }\r\n },\r\n },\r\n content: {\r\n immediate: true,\r\n handler(): void {\r\n if (this.lineNumbers) {\r\n this.$nextTick(() => {\r\n this.setLineNumbersHeight();\r\n });\r\n }\r\n },\r\n },\r\n lineNumbers(): void {\r\n this.$nextTick(() => {\r\n this.styleLineNumbers();\r\n this.setLineNumbersHeight();\r\n });\r\n },\r\n autocompleteIndex() {\r\n Vue.nextTick(() => {\r\n let node = this.$el.querySelector('ul.prism-editor__autocomplete > li.selected');\r\n if (node) node.scrollIntoView({block: 'nearest'});\r\n })\r\n },\r\n },\r\n computed: {\r\n isEmpty(): boolean {\r\n return this.codeData.length === 0;\r\n },\r\n content(): string {\r\n const result = this.highlight(this.codeData) + '
';\r\n // todo: VNode support?\r\n return result;\r\n },\r\n lineNumbersCount(): number {\r\n const totalLines = this.codeData.split(/\\r\\n|\\n/).length;\r\n return totalLines;\r\n },\r\n cursorOffset() {\r\n let text: string = this.codeData;\r\n let input = this.$refs.textarea as HTMLTextAreaElement;\r\n let wrapper = this.$refs.wrapper as HTMLDivElement;\r\n let lines = text.substring(0, input.selectionEnd || 0).split(/\\r\\n|\\n/);\r\n let font_size = parseFloat(getComputedStyle(input).getPropertyValue('font-size'));\r\n let line = lines.length;\r\n let column = lines[lines.length-1].length;\r\n return [\r\n Math.min((column * 8.85 * (font_size / 16)) - wrapper.scrollLeft, wrapper.clientWidth - Math.min(240, wrapper.clientWidth)),\r\n (line * 24.0 * (font_size / 16)) + 2 - wrapper.scrollTop,\r\n ]\r\n },\r\n },\r\n mounted() {\r\n this._recordCurrentState();\r\n this.styleLineNumbers();\r\n },\r\n\r\n methods: {\r\n updateAutocompleteData() {\r\n let input = this.$refs.textarea as HTMLTextAreaElement;\r\n let data: AutocompleteEntry[] = typeof this.autocomplete == 'function' ? this.autocomplete(this.codeData, input.selectionEnd) : [];\r\n let old_length = this.autocompleteData.length;\r\n this.autocompleteData.splice(0, Infinity, ...data);\r\n this.autocompleteOpen = true;\r\n this.autocompleteIndex = Math.max(0, Math.min(this.autocompleteIndex, this.autocompleteData.length-1));\r\n if (old_length > this.autocompleteData.length) this.autocompleteIndex = 0;\r\n },\r\n acceptAutocomplete(event: Event, option?: number) {\r\n event.preventDefault()\r\n if (option == undefined) option = this.autocompleteIndex;\r\n\r\n let input = this.$refs.textarea as HTMLTextAreaElement;\r\n let wrapper = this.$refs.wrapper as HTMLDivElement;\r\n let suggestion = this.autocompleteData[option] || this.autocompleteData[0];\r\n if (!suggestion) return;\r\n \r\n let overlap = suggestion.overlap || 0;\r\n let new_text = [\r\n this.codeData.substr(0, input.selectionEnd - overlap),\r\n suggestion.text,\r\n this.codeData.substring(input.selectionEnd),\r\n ]\r\n let result: string = new_text.join('');\r\n let cursor_pos = input.selectionEnd - overlap + suggestion.text.length + (suggestion.text.endsWith(')') ? -1 : 0);\r\n input.selectionStart = input.selectionEnd = cursor_pos;\r\n\r\n this._applyEdits({\r\n value: result,\r\n selectionStart: cursor_pos,\r\n selectionEnd: cursor_pos,\r\n });\r\n let inserted_characters = suggestion.text.length - suggestion.overlap;\r\n Vue.nextTick(() => {\r\n wrapper.scrollLeft += inserted_characters * 8.85;\r\n })\r\n\r\n if (suggestion.text.endsWith('.')) {\r\n setTimeout(() => {\r\n this.updateAutocompleteData();\r\n }, 1);\r\n } else {\r\n this.autocompleteOpen = false;\r\n }\r\n },\r\n setLineNumbersHeight(): void {\r\n this.lineNumbersHeight = getComputedStyle(this.$refs.pre as HTMLTextAreaElement).height;\r\n },\r\n styleLineNumbers(): void {\r\n if (!this.lineNumbers || !this.autoStyleLineNumbers) return;\r\n\r\n const $editor = this.$refs.pre as HTMLTextAreaElement;\r\n const $lineNumbers: HTMLDivElement | null = this.$el.querySelector('.prism-editor__line-numbers');\r\n const editorStyles = window.getComputedStyle($editor);\r\n\r\n this.$nextTick(() => {\r\n const btlr: any = 'border-top-left-radius';\r\n const bblr: any = 'border-bottom-left-radius';\r\n if (!$lineNumbers) return;\r\n $lineNumbers.style[btlr] = editorStyles[btlr];\r\n $lineNumbers.style[bblr] = editorStyles[bblr];\r\n $editor.style[btlr] = '0';\r\n $editor.style[bblr] = '0';\r\n\r\n const stylesList = ['background-color', 'margin-top', 'padding-top', 'font-family', 'font-size', 'line-height'];\r\n stylesList.forEach((style: any) => {\r\n $lineNumbers.style[style] = editorStyles[style];\r\n });\r\n $lineNumbers.style['margin-bottom' as any] = '-' + editorStyles['padding-top' as any];\r\n });\r\n },\r\n _recordCurrentState(): void {\r\n const input = this.$refs.textarea as HTMLTextAreaElement;\r\n\r\n if (!input) return;\r\n // Save current state of the input\r\n const { value, selectionStart, selectionEnd } = input;\r\n\r\n this._recordChange({\r\n value,\r\n selectionStart,\r\n selectionEnd,\r\n });\r\n },\r\n _getLines(text: string, position: number): Array {\r\n return text.substring(0, position).split('\\n');\r\n },\r\n _recordStateIfChange(): void {\r\n if (this.history.stack[this.history.offset].value != this.codeData) {\r\n this._recordChange({\r\n value: this.codeData,\r\n selectionStart: this.codeData.length,\r\n selectionEnd: this.codeData.length,\r\n });\r\n }\r\n },\r\n _applyEdits(record: Record): void {\r\n // Save last selection state\r\n const input = this.$refs.textarea as HTMLTextAreaElement;\r\n const last = this.history.stack[this.history.offset];\r\n\r\n if (last && input) {\r\n this.history.stack[this.history.offset] = {\r\n ...last,\r\n selectionStart: input.selectionStart,\r\n selectionEnd: input.selectionEnd,\r\n };\r\n }\r\n\r\n // Save the changes\r\n this._recordChange(record);\r\n this._updateInput(record);\r\n },\r\n _recordChange(record: Record, overwrite = false): void {\r\n const { stack, offset } = this.history;\r\n\r\n if (stack.length && offset > -1) {\r\n // When something updates, drop the redo operations\r\n this.history.stack = stack.slice(0, offset + 1);\r\n\r\n // Limit the number of operations to 100\r\n const count = this.history.stack.length;\r\n\r\n if (count > HISTORY_LIMIT) {\r\n const extras = count - HISTORY_LIMIT;\r\n\r\n this.history.stack = stack.slice(extras, count);\r\n this.history.offset = Math.max(this.history.offset - extras, 0);\r\n }\r\n }\r\n\r\n const timestamp = Date.now();\r\n\r\n if (overwrite) {\r\n const last = this.history.stack[this.history.offset];\r\n\r\n if (last && timestamp - last.timestamp < HISTORY_TIME_GAP) {\r\n // A previous entry exists and was in short interval\r\n\r\n // Match the last word in the line\r\n const re = /[^a-z0-9]([a-z0-9]+)$/i;\r\n\r\n // Get the previous line\r\n const previous = this._getLines(last.value, last.selectionStart).pop()?.match(re);\r\n\r\n // Get the current line\r\n const current = this._getLines(record.value, record.selectionStart).pop()?.match(re);\r\n\r\n if (previous && current && current[1].startsWith(previous[1])) {\r\n // The last word of the previous line and current line match\r\n // Overwrite previous entry so that undo will remove whole word\r\n this.history.stack[this.history.offset] = {\r\n ...record,\r\n timestamp,\r\n };\r\n\r\n return;\r\n }\r\n }\r\n }\r\n\r\n // Add the new operation to the stack\r\n this.history.stack.push({ ...record, timestamp });\r\n this.history.offset++;\r\n },\r\n\r\n _updateInput(record: Record): void {\r\n const input = this.$refs.textarea as HTMLTextAreaElement;\r\n\r\n if (!input) return;\r\n\r\n // Update values and selection state\r\n input.value = record.value;\r\n input.selectionStart = record.selectionStart;\r\n input.selectionEnd = record.selectionEnd;\r\n\r\n this.$emit('input', record.value);\r\n // this.props.onValueChange(record.value);\r\n },\r\n handleChange(e: KeyboardEvent): void {\r\n const { value, selectionStart, selectionEnd } = e.target as HTMLTextAreaElement;\r\n\r\n this._recordChange(\r\n {\r\n value,\r\n selectionStart,\r\n selectionEnd,\r\n },\r\n true\r\n );\r\n this.$emit('input', value);\r\n // this.props.onValueChange(value);\r\n },\r\n _undoEdit(): void {\r\n const { stack, offset } = this.history;\r\n\r\n // Get the previous edit\r\n const record = stack[offset - 1];\r\n\r\n if (record) {\r\n // Apply the changes and update the offset\r\n this._updateInput(record);\r\n this.history.offset = Math.max(offset - 1, 0);\r\n }\r\n },\r\n _redoEdit(): void {\r\n const { stack, offset } = this.history;\r\n\r\n // Get the next edit\r\n const record = stack[offset + 1];\r\n\r\n if (record) {\r\n // Apply the changes and update the offset\r\n this._updateInput(record);\r\n this.history.offset = Math.min(offset + 1, stack.length - 1);\r\n }\r\n },\r\n handleKeyDown(e: KeyboardEvent): void {\r\n // console.log(navigator.platform);\r\n const { tabSize, insertSpaces, ignoreTabKey } = this;\r\n\r\n if (this.$listeners.keydown) {\r\n // onKeyDown(e);\r\n this.$emit('keydown', e);\r\n\r\n if (e.defaultPrevented) {\r\n return;\r\n }\r\n }\r\n\r\n if (e.keyCode === 9 && this.autocompleteData.length && this.autocompleteOpen) {\r\n this.acceptAutocomplete(e);\r\n e.preventDefault();\r\n e.stopPropagation();\r\n return;\r\n }\r\n if (e.keyCode === 27) {\r\n // Escape\r\n if (this.autocompleteData.length && this.autocompleteOpen) {\r\n e.preventDefault();\r\n this.autocompleteOpen = false;\r\n return;\r\n }\r\n } else if (e.keyCode === 38) {\r\n // Up\r\n if (this.autocompleteData.length && this.autocompleteOpen) {\r\n e.preventDefault();\r\n this.autocompleteIndex = (this.autocompleteIndex ? this.autocompleteIndex : this.autocompleteData.length) - 1;\r\n return;\r\n }\r\n } else if (e.keyCode === 40) {\r\n // Down\r\n if (this.autocompleteData.length && this.autocompleteOpen) {\r\n e.preventDefault();\r\n this.autocompleteIndex = (this.autocompleteIndex + 1) % this.autocompleteData.length;\r\n return;\r\n }\r\n }\r\n\r\n if (e.keyCode === KEYCODE_ESCAPE) {\r\n (e.target).blur();\r\n this.$emit('blur', e);\r\n }\r\n\r\n const { value, selectionStart, selectionEnd } = e.target as HTMLTextAreaElement;\r\n\r\n const tabCharacter = (insertSpaces ? ' ' : '\\t').repeat(tabSize);\r\n\r\n if (e.keyCode === KEYCODE_TAB && !ignoreTabKey && this.capture) {\r\n // Prevent focus change\r\n e.preventDefault();\r\n\r\n if (e.shiftKey) {\r\n // Unindent selected lines\r\n const linesBeforeCaret = this._getLines(value, selectionStart);\r\n const startLine = linesBeforeCaret.length - 1;\r\n const endLine = this._getLines(value, selectionEnd).length - 1;\r\n const nextValue = value\r\n .split('\\n')\r\n .map((line, i) => {\r\n if (i >= startLine && i <= endLine && line.startsWith(tabCharacter)) {\r\n return line.substring(tabCharacter.length);\r\n }\r\n\r\n return line;\r\n })\r\n .join('\\n');\r\n\r\n if (value !== nextValue) {\r\n const startLineText = linesBeforeCaret[startLine];\r\n\r\n this._applyEdits({\r\n value: nextValue,\r\n // Move the start cursor if first line in selection was modified\r\n // It was modified only if it started with a tab\r\n selectionStart: startLineText.startsWith(tabCharacter)\r\n ? selectionStart - tabCharacter.length\r\n : selectionStart,\r\n // Move the end cursor by total number of characters removed\r\n selectionEnd: selectionEnd - (value.length - nextValue.length),\r\n });\r\n }\r\n } else if (selectionStart !== selectionEnd) {\r\n // Indent selected lines\r\n const linesBeforeCaret = this._getLines(value, selectionStart);\r\n const startLine = linesBeforeCaret.length - 1;\r\n const endLine = this._getLines(value, selectionEnd).length - 1;\r\n const startLineText = linesBeforeCaret[startLine];\r\n\r\n this._applyEdits({\r\n value: value\r\n .split('\\n')\r\n .map((line, i) => {\r\n if (i >= startLine && i <= endLine) {\r\n return tabCharacter + line;\r\n }\r\n\r\n return line;\r\n })\r\n .join('\\n'),\r\n // Move the start cursor by number of characters added in first line of selection\r\n // Don't move it if it there was no text before cursor\r\n selectionStart: /\\S/.test(startLineText) ? selectionStart + tabCharacter.length : selectionStart,\r\n // Move the end cursor by total number of characters added\r\n selectionEnd: selectionEnd + tabCharacter.length * (endLine - startLine + 1),\r\n });\r\n } else {\r\n const updatedSelection = selectionStart + tabCharacter.length;\r\n\r\n this._applyEdits({\r\n // Insert tab character at caret\r\n value: value.substring(0, selectionStart) + tabCharacter + value.substring(selectionEnd),\r\n // Update caret position\r\n selectionStart: updatedSelection,\r\n selectionEnd: updatedSelection,\r\n });\r\n }\r\n } else if (e.keyCode === KEYCODE_BACKSPACE) {\r\n const hasSelection = selectionStart !== selectionEnd;\r\n const textBeforeCaret = value.substring(0, selectionStart);\r\n\r\n if (textBeforeCaret.endsWith(tabCharacter) && !hasSelection) {\r\n // Prevent default delete behaviour\r\n e.preventDefault();\r\n\r\n const updatedSelection = selectionStart - tabCharacter.length;\r\n\r\n this._applyEdits({\r\n // Remove tab character at caret\r\n value: value.substring(0, selectionStart - tabCharacter.length) + value.substring(selectionEnd),\r\n // Update caret position\r\n selectionStart: updatedSelection,\r\n selectionEnd: updatedSelection,\r\n });\r\n }\r\n } else if (e.keyCode === KEYCODE_ENTER) {\r\n \r\n if (this.autocompleteData.length && this.autocompleteOpen) {\r\n this.acceptAutocomplete(e);\r\n\r\n } else if (selectionStart === selectionEnd) {\r\n // Get the current line\r\n const line = this._getLines(value, selectionStart).pop();\r\n const matches = line?.match(/^\\s+/);\r\n\r\n if (matches && matches[0]) {\r\n e.preventDefault();\r\n\r\n // Preserve indentation on inserting a new line\r\n const indent = '\\n' + matches[0];\r\n const updatedSelection = selectionStart + indent.length;\r\n\r\n this._applyEdits({\r\n // Insert indentation character at caret\r\n value: value.substring(0, selectionStart) + indent + value.substring(selectionEnd),\r\n // Update caret position\r\n selectionStart: updatedSelection,\r\n selectionEnd: updatedSelection,\r\n });\r\n }\r\n }\r\n } else if (BRACKET_PAIRS[e.key]) {\r\n // If text is selected, wrap them in the characters\r\n if (selectionStart !== selectionEnd) {\r\n e.preventDefault();\r\n\r\n this._applyEdits({\r\n value:\r\n value.substring(0, selectionStart) +\r\n e.key +\r\n value.substring(selectionStart, selectionEnd) +\r\n BRACKET_PAIRS[e.key] +\r\n value.substring(selectionEnd),\r\n // Update caret position\r\n selectionStart: selectionStart + 1,\r\n selectionEnd: selectionEnd + 1,\r\n });\r\n }\r\n } else if (\r\n (isMacLike\r\n ? // Trigger undo with ⌘+Z on Mac\r\n e.metaKey && e.keyCode === KEYCODE_Z\r\n : // Trigger undo with Ctrl+Z on other platforms\r\n e.ctrlKey && e.keyCode === KEYCODE_Z) &&\r\n !e.shiftKey &&\r\n !e.altKey\r\n ) {\r\n e.preventDefault();\r\n\r\n this._undoEdit();\r\n } else if (\r\n (isMacLike\r\n ? // Trigger redo with ⌘+Shift+Z on Mac\r\n e.metaKey && e.keyCode === KEYCODE_Z && e.shiftKey\r\n : isWindows\r\n ? // Trigger redo with Ctrl+Y on Windows\r\n e.ctrlKey && e.keyCode === KEYCODE_Y\r\n : // Trigger redo with Ctrl+Shift+Z on other platforms\r\n e.ctrlKey && e.keyCode === KEYCODE_Z && e.shiftKey) &&\r\n !e.altKey\r\n ) {\r\n e.preventDefault();\r\n\r\n this._redoEdit();\r\n } else if (e.keyCode === KEYCODE_M && e.ctrlKey && (isMacLike ? e.shiftKey : true)) {\r\n e.preventDefault();\r\n\r\n // Toggle capturing tab key so users can focus away\r\n this.capture = !this.capture;\r\n }\r\n if (e.keyCode !== 13 && e.keyCode !== 9) {\r\n setTimeout(() => {\r\n this.updateAutocompleteData();\r\n }, 1);\r\n }\r\n },\r\n },\r\n render(h): VNode {\r\n const lineNumberWidthCalculator = h(\r\n 'div',\r\n {\r\n attrs: {\r\n class: 'prism-editor__line-width-calc',\r\n style: 'height: 0px; visibility: hidden; pointer-events: none;',\r\n },\r\n },\r\n '999'\r\n );\r\n const lineNumbers = h(\r\n 'div',\r\n {\r\n staticClass: 'prism-editor__line-numbers',\r\n style: {\r\n 'min-height': this.lineNumbersHeight,\r\n },\r\n attrs: {\r\n 'aria-hidden': 'true',\r\n },\r\n },\r\n [\r\n lineNumberWidthCalculator,\r\n Array.from(Array(this.lineNumbersCount).keys()).map((_, index) => {\r\n return h('div', { attrs: { class: 'prism-editor__line-number token comment' } }, `${++index}`);\r\n }),\r\n ]\r\n );\r\n\r\n const autocompleteList = (this.autocompleteOpen && this.autocompleteData.length) ? h(\r\n 'ul',\r\n {\r\n staticClass: 'prism-editor__autocomplete',\r\n style: {left: this.cursorOffset[0] + 'px', top: this.cursorOffset[1] + 'px'}\r\n },\r\n this.autocompleteData.map((data: AutocompleteEntry, i) => {\r\n return h('li', {\r\n key: data.text,\r\n class: {selected: i == this.autocompleteIndex},\r\n on: {\r\n mousedown: ($event: MouseEvent) => {\r\n this.acceptAutocomplete($event, i);\r\n }\r\n }\r\n }, [data.label || data.text]);\r\n })\r\n ) : undefined;\r\n\r\n const textarea = h('textarea', {\r\n ref: 'textarea',\r\n on: {\r\n input: this.handleChange,\r\n keydown: this.handleKeyDown,\r\n click: ($event: MouseEvent) => {\r\n this.autocompleteOpen = false;\r\n this.$emit('click', $event);\r\n },\r\n keyup: ($event: KeyboardEvent) => {\r\n this.$emit('keyup', $event);\r\n },\r\n focus: ($event: FocusEvent) => {\r\n this._recordStateIfChange();\r\n this.$emit('focus', $event);\r\n },\r\n blur: ($event: FocusEvent) => {\r\n this.autocompleteOpen = false;\r\n this.$emit('blur', $event);\r\n },\r\n },\r\n staticClass: 'prism-editor__textarea',\r\n class: {\r\n 'prism-editor__textarea--empty': this.isEmpty,\r\n },\r\n attrs: {\r\n spellCheck: 'false',\r\n autocapitalize: 'off',\r\n autocomplete: 'off',\r\n autocorrect: 'off',\r\n 'data-gramm': 'false',\r\n placeholder: this.placeholder,\r\n 'data-testid': 'textarea',\r\n readonly: this.readonly,\r\n },\r\n domProps: {\r\n value: this.codeData,\r\n },\r\n });\r\n const preview = h('pre', {\r\n ref: 'pre',\r\n staticClass: 'prism-editor__editor',\r\n attrs: {\r\n 'data-testid': 'preview',\r\n },\r\n domProps: {\r\n innerHTML: this.content,\r\n },\r\n });\r\n const editorContainer = h('div', { staticClass: 'prism-editor__container' }, [textarea, preview]);\r\n const wrapper = h('div', { staticClass: 'prism-editor-wrapper', ref: 'wrapper' }, [this.lineNumbers && lineNumbers, editorContainer]);\r\n return h('div', { staticClass: 'prism-editor-component' }, [wrapper, autocompleteList]);\r\n },\r\n});\r\n"],"names":["KEYCODE_ENTER","KEYCODE_TAB","KEYCODE_BACKSPACE","KEYCODE_Y","KEYCODE_Z","KEYCODE_M","KEYCODE_ESCAPE","BRACKET_PAIRS","HISTORY_LIMIT","HISTORY_TIME_GAP","isWindows","global","test","navigator","platform","isMacLike","PrismEditor","Vue","extend","props","lineNumbers","type","Boolean","autoStyleLineNumbers","readonly","value","String","highlight","Function","required","tabSize","Number","insertSpaces","ignoreTabKey","placeholder","autocomplete","data","capture","history","stack","offset","lineNumbersHeight","codeData","autocompleteOpen","autocompleteIndex","autocompleteData","watch","immediate","handler","newVal","content","$nextTick","setLineNumbersHeight","styleLineNumbers","nextTick","node","$el","querySelector","scrollIntoView","block","computed","isEmpty","length","result","lineNumbersCount","totalLines","split","cursorOffset","text","input","$refs","textarea","wrapper","lines","substring","selectionEnd","font_size","parseFloat","getComputedStyle","getPropertyValue","line","column","Math","min","scrollLeft","clientWidth","scrollTop","mounted","_recordCurrentState","methods","updateAutocompleteData","old_length","splice","Infinity","max","acceptAutocomplete","event","option","preventDefault","undefined","suggestion","overlap","new_text","substr","join","cursor_pos","endsWith","selectionStart","_applyEdits","inserted_characters","setTimeout","pre","height","$editor","$lineNumbers","editorStyles","window","btlr","bblr","style","stylesList","forEach","_recordChange","_getLines","position","_recordStateIfChange","record","last","_updateInput","overwrite","slice","count","extras","timestamp","Date","now","re","previous","pop","match","current","startsWith","push","$emit","handleChange","e","target","_undoEdit","_redoEdit","handleKeyDown","$listeners","keydown","defaultPrevented","keyCode","stopPropagation","blur","tabCharacter","repeat","shiftKey","linesBeforeCaret","startLine","endLine","nextValue","map","i","startLineText","updatedSelection","hasSelection","textBeforeCaret","matches","indent","key","metaKey","ctrlKey","altKey","render","h","lineNumberWidthCalculator","attrs","staticClass","Array","from","keys","_","index","autocompleteList","left","top","selected","on","mousedown","$event","label","ref","click","keyup","focus","spellCheck","autocapitalize","autocorrect","domProps","preview","innerHTML","editorContainer"],"mappings":"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"} \ No newline at end of file diff --git a/packages/vue-prism-editor/dist/prismeditor.umd.production.min.js b/packages/vue-prism-editor/dist/prismeditor.umd.production.min.js index 825c6b6..7b8e69e 100644 --- a/packages/vue-prism-editor/dist/prismeditor.umd.production.min.js +++ b/packages/vue-prism-editor/dist/prismeditor.umd.production.min.js @@ -1,2 +1,2 @@ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("vue")):"function"==typeof define&&define.amd?define(["exports","vue"],e):e((t=t||self).PrismEditor={},t.Vue)}(this,(function(t,e){"use strict";var i=void 0!==typeof self?self:this;function s(){return(s=Object.assign||function(t){for(var e=1;e"},lineNumbersCount:function(){return this.codeData.split(/\r\n|\n/).length}},mounted:function(){this._recordCurrentState(),this.styleLineNumbers()},methods:{setLineNumbersHeight:function(){this.lineNumbersHeight=getComputedStyle(this.$refs.pre).height},styleLineNumbers:function(){if(this.lineNumbers&&this.autoStyleLineNumbers){var t=this.$refs.pre,e=this.$el.querySelector(".prism-editor__line-numbers"),i=window.getComputedStyle(t);this.$nextTick((function(){var s="border-top-left-radius",n="border-bottom-left-radius";e&&(e.style[s]=i[s],e.style[n]=i[n],t.style[s]="0",t.style[n]="0",["background-color","margin-top","padding-top","font-family","font-size","line-height"].forEach((function(t){e.style[t]=i[t]})),e.style["margin-bottom"]="-"+i["padding-top"])}))}},_recordCurrentState:function(){var t=this.$refs.textarea;t&&this._recordChange({value:t.value,selectionStart:t.selectionStart,selectionEnd:t.selectionEnd})},_getLines:function(t,e){return t.substring(0,e).split("\n")},_recordStateIfChange:function(){this.history.stack[this.history.offset].value!=this.codeData&&this._recordChange({value:this.codeData,selectionStart:this.codeData.length,selectionEnd:this.codeData.length})},_applyEdits:function(t){var e=this.$refs.textarea,i=this.history.stack[this.history.offset];i&&e&&(this.history.stack[this.history.offset]=s({},i,{selectionStart:e.selectionStart,selectionEnd:e.selectionEnd})),this._recordChange(t),this._updateInput(t)},_recordChange:function(t,e){void 0===e&&(e=!1);var i=this.history,n=i.stack,r=i.offset;if(n.length&&r>-1){this.history.stack=n.slice(0,r+1);var a=this.history.stack.length;if(a>100){var o=a-100;this.history.stack=n.slice(o,a),this.history.offset=Math.max(this.history.offset-o,0)}}var l=Date.now();if(e){var h=this.history.stack[this.history.offset];if(h&&l-h.timestamp<3e3){var u,c,d=/[^a-z0-9]([a-z0-9]+)$/i,f=null===(u=this._getLines(h.value,h.selectionStart).pop())||void 0===u?void 0:u.match(d),p=null===(c=this._getLines(t.value,t.selectionStart).pop())||void 0===c?void 0:c.match(d);if(f&&p&&p[1].startsWith(f[1]))return void(this.history.stack[this.history.offset]=s({},t,{timestamp:l}))}}this.history.stack.push(s({},t,{timestamp:l})),this.history.offset++},_updateInput:function(t){var e=this.$refs.textarea;e&&(e.value=t.value,e.selectionStart=t.selectionStart,e.selectionEnd=t.selectionEnd,this.$emit("input",t.value))},handleChange:function(t){var e=t.target,i=e.value;this._recordChange({value:i,selectionStart:e.selectionStart,selectionEnd:e.selectionEnd},!0),this.$emit("input",i)},_undoEdit:function(){var t=this.history,e=t.offset,i=t.stack[e-1];i&&(this._updateInput(i),this.history.offset=Math.max(e-1,0))},_redoEdit:function(){var t=this.history,e=t.stack,i=t.offset,s=e[i+1];s&&(this._updateInput(s),this.history.offset=Math.min(i+1,e.length-1))},handleKeyDown:function(t){var e=this.tabSize,i=this.insertSpaces,s=this.ignoreTabKey;if(!this.$listeners.keydown||(this.$emit("keydown",t),!t.defaultPrevented)){27===t.keyCode&&(t.target.blur(),this.$emit("blur",t));var o=t.target,l=o.value,h=o.selectionStart,u=o.selectionEnd,c=(i?" ":"\t").repeat(e);if(9===t.keyCode&&!s&&this.capture)if(t.preventDefault(),t.shiftKey){var d=this._getLines(l,h),f=d.length-1,p=this._getLines(l,u).length-1,y=l.split("\n").map((function(t,e){return e>=f&&e<=p&&t.startsWith(c)?t.substring(c.length):t})).join("\n");l!==y&&this._applyEdits({value:y,selectionStart:d[f].startsWith(c)?h-c.length:h,selectionEnd:u-(l.length-y.length)})}else if(h!==u){var m=this._getLines(l,h),g=m.length-1,v=this._getLines(l,u).length-1,b=m[g];this._applyEdits({value:l.split("\n").map((function(t,e){return e>=g&&e<=v?c+t:t})).join("\n"),selectionStart:/\S/.test(b)?h+c.length:h,selectionEnd:u+c.length*(v-g+1)})}else{var _=h+c.length;this._applyEdits({value:l.substring(0,h)+c+l.substring(u),selectionStart:_,selectionEnd:_})}else if(8===t.keyCode){var k=h!==u;if(l.substring(0,h).endsWith(c)&&!k){t.preventDefault();var S=h-c.length;this._applyEdits({value:l.substring(0,h-c.length)+l.substring(u),selectionStart:S,selectionEnd:S})}}else if(13===t.keyCode){if(h===u){var E=this._getLines(l,h).pop(),C=null==E?void 0:E.match(/^\s+/);if(C&&C[0]){t.preventDefault();var D="\n"+C[0],x=h+D.length;this._applyEdits({value:l.substring(0,h)+D+l.substring(u),selectionStart:x,selectionEnd:x})}}}else n[t.key]?h!==u&&(t.preventDefault(),this._applyEdits({value:l.substring(0,h)+t.key+l.substring(h,u)+n[t.key]+l.substring(u),selectionStart:h+1,selectionEnd:u+1})):!(a?t.metaKey&&90===t.keyCode:t.ctrlKey&&90===t.keyCode)||t.shiftKey||t.altKey?(a?t.metaKey&&90===t.keyCode&&t.shiftKey:r?t.ctrlKey&&89===t.keyCode:t.ctrlKey&&90===t.keyCode&&t.shiftKey)&&!t.altKey?(t.preventDefault(),this._redoEdit()):77!==t.keyCode||!t.ctrlKey||a&&!t.shiftKey||(t.preventDefault(),this.capture=!this.capture):(t.preventDefault(),this._undoEdit())}}},render:function(t){var e=this,i=t("div",{attrs:{class:"prism-editor__line-width-calc",style:"height: 0px; visibility: hidden; pointer-events: none;"}},"999"),s=t("div",{staticClass:"prism-editor__line-numbers",style:{"min-height":this.lineNumbersHeight},attrs:{"aria-hidden":"true"}},[i,Array.from(Array(this.lineNumbersCount).keys()).map((function(e,i){return t("div",{attrs:{class:"prism-editor__line-number token comment"}},""+ ++i)}))]),n=t("textarea",{ref:"textarea",on:{input:this.handleChange,keydown:this.handleKeyDown,click:function(t){e.$emit("click",t)},keyup:function(t){e.$emit("keyup",t)},focus:function(t){e._recordStateIfChange(),e.$emit("focus",t)},blur:function(t){e.$emit("blur",t)}},staticClass:"prism-editor__textarea",class:{"prism-editor__textarea--empty":this.isEmpty},attrs:{spellCheck:"false",autocapitalize:"off",autocomplete:"off",autocorrect:"off","data-gramm":"false",placeholder:this.placeholder,"data-testid":"textarea",readonly:this.readonly},domProps:{value:this.codeData}}),r=t("pre",{ref:"pre",staticClass:"prism-editor__editor",attrs:{"data-testid":"preview"},domProps:{innerHTML:this.content}}),a=t("div",{staticClass:"prism-editor__container"},[n,r]);return t("div",{staticClass:"prism-editor-wrapper"},[this.lineNumbers&&s,a])}});t.PrismEditor=o,Object.defineProperty(t,"__esModule",{value:!0});let l=null;"undefined"!=typeof window?l=window.Vue:void 0!==i&&(l=i.Vue),l&&l.component("PrismEditor",o)})); +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("vue")):"function"==typeof define&&define.amd?define(["exports","vue"],e):e((t=t||self).PrismEditor={},t.Vue)}(this,(function(t,e){"use strict";var i=void 0!==typeof self?self:this;function s(){return(s=Object.assign||function(t){for(var e=1;e li.selected");e&&e.scrollIntoView({block:"nearest"})}))}},computed:{isEmpty:function(){return 0===this.codeData.length},content:function(){return this.highlight(this.codeData)+"
"},lineNumbersCount:function(){return this.codeData.split(/\r\n|\n/).length},cursorOffset:function(){var t=this.$refs.textarea,e=this.$refs.wrapper,i=this.codeData.substring(0,t.selectionEnd||0).split(/\r\n|\n/),s=parseFloat(getComputedStyle(t).getPropertyValue("font-size")),n=i.length;return[Math.min(8.85*i[i.length-1].length*(s/16)-e.scrollLeft,e.clientWidth-Math.min(240,e.clientWidth)),24*n*(s/16)+2-e.scrollTop]}},mounted:function(){this._recordCurrentState(),this.styleLineNumbers()},methods:{updateAutocompleteData:function(){var t,e="function"==typeof this.autocomplete?this.autocomplete(this.codeData,this.$refs.textarea.selectionEnd):[],i=this.autocompleteData.length;(t=this.autocompleteData).splice.apply(t,[0,Infinity].concat(e)),this.autocompleteOpen=!0,this.autocompleteIndex=Math.max(0,Math.min(this.autocompleteIndex,this.autocompleteData.length-1)),i>this.autocompleteData.length&&(this.autocompleteIndex=0)},acceptAutocomplete:function(t,i){var s=this;t.preventDefault(),null==i&&(i=this.autocompleteIndex);var n=this.$refs.textarea,o=this.$refs.wrapper,a=this.autocompleteData[i]||this.autocompleteData[0];if(a){var r=a.overlap||0,l=[this.codeData.substr(0,n.selectionEnd-r),a.text,this.codeData.substring(n.selectionEnd)].join(""),u=n.selectionEnd-r+a.text.length+(a.text.endsWith(")")?-1:0);n.selectionStart=n.selectionEnd=u,this._applyEdits({value:l,selectionStart:u,selectionEnd:u});var h=a.text.length-a.overlap;e.nextTick((function(){o.scrollLeft+=8.85*h})),a.text.endsWith(".")?setTimeout((function(){s.updateAutocompleteData()}),1):this.autocompleteOpen=!1}},setLineNumbersHeight:function(){this.lineNumbersHeight=getComputedStyle(this.$refs.pre).height},styleLineNumbers:function(){if(this.lineNumbers&&this.autoStyleLineNumbers){var t=this.$refs.pre,e=this.$el.querySelector(".prism-editor__line-numbers"),i=window.getComputedStyle(t);this.$nextTick((function(){var s="border-top-left-radius",n="border-bottom-left-radius";e&&(e.style[s]=i[s],e.style[n]=i[n],t.style[s]="0",t.style[n]="0",["background-color","margin-top","padding-top","font-family","font-size","line-height"].forEach((function(t){e.style[t]=i[t]})),e.style["margin-bottom"]="-"+i["padding-top"])}))}},_recordCurrentState:function(){var t=this.$refs.textarea;t&&this._recordChange({value:t.value,selectionStart:t.selectionStart,selectionEnd:t.selectionEnd})},_getLines:function(t,e){return t.substring(0,e).split("\n")},_recordStateIfChange:function(){this.history.stack[this.history.offset].value!=this.codeData&&this._recordChange({value:this.codeData,selectionStart:this.codeData.length,selectionEnd:this.codeData.length})},_applyEdits:function(t){var e=this.$refs.textarea,i=this.history.stack[this.history.offset];i&&e&&(this.history.stack[this.history.offset]=s({},i,{selectionStart:e.selectionStart,selectionEnd:e.selectionEnd})),this._recordChange(t),this._updateInput(t)},_recordChange:function(t,e){void 0===e&&(e=!1);var i=this.history,n=i.stack,o=i.offset;if(n.length&&o>-1){this.history.stack=n.slice(0,o+1);var a=this.history.stack.length;if(a>100){var r=a-100;this.history.stack=n.slice(r,a),this.history.offset=Math.max(this.history.offset-r,0)}}var l=Date.now();if(e){var u=this.history.stack[this.history.offset];if(u&&l-u.timestamp<3e3){var h,c,p=/[^a-z0-9]([a-z0-9]+)$/i,d=null===(h=this._getLines(u.value,u.selectionStart).pop())||void 0===h?void 0:h.match(p),f=null===(c=this._getLines(t.value,t.selectionStart).pop())||void 0===c?void 0:c.match(p);if(d&&f&&f[1].startsWith(d[1]))return void(this.history.stack[this.history.offset]=s({},t,{timestamp:l}))}}this.history.stack.push(s({},t,{timestamp:l})),this.history.offset++},_updateInput:function(t){var e=this.$refs.textarea;e&&(e.value=t.value,e.selectionStart=t.selectionStart,e.selectionEnd=t.selectionEnd,this.$emit("input",t.value))},handleChange:function(t){var e=t.target,i=e.value;this._recordChange({value:i,selectionStart:e.selectionStart,selectionEnd:e.selectionEnd},!0),this.$emit("input",i)},_undoEdit:function(){var t=this.history,e=t.offset,i=t.stack[e-1];i&&(this._updateInput(i),this.history.offset=Math.max(e-1,0))},_redoEdit:function(){var t=this.history,e=t.stack,i=t.offset,s=e[i+1];s&&(this._updateInput(s),this.history.offset=Math.min(i+1,e.length-1))},handleKeyDown:function(t){var e=this,i=this.tabSize,s=this.insertSpaces,r=this.ignoreTabKey;if(!this.$listeners.keydown||(this.$emit("keydown",t),!t.defaultPrevented)){if(9===t.keyCode&&this.autocompleteData.length&&this.autocompleteOpen)return this.acceptAutocomplete(t),t.preventDefault(),void t.stopPropagation();if(27===t.keyCode){if(this.autocompleteData.length&&this.autocompleteOpen)return t.preventDefault(),void(this.autocompleteOpen=!1)}else if(38===t.keyCode){if(this.autocompleteData.length&&this.autocompleteOpen)return t.preventDefault(),void(this.autocompleteIndex=(this.autocompleteIndex?this.autocompleteIndex:this.autocompleteData.length)-1)}else if(40===t.keyCode&&this.autocompleteData.length&&this.autocompleteOpen)return t.preventDefault(),void(this.autocompleteIndex=(this.autocompleteIndex+1)%this.autocompleteData.length);27===t.keyCode&&(t.target.blur(),this.$emit("blur",t));var l=t.target,u=l.value,h=l.selectionStart,c=l.selectionEnd,p=(s?" ":"\t").repeat(i);if(9===t.keyCode&&!r&&this.capture)if(t.preventDefault(),t.shiftKey){var d=this._getLines(u,h),f=d.length-1,m=this._getLines(u,c).length-1,y=u.split("\n").map((function(t,e){return e>=f&&e<=m&&t.startsWith(p)?t.substring(p.length):t})).join("\n");u!==y&&this._applyEdits({value:y,selectionStart:d[f].startsWith(p)?h-p.length:h,selectionEnd:c-(u.length-y.length)})}else if(h!==c){var g=this._getLines(u,h),v=g.length-1,b=this._getLines(u,c).length-1,_=g[v];this._applyEdits({value:u.split("\n").map((function(t,e){return e>=v&&e<=b?p+t:t})).join("\n"),selectionStart:/\S/.test(_)?h+p.length:h,selectionEnd:c+p.length*(b-v+1)})}else{var k=h+p.length;this._applyEdits({value:u.substring(0,h)+p+u.substring(c),selectionStart:k,selectionEnd:k})}else if(8===t.keyCode){var D=h!==c;if(u.substring(0,h).endsWith(p)&&!D){t.preventDefault();var x=h-p.length;this._applyEdits({value:u.substring(0,h-p.length)+u.substring(c),selectionStart:x,selectionEnd:x})}}else if(13===t.keyCode){if(this.autocompleteData.length&&this.autocompleteOpen)this.acceptAutocomplete(t);else if(h===c){var E=this._getLines(u,h).pop(),C=null==E?void 0:E.match(/^\s+/);if(C&&C[0]){t.preventDefault();var S="\n"+C[0],$=h+S.length;this._applyEdits({value:u.substring(0,h)+S+u.substring(c),selectionStart:$,selectionEnd:$})}}}else n[t.key]?h!==c&&(t.preventDefault(),this._applyEdits({value:u.substring(0,h)+t.key+u.substring(h,c)+n[t.key]+u.substring(c),selectionStart:h+1,selectionEnd:c+1})):!(a?t.metaKey&&90===t.keyCode:t.ctrlKey&&90===t.keyCode)||t.shiftKey||t.altKey?(a?t.metaKey&&90===t.keyCode&&t.shiftKey:o?t.ctrlKey&&89===t.keyCode:t.ctrlKey&&90===t.keyCode&&t.shiftKey)&&!t.altKey?(t.preventDefault(),this._redoEdit()):77!==t.keyCode||!t.ctrlKey||a&&!t.shiftKey||(t.preventDefault(),this.capture=!this.capture):(t.preventDefault(),this._undoEdit());13!==t.keyCode&&9!==t.keyCode&&setTimeout((function(){e.updateAutocompleteData()}),1)}}},render:function(t){var e=this,i=t("div",{attrs:{class:"prism-editor__line-width-calc",style:"height: 0px; visibility: hidden; pointer-events: none;"}},"999"),s=t("div",{staticClass:"prism-editor__line-numbers",style:{"min-height":this.lineNumbersHeight},attrs:{"aria-hidden":"true"}},[i,Array.from(Array(this.lineNumbersCount).keys()).map((function(e,i){return t("div",{attrs:{class:"prism-editor__line-number token comment"}},""+ ++i)}))]),n=this.autocompleteOpen&&this.autocompleteData.length?t("ul",{staticClass:"prism-editor__autocomplete",style:{left:this.cursorOffset[0]+"px",top:this.cursorOffset[1]+"px"}},this.autocompleteData.map((function(i,s){return t("li",{key:i.text,class:{selected:s==e.autocompleteIndex},on:{mousedown:function(t){e.acceptAutocomplete(t,s)}}},[i.label||i.text])}))):void 0,o=t("textarea",{ref:"textarea",on:{input:this.handleChange,keydown:this.handleKeyDown,click:function(t){e.autocompleteOpen=!1,e.$emit("click",t)},keyup:function(t){e.$emit("keyup",t)},focus:function(t){e._recordStateIfChange(),e.$emit("focus",t)},blur:function(t){e.autocompleteOpen=!1,e.$emit("blur",t)}},staticClass:"prism-editor__textarea",class:{"prism-editor__textarea--empty":this.isEmpty},attrs:{spellCheck:"false",autocapitalize:"off",autocomplete:"off",autocorrect:"off","data-gramm":"false",placeholder:this.placeholder,"data-testid":"textarea",readonly:this.readonly},domProps:{value:this.codeData}}),a=t("pre",{ref:"pre",staticClass:"prism-editor__editor",attrs:{"data-testid":"preview"},domProps:{innerHTML:this.content}}),r=t("div",{staticClass:"prism-editor__container"},[o,a]),l=t("div",{staticClass:"prism-editor-wrapper",ref:"wrapper"},[this.lineNumbers&&s,r]);return t("div",{staticClass:"prism-editor-component"},[l,n])}});t.PrismEditor=r,Object.defineProperty(t,"__esModule",{value:!0});let l=null;"undefined"!=typeof window?l=window.Vue:void 0!==i&&(l=i.Vue),l&&l.component("PrismEditor",r)})); //# sourceMappingURL=prismeditor.umd.production.min.js.map diff --git a/packages/vue-prism-editor/dist/prismeditor.umd.production.min.js.map b/packages/vue-prism-editor/dist/prismeditor.umd.production.min.js.map index 60293cf..bd3f0ae 100644 --- a/packages/vue-prism-editor/dist/prismeditor.umd.production.min.js.map +++ b/packages/vue-prism-editor/dist/prismeditor.umd.production.min.js.map @@ -1 +1 @@ -{"version":3,"file":"prismeditor.umd.production.min.js","sources":["../src/Editor.ts"],"sourcesContent":["import Vue, { VNode } from 'vue';\r\n\r\nimport './styles.css';\r\nconst KEYCODE_ENTER = 13;\r\nconst KEYCODE_TAB = 9;\r\nconst KEYCODE_BACKSPACE = 8;\r\nconst KEYCODE_Y = 89;\r\nconst KEYCODE_Z = 90;\r\nconst KEYCODE_M = 77;\r\nconst KEYCODE_ESCAPE = 27;\r\n\r\nconst BRACKET_PAIRS: {[opening: string]: string} = {\r\n '(':')',\r\n '{':'}',\r\n '[':']',\r\n '\"':'\"',\r\n \"'\":\"'\",\r\n};\r\n\r\nconst HISTORY_LIMIT = 100;\r\nconst HISTORY_TIME_GAP = 3000;\r\n\r\nconst isWindows = 'navigator' in global && /Win/i.test(navigator.platform);\r\nconst isMacLike = 'navigator' in global && /(Mac|iPhone|iPod|iPad)/i.test(navigator.platform);\r\n\r\nexport interface EditorProps {\r\n lineNumbers: boolean;\r\n autoStyleLineNumbers: boolean;\r\n readonly: boolean;\r\n value: string;\r\n highlight: () => string;\r\n tabSize: number;\r\n insertSpaces: boolean;\r\n ignoreTabKey: boolean;\r\n placeholder: string;\r\n}\r\nexport interface Record {\r\n value: string;\r\n selectionStart: number;\r\n selectionEnd: number;\r\n}\r\n\r\nexport interface History {\r\n stack: Array;\r\n offset: number;\r\n}\r\n\r\nexport const PrismEditor = Vue.extend({\r\n props: {\r\n lineNumbers: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n autoStyleLineNumbers: {\r\n type: Boolean,\r\n default: true,\r\n },\r\n readonly: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n value: {\r\n type: String,\r\n default: '',\r\n },\r\n highlight: {\r\n type: Function,\r\n required: true,\r\n },\r\n tabSize: {\r\n type: Number,\r\n default: 2,\r\n },\r\n insertSpaces: {\r\n type: Boolean,\r\n default: true,\r\n },\r\n ignoreTabKey: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n placeholder: {\r\n type: String,\r\n default: '',\r\n },\r\n },\r\n data() {\r\n return {\r\n capture: true,\r\n history: {\r\n stack: [],\r\n offset: -1,\r\n } as History,\r\n lineNumbersHeight: '20px',\r\n codeData: '',\r\n };\r\n },\r\n watch: {\r\n value: {\r\n immediate: true,\r\n handler(newVal: string): void {\r\n if (!newVal) {\r\n this.codeData = '';\r\n } else {\r\n this.codeData = newVal;\r\n }\r\n },\r\n },\r\n content: {\r\n immediate: true,\r\n handler(): void {\r\n if (this.lineNumbers) {\r\n this.$nextTick(() => {\r\n this.setLineNumbersHeight();\r\n });\r\n }\r\n },\r\n },\r\n lineNumbers(): void {\r\n this.$nextTick(() => {\r\n this.styleLineNumbers();\r\n this.setLineNumbersHeight();\r\n });\r\n },\r\n },\r\n computed: {\r\n isEmpty(): boolean {\r\n return this.codeData.length === 0;\r\n },\r\n content(): string {\r\n const result = this.highlight(this.codeData) + '
';\r\n // todo: VNode support?\r\n return result;\r\n },\r\n lineNumbersCount(): number {\r\n const totalLines = this.codeData.split(/\\r\\n|\\n/).length;\r\n return totalLines;\r\n },\r\n },\r\n mounted() {\r\n this._recordCurrentState();\r\n this.styleLineNumbers();\r\n },\r\n\r\n methods: {\r\n setLineNumbersHeight(): void {\r\n this.lineNumbersHeight = getComputedStyle(this.$refs.pre as HTMLTextAreaElement).height;\r\n },\r\n styleLineNumbers(): void {\r\n if (!this.lineNumbers || !this.autoStyleLineNumbers) return;\r\n\r\n const $editor = this.$refs.pre as HTMLTextAreaElement;\r\n const $lineNumbers: HTMLDivElement | null = this.$el.querySelector('.prism-editor__line-numbers');\r\n const editorStyles = window.getComputedStyle($editor);\r\n\r\n this.$nextTick(() => {\r\n const btlr: any = 'border-top-left-radius';\r\n const bblr: any = 'border-bottom-left-radius';\r\n if (!$lineNumbers) return;\r\n $lineNumbers.style[btlr] = editorStyles[btlr];\r\n $lineNumbers.style[bblr] = editorStyles[bblr];\r\n $editor.style[btlr] = '0';\r\n $editor.style[bblr] = '0';\r\n\r\n const stylesList = ['background-color', 'margin-top', 'padding-top', 'font-family', 'font-size', 'line-height'];\r\n stylesList.forEach((style: any) => {\r\n $lineNumbers.style[style] = editorStyles[style];\r\n });\r\n $lineNumbers.style['margin-bottom' as any] = '-' + editorStyles['padding-top' as any];\r\n });\r\n },\r\n _recordCurrentState(): void {\r\n const input = this.$refs.textarea as HTMLTextAreaElement;\r\n\r\n if (!input) return;\r\n // Save current state of the input\r\n const { value, selectionStart, selectionEnd } = input;\r\n\r\n this._recordChange({\r\n value,\r\n selectionStart,\r\n selectionEnd,\r\n });\r\n },\r\n _getLines(text: string, position: number): Array {\r\n return text.substring(0, position).split('\\n');\r\n },\r\n _recordStateIfChange(): void {\r\n if (this.history.stack[this.history.offset].value != this.codeData) {\r\n this._recordChange({\r\n value: this.codeData,\r\n selectionStart: this.codeData.length,\r\n selectionEnd: this.codeData.length,\r\n });\r\n }\r\n },\r\n _applyEdits(record: Record): void {\r\n // Save last selection state\r\n const input = this.$refs.textarea as HTMLTextAreaElement;\r\n const last = this.history.stack[this.history.offset];\r\n\r\n if (last && input) {\r\n this.history.stack[this.history.offset] = {\r\n ...last,\r\n selectionStart: input.selectionStart,\r\n selectionEnd: input.selectionEnd,\r\n };\r\n }\r\n\r\n // Save the changes\r\n this._recordChange(record);\r\n this._updateInput(record);\r\n },\r\n _recordChange(record: Record, overwrite = false): void {\r\n const { stack, offset } = this.history;\r\n\r\n if (stack.length && offset > -1) {\r\n // When something updates, drop the redo operations\r\n this.history.stack = stack.slice(0, offset + 1);\r\n\r\n // Limit the number of operations to 100\r\n const count = this.history.stack.length;\r\n\r\n if (count > HISTORY_LIMIT) {\r\n const extras = count - HISTORY_LIMIT;\r\n\r\n this.history.stack = stack.slice(extras, count);\r\n this.history.offset = Math.max(this.history.offset - extras, 0);\r\n }\r\n }\r\n\r\n const timestamp = Date.now();\r\n\r\n if (overwrite) {\r\n const last = this.history.stack[this.history.offset];\r\n\r\n if (last && timestamp - last.timestamp < HISTORY_TIME_GAP) {\r\n // A previous entry exists and was in short interval\r\n\r\n // Match the last word in the line\r\n const re = /[^a-z0-9]([a-z0-9]+)$/i;\r\n\r\n // Get the previous line\r\n const previous = this._getLines(last.value, last.selectionStart).pop()?.match(re);\r\n\r\n // Get the current line\r\n const current = this._getLines(record.value, record.selectionStart).pop()?.match(re);\r\n\r\n if (previous && current && current[1].startsWith(previous[1])) {\r\n // The last word of the previous line and current line match\r\n // Overwrite previous entry so that undo will remove whole word\r\n this.history.stack[this.history.offset] = {\r\n ...record,\r\n timestamp,\r\n };\r\n\r\n return;\r\n }\r\n }\r\n }\r\n\r\n // Add the new operation to the stack\r\n this.history.stack.push({ ...record, timestamp });\r\n this.history.offset++;\r\n },\r\n\r\n _updateInput(record: Record): void {\r\n const input = this.$refs.textarea as HTMLTextAreaElement;\r\n\r\n if (!input) return;\r\n\r\n // Update values and selection state\r\n input.value = record.value;\r\n input.selectionStart = record.selectionStart;\r\n input.selectionEnd = record.selectionEnd;\r\n\r\n this.$emit('input', record.value);\r\n // this.props.onValueChange(record.value);\r\n },\r\n handleChange(e: KeyboardEvent): void {\r\n const { value, selectionStart, selectionEnd } = e.target as HTMLTextAreaElement;\r\n\r\n this._recordChange(\r\n {\r\n value,\r\n selectionStart,\r\n selectionEnd,\r\n },\r\n true\r\n );\r\n this.$emit('input', value);\r\n // this.props.onValueChange(value);\r\n },\r\n _undoEdit(): void {\r\n const { stack, offset } = this.history;\r\n\r\n // Get the previous edit\r\n const record = stack[offset - 1];\r\n\r\n if (record) {\r\n // Apply the changes and update the offset\r\n this._updateInput(record);\r\n this.history.offset = Math.max(offset - 1, 0);\r\n }\r\n },\r\n _redoEdit(): void {\r\n const { stack, offset } = this.history;\r\n\r\n // Get the next edit\r\n const record = stack[offset + 1];\r\n\r\n if (record) {\r\n // Apply the changes and update the offset\r\n this._updateInput(record);\r\n this.history.offset = Math.min(offset + 1, stack.length - 1);\r\n }\r\n },\r\n handleKeyDown(e: KeyboardEvent): void {\r\n // console.log(navigator.platform);\r\n const { tabSize, insertSpaces, ignoreTabKey } = this;\r\n\r\n if (this.$listeners.keydown) {\r\n // onKeyDown(e);\r\n this.$emit('keydown', e);\r\n\r\n if (e.defaultPrevented) {\r\n return;\r\n }\r\n }\r\n\r\n if (e.keyCode === KEYCODE_ESCAPE) {\r\n (e.target).blur();\r\n this.$emit('blur', e);\r\n }\r\n\r\n const { value, selectionStart, selectionEnd } = e.target as HTMLTextAreaElement;\r\n\r\n const tabCharacter = (insertSpaces ? ' ' : '\\t').repeat(tabSize);\r\n\r\n if (e.keyCode === KEYCODE_TAB && !ignoreTabKey && this.capture) {\r\n // Prevent focus change\r\n e.preventDefault();\r\n\r\n if (e.shiftKey) {\r\n // Unindent selected lines\r\n const linesBeforeCaret = this._getLines(value, selectionStart);\r\n const startLine = linesBeforeCaret.length - 1;\r\n const endLine = this._getLines(value, selectionEnd).length - 1;\r\n const nextValue = value\r\n .split('\\n')\r\n .map((line, i) => {\r\n if (i >= startLine && i <= endLine && line.startsWith(tabCharacter)) {\r\n return line.substring(tabCharacter.length);\r\n }\r\n\r\n return line;\r\n })\r\n .join('\\n');\r\n\r\n if (value !== nextValue) {\r\n const startLineText = linesBeforeCaret[startLine];\r\n\r\n this._applyEdits({\r\n value: nextValue,\r\n // Move the start cursor if first line in selection was modified\r\n // It was modified only if it started with a tab\r\n selectionStart: startLineText.startsWith(tabCharacter)\r\n ? selectionStart - tabCharacter.length\r\n : selectionStart,\r\n // Move the end cursor by total number of characters removed\r\n selectionEnd: selectionEnd - (value.length - nextValue.length),\r\n });\r\n }\r\n } else if (selectionStart !== selectionEnd) {\r\n // Indent selected lines\r\n const linesBeforeCaret = this._getLines(value, selectionStart);\r\n const startLine = linesBeforeCaret.length - 1;\r\n const endLine = this._getLines(value, selectionEnd).length - 1;\r\n const startLineText = linesBeforeCaret[startLine];\r\n\r\n this._applyEdits({\r\n value: value\r\n .split('\\n')\r\n .map((line, i) => {\r\n if (i >= startLine && i <= endLine) {\r\n return tabCharacter + line;\r\n }\r\n\r\n return line;\r\n })\r\n .join('\\n'),\r\n // Move the start cursor by number of characters added in first line of selection\r\n // Don't move it if it there was no text before cursor\r\n selectionStart: /\\S/.test(startLineText) ? selectionStart + tabCharacter.length : selectionStart,\r\n // Move the end cursor by total number of characters added\r\n selectionEnd: selectionEnd + tabCharacter.length * (endLine - startLine + 1),\r\n });\r\n } else {\r\n const updatedSelection = selectionStart + tabCharacter.length;\r\n\r\n this._applyEdits({\r\n // Insert tab character at caret\r\n value: value.substring(0, selectionStart) + tabCharacter + value.substring(selectionEnd),\r\n // Update caret position\r\n selectionStart: updatedSelection,\r\n selectionEnd: updatedSelection,\r\n });\r\n }\r\n } else if (e.keyCode === KEYCODE_BACKSPACE) {\r\n const hasSelection = selectionStart !== selectionEnd;\r\n const textBeforeCaret = value.substring(0, selectionStart);\r\n\r\n if (textBeforeCaret.endsWith(tabCharacter) && !hasSelection) {\r\n // Prevent default delete behaviour\r\n e.preventDefault();\r\n\r\n const updatedSelection = selectionStart - tabCharacter.length;\r\n\r\n this._applyEdits({\r\n // Remove tab character at caret\r\n value: value.substring(0, selectionStart - tabCharacter.length) + value.substring(selectionEnd),\r\n // Update caret position\r\n selectionStart: updatedSelection,\r\n selectionEnd: updatedSelection,\r\n });\r\n }\r\n } else if (e.keyCode === KEYCODE_ENTER) {\r\n // Ignore selections\r\n if (selectionStart === selectionEnd) {\r\n // Get the current line\r\n const line = this._getLines(value, selectionStart).pop();\r\n const matches = line?.match(/^\\s+/);\r\n\r\n if (matches && matches[0]) {\r\n e.preventDefault();\r\n\r\n // Preserve indentation on inserting a new line\r\n const indent = '\\n' + matches[0];\r\n const updatedSelection = selectionStart + indent.length;\r\n\r\n this._applyEdits({\r\n // Insert indentation character at caret\r\n value: value.substring(0, selectionStart) + indent + value.substring(selectionEnd),\r\n // Update caret position\r\n selectionStart: updatedSelection,\r\n selectionEnd: updatedSelection,\r\n });\r\n }\r\n }\r\n } else if (BRACKET_PAIRS[e.key]) {\r\n // If text is selected, wrap them in the characters\r\n if (selectionStart !== selectionEnd) {\r\n e.preventDefault();\r\n\r\n this._applyEdits({\r\n value:\r\n value.substring(0, selectionStart) +\r\n e.key +\r\n value.substring(selectionStart, selectionEnd) +\r\n BRACKET_PAIRS[e.key] +\r\n value.substring(selectionEnd),\r\n // Update caret position\r\n selectionStart: selectionStart + 1,\r\n selectionEnd: selectionEnd + 1,\r\n });\r\n }\r\n } else if (\r\n (isMacLike\r\n ? // Trigger undo with ⌘+Z on Mac\r\n e.metaKey && e.keyCode === KEYCODE_Z\r\n : // Trigger undo with Ctrl+Z on other platforms\r\n e.ctrlKey && e.keyCode === KEYCODE_Z) &&\r\n !e.shiftKey &&\r\n !e.altKey\r\n ) {\r\n e.preventDefault();\r\n\r\n this._undoEdit();\r\n } else if (\r\n (isMacLike\r\n ? // Trigger redo with ⌘+Shift+Z on Mac\r\n e.metaKey && e.keyCode === KEYCODE_Z && e.shiftKey\r\n : isWindows\r\n ? // Trigger redo with Ctrl+Y on Windows\r\n e.ctrlKey && e.keyCode === KEYCODE_Y\r\n : // Trigger redo with Ctrl+Shift+Z on other platforms\r\n e.ctrlKey && e.keyCode === KEYCODE_Z && e.shiftKey) &&\r\n !e.altKey\r\n ) {\r\n e.preventDefault();\r\n\r\n this._redoEdit();\r\n } else if (e.keyCode === KEYCODE_M && e.ctrlKey && (isMacLike ? e.shiftKey : true)) {\r\n e.preventDefault();\r\n\r\n // Toggle capturing tab key so users can focus away\r\n this.capture = !this.capture;\r\n }\r\n },\r\n },\r\n render(h): VNode {\r\n const lineNumberWidthCalculator = h(\r\n 'div',\r\n {\r\n attrs: {\r\n class: 'prism-editor__line-width-calc',\r\n style: 'height: 0px; visibility: hidden; pointer-events: none;',\r\n },\r\n },\r\n '999'\r\n );\r\n const lineNumbers = h(\r\n 'div',\r\n {\r\n staticClass: 'prism-editor__line-numbers',\r\n style: {\r\n 'min-height': this.lineNumbersHeight,\r\n },\r\n attrs: {\r\n 'aria-hidden': 'true',\r\n },\r\n },\r\n [\r\n lineNumberWidthCalculator,\r\n Array.from(Array(this.lineNumbersCount).keys()).map((_, index) => {\r\n return h('div', { attrs: { class: 'prism-editor__line-number token comment' } }, `${++index}`);\r\n }),\r\n ]\r\n );\r\n\r\n const textarea = h('textarea', {\r\n ref: 'textarea',\r\n on: {\r\n input: this.handleChange,\r\n keydown: this.handleKeyDown,\r\n click: ($event: MouseEvent) => {\r\n this.$emit('click', $event);\r\n },\r\n keyup: ($event: KeyboardEvent) => {\r\n this.$emit('keyup', $event);\r\n },\r\n focus: ($event: FocusEvent) => {\r\n this._recordStateIfChange();\r\n this.$emit('focus', $event);\r\n },\r\n blur: ($event: FocusEvent) => {\r\n this.$emit('blur', $event);\r\n },\r\n },\r\n staticClass: 'prism-editor__textarea',\r\n class: {\r\n 'prism-editor__textarea--empty': this.isEmpty,\r\n },\r\n attrs: {\r\n spellCheck: 'false',\r\n autocapitalize: 'off',\r\n autocomplete: 'off',\r\n autocorrect: 'off',\r\n 'data-gramm': 'false',\r\n placeholder: this.placeholder,\r\n 'data-testid': 'textarea',\r\n readonly: this.readonly,\r\n },\r\n domProps: {\r\n value: this.codeData,\r\n },\r\n });\r\n const preview = h('pre', {\r\n ref: 'pre',\r\n staticClass: 'prism-editor__editor',\r\n attrs: {\r\n 'data-testid': 'preview',\r\n },\r\n domProps: {\r\n innerHTML: this.content,\r\n },\r\n });\r\n const editorContainer = h('div', { staticClass: 'prism-editor__container' }, [textarea, preview]);\r\n return h('div', { staticClass: 'prism-editor-wrapper' }, [this.lineNumbers && lineNumbers, editorContainer]);\r\n },\r\n});\r\n"],"names":["BRACKET_PAIRS","isWindows","global","test","navigator","platform","isMacLike","PrismEditor","Vue","extend","props","lineNumbers","type","Boolean","autoStyleLineNumbers","readonly","value","String","highlight","Function","required","tabSize","Number","insertSpaces","ignoreTabKey","placeholder","data","capture","history","stack","offset","lineNumbersHeight","codeData","watch","immediate","handler","newVal","content","this","$nextTick","_this","setLineNumbersHeight","_this2","styleLineNumbers","computed","isEmpty","length","lineNumbersCount","split","mounted","_recordCurrentState","methods","getComputedStyle","$refs","pre","height","$editor","$lineNumbers","$el","querySelector","editorStyles","window","btlr","bblr","style","forEach","input","textarea","_recordChange","selectionStart","selectionEnd","_getLines","text","position","substring","_recordStateIfChange","_applyEdits","record","last","_updateInput","overwrite","slice","count","extras","Math","max","timestamp","Date","now","re","previous","pop","_this$_getLines$pop","match","current","_this$_getLines$pop2","startsWith","push","$emit","handleChange","e","target","_undoEdit","_redoEdit","min","handleKeyDown","$listeners","keydown","defaultPrevented","keyCode","blur","tabCharacter","repeat","preventDefault","shiftKey","linesBeforeCaret","startLine","endLine","nextValue","map","line","i","join","startLineText","updatedSelection","hasSelection","endsWith","matches","indent","key","metaKey","ctrlKey","altKey","render","h","lineNumberWidthCalculator","attrs","staticClass","Array","from","keys","_","index","ref","on","click","$event","_this3","keyup","focus","spellCheck","autocapitalize","autocomplete","autocorrect","domProps","preview","innerHTML","editorContainer"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"prismeditor.umd.production.min.js","sources":["../src/Editor.ts"],"sourcesContent":["import Vue, { VNode } from 'vue';\r\n\r\nimport './styles.css';\r\nconst KEYCODE_ENTER = 13;\r\nconst KEYCODE_TAB = 9;\r\nconst KEYCODE_BACKSPACE = 8;\r\nconst KEYCODE_Y = 89;\r\nconst KEYCODE_Z = 90;\r\nconst KEYCODE_M = 77;\r\nconst KEYCODE_ESCAPE = 27;\r\n\r\nconst BRACKET_PAIRS: {[opening: string]: string} = {\r\n '(':')',\r\n '{':'}',\r\n '[':']',\r\n '\"':'\"',\r\n \"'\":\"'\",\r\n};\r\n\r\nconst HISTORY_LIMIT = 100;\r\nconst HISTORY_TIME_GAP = 3000;\r\n\r\nconst isWindows = 'navigator' in global && /Win/i.test(navigator.platform);\r\nconst isMacLike = 'navigator' in global && /(Mac|iPhone|iPod|iPad)/i.test(navigator.platform);\r\n\r\nexport interface EditorProps {\r\n lineNumbers: boolean;\r\n autoStyleLineNumbers: boolean;\r\n readonly: boolean;\r\n value: string;\r\n highlight: () => string;\r\n tabSize: number;\r\n insertSpaces: boolean;\r\n ignoreTabKey: boolean;\r\n placeholder: string;\r\n}\r\nexport interface Record {\r\n value: string;\r\n selectionStart: number;\r\n selectionEnd: number;\r\n}\r\n\r\nexport interface History {\r\n stack: Array;\r\n offset: number;\r\n}\r\ninterface AutocompleteEntry {\r\n text: string\r\n overlap: number\r\n label?: string\r\n}\r\n\r\nexport const PrismEditor = Vue.extend({\r\n props: {\r\n lineNumbers: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n autoStyleLineNumbers: {\r\n type: Boolean,\r\n default: true,\r\n },\r\n readonly: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n value: {\r\n type: String,\r\n default: '',\r\n },\r\n highlight: {\r\n type: Function,\r\n required: true,\r\n },\r\n tabSize: {\r\n type: Number,\r\n default: 2,\r\n },\r\n insertSpaces: {\r\n type: Boolean,\r\n default: true,\r\n },\r\n ignoreTabKey: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n placeholder: {\r\n type: String,\r\n default: '',\r\n },\r\n autocomplete: {\r\n type: Function,\r\n default() {\r\n return []\r\n }\r\n }\r\n },\r\n data() {\r\n return {\r\n capture: true,\r\n history: {\r\n stack: [],\r\n offset: -1,\r\n } as History,\r\n lineNumbersHeight: '20px',\r\n codeData: '',\r\n\r\n autocompleteOpen: false,\r\n autocompleteIndex: 0,\r\n autocompleteData: [] as AutocompleteEntry[]\r\n };\r\n },\r\n watch: {\r\n value: {\r\n immediate: true,\r\n handler(newVal: string): void {\r\n if (!newVal) {\r\n this.codeData = '';\r\n } else {\r\n this.codeData = newVal;\r\n }\r\n },\r\n },\r\n content: {\r\n immediate: true,\r\n handler(): void {\r\n if (this.lineNumbers) {\r\n this.$nextTick(() => {\r\n this.setLineNumbersHeight();\r\n });\r\n }\r\n },\r\n },\r\n lineNumbers(): void {\r\n this.$nextTick(() => {\r\n this.styleLineNumbers();\r\n this.setLineNumbersHeight();\r\n });\r\n },\r\n autocompleteIndex() {\r\n Vue.nextTick(() => {\r\n let node = this.$el.querySelector('ul.prism-editor__autocomplete > li.selected');\r\n if (node) node.scrollIntoView({block: 'nearest'});\r\n })\r\n },\r\n },\r\n computed: {\r\n isEmpty(): boolean {\r\n return this.codeData.length === 0;\r\n },\r\n content(): string {\r\n const result = this.highlight(this.codeData) + '
';\r\n // todo: VNode support?\r\n return result;\r\n },\r\n lineNumbersCount(): number {\r\n const totalLines = this.codeData.split(/\\r\\n|\\n/).length;\r\n return totalLines;\r\n },\r\n cursorOffset() {\r\n let text: string = this.codeData;\r\n let input = this.$refs.textarea as HTMLTextAreaElement;\r\n let wrapper = this.$refs.wrapper as HTMLDivElement;\r\n let lines = text.substring(0, input.selectionEnd || 0).split(/\\r\\n|\\n/);\r\n let font_size = parseFloat(getComputedStyle(input).getPropertyValue('font-size'));\r\n let line = lines.length;\r\n let column = lines[lines.length-1].length;\r\n return [\r\n Math.min((column * 8.85 * (font_size / 16)) - wrapper.scrollLeft, wrapper.clientWidth - Math.min(240, wrapper.clientWidth)),\r\n (line * 24.0 * (font_size / 16)) + 2 - wrapper.scrollTop,\r\n ]\r\n },\r\n },\r\n mounted() {\r\n this._recordCurrentState();\r\n this.styleLineNumbers();\r\n },\r\n\r\n methods: {\r\n updateAutocompleteData() {\r\n let input = this.$refs.textarea as HTMLTextAreaElement;\r\n let data: AutocompleteEntry[] = typeof this.autocomplete == 'function' ? this.autocomplete(this.codeData, input.selectionEnd) : [];\r\n let old_length = this.autocompleteData.length;\r\n this.autocompleteData.splice(0, Infinity, ...data);\r\n this.autocompleteOpen = true;\r\n this.autocompleteIndex = Math.max(0, Math.min(this.autocompleteIndex, this.autocompleteData.length-1));\r\n if (old_length > this.autocompleteData.length) this.autocompleteIndex = 0;\r\n },\r\n acceptAutocomplete(event: Event, option?: number) {\r\n event.preventDefault()\r\n if (option == undefined) option = this.autocompleteIndex;\r\n\r\n let input = this.$refs.textarea as HTMLTextAreaElement;\r\n let wrapper = this.$refs.wrapper as HTMLDivElement;\r\n let suggestion = this.autocompleteData[option] || this.autocompleteData[0];\r\n if (!suggestion) return;\r\n \r\n let overlap = suggestion.overlap || 0;\r\n let new_text = [\r\n this.codeData.substr(0, input.selectionEnd - overlap),\r\n suggestion.text,\r\n this.codeData.substring(input.selectionEnd),\r\n ]\r\n let result: string = new_text.join('');\r\n let cursor_pos = input.selectionEnd - overlap + suggestion.text.length + (suggestion.text.endsWith(')') ? -1 : 0);\r\n input.selectionStart = input.selectionEnd = cursor_pos;\r\n\r\n this._applyEdits({\r\n value: result,\r\n selectionStart: cursor_pos,\r\n selectionEnd: cursor_pos,\r\n });\r\n let inserted_characters = suggestion.text.length - suggestion.overlap;\r\n Vue.nextTick(() => {\r\n wrapper.scrollLeft += inserted_characters * 8.85;\r\n })\r\n\r\n if (suggestion.text.endsWith('.')) {\r\n setTimeout(() => {\r\n this.updateAutocompleteData();\r\n }, 1);\r\n } else {\r\n this.autocompleteOpen = false;\r\n }\r\n },\r\n setLineNumbersHeight(): void {\r\n this.lineNumbersHeight = getComputedStyle(this.$refs.pre as HTMLTextAreaElement).height;\r\n },\r\n styleLineNumbers(): void {\r\n if (!this.lineNumbers || !this.autoStyleLineNumbers) return;\r\n\r\n const $editor = this.$refs.pre as HTMLTextAreaElement;\r\n const $lineNumbers: HTMLDivElement | null = this.$el.querySelector('.prism-editor__line-numbers');\r\n const editorStyles = window.getComputedStyle($editor);\r\n\r\n this.$nextTick(() => {\r\n const btlr: any = 'border-top-left-radius';\r\n const bblr: any = 'border-bottom-left-radius';\r\n if (!$lineNumbers) return;\r\n $lineNumbers.style[btlr] = editorStyles[btlr];\r\n $lineNumbers.style[bblr] = editorStyles[bblr];\r\n $editor.style[btlr] = '0';\r\n $editor.style[bblr] = '0';\r\n\r\n const stylesList = ['background-color', 'margin-top', 'padding-top', 'font-family', 'font-size', 'line-height'];\r\n stylesList.forEach((style: any) => {\r\n $lineNumbers.style[style] = editorStyles[style];\r\n });\r\n $lineNumbers.style['margin-bottom' as any] = '-' + editorStyles['padding-top' as any];\r\n });\r\n },\r\n _recordCurrentState(): void {\r\n const input = this.$refs.textarea as HTMLTextAreaElement;\r\n\r\n if (!input) return;\r\n // Save current state of the input\r\n const { value, selectionStart, selectionEnd } = input;\r\n\r\n this._recordChange({\r\n value,\r\n selectionStart,\r\n selectionEnd,\r\n });\r\n },\r\n _getLines(text: string, position: number): Array {\r\n return text.substring(0, position).split('\\n');\r\n },\r\n _recordStateIfChange(): void {\r\n if (this.history.stack[this.history.offset].value != this.codeData) {\r\n this._recordChange({\r\n value: this.codeData,\r\n selectionStart: this.codeData.length,\r\n selectionEnd: this.codeData.length,\r\n });\r\n }\r\n },\r\n _applyEdits(record: Record): void {\r\n // Save last selection state\r\n const input = this.$refs.textarea as HTMLTextAreaElement;\r\n const last = this.history.stack[this.history.offset];\r\n\r\n if (last && input) {\r\n this.history.stack[this.history.offset] = {\r\n ...last,\r\n selectionStart: input.selectionStart,\r\n selectionEnd: input.selectionEnd,\r\n };\r\n }\r\n\r\n // Save the changes\r\n this._recordChange(record);\r\n this._updateInput(record);\r\n },\r\n _recordChange(record: Record, overwrite = false): void {\r\n const { stack, offset } = this.history;\r\n\r\n if (stack.length && offset > -1) {\r\n // When something updates, drop the redo operations\r\n this.history.stack = stack.slice(0, offset + 1);\r\n\r\n // Limit the number of operations to 100\r\n const count = this.history.stack.length;\r\n\r\n if (count > HISTORY_LIMIT) {\r\n const extras = count - HISTORY_LIMIT;\r\n\r\n this.history.stack = stack.slice(extras, count);\r\n this.history.offset = Math.max(this.history.offset - extras, 0);\r\n }\r\n }\r\n\r\n const timestamp = Date.now();\r\n\r\n if (overwrite) {\r\n const last = this.history.stack[this.history.offset];\r\n\r\n if (last && timestamp - last.timestamp < HISTORY_TIME_GAP) {\r\n // A previous entry exists and was in short interval\r\n\r\n // Match the last word in the line\r\n const re = /[^a-z0-9]([a-z0-9]+)$/i;\r\n\r\n // Get the previous line\r\n const previous = this._getLines(last.value, last.selectionStart).pop()?.match(re);\r\n\r\n // Get the current line\r\n const current = this._getLines(record.value, record.selectionStart).pop()?.match(re);\r\n\r\n if (previous && current && current[1].startsWith(previous[1])) {\r\n // The last word of the previous line and current line match\r\n // Overwrite previous entry so that undo will remove whole word\r\n this.history.stack[this.history.offset] = {\r\n ...record,\r\n timestamp,\r\n };\r\n\r\n return;\r\n }\r\n }\r\n }\r\n\r\n // Add the new operation to the stack\r\n this.history.stack.push({ ...record, timestamp });\r\n this.history.offset++;\r\n },\r\n\r\n _updateInput(record: Record): void {\r\n const input = this.$refs.textarea as HTMLTextAreaElement;\r\n\r\n if (!input) return;\r\n\r\n // Update values and selection state\r\n input.value = record.value;\r\n input.selectionStart = record.selectionStart;\r\n input.selectionEnd = record.selectionEnd;\r\n\r\n this.$emit('input', record.value);\r\n // this.props.onValueChange(record.value);\r\n },\r\n handleChange(e: KeyboardEvent): void {\r\n const { value, selectionStart, selectionEnd } = e.target as HTMLTextAreaElement;\r\n\r\n this._recordChange(\r\n {\r\n value,\r\n selectionStart,\r\n selectionEnd,\r\n },\r\n true\r\n );\r\n this.$emit('input', value);\r\n // this.props.onValueChange(value);\r\n },\r\n _undoEdit(): void {\r\n const { stack, offset } = this.history;\r\n\r\n // Get the previous edit\r\n const record = stack[offset - 1];\r\n\r\n if (record) {\r\n // Apply the changes and update the offset\r\n this._updateInput(record);\r\n this.history.offset = Math.max(offset - 1, 0);\r\n }\r\n },\r\n _redoEdit(): void {\r\n const { stack, offset } = this.history;\r\n\r\n // Get the next edit\r\n const record = stack[offset + 1];\r\n\r\n if (record) {\r\n // Apply the changes and update the offset\r\n this._updateInput(record);\r\n this.history.offset = Math.min(offset + 1, stack.length - 1);\r\n }\r\n },\r\n handleKeyDown(e: KeyboardEvent): void {\r\n // console.log(navigator.platform);\r\n const { tabSize, insertSpaces, ignoreTabKey } = this;\r\n\r\n if (this.$listeners.keydown) {\r\n // onKeyDown(e);\r\n this.$emit('keydown', e);\r\n\r\n if (e.defaultPrevented) {\r\n return;\r\n }\r\n }\r\n\r\n if (e.keyCode === 9 && this.autocompleteData.length && this.autocompleteOpen) {\r\n this.acceptAutocomplete(e);\r\n e.preventDefault();\r\n e.stopPropagation();\r\n return;\r\n }\r\n if (e.keyCode === 27) {\r\n // Escape\r\n if (this.autocompleteData.length && this.autocompleteOpen) {\r\n e.preventDefault();\r\n this.autocompleteOpen = false;\r\n return;\r\n }\r\n } else if (e.keyCode === 38) {\r\n // Up\r\n if (this.autocompleteData.length && this.autocompleteOpen) {\r\n e.preventDefault();\r\n this.autocompleteIndex = (this.autocompleteIndex ? this.autocompleteIndex : this.autocompleteData.length) - 1;\r\n return;\r\n }\r\n } else if (e.keyCode === 40) {\r\n // Down\r\n if (this.autocompleteData.length && this.autocompleteOpen) {\r\n e.preventDefault();\r\n this.autocompleteIndex = (this.autocompleteIndex + 1) % this.autocompleteData.length;\r\n return;\r\n }\r\n }\r\n\r\n if (e.keyCode === KEYCODE_ESCAPE) {\r\n (e.target).blur();\r\n this.$emit('blur', e);\r\n }\r\n\r\n const { value, selectionStart, selectionEnd } = e.target as HTMLTextAreaElement;\r\n\r\n const tabCharacter = (insertSpaces ? ' ' : '\\t').repeat(tabSize);\r\n\r\n if (e.keyCode === KEYCODE_TAB && !ignoreTabKey && this.capture) {\r\n // Prevent focus change\r\n e.preventDefault();\r\n\r\n if (e.shiftKey) {\r\n // Unindent selected lines\r\n const linesBeforeCaret = this._getLines(value, selectionStart);\r\n const startLine = linesBeforeCaret.length - 1;\r\n const endLine = this._getLines(value, selectionEnd).length - 1;\r\n const nextValue = value\r\n .split('\\n')\r\n .map((line, i) => {\r\n if (i >= startLine && i <= endLine && line.startsWith(tabCharacter)) {\r\n return line.substring(tabCharacter.length);\r\n }\r\n\r\n return line;\r\n })\r\n .join('\\n');\r\n\r\n if (value !== nextValue) {\r\n const startLineText = linesBeforeCaret[startLine];\r\n\r\n this._applyEdits({\r\n value: nextValue,\r\n // Move the start cursor if first line in selection was modified\r\n // It was modified only if it started with a tab\r\n selectionStart: startLineText.startsWith(tabCharacter)\r\n ? selectionStart - tabCharacter.length\r\n : selectionStart,\r\n // Move the end cursor by total number of characters removed\r\n selectionEnd: selectionEnd - (value.length - nextValue.length),\r\n });\r\n }\r\n } else if (selectionStart !== selectionEnd) {\r\n // Indent selected lines\r\n const linesBeforeCaret = this._getLines(value, selectionStart);\r\n const startLine = linesBeforeCaret.length - 1;\r\n const endLine = this._getLines(value, selectionEnd).length - 1;\r\n const startLineText = linesBeforeCaret[startLine];\r\n\r\n this._applyEdits({\r\n value: value\r\n .split('\\n')\r\n .map((line, i) => {\r\n if (i >= startLine && i <= endLine) {\r\n return tabCharacter + line;\r\n }\r\n\r\n return line;\r\n })\r\n .join('\\n'),\r\n // Move the start cursor by number of characters added in first line of selection\r\n // Don't move it if it there was no text before cursor\r\n selectionStart: /\\S/.test(startLineText) ? selectionStart + tabCharacter.length : selectionStart,\r\n // Move the end cursor by total number of characters added\r\n selectionEnd: selectionEnd + tabCharacter.length * (endLine - startLine + 1),\r\n });\r\n } else {\r\n const updatedSelection = selectionStart + tabCharacter.length;\r\n\r\n this._applyEdits({\r\n // Insert tab character at caret\r\n value: value.substring(0, selectionStart) + tabCharacter + value.substring(selectionEnd),\r\n // Update caret position\r\n selectionStart: updatedSelection,\r\n selectionEnd: updatedSelection,\r\n });\r\n }\r\n } else if (e.keyCode === KEYCODE_BACKSPACE) {\r\n const hasSelection = selectionStart !== selectionEnd;\r\n const textBeforeCaret = value.substring(0, selectionStart);\r\n\r\n if (textBeforeCaret.endsWith(tabCharacter) && !hasSelection) {\r\n // Prevent default delete behaviour\r\n e.preventDefault();\r\n\r\n const updatedSelection = selectionStart - tabCharacter.length;\r\n\r\n this._applyEdits({\r\n // Remove tab character at caret\r\n value: value.substring(0, selectionStart - tabCharacter.length) + value.substring(selectionEnd),\r\n // Update caret position\r\n selectionStart: updatedSelection,\r\n selectionEnd: updatedSelection,\r\n });\r\n }\r\n } else if (e.keyCode === KEYCODE_ENTER) {\r\n \r\n if (this.autocompleteData.length && this.autocompleteOpen) {\r\n this.acceptAutocomplete(e);\r\n\r\n } else if (selectionStart === selectionEnd) {\r\n // Get the current line\r\n const line = this._getLines(value, selectionStart).pop();\r\n const matches = line?.match(/^\\s+/);\r\n\r\n if (matches && matches[0]) {\r\n e.preventDefault();\r\n\r\n // Preserve indentation on inserting a new line\r\n const indent = '\\n' + matches[0];\r\n const updatedSelection = selectionStart + indent.length;\r\n\r\n this._applyEdits({\r\n // Insert indentation character at caret\r\n value: value.substring(0, selectionStart) + indent + value.substring(selectionEnd),\r\n // Update caret position\r\n selectionStart: updatedSelection,\r\n selectionEnd: updatedSelection,\r\n });\r\n }\r\n }\r\n } else if (BRACKET_PAIRS[e.key]) {\r\n // If text is selected, wrap them in the characters\r\n if (selectionStart !== selectionEnd) {\r\n e.preventDefault();\r\n\r\n this._applyEdits({\r\n value:\r\n value.substring(0, selectionStart) +\r\n e.key +\r\n value.substring(selectionStart, selectionEnd) +\r\n BRACKET_PAIRS[e.key] +\r\n value.substring(selectionEnd),\r\n // Update caret position\r\n selectionStart: selectionStart + 1,\r\n selectionEnd: selectionEnd + 1,\r\n });\r\n }\r\n } else if (\r\n (isMacLike\r\n ? // Trigger undo with ⌘+Z on Mac\r\n e.metaKey && e.keyCode === KEYCODE_Z\r\n : // Trigger undo with Ctrl+Z on other platforms\r\n e.ctrlKey && e.keyCode === KEYCODE_Z) &&\r\n !e.shiftKey &&\r\n !e.altKey\r\n ) {\r\n e.preventDefault();\r\n\r\n this._undoEdit();\r\n } else if (\r\n (isMacLike\r\n ? // Trigger redo with ⌘+Shift+Z on Mac\r\n e.metaKey && e.keyCode === KEYCODE_Z && e.shiftKey\r\n : isWindows\r\n ? // Trigger redo with Ctrl+Y on Windows\r\n e.ctrlKey && e.keyCode === KEYCODE_Y\r\n : // Trigger redo with Ctrl+Shift+Z on other platforms\r\n e.ctrlKey && e.keyCode === KEYCODE_Z && e.shiftKey) &&\r\n !e.altKey\r\n ) {\r\n e.preventDefault();\r\n\r\n this._redoEdit();\r\n } else if (e.keyCode === KEYCODE_M && e.ctrlKey && (isMacLike ? e.shiftKey : true)) {\r\n e.preventDefault();\r\n\r\n // Toggle capturing tab key so users can focus away\r\n this.capture = !this.capture;\r\n }\r\n if (e.keyCode !== 13 && e.keyCode !== 9) {\r\n setTimeout(() => {\r\n this.updateAutocompleteData();\r\n }, 1);\r\n }\r\n },\r\n },\r\n render(h): VNode {\r\n const lineNumberWidthCalculator = h(\r\n 'div',\r\n {\r\n attrs: {\r\n class: 'prism-editor__line-width-calc',\r\n style: 'height: 0px; visibility: hidden; pointer-events: none;',\r\n },\r\n },\r\n '999'\r\n );\r\n const lineNumbers = h(\r\n 'div',\r\n {\r\n staticClass: 'prism-editor__line-numbers',\r\n style: {\r\n 'min-height': this.lineNumbersHeight,\r\n },\r\n attrs: {\r\n 'aria-hidden': 'true',\r\n },\r\n },\r\n [\r\n lineNumberWidthCalculator,\r\n Array.from(Array(this.lineNumbersCount).keys()).map((_, index) => {\r\n return h('div', { attrs: { class: 'prism-editor__line-number token comment' } }, `${++index}`);\r\n }),\r\n ]\r\n );\r\n\r\n const autocompleteList = (this.autocompleteOpen && this.autocompleteData.length) ? h(\r\n 'ul',\r\n {\r\n staticClass: 'prism-editor__autocomplete',\r\n style: {left: this.cursorOffset[0] + 'px', top: this.cursorOffset[1] + 'px'}\r\n },\r\n this.autocompleteData.map((data: AutocompleteEntry, i) => {\r\n return h('li', {\r\n key: data.text,\r\n class: {selected: i == this.autocompleteIndex},\r\n on: {\r\n mousedown: ($event: MouseEvent) => {\r\n this.acceptAutocomplete($event, i);\r\n }\r\n }\r\n }, [data.label || data.text]);\r\n })\r\n ) : undefined;\r\n\r\n const textarea = h('textarea', {\r\n ref: 'textarea',\r\n on: {\r\n input: this.handleChange,\r\n keydown: this.handleKeyDown,\r\n click: ($event: MouseEvent) => {\r\n this.autocompleteOpen = false;\r\n this.$emit('click', $event);\r\n },\r\n keyup: ($event: KeyboardEvent) => {\r\n this.$emit('keyup', $event);\r\n },\r\n focus: ($event: FocusEvent) => {\r\n this._recordStateIfChange();\r\n this.$emit('focus', $event);\r\n },\r\n blur: ($event: FocusEvent) => {\r\n this.autocompleteOpen = false;\r\n this.$emit('blur', $event);\r\n },\r\n },\r\n staticClass: 'prism-editor__textarea',\r\n class: {\r\n 'prism-editor__textarea--empty': this.isEmpty,\r\n },\r\n attrs: {\r\n spellCheck: 'false',\r\n autocapitalize: 'off',\r\n autocomplete: 'off',\r\n autocorrect: 'off',\r\n 'data-gramm': 'false',\r\n placeholder: this.placeholder,\r\n 'data-testid': 'textarea',\r\n readonly: this.readonly,\r\n },\r\n domProps: {\r\n value: this.codeData,\r\n },\r\n });\r\n const preview = h('pre', {\r\n ref: 'pre',\r\n staticClass: 'prism-editor__editor',\r\n attrs: {\r\n 'data-testid': 'preview',\r\n },\r\n domProps: {\r\n innerHTML: this.content,\r\n },\r\n });\r\n const editorContainer = h('div', { staticClass: 'prism-editor__container' }, [textarea, preview]);\r\n const wrapper = h('div', { staticClass: 'prism-editor-wrapper', ref: 'wrapper' }, [this.lineNumbers && lineNumbers, editorContainer]);\r\n return h('div', { staticClass: 'prism-editor-component' }, [wrapper, autocompleteList]);\r\n },\r\n});\r\n"],"names":["BRACKET_PAIRS","isWindows","global","test","navigator","platform","isMacLike","PrismEditor","Vue","extend","props","lineNumbers","type","Boolean","autoStyleLineNumbers","readonly","value","String","highlight","Function","required","tabSize","Number","insertSpaces","ignoreTabKey","placeholder","autocomplete","data","capture","history","stack","offset","lineNumbersHeight","codeData","autocompleteOpen","autocompleteIndex","autocompleteData","watch","immediate","handler","newVal","content","this","$nextTick","_this","setLineNumbersHeight","_this2","styleLineNumbers","nextTick","node","_this3","$el","querySelector","scrollIntoView","block","computed","isEmpty","length","lineNumbersCount","split","cursorOffset","input","$refs","textarea","wrapper","lines","substring","selectionEnd","font_size","parseFloat","getComputedStyle","getPropertyValue","line","Math","min","scrollLeft","clientWidth","scrollTop","mounted","_recordCurrentState","methods","updateAutocompleteData","old_length","splice","Infinity","max","acceptAutocomplete","event","option","preventDefault","undefined","suggestion","overlap","result","substr","text","join","cursor_pos","endsWith","selectionStart","_applyEdits","inserted_characters","setTimeout","_this4","pre","height","$editor","$lineNumbers","editorStyles","window","btlr","bblr","style","forEach","_recordChange","_getLines","position","_recordStateIfChange","record","last","_updateInput","overwrite","slice","count","extras","timestamp","Date","now","re","previous","pop","_this$_getLines$pop","match","current","_this$_getLines$pop2","startsWith","push","$emit","handleChange","e","target","_undoEdit","_redoEdit","handleKeyDown","$listeners","keydown","defaultPrevented","keyCode","stopPropagation","blur","tabCharacter","repeat","shiftKey","linesBeforeCaret","startLine","endLine","nextValue","map","i","startLineText","updatedSelection","hasSelection","matches","indent","key","metaKey","ctrlKey","altKey","_this5","render","h","lineNumberWidthCalculator","attrs","staticClass","Array","from","keys","_","index","autocompleteList","left","top","selected","_this6","on","mousedown","$event","label","ref","click","keyup","focus","spellCheck","autocapitalize","autocorrect","domProps","preview","innerHTML","editorContainer"],"mappings":"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"} \ No newline at end of file diff --git a/packages/vue-prism-editor/src/Editor.ts b/packages/vue-prism-editor/src/Editor.ts index 0c64e34..5f5669e 100644 --- a/packages/vue-prism-editor/src/Editor.ts +++ b/packages/vue-prism-editor/src/Editor.ts @@ -44,6 +44,11 @@ export interface History { stack: Array; offset: number; } +interface AutocompleteEntry { + text: string + overlap: number + label?: string +} export const PrismEditor = Vue.extend({ props: { @@ -83,6 +88,12 @@ export const PrismEditor = Vue.extend({ type: String, default: '', }, + autocomplete: { + type: Function, + default() { + return [] + } + } }, data() { return { @@ -93,6 +104,10 @@ export const PrismEditor = Vue.extend({ } as History, lineNumbersHeight: '20px', codeData: '', + + autocompleteOpen: false, + autocompleteIndex: 0, + autocompleteData: [] as AutocompleteEntry[] }; }, watch: { @@ -122,6 +137,12 @@ export const PrismEditor = Vue.extend({ this.setLineNumbersHeight(); }); }, + autocompleteIndex() { + Vue.nextTick(() => { + let node = this.$el.querySelector('ul.prism-editor__autocomplete > li.selected'); + if (node) node.scrollIntoView({block: 'nearest'}); + }) + }, }, computed: { isEmpty(): boolean { @@ -136,6 +157,19 @@ export const PrismEditor = Vue.extend({ const totalLines = this.codeData.split(/\r\n|\n/).length; return totalLines; }, + cursorOffset() { + let text: string = this.codeData; + let input = this.$refs.textarea as HTMLTextAreaElement; + let wrapper = this.$refs.wrapper as HTMLDivElement; + let lines = text.substring(0, input.selectionEnd || 0).split(/\r\n|\n/); + let font_size = parseFloat(getComputedStyle(input).getPropertyValue('font-size')); + let line = lines.length; + let column = lines[lines.length-1].length; + return [ + Math.min((column * 8.85 * (font_size / 16)) - wrapper.scrollLeft, wrapper.clientWidth - Math.min(240, wrapper.clientWidth)), + (line * 24.0 * (font_size / 16)) + 2 - wrapper.scrollTop, + ] + }, }, mounted() { this._recordCurrentState(); @@ -143,6 +177,52 @@ export const PrismEditor = Vue.extend({ }, methods: { + updateAutocompleteData() { + let input = this.$refs.textarea as HTMLTextAreaElement; + let data: AutocompleteEntry[] = typeof this.autocomplete == 'function' ? this.autocomplete(this.codeData, input.selectionEnd) : []; + let old_length = this.autocompleteData.length; + this.autocompleteData.splice(0, Infinity, ...data); + this.autocompleteOpen = true; + this.autocompleteIndex = Math.max(0, Math.min(this.autocompleteIndex, this.autocompleteData.length-1)); + if (old_length > this.autocompleteData.length) this.autocompleteIndex = 0; + }, + acceptAutocomplete(event: Event, option?: number) { + event.preventDefault() + if (option == undefined) option = this.autocompleteIndex; + + let input = this.$refs.textarea as HTMLTextAreaElement; + let wrapper = this.$refs.wrapper as HTMLDivElement; + let suggestion = this.autocompleteData[option] || this.autocompleteData[0]; + if (!suggestion) return; + + let overlap = suggestion.overlap || 0; + let new_text = [ + this.codeData.substr(0, input.selectionEnd - overlap), + suggestion.text, + this.codeData.substring(input.selectionEnd), + ] + let result: string = new_text.join(''); + let cursor_pos = input.selectionEnd - overlap + suggestion.text.length + (suggestion.text.endsWith(')') ? -1 : 0); + input.selectionStart = input.selectionEnd = cursor_pos; + + this._applyEdits({ + value: result, + selectionStart: cursor_pos, + selectionEnd: cursor_pos, + }); + let inserted_characters = suggestion.text.length - suggestion.overlap; + Vue.nextTick(() => { + wrapper.scrollLeft += inserted_characters * 8.85; + }) + + if (suggestion.text.endsWith('.')) { + setTimeout(() => { + this.updateAutocompleteData(); + }, 1); + } else { + this.autocompleteOpen = false; + } + }, setLineNumbersHeight(): void { this.lineNumbersHeight = getComputedStyle(this.$refs.pre as HTMLTextAreaElement).height; }, @@ -328,6 +408,35 @@ export const PrismEditor = Vue.extend({ } } + if (e.keyCode === 9 && this.autocompleteData.length && this.autocompleteOpen) { + this.acceptAutocomplete(e); + e.preventDefault(); + e.stopPropagation(); + return; + } + if (e.keyCode === 27) { + // Escape + if (this.autocompleteData.length && this.autocompleteOpen) { + e.preventDefault(); + this.autocompleteOpen = false; + return; + } + } else if (e.keyCode === 38) { + // Up + if (this.autocompleteData.length && this.autocompleteOpen) { + e.preventDefault(); + this.autocompleteIndex = (this.autocompleteIndex ? this.autocompleteIndex : this.autocompleteData.length) - 1; + return; + } + } else if (e.keyCode === 40) { + // Down + if (this.autocompleteData.length && this.autocompleteOpen) { + e.preventDefault(); + this.autocompleteIndex = (this.autocompleteIndex + 1) % this.autocompleteData.length; + return; + } + } + if (e.keyCode === KEYCODE_ESCAPE) { (e.target).blur(); this.$emit('blur', e); @@ -425,8 +534,11 @@ export const PrismEditor = Vue.extend({ }); } } else if (e.keyCode === KEYCODE_ENTER) { - // Ignore selections - if (selectionStart === selectionEnd) { + + if (this.autocompleteData.length && this.autocompleteOpen) { + this.acceptAutocomplete(e); + + } else if (selectionStart === selectionEnd) { // Get the current line const line = this._getLines(value, selectionStart).pop(); const matches = line?.match(/^\s+/); @@ -496,6 +608,11 @@ export const PrismEditor = Vue.extend({ // Toggle capturing tab key so users can focus away this.capture = !this.capture; } + if (e.keyCode !== 13 && e.keyCode !== 9) { + setTimeout(() => { + this.updateAutocompleteData(); + }, 1); + } }, }, render(h): VNode { @@ -528,12 +645,32 @@ export const PrismEditor = Vue.extend({ ] ); + const autocompleteList = (this.autocompleteOpen && this.autocompleteData.length) ? h( + 'ul', + { + staticClass: 'prism-editor__autocomplete', + style: {left: this.cursorOffset[0] + 'px', top: this.cursorOffset[1] + 'px'} + }, + this.autocompleteData.map((data: AutocompleteEntry, i) => { + return h('li', { + key: data.text, + class: {selected: i == this.autocompleteIndex}, + on: { + mousedown: ($event: MouseEvent) => { + this.acceptAutocomplete($event, i); + } + } + }, [data.label || data.text]); + }) + ) : undefined; + const textarea = h('textarea', { ref: 'textarea', on: { input: this.handleChange, keydown: this.handleKeyDown, click: ($event: MouseEvent) => { + this.autocompleteOpen = false; this.$emit('click', $event); }, keyup: ($event: KeyboardEvent) => { @@ -544,6 +681,7 @@ export const PrismEditor = Vue.extend({ this.$emit('focus', $event); }, blur: ($event: FocusEvent) => { + this.autocompleteOpen = false; this.$emit('blur', $event); }, }, @@ -576,6 +714,7 @@ export const PrismEditor = Vue.extend({ }, }); const editorContainer = h('div', { staticClass: 'prism-editor__container' }, [textarea, preview]); - return h('div', { staticClass: 'prism-editor-wrapper' }, [this.lineNumbers && lineNumbers, editorContainer]); + const wrapper = h('div', { staticClass: 'prism-editor-wrapper', ref: 'wrapper' }, [this.lineNumbers && lineNumbers, editorContainer]); + return h('div', { staticClass: 'prism-editor-component' }, [wrapper, autocompleteList]); }, }); diff --git a/packages/vue-prism-editor/src/styles.css b/packages/vue-prism-editor/src/styles.css index 7426cfd..68e051e 100644 --- a/packages/vue-prism-editor/src/styles.css +++ b/packages/vue-prism-editor/src/styles.css @@ -1,11 +1,23 @@ + +.prism-editor-component { + width: 100%; + height: auto; + max-height: 100%; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + align-items: flex-start; + position: relative; +} + .prism-editor-wrapper { width: 100%; height: 100%; - display: flex; - align-items: flex-start; + display: block; overflow: auto; tab-size: 1.5em; -moz-tab-size: 1.5em; +} @media all and (-ms-high-contrast: none), (-ms-high-contrast: active) { .prism-editor__textarea { @@ -16,14 +28,31 @@ color: transparent !important; } } + .prism-editor__autocomplete { + position: absolute; + min-width: 100px; + width: 100%; + max-width: 250px; + top: 25px; + min-height: 12px; + max-height: 180px; + overflow-y: auto; + z-index: 4; + } + .prism-editor__autocomplete li { + overflow: hidden; + white-space: nowrap; + padding: 1px 5px; + cursor: pointer; + } .prism-editor__container { position: relative; text-align: left; box-sizing: border-box; padding: 0; - overflow: hidden; - width: 100%; + width: max-content; + min-width: 100%; } .prism-editor__line-numbers { @@ -84,5 +113,6 @@ .prism-editor__editor { position: relative; pointer-events: none; + overflow: visible; } -} +