vm-editor.vue 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. <template>
  2. <section>
  3. <h3 v-text="i18n('labelEditor')"></h3>
  4. <p v-html="i18n('descEditorOptions')" />
  5. <setting-text name="editor" ref="editor" :json="true" :has-reset="true" @save="onSave">
  6. <button v-text="i18n('buttonShowEditorState')" @click="toggleStateHint"/>
  7. </setting-text>
  8. <pre v-text="hint" class="monospace-font dim-hint" />
  9. </section>
  10. </template>
  11. <script>
  12. import options from '#/common/options';
  13. import { showMessage } from '#/options/utils';
  14. import SettingText from '#/common/ui/setting-text';
  15. export default {
  16. data() {
  17. return { hint: null };
  18. },
  19. components: {
  20. SettingText,
  21. },
  22. mounted() {
  23. this.$refs.editor.$el.addEventListener('dblclick', this.toggleBoolean);
  24. },
  25. methods: {
  26. onSave() {
  27. showMessage({ text: this.$refs.editor.error || this.i18n('msgSavedEditorOptions') });
  28. },
  29. toggleBoolean(event) {
  30. const el = /** @type HTMLTextAreaElement */ event.target;
  31. const { selectionStart: start, selectionEnd: end, value } = el;
  32. const toggled = { false: 'true', true: 'false' }[value.slice(start, end)];
  33. // FF can't run execCommand on textarea, https://bugzil.la/1220696#c24
  34. if (toggled && !document.execCommand('insertText', false, toggled)) {
  35. el.value = value.slice(0, start) + toggled + value.slice(end);
  36. el.setSelectionRange(start + toggled.length, start + toggled.length);
  37. el.dispatchEvent(new Event('input'));
  38. el.onblur = () => el.dispatchEvent(new Event('change'));
  39. }
  40. },
  41. async toggleStateHint() {
  42. if (this.hint) {
  43. this.hint = null;
  44. return;
  45. }
  46. const HIDE_OPTS = [
  47. // we activate only one mode: js
  48. 'mode',
  49. // duh
  50. 'value',
  51. // these accept only a function
  52. 'configureMouse',
  53. 'lineNumberFormatter',
  54. 'specialCharPlaceholder',
  55. ];
  56. const opts = {};
  57. Object.entries({
  58. ...(await import('codemirror')).defaults,
  59. ...(await import('#/common/ui/code')).cmOptions,
  60. ...options.get('editor'),
  61. })
  62. // sort by keys alphabetically to make it more readable
  63. .sort(([a], [b]) => (a < b ? -1 : a > b))
  64. .filter(([key, val]) => !HIDE_OPTS.includes(key) && typeof val !== 'function')
  65. .forEach(([key, val]) => { opts[key] = val; });
  66. this.hint = JSON.stringify(opts, null, ' ');
  67. setTimeout(() => {
  68. if (this.$el.getBoundingClientRect().bottom > window.innerHeight) {
  69. this.$el.scrollIntoView({ behavior: 'smooth' });
  70. }
  71. });
  72. },
  73. },
  74. };
  75. </script>
  76. <style>
  77. .dim-hint {
  78. font-size: .85rem;
  79. color: var(--fill-8);
  80. }
  81. </style>