|
| 1 | +import { EditorState, basicSetup } from "@codemirror/basic-setup"; |
| 2 | +import { EditorView, keymap, KeyBinding } from "@codemirror/view"; |
| 3 | +import { defaultKeymap, indentMore, indentLess } from "@codemirror/commands"; |
| 4 | +import { javascript } from "@codemirror/lang-javascript"; |
| 5 | +import { oneDark } from "@codemirror/theme-one-dark"; |
| 6 | + |
| 7 | +import { getHashCode, updateHash, decodeHash, defaultHash } from "./urlHash"; |
| 8 | + |
| 9 | +const insertSoftTab = ({ state, dispatch }: EditorView) => { |
| 10 | + if (state.selection.ranges.some((r) => !r.empty)) { |
| 11 | + return indentMore({ state, dispatch }); |
| 12 | + } |
| 13 | + |
| 14 | + dispatch( |
| 15 | + state.update(state.replaceSelection(" "), { |
| 16 | + scrollIntoView: true, |
| 17 | + userEvent: "input", |
| 18 | + }) |
| 19 | + ); |
| 20 | + return true; |
| 21 | +}; |
| 22 | + |
| 23 | +const extendedKeymap: KeyBinding[] = [ |
| 24 | + ...defaultKeymap, |
| 25 | + { |
| 26 | + key: "Tab", |
| 27 | + run: insertSoftTab, |
| 28 | + shift: indentLess, |
| 29 | + }, |
| 30 | +]; |
| 31 | + |
| 32 | +const view = new EditorView({ |
| 33 | + state: EditorState.create({ |
| 34 | + doc: getHashCode(), |
| 35 | + extensions: [ |
| 36 | + basicSetup, |
| 37 | + oneDark, |
| 38 | + keymap.of(extendedKeymap), |
| 39 | + javascript({ |
| 40 | + jsx: true, |
| 41 | + typescript: true, |
| 42 | + }), |
| 43 | + ], |
| 44 | + }), |
| 45 | + parent: document.getElementById("editor")!, |
| 46 | + dispatch: (tr) => { |
| 47 | + view.update([tr]); |
| 48 | + |
| 49 | + if (tr.docChanged) { |
| 50 | + const newCode = tr.newDoc.sliceString(0, tr.newDoc.length); |
| 51 | + updateHash(newCode); |
| 52 | + window.dispatchEvent( |
| 53 | + new CustomEvent("code", { |
| 54 | + detail: newCode, |
| 55 | + }) |
| 56 | + ); |
| 57 | + } |
| 58 | + }, |
| 59 | +}); |
| 60 | + |
| 61 | +const examples = [ |
| 62 | + { name: "Select example...", hash: "" }, |
| 63 | + { |
| 64 | + name: "Hacker News", |
| 65 | + hash: defaultHash, |
| 66 | + }, |
| 67 | + { |
| 68 | + name: "React Runner", |
| 69 | + hash: "JYWwDg9gTgLgBAbzgYQgEwKYFE3BtAGjgFcBnDAGWADcMAlYgO0YyiIGMoMBDGejAI7FgXOAF84AMygQQcAORdu7GAFoANjQyqoTFlHkAoUJFiI47dBgBC6iOwDW4qTLnzLIEBEaqY3AOakRoaWjKTwwIx4wNzqqJhwALwWVrb2DgAGhnBwJtDwSPHYuPhsJORUtAzMrBxKfHSCwqIS0rIKSioaWjp6rME5GAAepvCYktzE6vAAFACUSQB8iNk5KWEFcBjqGCAYjDBErDJllphE3sgAFtyM-hjOyWSUWtX6Mwira3CklmAYAC4Vt9vpForEigQviDMGAYFcgbD4XAANRwACMUJBay4QhEgIs9X4eK4H2h2MUPC6mlovRqBiBhSsODwhHKLyqfVORMaJIeYix2PEc0F3wF5NyURgMTiVlFwsM0OAkjgMyRVzgywATAAGBZcGDEKCMOCMKbqRXfA1Gk0zCUAHlw1B+MAAnjtEggkGBuGhcHcgfIABxgIZwHXhuAhobycRiRYSnL2oos0pwaixYgYT1nDASS43O7ZhAF273CQAegTQsQx2gcAAZA24PawFxFgg61AxPaK22MIsxImW06O9tdvsYD2K6OHTOaNW1nNVkOsoZhqM4ONJtNVQtEstPjlQuFzOO9gcjlAThw5XBS0XHuzKvQuWTvr8IP9GRKwdKIXKErqkCOryjkuLNASnA8A0TT4u+QqUsoag0touj0vIjIoMyJRss8L5vLUhIwcSkHiGBwryuKoJSjKkIrsuqzWsaqrQvai7fMmOGslA6aZsWub5ow1xlsWD7lnAVYSp2171k2Lb9mOsndr2ilDtijoLp2OwXlOvazpxUk5MuQ5AA", |
| 70 | + }, |
| 71 | + { |
| 72 | + name: "React Select", |
| 73 | + hash: "JYWwDg9gTgLgBAZQKYBskGN4DMoRHAciiQENMBaAZ1QxgICh70IA7S+CMGYVyuAXjgBtenDgBvOADcSKAK5IAXIXQALCMxQkYSAgBo4WgEaplBAMLrN23XAC+e0ROmyFZ9lBIB3E1CgBPfUMSExQzBBhPHyQ-QPtHMUkZeSVCGRZgFC0g41NCADUSDKySAnt6AF1GJAAPSFg4ABMkLBI5FHgACgBKAQA+OE6nAB5kNEw4Tm5efnEpnjY7OAB6Pvpu+iA", |
| 74 | + }, |
| 75 | + { |
| 76 | + name: "Reach UI", |
| 77 | + hash: "JYWwDg9gTgLgBAFQhANjYYA0cDecCuAzgKZKrpaLJoYAKEY+YcAvnAGZQQhwBEAAlGIBDAMYALAPQxqFXgG4AUKEiw+gkROmyMkwjACeKYoQB0owoQWLFxAB6r4AE2Lth+NB3wA7UegjecACidsLgxgAUAJS4inBwQjD4UIERcfFwADxOwABuAHzpGVlkNMwowgBGxCgAvLwAchDo7MCiwv7eVoXFxZmV+DAygfpGxLU4eOwBMADKwABexABccABMAKysLD29fYRgwt75gLwbgCi7mXqHx0W9lwNDAbt9kqUUzxmZbxhwFdV1vFmxCGwG8AHNurc+g9hnBRsYJlMZvMlqtNtsPntMgcjnBhFBgMIALTiYBOFzHQCZZIB4P8uOJue3i90Gw0xWVeOjAhShWRyuThhgRkw4KAgHVWvAJYPEMF4GJ5TO+5SqNXqTRabQ6wACVjxBOJf1VvAAzHB1cBWu1OpDGZ8YQEBWNERxkYsVustiwdgq7vTThcrkc2Vi-ca6ddg59JPaGYzLkq2Zc+R8k3ldlElCwgA", |
| 78 | + }, |
| 79 | + { |
| 80 | + name: "React Three Fiber", |
| 81 | + hash: "JYWwDg9gTgLgBAJQKYEMDGMA0cDecCuAzksgGbZFIDKMKMScAvnKVBCHAORSoacBQoSLFxwAwigB2ANxSEKxAGJQUIBs1bsuAAR7oYAWhgALHkgD0pYACMkUAf1L5JGYBElwAQhAAeACjA2MEIASlx+ODhzczgAFWNgQjgeUjskFwYAd2AAGxy4AHNgaQYiOAATYB4MOHQ0JEIkmAg4EwY1QmMIuDR3QngO4zgAXgJiMj8Q7ui4KiR4fDA4froGUmhW4wZjCBKectrJA-1ihhX6bt7JfrgAbR29pHLsYhgACV27AF0Rsepaeh+UgoHLEKaRK43W4nEoveYAQVcJR+o0oNFWQJBYOmMSo+GshDQUBsDBMiR67EgknS8GamwYPCOdgMOQgEDA2DYANJWzggzgSD2AE8WCo1N1KMpVEg-H5zkhsOUkDlaGFhgA+OB+QYAOjQ+CgjJgOq5dDckh1PjgAGpRgAGHV2gCMIXBURiyBgBo80mASEy2DaxFqPGSSAK+ByKCgmzMOoAVkllUg1JIYEmfIEGsQDsAPAApKgADW6PC9UA8fm6kQAPINq5FcDrm4F2YRGA3IilhjhBh3G43CSCkD2YQwAPxwJ06gCscAAXFP+wO4O4xDlgGgANY9vyCmlqzWvREwU5+ACEY5Cy4H7gAChA8-QoAB5Pa7-dpw-LeYfPZ+GAoHwJBr07VdJAfJ87BffAYA-EovxGI9f0+KBMVBEDGHVMCa2sXwAHEkHYeYoBFaMCkIHtbidbAaKnL5mHMbCVzgOsGmMdEjmjcoAFlVmJEEKVZKAeweNIDknTgdhgMA8y3TgFy4aApAKJBOEY5jGxrcxBk0qYO34RklTQ7oawkGQ5E02tVGsP00wAGWAApjHgJiGxrSAn0c5z4EgQhgFPdwqKdO1aNCqc7QYqIrNY7wrT8gLzSogxpwAJmwcLIo09y4rgBLAskYKdXSuBMqitza3MczZEIbCQiAA", |
| 82 | + }, |
| 83 | + { |
| 84 | + name: "canvas-confetti", |
| 85 | + hash: "JYWwDg9gTgLgBAYwgOwGYFMY2HVUIhwDkCAhsgG6kDOAtEmptkQFAsMZbAAUAlEA", |
| 86 | + }, |
| 87 | + { |
| 88 | + name: "swr", |
| 89 | + hash: "JYWwDg9gTgLgBAJQKYEMDG8BmUIjgIilQ3wG4AoUSWOAVwGckBlAdQTm1wPoHcozy5NBAB29LEhhoAFkihwAvHAAUtKABsAlIoB8HSTNUbNAOhiyRy5UXraFemyYBW9Ucs2aK5JAA9q8ABMkTBRadSxaEQxgUTgAQTAwdzgAb3I4OGExeBS4AJQYFAAaODkceQBfRTpGVgRldIyCaRgYMHoALgB6LpQwYBMAc2BzWgAjE2EQLqJIei6ANzk0JHUu3n4ixozMA1koRs9BDOBMFTLobSIYNRECOLuL+WkUejgINDQ1IgCTAROzsoAIT5QpXSS3AgAGQgKACwBEgxMyP+cGukIaTTgAB54QsdNsmtjpABGHQpUEoEwiFAgJAVbFdUkErEZbFgcmUkxBehoKDAMAwGIiBldDmEtniHCInSAXg3AII7qS59HGvP5Yzk9AA+sJIjBRVLRINyfgCBUJTjDTLABTkSoKVPEKCggxQAC9NTqIHqDTBpcaUqb8ObWZbfUadIAeDcALvt2womTDQADW2t1In1jKtxsJjLxLLgR3NQA", |
| 90 | + }, |
| 91 | +]; |
| 92 | + |
| 93 | +const select = document.getElementById("examples") as HTMLSelectElement; |
| 94 | +select.onchange = () => { |
| 95 | + const hash = examples[select.selectedIndex].hash; |
| 96 | + view.dispatch({ |
| 97 | + changes: { |
| 98 | + from: 0, |
| 99 | + to: view.state.doc.length, |
| 100 | + insert: decodeHash(hash), |
| 101 | + }, |
| 102 | + }); |
| 103 | +}; |
| 104 | + |
| 105 | +examples.forEach((example) => { |
| 106 | + const option = document.createElement("option"); |
| 107 | + option.innerText = example.name; |
| 108 | + select.appendChild(option); |
| 109 | +}); |
0 commit comments