Browse Source

Moderately good editor

Arjun Barrett 4 năm trước cách đây
mục cha
commit
749f838188
5 tập tin đã thay đổi với 164 bổ sung115 xóa
  1. 1 0
      package.json
  2. 154 11
      src/demo/components/code-box/index.tsx
  3. 0 0
      src/demo/components/code-box/prism.js
  4. 2 1
      src/index.ts
  5. 7 103
      yarn.lock

+ 1 - 0
package.json

@@ -62,6 +62,7 @@
     "parcel": "^2.0.0-nightly.440",
     "parcel-config-precache-manifest": "^0.0.3",
     "preact": "^10.5.5",
+    "prism-react-renderer": "^1.1.1",
     "react": "^17.0.1",
     "react-dom": "^17.0.1",
     "rmwc": "^6.1.4",

+ 154 - 11
src/demo/components/code-box/index.tsx

@@ -1,9 +1,10 @@
-import React, { FC, FormEvent, useState } from 'react';
+import React, { FC, useRef, useState } from 'react';
+import Highlight, { DefaultProps } from 'prism-react-renderer';
+import Prism from './prism';
+import './prism';
+import './prism.css';
 import exec from './sandbox';
-
-declare const Prism: {
-  highlightElement(el: Element): void;
-};
+import ts from 'typescript';
 
 const canStream = 'stream' in File.prototype;
 
@@ -88,15 +89,157 @@ fakeResponse.arrayBuffer().then(buf => {
   };
 }
 
