[
  {
    "path": ".gitignore",
    "content": "/node_modules\n/*.log\n/demo-source\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2020 Carter Li\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "vue3-ace-editor\n====================\n\n\n[![npm](https://img.shields.io/npm/v/vue3-ace-editor.svg)](https://www.npmjs.com/package/vue3-ace-editor)\n\n\nA packaging of [ace](https://ace.c9.io/). Inspired by [vue2-ace-editor](https://github.com/chairuosen/vue2-ace-editor), but supports [Vue 3](https://github.com/vuejs/vue-next)\n\n## Install\n\n`ace-builds` must be installed alongside `vue3-ace-editor` using your favorite package manager.\n\n* npm i vue3-ace-editor ace-builds\n* yarn add vue3-ace-editor ace-builds\n* pnpm i vue3-ace-editor ace-builds\n\n## Usage\n\n```vue\n<script setup>\n    import { ref } from 'vue';\n    import { VAceEditor } from 'vue3-ace-editor';\n    import 'ace-builds/src-noconflict/mode-json'; // Load the language definition file used below\n    import 'ace-builds/src-noconflict/theme-chrome'; // Load the theme definition file used below\n\n    const content = ref(JSON.stringify({ message: 'Hello Ace' }));\n</script>\n<template>\n    <v-ace-editor\n        v-model:value=\"content\"\n        lang=\"json\"\n        theme=\"chrome\"\n        style=\"height: 300px\" />\n</template>\n```\n\nProperty `v-model:value` is required. `<v-ace-editor>` has no height by default. Its height must be specified manually, or set both `min-lines` and `max-lines` to make the editor's height auto-grow.\n\nProperty `lang`, `theme` is same as [ace-editor's doc](https://github.com/ajaxorg/ace)\n\n\n## Load modes and themes (**REQUIRED**)\n\nUsing of `ace-builds/webpack-resolver` is removed due to bug https://github.com/CarterLi/vue3-ace-editor/issues/3. You **MUST** import `theme` and `mode` yourself. eg.\n\n```js\n// You MUST make sure that `ace-builds` or `vue3-ace-editor` (which imports `ace-builds` internally) is loaded before importing `mode` and `theme`\nimport 'ace-builds/src-noconflict/mode-json';\nimport 'ace-builds/src-noconflict/theme-chrome';\n```\n\nTo use dynamic loading to avoid first-load overhead\n\n```js\nimport ace from 'ace-builds';\n\nimport modeJsonUrl from 'ace-builds/src-noconflict/mode-json?url';\nace.config.setModuleUrl('ace/mode/json', modeJsonUrl);\n\nimport themeChromeUrl from 'ace-builds/src-noconflict/theme-chrome?url';\nace.config.setModuleUrl('ace/theme/chrome', themeChromeUrl);\n```\n\nNote that to make search box (`Ctrl+F` or `Command+F`) work, `ext-searchbox` must also be loaded.\n\n```js\nimport extSearchboxUrl from 'ace-builds/src-noconflict/ext-searchbox?url';\nace.config.setModuleUrl('ace/ext/searchbox', extSearchboxUrl);\n```\n\nFind all supported themes and modes in `node_modules/ace-builds/src-noconflict`\n\n## Deferences with [vue2-ace-editor](https://github.com/chairuosen/vue2-ace-editor)\n\n1. This component uses [ace-builds](https://www.npmjs.com/package/ace-builds) directly, instead of the outdated wrapper [brace](https://www.npmjs.com/package/brace)\n1. DOM size changes are detected automatically using [ResizeObserver](resize-observer-polyfill), thus no `width` / `height` props needed.\n1. For easier usage, more props / events added / emitted.\n    1. Prop `readonly`: This Boolean attribute indicates that the user cannot modify the value of the control.\n    1. Prop `placeholder`: A hint to the user of what can be entered in the control.\n    1. Prop `wrap`: Indicates whether the control wraps text.\n    1. Prop `printMargin`: A short hand of `showPrintMargin` and `printMarginColumn`.\n    1. Prop `minLines` and `maxLines`: Specifiy the minimum and maximum number of lines.\n    1. All ace events emitted. Docs can be found here: <https://ace.c9.io/#api=editor&nav=api>\n    1. Some commonly used methods `focus`, `blur`, `selectAll` provided as shortcuts.\n\n## Get raw ace instance\n\nUse `getAceInstance`\n\n```vue\n<script setup>\n    import { ref, onMounted } from 'vue';\n\n    const aceRef = ref(null);\n\n    onMounted(() => {\n        console.log(aceRef.value.getAceInstance());\n    })\n</script>\n<template>\n    <v-ace-editor ref=\"aceRef\" v-bind=\"...\" />\n</template>\n```\n\n`@init` is provided for `vue2-ace-editor` compatibility only but is not recommanded to use.\n\n## Enable syntax checking\n\nTo enable syntax checking, module `ace/mode/lang_worker` must be registered, and option `useWorker: true` must be set.\n\nTake JSON for example:\n\n```ts\nimport workerJsonUrl from 'ace-builds/src-noconflict/worker-json?url'; // For vite\n\nimport workerJsonUrl from 'file-loader?esModule=false!ace-builds/src-noconflict/worker-json.js'; // For webpack / vue-cli\n\nace.config.setModuleUrl('ace/mode/json_worker', workerJsonUrl);\n```\n\n```html\n<v-ace-editor v-model:value=\"json\" lang=\"json\" :options=\"{ useWorker: true }\" />\n```\n\nSee also https://github.com/CarterLi/vue3-ace-editor/issues/3#issuecomment-768190528 to load the worker file from CDN\n\n## Minimal example using vite\n\n* Preview: <https://carterli.github.io/vue3-ace-editor/>\n* Source: <https://github.com/CarterLi/vue3-ace-editor/tree/gh-pages/demo-source>\n\n## Use it with Nuxt\n\nSince ace doesn't support SSR, using it with Nuxt can be tricky. You must make sure that `ace` related things are loaded only at client side.\n\n```vue\n<script setup>\nimport { markRaw, onMounted, ref } from 'vue';\n\nconst VAceEditor = ref('div'); // Stores dynamic loaded component. Before `vue3-ace-editor` is loaded, a `div` is used as a placeholder\nconst content = ref(JSON.stringify({ platform: 'Nuxt', env: 'SSR' }, null, 2));\n\nonMounted(async () => { // onMounted is a client-only lifecycle hook\n  await import('ace-builds'); // To importing things in a function, dynamic import must be used\n  await import('ace-builds/src-noconflict/mode-json');\n  await import('ace-builds/src-noconflict/theme-chrome');\n  VAceEditor.value = markRaw((await import('vue3-ace-editor')).VAceEditor);\n});\n</script>\n<template>\n  <div>\n    <component :is=\"VAceEditor\" v-model:value=\"content\" lang=\"json\" theme=\"chrome\" style=\"height: 400px\" />\n    <textarea :value=\"content\" style=\"width: 100%; margin-top: 10px\" rows=\"5\" />\n  </div>\n</template>\n```\n\nFull example: <https://stackblitz.com/edit/github-oeoxgm?file=app.vue>\n\n## LICENSE\n\nMIT\n"
  },
  {
    "path": "index.d.ts",
    "content": "import { type Ace } from 'ace-builds';\nimport type { VAceEditorInstance } from './types';\nexport declare const VAceEditor: import(\"vue\").DefineComponent<{\n    value: {\n        type: StringConstructor;\n        required: true;\n    };\n    lang: {\n        type: StringConstructor;\n        default: string;\n    };\n    theme: {\n        type: StringConstructor;\n        default: string;\n    };\n    options: ObjectConstructor;\n    placeholder: StringConstructor;\n    readonly: BooleanConstructor;\n    wrap: BooleanConstructor;\n    printMargin: {\n        type: (BooleanConstructor | NumberConstructor)[];\n        default: boolean;\n    };\n    minLines: NumberConstructor;\n    maxLines: NumberConstructor;\n}, unknown, unknown, {}, {\n    focus(this: VAceEditorInstance): void;\n    blur(this: VAceEditorInstance): void;\n    selectAll(this: VAceEditorInstance): void;\n    getAceInstance(this: VAceEditorInstance): Ace.Editor;\n}, import(\"vue\").ComponentOptionsMixin, import(\"vue\").ComponentOptionsMixin, string[], string, import(\"vue\").VNodeProps & import(\"vue\").AllowedComponentProps & import(\"vue\").ComponentCustomProps, Readonly<import(\"vue\").ExtractPropTypes<{\n    value: {\n        type: StringConstructor;\n        required: true;\n    };\n    lang: {\n        type: StringConstructor;\n        default: string;\n    };\n    theme: {\n        type: StringConstructor;\n        default: string;\n    };\n    options: ObjectConstructor;\n    placeholder: StringConstructor;\n    readonly: BooleanConstructor;\n    wrap: BooleanConstructor;\n    printMargin: {\n        type: (BooleanConstructor | NumberConstructor)[];\n        default: boolean;\n    };\n    minLines: NumberConstructor;\n    maxLines: NumberConstructor;\n}>> & {\n    [x: `on${Capitalize<string>}`]: ((...args: any[]) => any) | undefined;\n}, {\n    lang: string;\n    theme: string;\n    readonly: boolean;\n    wrap: boolean;\n    printMargin: number | boolean;\n}, {}>;\n"
  },
  {
    "path": "index.js",
    "content": "import ace from 'ace-builds';\nimport { capitalize, defineComponent, markRaw, h } from 'vue';\nimport ResizeObserver from 'resize-observer-polyfill';\nconst Events = [\n    'blur',\n    'input',\n    'change',\n    'changeSelection',\n    'changeSelectionStyle',\n    'changeSession',\n    'copy',\n    'focus',\n    'paste',\n];\nexport const VAceEditor = defineComponent({\n    name: 'VAceEditor',\n    props: {\n        value: {\n            type: String,\n            required: true,\n        },\n        lang: {\n            type: String,\n            default: 'text',\n        },\n        theme: {\n            type: String,\n            default: 'chrome',\n        },\n        options: Object,\n        placeholder: String,\n        readonly: Boolean,\n        wrap: Boolean,\n        printMargin: {\n            type: [Boolean, Number],\n            default: true,\n        },\n        minLines: Number,\n        maxLines: Number,\n    },\n    emits: ['update:value', 'init', ...Events],\n    render() {\n        return h('div');\n    },\n    mounted() {\n        const editor = this._editor = markRaw(ace.edit(this.$el, {\n            placeholder: this.placeholder,\n            readOnly: this.readonly,\n            value: this.value,\n            mode: 'ace/mode/' + this.lang,\n            theme: 'ace/theme/' + this.theme,\n            wrap: this.wrap,\n            printMargin: this.printMargin,\n            useWorker: false,\n            minLines: this.minLines,\n            maxLines: this.maxLines,\n            ...this.options,\n        }));\n        this._contentBackup = this.value;\n        this._isSettingContent = false;\n        editor.on('change', () => {\n            // ref: https://github.com/CarterLi/vue3-ace-editor/issues/11\n            if (this._isSettingContent)\n                return;\n            const content = editor.getValue();\n            this._contentBackup = content;\n            this.$emit('update:value', content);\n        });\n        Events.forEach(x => {\n            const eventName = 'on' + capitalize(x);\n            if (typeof this.$.vnode.props[eventName] === 'function') {\n                editor.on(x, this.$emit.bind(this, x));\n            }\n        });\n        this._ro = new ResizeObserver(() => editor.resize());\n        this._ro.observe(this.$el);\n        this.$emit('init', editor);\n    },\n    beforeUnmount() {\n        var _a, _b;\n        (_a = this._ro) === null || _a === void 0 ? void 0 : _a.disconnect();\n        (_b = this._editor) === null || _b === void 0 ? void 0 : _b.destroy();\n    },\n    methods: {\n        focus() {\n            this._editor.focus();\n        },\n        blur() {\n            this._editor.blur();\n        },\n        selectAll() {\n            this._editor.selectAll();\n        },\n        getAceInstance() {\n            return this._editor;\n        },\n    },\n    watch: {\n        value(val) {\n            if (this._contentBackup !== val) {\n                try {\n                    this._isSettingContent = true;\n                    this._editor.setValue(val, 1);\n                }\n                finally {\n                    this._isSettingContent = false;\n                }\n                this._contentBackup = val;\n            }\n        },\n        theme(val) {\n            this._editor.setTheme('ace/theme/' + val);\n        },\n        options(val) {\n            this._editor.setOptions(val);\n        },\n        readonly(val) {\n            this._editor.setReadOnly(val);\n        },\n        placeholder(val) {\n            this._editor.setOption('placeholder', val);\n        },\n        wrap(val) {\n            this._editor.setWrapBehavioursEnabled(val);\n        },\n        printMargin(val) {\n            this._editor.setOption('printMargin', val);\n        },\n        lang(val) {\n            this._editor.setOption('mode', 'ace/mode/' + val);\n        },\n        minLines(val) {\n            this._editor.setOption('minLines', val);\n        },\n        maxLines(val) {\n            this._editor.setOption('maxLines', val);\n        },\n    }\n});\n//# sourceMappingURL=index.js.map"
  },
  {
    "path": "index.ts",
    "content": "import ace, { type Ace } from 'ace-builds';\nimport { capitalize, defineComponent, markRaw, h } from 'vue';\nimport ResizeObserver from 'resize-observer-polyfill';\n\nimport type { VAceEditorInstance } from './types';\n\nconst Events = [\n  'blur',\n  'input',\n  'change',\n  'changeSelection',\n  'changeSelectionStyle',\n  'changeSession',\n  'copy',\n  'focus',\n  'paste',\n];\n\nexport const VAceEditor = defineComponent({\n  name: 'VAceEditor',\n  props: {\n    value: {\n      type: String,\n      required: true,\n    },\n    lang: {\n      type: String,\n      default: 'text',\n    },\n    theme: {\n      type: String,\n      default: 'chrome',\n    },\n    options: Object,\n    placeholder: String,\n    readonly: Boolean,\n    wrap: Boolean,\n    printMargin: {\n      type: [Boolean, Number],\n      default: true,\n    },\n    minLines: Number,\n    maxLines: Number,\n  },\n  emits: ['update:value', 'init', ...Events],\n  render(this: VAceEditorInstance) {\n    return h('div');\n  },\n  mounted(this: VAceEditorInstance) {\n    const editor = this._editor = markRaw(ace.edit(this.$el, {\n      placeholder: this.placeholder,\n      readOnly: this.readonly,\n      value: this.value,\n      mode: 'ace/mode/' + this.lang,\n      theme: 'ace/theme/' + this.theme,\n      wrap: this.wrap,\n      printMargin: this.printMargin,\n      useWorker: false,\n      minLines: this.minLines,\n      maxLines: this.maxLines,\n      ...this.options,\n    }));\n    this._contentBackup = this.value;\n    this._isSettingContent = false;\n    editor.on('change', () => {\n      // ref: https://github.com/CarterLi/vue3-ace-editor/issues/11\n      if (this._isSettingContent) return;\n      const content = editor.getValue();\n      this._contentBackup = content;\n      this.$emit('update:value', content);\n    });\n    Events.forEach(x => {\n      const eventName = 'on' + capitalize(x);\n      if (typeof this.$.vnode.props![eventName] === 'function') {\n        editor.on(x as any, this.$emit.bind(this, x));\n      }\n    });\n    this._ro = new ResizeObserver(() => editor.resize());\n    this._ro.observe(this.$el);\n    this.$emit('init', editor);\n  },\n  beforeUnmount(this: VAceEditorInstance) {\n    this._ro?.disconnect();\n    this._editor?.destroy();\n  },\n  methods: {\n    focus(this: VAceEditorInstance) {\n      this._editor.focus();\n    },\n    blur(this: VAceEditorInstance) {\n      this._editor.blur();\n    },\n    selectAll(this: VAceEditorInstance) {\n      this._editor.selectAll();\n    },\n    getAceInstance(this: VAceEditorInstance) {\n      return this._editor;\n    },\n  },\n  watch: {\n    value(this: VAceEditorInstance, val: string) {\n      if (this._contentBackup !== val) {\n        try {\n          this._isSettingContent = true;\n          this._editor.setValue(val, 1);\n        } finally {\n          this._isSettingContent = false;\n        }\n        this._contentBackup = val;\n      }\n    },\n    theme(this: VAceEditorInstance, val: string) {\n      this._editor.setTheme('ace/theme/' + val);\n    },\n    options(this: VAceEditorInstance, val: Partial<Ace.EditorOptions>) {\n      this._editor.setOptions(val);\n    },\n    readonly(this: VAceEditorInstance, val: boolean) {\n      this._editor.setReadOnly(val);\n    },\n    placeholder(this: VAceEditorInstance, val: string) {\n      this._editor.setOption('placeholder', val);\n    },\n    wrap(this: VAceEditorInstance, val: boolean) {\n      this._editor.setWrapBehavioursEnabled(val);\n    },\n    printMargin(this: VAceEditorInstance, val: boolean | number) {\n      this._editor.setOption('printMargin', val);\n    },\n    lang(this: VAceEditorInstance, val: string) {\n      this._editor.setOption('mode', 'ace/mode/' + val);\n    },\n    minLines(this: VAceEditorInstance, val: number) {\n      this._editor.setOption('minLines', val);\n    },\n    maxLines(this: VAceEditorInstance, val: number) {\n      this._editor.setOption('maxLines', val);\n    },\n  }\n});\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"vue3-ace-editor\",\n  \"version\": \"2.2.4\",\n  \"description\": \"Like vue2-ace-editor but more functional and supports Vue 3\",\n  \"main\": \"index.js\",\n  \"module\": \"index.js\",\n  \"type\": \"module\",\n  \"types\": \"index.d.ts\",\n  \"repository\": \"git@github.com:CarterLi/vue3-ace-editor.git\",\n  \"author\": \"李通洲 <zhangsongcui@live.cn>\",\n  \"license\": \"MIT\",\n  \"scripts\": {\n    \"build\": \"tsc -p .\"\n  },\n  \"dependencies\": {\n    \"resize-observer-polyfill\": \"^1.5.1\"\n  },\n  \"peerDependencies\": {\n    \"ace-builds\": \"*\",\n    \"vue\": \"^3\"\n  },\n  \"devDependencies\": {\n    \"typescript\": \"^5.2.2\"\n  }\n}\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"es2019\",\n    \"module\": \"esnext\",\n    \"strict\": true,\n    \"importHelpers\": true,\n    \"moduleResolution\": \"node\",\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true,\n    \"allowSyntheticDefaultImports\": true,\n    \"resolveJsonModule\": true,\n    \"sourceMap\": true,\n    \"declaration\": true,\n    \"baseUrl\": \"./\",\n    \"lib\": [\n      \"esnext\",\n      \"dom\",\n      \"dom.iterable\"\n    ]\n  },\n  \"exclude\": [\n    \"node_modules\"\n  ]\n}\n"
  },
  {
    "path": "types.d.ts",
    "content": "import { ComponentPublicInstance } from 'vue';\nimport type { Ace } from 'ace-builds';\n\nexport interface VAceEditorPrivate {\n  _editor: Ace.Editor;\n  _contentBackup: string;\n  _isSettingContent: boolean;\n  _ro: ResizeObserver;\n}\n\nexport interface VAceEditorProps {\n  readonly value: string;\n  readonly lang: string;\n  readonly theme: string;\n  readonly options: Partial<Ace.EditorOptions>;\n  readonly placeholder: string;\n  readonly readonly: boolean;\n  readonly wrap: boolean;\n  readonly printMargin: boolean | number;\n  readonly minLines: number;\n  readonly maxLines: number;\n}\n\nexport interface VAceEditorMethods {\n  focus(): void;\n  blur(): void;\n  selectAll(): void;\n  getAceInstance(): Ace.Editor;\n}\n\nexport interface VAceEditorInstance extends\n  ComponentPublicInstance,\n  VAceEditorPrivate,\n  VAceEditorProps,\n  VAceEditorMethods {}\n"
  }
]