+const CodeHighlight: FC<{
+  code: string;
+  onInput: (newCode: string) => void;
+}> = ({ code, onInput }) => {
+  const tmpParen = useRef(-1);
+  return (
+    <>
+      <pre className="language-javascript" style={{
+        width: '100%',
+        height: '100%',
+        position: 'relative',
+        backgroundColor: '#2a2734',
+        color: '#9a86fd',
+        fontSize: '0.7em'
+      }}>
+        <div>
+        <Highlight Prism={Prism.Prism as unknown as DefaultProps['Prism']} code={code} language="javascript">
+          {({ tokens, getLineProps, getTokenProps }) => (
+              tokens.map((line, i) => (
+                <div {...getLineProps({ line, key: i })}>
+                  {line.map((token, key) => (
+                    <span {...getTokenProps({ token, key })} />
+                  ))}
+                </div>
+              ))
+          )}
+        </Highlight>
+        </div>
+        <textarea
+          autoComplete="off"
+          autoCorrect="off"
+          autoCapitalize="off"
+          spellCheck="false"
+          style={{
+            border: 'unset',
+            resize: 'none',
+            outline: 'none',
+            position: 'absolute',
+            background: 'transparent',
+            top: 0,
+            left: 0,
+            width: '100%',
+            height: '100%',
+            lineHeight: 'inherit',
+            fontSize: 'inherit',
+            padding: 'inherit',
+            color: 'transparent',
+            caretColor: 'white',
+            fontFamily: 'inherit'
+          }}
+          onKeyDown={e => {
+            const t = e.currentTarget;
+            let val = t.value;
+            const loc = t.selectionStart;
+            let newTmpParen = -1;
+            if (e.key == 'Enter') {
+              const lastNL = val.lastIndexOf('\n', loc - 1);
+              let indent = 0;
+              for (; val.charCodeAt(indent + lastNL + 1) == 32; ++indent);
+              const lastChar = val.charAt(loc - 1);
+              const nextChar = val.charAt(loc);
+              if (lastChar == '{'|| lastChar == '(' || lastChar == '[') indent += 2;
+              const addNL = nextChar == '}' || nextChar == ')' || nextChar == ']';
+              const tail = val.slice(t.selectionEnd);
+              val = val.slice(0, loc) + '\n';
+              for (let i = 0; i < indent; ++i) val += ' ';
+              if (addNL) {
+                if (
+                  (lastChar == '{' && nextChar == '}') ||
+                  (lastChar == '[' && nextChar == ']') || 
+                  (lastChar == '(' && nextChar == ')')
+                ) {
+                  val += '\n';
+                  for (let i = 2; i < indent; ++i) val += ' ';
+                } else {
+                  const end = Math.min(indent, 2);
+                  indent -= end;
+                  val = val.slice(0, -end);
+                }
+              }
+              val += tail;
+              t.value = val;
+              t.selectionStart = t.selectionEnd = loc + indent + 1;
+            } else if (e.key == 'Tab') {
+              val = val.slice(0, loc) + '  ' + val.slice(t.selectionEnd);
+              t.value = val;
+              t.selectionStart = t.selectionEnd = loc + 2;
+            } else if (t.selectionStart == t.selectionEnd) {
+              if (e.key == 'Backspace') {
+                if (val.charCodeAt(loc - 1) == 32 && !val.slice(val.lastIndexOf('\n', loc - 1), loc).trim().length) {
+                  val = val.slice(0, loc - 2) + val.slice(loc);
+                  t.value = val;
+                  t.selectionStart = t.selectionEnd = loc - 2;
+                } else if (
+                  (val.charAt(loc - 1) == '{' && val.charAt(loc) == '}') ||
+                  (val.charAt(loc - 1) == '[' && val.charAt(loc) == ']') ||
+                  (val.charAt(loc - 1) == '(' && val.charAt(loc) == ')')
+                ) {
+                  val = val.slice(0, loc - 1) + val.slice(loc + 1);
+                  t.value = val;
+                  t.selectionStart = t.selectionEnd = loc - 1;
+                } else return;
+              } else {
+                let a: string;
+                switch(e.key) {
+                  case '{':
+                  case '[':
+                  case '(':
+                    t.value = val = val.slice(0, loc) + (e.key == '{' ? '{}' : e.key == '[' ? '[]' : '()') + val.slice(loc);
+                    t.selectionStart = t.selectionEnd = newTmpParen = loc + 1;
+                    break;
+                  case '}':
+                  case ']':
+                  case ')': 
+                    // BUG: if the cursor is moved, this false activates
+                    if (tmpParen.current != loc) {
+                      const lastNL = val.lastIndexOf('\n', loc - 1);
+                      const sl = val.slice(lastNL, loc);
+                      t.value = val = val.slice(0, loc - (sl.length > 1 && !sl.trim().length ? 2 : 0)) + e.key + val.slice(loc);
+                    }
+                    t.selectionEnd = t.selectionStart = loc + 1;
+                    break;
+                  default:
+                    tmpParen.current = -1;
+                    return;
+                }
+              };
+            } else return;
+            tmpParen.current = newTmpParen;
+            e.preventDefault();
+            onInput(val);
+          }}
+          onInput={e => onInput(e.currentTarget.value)}
+          >
+          {code}
+        </textarea>
+      </pre>
+    </>
+    
+  )
+};
+
 const CodeBox: FC<{files: File[]}> = ({ files }) => {
   const [{ fflate, uzip, pako }, setCodes] = useState(presets['Streaming GZIP compression']);
-  const onInput = (ev: FormEvent<HTMLInputElement>) => {
-    const codes: Preset ={
+  const onInput = (lib: 'fflate' | 'uzip' | 'pako', code: string) => {
+    const codes: Preset = {
       fflate,
       uzip,
       pako
     };
-    codes[this as unknown as string] = ev.currentTarget.innerText;
+    codes[lib] = code;
     setCodes(codes);
   }
   return (
@@ -115,15 +258,15 @@ const CodeBox: FC<{files: File[]}> = ({ files }) => {
       }}>
         <div>
           fflate:
-          <code contentEditable className="lang-javascript" onInput={onInput.bind('fflate')}>{fflate}</code>
+          <CodeHighlight code={fflate.trim()} onInput={t => onInput('fflate', t)} />
         </div>
         <div>
           UZIP (shimmed):
-          <code contentEditable className="lang-javascript" onInput={onInput.bind('uzip')}>{uzip}</code>
+          <CodeHighlight code={uzip.trim()} onInput={t => onInput('uzip', t)} />
         </div>
         <div>
           Pako (shimmed):
-          <code contentEditable className="lang-javascript" onInput={onInput.bind('pako')}>{pako}</code>
+          <CodeHighlight code={pako.trim()} onInput={t => onInput('pako', t)} />
         </div>
       </div>
       <button onClick={() => {

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
src/demo/components/code-box/prism.js


+ 2 - 1
src/index.ts

@@ -2219,7 +2219,8 @@ export function unzip(data: Uint8Array, cb: UnzipCallback): AsyncTerminable {
 }
 
 /**
- * Synchronously decompresses a ZIP archive
+ * Synchronously decompresses a ZIP archive. Prefer using `unzip` for better
+ * performance with more than one file.
  * @param data The raw compressed ZIP file
  * @returns The decompressed files
  */

+ 7 - 103
yarn.lock

@@ -3091,11 +3091,6 @@ bcrypt-pbkdf@^1.0.0:
   dependencies:
     tweetnacl "^0.14.3"
 
-big.js@^5.2.2:
-  version "5.2.2"
-  resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
-  integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==
-
 bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.4.0:
   version "4.11.9"
   resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.9.tgz#26d556829458f9d1e81fc48952493d0ba3507828"
@@ -4104,11 +4099,6 @@ emoji-regex@^8.0.0:
   resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
   integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
 
-emojis-list@^3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78"
-  integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==
-
 emphasize@^2.1.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/emphasize/-/emphasize-2.1.0.tgz#4dbb279f3df30822e8d9c6476b856f09706a0dd8"
@@ -4494,13 +4484,6 @@ function-bind@^1.1.1:
   resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
   integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
 
-generic-names@^2.0.1:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/generic-names/-/generic-names-2.0.1.tgz#f8a378ead2ccaa7a34f0317b05554832ae41b872"
-  integrity sha512-kPCHWa1m9wGG/OwQpeweTwM/PYiQLrUIxXbt/P4Nic3LbGjCP0YwrALHW1uNLKZ0LIMg+RF+XRlj2ekT9ZlZAQ==
-  dependencies:
-    loader-utils "^1.1.0"
-
 gensync@^1.0.0-beta.1:
   version "1.0.0-beta.2"
   resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
@@ -4823,13 +4806,6 @@ [email protected], icss-replace-symbols@^1.1.0:
   resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded"
   integrity sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=
 
-icss-utils@^4.0.0, icss-utils@^4.1.1:
-  version "4.1.1"
-  resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-4.1.1.tgz#21170b53789ee27447c2f47dd683081403f9a467"
-  integrity sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA==
-  dependencies:
-    postcss "^7.0.14"
-
 ieee754@^1.1.13:
   version "1.2.1"
   resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
@@ -5424,20 +5400,6 @@ listr2@^3.2.2:
     rxjs "^6.6.3"
     through "^2.3.8"
 
-loader-utils@^1.1.0:
-  version "1.4.0"
-  resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613"
-  integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==
-  dependencies:
-    big.js "^5.2.2"
-    emojis-list "^3.0.0"
-    json5 "^1.0.1"
-
-lodash.camelcase@^4.3.0:
-  version "4.3.0"
-  resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6"
-  integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY=
-
 lodash.clone@^4.5.0:
   version "4.5.0"
   resolved "https://registry.yarnpkg.com/lodash.clone/-/lodash.clone-4.5.0.tgz#195870450f5a13192478df4bc3d23d2dea1907b6"
@@ -6264,13 +6226,6 @@ [email protected]:
   dependencies:
     postcss "^6.0.1"
 
-postcss-modules-extract-imports@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz#818719a1ae1da325f9832446b01136eeb493cd7e"
-  integrity sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==
-  dependencies:
-    postcss "^7.0.5"
-
 [email protected]:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz#f7d80c398c5a393fa7964466bd19500a7d61c069"
@@ -6279,16 +6234,6 @@ [email protected]:
     css-selector-tokenizer "^0.7.0"
     postcss "^6.0.1"
 
-postcss-modules-local-by-default@^3.0.2:
-  version "3.0.3"
-  resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz#bb14e0cc78279d504dbdcbfd7e0ca28993ffbbb0"
-  integrity sha512-e3xDq+LotiGesympRlKNgaJ0PCzoUIdpH0dj47iWAui/kyTgh3CiAr1qP54uodmJhl6p9rN6BoNcdEDVJx9RDw==
-  dependencies:
-    icss-utils "^4.1.1"
-    postcss "^7.0.32"
-    postcss-selector-parser "^6.0.2"
-    postcss-value-parser "^4.1.0"
-
 [email protected]:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz#d6ea64994c79f97b62a72b426fbe6056a194bb90"
@@ -6297,14 +6242,6 @@ [email protected]:
     css-selector-tokenizer "^0.7.0"
     postcss "^6.0.1"
 
-postcss-modules-scope@^2.2.0:
-  version "2.2.0"
-  resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz#385cae013cc7743f5a7d7602d1073a89eaae62ee"
-  integrity sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ==
-  dependencies:
-    postcss "^7.0.6"
-    postcss-selector-parser "^6.0.0"
-
 [email protected]:
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz#ecffa9d7e192518389f42ad0e83f72aec456ea20"
@@ -6313,29 +6250,6 @@ [email protected]:
     icss-replace-symbols "^1.1.0"
     postcss "^6.0.1"
 
-postcss-modules-values@^3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz#5b5000d6ebae29b4255301b4a3a54574423e7f10"
-  integrity sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg==
-  dependencies:
-    icss-utils "^4.0.0"
-    postcss "^7.0.6"
-
-postcss-modules@^3.2.2:
-  version "3.2.2"
-  resolved "https://registry.yarnpkg.com/postcss-modules/-/postcss-modules-3.2.2.tgz#ee390de0f9f18e761e1778dfb9be26685c02c51f"
-  integrity sha512-JQ8IAqHELxC0N6tyCg2UF40pACY5oiL6UpiqqcIFRWqgDYO8B0jnxzoQ0EOpPrWXvcpu6BSbQU/3vSiq7w8Nhw==
-  dependencies:
-    generic-names "^2.0.1"
-    icss-replace-symbols "^1.1.0"
-    lodash.camelcase "^4.3.0"
-    postcss "^7.0.32"
-    postcss-modules-extract-imports "^2.0.0"
-    postcss-modules-local-by-default "^3.0.2"
-    postcss-modules-scope "^2.2.0"
-    postcss-modules-values "^3.0.0"
-    string-hash "^1.1.1"
-
 postcss-normalize-charset@^4.0.1:
   version "4.0.1"
   resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz#8b35add3aee83a136b0471e0d59be58a50285dd4"
@@ -6464,7 +6378,7 @@ postcss-selector-parser@^3.0.0:
     indexes-of "^1.0.1"
     uniq "^1.0.1"
 
-postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2:
+postcss-selector-parser@^6.0.2:
   version "6.0.4"
   resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.4.tgz#56075a1380a04604c38b063ea7767a129af5c2b3"
   integrity sha512-gjMeXBempyInaBqpp8gODmwZ52WaYsVOsfr4L4lDQ7n3ncD6mEyySiDtgzCT+NYC0mmeOLvtsF8iaEf0YT6dBw==
@@ -6530,7 +6444,7 @@ postcss@^6.0.1:
     source-map "^0.6.1"
     supports-color "^5.4.0"
 
-postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.17, postcss@^7.0.27, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6:
+postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.17, postcss@^7.0.27:
   version "7.0.35"
   resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.35.tgz#d2be00b998f7f211d8a276974079f2e92b970e24"
   integrity sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==
@@ -6539,16 +6453,6 @@ postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.17, postcss@^7.0.2
     source-map "^0.6.1"
     supports-color "^6.1.0"
 
-postcss@^8.0.0:
-  version "8.1.7"
-  resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.1.7.tgz#ff6a82691bd861f3354fd9b17b2332f88171233f"
-  integrity sha512-llCQW1Pz4MOPwbZLmOddGM9eIJ8Bh7SZ2Oj5sxZva77uVaotYDsYTch1WBTNu7fUY0fpWp0fdt7uW40D4sRiiQ==
-  dependencies:
-    colorette "^1.2.1"
-    line-column "^1.0.2"
-    nanoid "^3.1.16"
-    source-map "^0.6.1"
-
 postcss@^8.0.5:
   version "8.1.6"
   resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.1.6.tgz#b022ba2cfb8701da234d073ed3128c5a384c35ff"
@@ -6604,6 +6508,11 @@ prelude-ls@~1.1.2:
   resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
   integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=
 
+prism-react-renderer@^1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/prism-react-renderer/-/prism-react-renderer-1.1.1.tgz#1c1be61b1eb9446a146ca7a50b7bcf36f2a70a44"
+  integrity sha512-MgMhSdHuHymNRqD6KM3eGS0PNqgK9q4QF5P0yoQQvpB6jNjeSAi3jcSAz0Sua/t9fa4xDOMar9HJbLa08gl9ug==
+
 process-nextick-args@~2.0.0:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
@@ -7412,11 +7321,6 @@ [email protected]:
   resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da"
   integrity sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==
 
-string-hash@^1.1.1:
-  version "1.1.3"
-  resolved "https://registry.yarnpkg.com/string-hash/-/string-hash-1.1.3.tgz#e8aafc0ac1855b4666929ed7dd1275df5d6c811b"
-  integrity sha1-6Kr8CsGFW0Zmkp7X3RJ1311sgRs=
-
 string-width@^4.1.0, string-width@^4.2.0:
   version "4.2.0"
   resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5"

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác