diff --git a/.gitpod.yml b/.gitpod.yml index 0a88a207..47f82972 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -4,7 +4,7 @@ image: # List the ports you want to expose and what to do when they are served. See https://www.gitpod.io/docs/43_config_ports/ ports: - port: 3000 - onOpen: open-preview + onOpen: ignore - port: 3001 onOpen: ignore diff --git a/env.js b/env.js index 0c30eada..d4d833b7 100644 --- a/env.js +++ b/env.js @@ -1,2 +1,2 @@ -export const ENABLE_SW = true; -export const USE_SHAREDWORKER = true; +export const ENABLE_SW = false; +export const USE_SHAREDWORKER = false; diff --git a/package.json b/package.json index cad3e215..93bff1ba 100644 --- a/package.json +++ b/package.json @@ -73,7 +73,7 @@ "hastscript": "^7.0.2", "husky": "^7.0.4", "jstransformer-markdown-it": "^2.1.0", - "postcss": "^8.4.6", + "postcss": "^8.4.7", "postcss-csso": "^6.0.0", "postcss-scss": "^4.0.3", "posthtml-parser": "^0.10.2", @@ -83,7 +83,7 @@ "rehype-external-links": "^1.0.1", "rehype-highlight": "^5.0.2", "rehype-slug": "^5.0.1", - "sass": "^1.49.8", + "sass": "^1.49.9", "standard-version": "^9.3.2", "tailwindcss": "^3.0.23", "tiny-glob": "^0.2.9", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d9ac55a4..af837842 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -34,7 +34,7 @@ specifiers: monaco-editor: ^0.32.1 pako: ^2.0.4 parse-package-name: ^1.0.0 - postcss: ^8.4.6 + postcss: ^8.4.7 postcss-csso: ^6.0.0 postcss-scss: ^4.0.3 posthtml-parser: ^0.10.2 @@ -47,7 +47,7 @@ specifiers: rehype-highlight: ^5.0.2 rehype-slug: ^5.0.1 resolve.exports: ^1.1.0 - sass: ^1.49.8 + sass: ^1.49.9 solid-js: ^1.3.8 standard-version: ^9.3.2 tailwindcss: ^3.0.23 @@ -80,9 +80,9 @@ dependencies: devDependencies: '@commitlint/cli': 16.2.1 '@commitlint/config-conventional': 16.2.1 - '@csstools/postcss-sass': 5.0.0_postcss@8.4.6 + '@csstools/postcss-sass': 5.0.0_postcss@8.4.7 '@types/node': 17.0.21 - autoprefixer: 10.4.2_postcss@8.4.6 + autoprefixer: 10.4.2_postcss@8.4.7 browser-sync: 2.27.7 commitizen: 4.2.4 del: 6.0.0 @@ -92,7 +92,7 @@ devDependencies: gulp-esbuild: 0.10.2 gulp-if: 3.0.0 gulp-plumber: 1.2.1 - gulp-postcss: 9.0.1_postcss@8.4.6 + gulp-postcss: 9.0.1_postcss@8.4.7 gulp-posthtml: 3.0.5 gulp-pug: 5.0.0 gulp-rename: 2.0.0 @@ -101,9 +101,9 @@ devDependencies: hastscript: 7.0.2 husky: 7.0.4 jstransformer-markdown-it: 2.1.0 - postcss: 8.4.6 - postcss-csso: 6.0.0_postcss@8.4.6 - postcss-scss: 4.0.3_postcss@8.4.6 + postcss: 8.4.7 + postcss-csso: 6.0.0_postcss@8.4.7 + postcss-scss: 4.0.3_postcss@8.4.7 posthtml-parser: 0.10.2 posthtml-render: 3.0.0 rehype: 12.0.1 @@ -111,7 +111,7 @@ devDependencies: rehype-external-links: 1.0.1 rehype-highlight: 5.0.2 rehype-slug: 5.0.1 - sass: 1.49.8 + sass: 1.49.9 standard-version: 9.3.2 tailwindcss: 3.0.23_autoprefixer@10.4.2 tiny-glob: 0.2.9 @@ -1494,15 +1494,15 @@ packages: '@cspotcode/source-map-consumer': 0.8.0 dev: true - /@csstools/postcss-sass/5.0.0_postcss@8.4.6: + /@csstools/postcss-sass/5.0.0_postcss@8.4.7: resolution: {integrity: sha512-jlIF3pcuZtHq41+dKfV51bqJ/VcXNdAST5S8HYxXu1wAfce0Pcf4g87GijhEqjNSIvHqajmbyx49UHLt9cT/cA==} engines: {node: ^12 || ^14 || >=16} peerDependencies: postcss: ^8.4.6 dependencies: '@csstools/sass-import-resolve': 1.0.0 - postcss: 8.4.6 - sass: 1.49.8 + postcss: 8.4.7 + sass: 1.49.9 source-map: 0.7.3 dev: true @@ -2095,7 +2095,7 @@ packages: hasBin: true dev: true - /autoprefixer/10.4.2_postcss@8.4.6: + /autoprefixer/10.4.2_postcss@8.4.7: resolution: {integrity: sha512-9fOPpHKuDW1w/0EKfRmVnxTDt8166MAnLI3mgZ1JCnhNtYWxcJ6Ud5CO/AVOZi/AvFa8DY9RTy3h3+tFBlrrdQ==} engines: {node: ^10 || ^12 || >=14} hasBin: true @@ -2107,7 +2107,7 @@ packages: fraction.js: 4.1.3 normalize-range: 0.1.2 picocolors: 1.0.0 - postcss: 8.4.6 + postcss: 8.4.7 postcss-value-parser: 4.2.0 dev: true @@ -2378,7 +2378,7 @@ packages: hasBin: true dependencies: caniuse-lite: 1.0.30001312 - electron-to-chromium: 1.4.71 + electron-to-chromium: 1.4.72 escalade: 3.1.1 node-releases: 2.0.2 picocolors: 1.0.0 @@ -3449,8 +3449,8 @@ packages: jake: 10.8.2 dev: true - /electron-to-chromium/1.4.71: - resolution: {integrity: sha512-Hk61vXXKRb2cd3znPE9F+2pLWdIOmP7GjiTj45y6L3W/lO+hSnUSUhq+6lEaERWBdZOHbk2s3YV5c9xVl3boVw==} + /electron-to-chromium/1.4.72: + resolution: {integrity: sha512-9LkRQwjW6/wnSfevR21a3k8sOJ+XWSH7kkzs9/EUenKmuDkndP3W9y1yCZpOxufwGbX3JV8glZZSDb4o95zwXQ==} dev: true /emoji-regex/8.0.0: @@ -4563,7 +4563,7 @@ packages: through2: 2.0.5 dev: true - /gulp-postcss/9.0.1_postcss@8.4.6: + /gulp-postcss/9.0.1_postcss@8.4.7: resolution: {integrity: sha512-9QUHam5JyXwGUxaaMvoFQVT44tohpEFpM8xBdPfdwTYGM0AItS1iTQz0MpsF8Jroh7GF5Jt2GVPaYgvy8qD2Fw==} engines: {node: ^10 || ^12 || >=14} peerDependencies: @@ -4571,7 +4571,7 @@ packages: dependencies: fancy-log: 1.3.3 plugin-error: 1.0.1 - postcss: 8.4.6 + postcss: 8.4.7 postcss-load-config: 3.1.3 vinyl-sourcemaps-apply: 0.2.1 transitivePeerDependencies: @@ -6517,24 +6517,24 @@ packages: engines: {node: '>=0.10.0'} dev: true - /postcss-csso/6.0.0_postcss@8.4.6: + /postcss-csso/6.0.0_postcss@8.4.7: resolution: {integrity: sha512-LsrU+LVR0mNIYauoTEbYVC81i+yXcGWa9kqW6Lvm+gYUZTaNTJmJT6Dbv+fqT8gOnwXAH1RV+5RXvAVoRtwO+g==} engines: {node: ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} peerDependencies: postcss: ^8.0.0 dependencies: csso: 5.0.2 - postcss: 8.4.6 + postcss: 8.4.7 dev: true - /postcss-js/4.0.0_postcss@8.4.6: + /postcss-js/4.0.0_postcss@8.4.7: resolution: {integrity: sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ==} engines: {node: ^12 || ^14 || >= 16} peerDependencies: postcss: ^8.3.3 dependencies: camelcase-css: 2.0.1 - postcss: 8.4.6 + postcss: 8.4.7 dev: true /postcss-load-config/3.1.3: @@ -6550,23 +6550,23 @@ packages: yaml: 1.10.2 dev: true - /postcss-nested/5.0.6_postcss@8.4.6: + /postcss-nested/5.0.6_postcss@8.4.7: resolution: {integrity: sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA==} engines: {node: '>=12.0'} peerDependencies: postcss: ^8.2.14 dependencies: - postcss: 8.4.6 + postcss: 8.4.7 postcss-selector-parser: 6.0.9 dev: true - /postcss-scss/4.0.3_postcss@8.4.6: + /postcss-scss/4.0.3_postcss@8.4.7: resolution: {integrity: sha512-j4KxzWovfdHsyxwl1BxkUal/O4uirvHgdzMKS1aWJBAV0qh2qj5qAZqpeBfVUYGWv+4iK9Az7SPyZ4fyNju1uA==} engines: {node: '>=12.0'} peerDependencies: postcss: ^8.3.3 dependencies: - postcss: 8.4.6 + postcss: 8.4.7 dev: true /postcss-selector-parser/6.0.9: @@ -6581,8 +6581,8 @@ packages: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} dev: true - /postcss/8.4.6: - resolution: {integrity: sha512-OovjwIzs9Te46vlEx7+uXB0PLijpwjXGKXjVGGPIGubGpq7uh5Xgf6D6FiJ/SzJMBosHDp6a2hiXOS97iBXcaA==} + /postcss/8.4.7: + resolution: {integrity: sha512-L9Ye3r6hkkCeOETQX6iOaWZgjp3LL6Lpqm6EtgbKrgqGGteRMNb9vzBfRL96YOSu8o7x3MfIH9Mo5cPJFGrW6A==} engines: {node: ^10 || ^12 || >=14} dependencies: nanoid: 3.3.1 @@ -7293,8 +7293,8 @@ packages: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} dev: true - /sass/1.49.8: - resolution: {integrity: sha512-NoGOjvDDOU9og9oAxhRnap71QaTjjlzrvLnKecUJ3GxhaQBrV6e7gPuSPF28u1OcVAArVojPAe4ZhOXwwC4tGw==} + /sass/1.49.9: + resolution: {integrity: sha512-YlYWkkHP9fbwaFRZQRXgDi3mXZShslVmmo+FVK3kHLUELHHEYrCmL1x6IUjC7wLS6VuJSAFXRQS/DxdsC4xL1A==} engines: {node: '>=12.0.0'} hasBin: true dependencies: @@ -7898,7 +7898,7 @@ packages: autoprefixer: ^10.0.2 dependencies: arg: 5.0.1 - autoprefixer: 10.4.2_postcss@8.4.6 + autoprefixer: 10.4.2_postcss@8.4.7 chalk: 4.1.2 chokidar: 3.5.3 color-name: 1.1.4 @@ -7911,10 +7911,10 @@ packages: is-glob: 4.0.3 normalize-path: 3.0.0 object-hash: 2.2.0 - postcss: 8.4.6 - postcss-js: 4.0.0_postcss@8.4.6 + postcss: 8.4.7 + postcss-js: 4.0.0_postcss@8.4.7 postcss-load-config: 3.1.3 - postcss-nested: 5.0.6_postcss@8.4.6 + postcss-nested: 5.0.6_postcss@8.4.7 postcss-selector-parser: 6.0.9 postcss-value-parser: 4.2.0 quick-lru: 5.1.1 diff --git a/src/css/app.scss b/src/css/app.scss index 89fdb98f..059b9b27 100644 --- a/src/css/app.scss +++ b/src/css/app.scss @@ -173,7 +173,7 @@ main { } header { - @apply p-6 text-center; + @apply py-6 text-center; h1 { @apply text-5xl font-bold mb-2; @@ -214,11 +214,11 @@ main { // my-8 } - h3#console { - @apply text-xl pb-0; + .tab-style { + // @apply text-lg; text-decoration: underline; text-decoration-style: wavy; - text-underline-offset: 0.4rem; + text-underline-offset: 0.2rem; } h2#faq { diff --git a/src/css/components/_highlightjs.scss b/src/css/components/_highlightjs.scss index 9f0f18f7..eb143998 100644 --- a/src/css/components/_highlightjs.scss +++ b/src/css/components/_highlightjs.scss @@ -1,113 +1,152 @@ - :root { - --black: #222; - --highlight: #ffcf00; - --red: #e54245; - --green: #608b00; - --blue: #0089b0; - --cyan: #008c98; - --magenta: #776eeb; - --yellow: #ffcf00; - --dim: #777; - --white: #fff; - --mono: "Noto Sans Mono", monospace; + --black: #222; + --highlight: #ffcf00; + --red: #e54245; + --green: #608b00; + --blue: #0089b0; + --cyan: #008c98; + --magenta: #776eeb; + --yellow: #ffcf00; + --dim: #777; + --white: #fff; + --mono: "Noto Sans Mono", monospace; } .color-red { - color: var(--red); + color: var(--red); } .color-green { - color: var(--green); + color: var(--green); } .color-blue { - color: var(--blue); + color: var(--blue); } .color-cyan { - color: var(--cyan); + color: var(--cyan); } .color-magenta { - color: var(--magenta); + color: var(--magenta); } .color-yellow { - color: var(--yellow); + color: var(--yellow); } .color-dim { - color: var(--dim); + color: var(--dim); } .color-red-bg-red { - color: var(--red); - background-color: var(--red); + color: var(--red); + background-color: var(--red); } .color-red-bg-white { - color: var(--white); - background-color: var(--red); + color: var(--white); + background-color: var(--red); } .color-green-bg-green { - color: var(--green); - background-color: var(--green); + color: var(--green); + background-color: var(--green); } .color-green-bg-white { - color: var(--white); - background-color: var(--green); + color: var(--white); + background-color: var(--green); } .color-blue-bg-blue { - color: var(--blue); - background-color: var(--blue); + color: var(--blue); + background-color: var(--blue); } .color-blue-bg-white { - color: var(--white); - background-color: var(--blue); + color: var(--white); + background-color: var(--blue); } .color-cyan-bg-cyan { - color: var(--cyan); - background-color: var(--cyan); + color: var(--cyan); + background-color: var(--cyan); } .color-cyan-bg-black { - color: var(--black); - background-color: var(--cyan); + color: var(--black); + background-color: var(--cyan); } .color-magenta-bg-magenta { - color: var(--magenta); - background-color: var(--magenta); + color: var(--magenta); + background-color: var(--magenta); } .color-magenta-bg-black { - color: var(--black); - background-color: var(--magenta); + color: var(--black); + background-color: var(--magenta); } .color-yellow-bg-yellow { - color: var(--yellow); - background-color: var(--yellow); + color: var(--yellow); + background-color: var(--yellow); } .color-yellow-bg-black { - color: var(--black); - background-color: var(--yellow); + color: var(--black); + background-color: var(--yellow); +} + +pre.console { + @apply cursor-auto; + @apply rounded-lg border border-gray-300 dark:border-transparent; + color: #24292e; + background: #fff; + border-radius: 0.3rem; + + @apply px-1 py-0.5; + font-family: Consolas, "Courier New", monospace; + font-weight: normal; + font-size: 14px; + font-feature-settings: "liga" 0, "calt" 0; + line-height: 19px; + + code, + .hljs { + color: inherit; + background: none; + border: none; + + @apply p-0; + } + + .dark :is(code, .hljs) { + color: inherit; + background: none; + border: none; + } } -code.console summary { - @apply cursor-auto; +.dark pre.console { + color: #adbac7; + background: #000000; + border: 1px solid #30363d; +} + +pre.console code summary { + @apply cursor-auto; +} +pre.console code p { + word-break: break-word; + @apply break-words; } -code.console details p { - // word-wrap: k - @apply lt-md:whitespace-nowrap; +pre.console code details p { + // word-wrap: k + @apply lt-md:whitespace-nowrap; } -code.console .content span { - white-space: break-spaces; - @apply lt-md:whitespace-pre; +pre.console code .content span { + white-space: break-spaces; + @apply lt-md:whitespace-pre; } code { @apply rounded-lg border border-gray-300 dark:border-transparent; - // shadow-lg + // shadow-lg } code { color: #24292e; background: #fff; border-radius: 0.3rem; - - @apply px-1 py-0.5; + + @apply px-1 py-0.5; font-family: Consolas, "Courier New", monospace; font-weight: normal; font-size: 14px; @@ -118,11 +157,10 @@ code { .dark code { color: #adbac7; background: #0d1117; - border: 1px solid #30363D; + border: 1px solid #30363d; } pre { padding-top: 15px; - } pre code { display: block; @@ -220,7 +258,6 @@ code.hljs { background-color: #ffeef0; } - /*! Theme: GitHub Dark Description: Dark theme as seen on github.com @@ -232,119 +269,118 @@ code.hljs { Current colors taken from GitHub's CSS */ .dark { + .hljs { + color: #c9d1d9; + background: #0d1117; + } -.hljs { - color: #c9d1d9; - background: #0d1117; - } - - .hljs-doctag, - .hljs-keyword, - .hljs-meta .hljs-keyword, - .hljs-template-tag, - .hljs-template-variable, - .hljs-type, - .hljs-variable.language_ { - /* prettylights-syntax-keyword */ - color: #ff7b72; - } - - .hljs-title, - .hljs-title.class_, - .hljs-title.class_.inherited__, - .hljs-title.function_ { - /* prettylights-syntax-entity */ - color: #d2a8ff; - } - - .hljs-attr, - .hljs-attribute, - .hljs-literal, - .hljs-meta, - .hljs-number, - .hljs-operator, - .hljs-variable, - .hljs-selector-attr, - .hljs-selector-class, - .hljs-selector-id { - /* prettylights-syntax-constant */ - color: #79c0ff; - } - - .hljs-regexp, - .hljs-string, - .hljs-meta .hljs-string { - /* prettylights-syntax-string */ - color: #a5d6ff; - } - - .hljs-built_in, - .hljs-symbol { - /* prettylights-syntax-variable */ - color: #ffa657; - } - - .hljs-comment, - .hljs-code, - .hljs-formula { - /* prettylights-syntax-comment */ - color: #8b949e; - } - - .hljs-name, - .hljs-quote, - .hljs-selector-tag, - .hljs-selector-pseudo { - /* prettylights-syntax-entity-tag */ - color: #7ee787; - } - - .hljs-subst { - /* prettylights-syntax-storage-modifier-import */ - color: #c9d1d9; - } - - .hljs-section { - /* prettylights-syntax-markup-heading */ - color: #1f6feb; - font-weight: bold; - } - - .hljs-bullet { - /* prettylights-syntax-markup-list */ - color: #f2cc60; - } - - .hljs-emphasis { - /* prettylights-syntax-markup-italic */ - color: #c9d1d9; - font-style: italic; - } - - .hljs-strong { - /* prettylights-syntax-markup-bold */ - color: #c9d1d9; - font-weight: bold; - } - - .hljs-addition { - /* prettylights-syntax-markup-inserted */ - color: #aff5b4; - background-color: #033a16; - } - - .hljs-deletion { - /* prettylights-syntax-markup-deleted */ - color: #ffdcd7; - background-color: #67060c; - } - - .hljs-char.escape_, - .hljs-link, - .hljs-params, - .hljs-property, - .hljs-punctuation, - .hljs-tag { - /* purposely ignored */ - } + .hljs-doctag, + .hljs-keyword, + .hljs-meta .hljs-keyword, + .hljs-template-tag, + .hljs-template-variable, + .hljs-type, + .hljs-variable.language_ { + /* prettylights-syntax-keyword */ + color: #ff7b72; + } + + .hljs-title, + .hljs-title.class_, + .hljs-title.class_.inherited__, + .hljs-title.function_ { + /* prettylights-syntax-entity */ + color: #d2a8ff; + } + + .hljs-attr, + .hljs-attribute, + .hljs-literal, + .hljs-meta, + .hljs-number, + .hljs-operator, + .hljs-variable, + .hljs-selector-attr, + .hljs-selector-class, + .hljs-selector-id { + /* prettylights-syntax-constant */ + color: #79c0ff; + } + + .hljs-regexp, + .hljs-string, + .hljs-meta .hljs-string { + /* prettylights-syntax-string */ + color: #a5d6ff; + } + + .hljs-built_in, + .hljs-symbol { + /* prettylights-syntax-variable */ + color: #ffa657; + } + + .hljs-comment, + .hljs-code, + .hljs-formula { + /* prettylights-syntax-comment */ + color: #8b949e; + } + + .hljs-name, + .hljs-quote, + .hljs-selector-tag, + .hljs-selector-pseudo { + /* prettylights-syntax-entity-tag */ + color: #7ee787; + } + + .hljs-subst { + /* prettylights-syntax-storage-modifier-import */ + color: #c9d1d9; + } + + .hljs-section { + /* prettylights-syntax-markup-heading */ + color: #1f6feb; + font-weight: bold; + } + + .hljs-bullet { + /* prettylights-syntax-markup-list */ + color: #f2cc60; + } + + .hljs-emphasis { + /* prettylights-syntax-markup-italic */ + color: #c9d1d9; + font-style: italic; + } + + .hljs-strong { + /* prettylights-syntax-markup-bold */ + color: #c9d1d9; + font-weight: bold; + } + + .hljs-addition { + /* prettylights-syntax-markup-inserted */ + color: #aff5b4; + background-color: #033a16; + } + + .hljs-deletion { + /* prettylights-syntax-markup-deleted */ + color: #ffdcd7; + background-color: #67060c; + } + + .hljs-char.escape_, + .hljs-link, + .hljs-params, + .hljs-property, + .hljs-punctuation, + .hljs-tag { + /* purposely ignored */ + } } diff --git a/src/css/components/_monaco.scss b/src/css/components/_monaco.scss index 54886550..84a16747 100644 --- a/src/css/components/_monaco.scss +++ b/src/css/components/_monaco.scss @@ -1,82 +1,96 @@ .flex-wrapper { - --cols: 1fr; - @apply w-full relative; - @apply grid gap-3; - // mb-8 - // grid-template-columns: auto; - height: (400px - 56px); - resize: vertical; - overflow: hidden; - - @screen lt-sm { - grid-template-rows: auto auto; - grid-template-rows: var(--cols) var(--cols); - // grid-flow: rows; - - // @apply grid-flow-row; - } + @apply w-full relative block; + @apply flex gap-1; - @screen sm { - min-height: 350px - 56px; - grid-template-columns: auto auto; - grid-template-columns: var(--cols) var(--cols); + height: 350px; + min-height: 350px; + + @apply lt-sm:flex-col; +} + +.tab-btns { + .action-btns { + @apply flex; + } + .active { + @apply bg-gray-100 dark:bg-quaternary dark:hover:bg-gray-800; +} +} - @apply grid-rows-1; +.drag-section { + &, + &.drag-handle { + touch-action: none; } - // @screen md { - // min-height: 400px - 56px; - // } + &.dynamic { + @apply flex lt-sm:flex-row items-center justify-center sm:h-full lt-sm:pt-2 lt-sm:pb-1; - &.loaded { - --cols: auto; + .drag-handle { + @apply w-12 h-1 sm:w-1 sm:h-12 rounded-full; + @apply bg-slate-500/30 hover:bg-gray-600/40 dark:hover:bg-gray-400/40 cursor-ns-resize sm:cursor-ew-resize; + + @media (pointer: coarse) { + @apply w-12 h-2 sm:w-2 sm:h-12; + } + } } -} -.emulate-monaco { - font-family: Consolas, "Courier New", monospace; - font-weight: normal; - font-size: 14px; - font-feature-settings: "liga" 0, "calt" 0; - line-height: 19px; - letter-spacing: 0px; - word-break: break-word; - padding-left: 64px; - padding-right: 14px; -} + &.horizontal { + @apply flex flex-row items-center justify-center h-full px-2; -.app { - @apply bg-white border border-gray-300; - @apply dark:bg-elevated dark:border-gray-700; - @apply rounded-lg shadow-lg; - @apply relative block; - padding-top: 15px; - padding-bottom: 15px; - height: 100%; + .drag-handle { + @apply w-1 h-12 rounded-full; + @apply bg-slate-500/30 hover:bg-gray-600/40 dark:hover:bg-gray-400/40 cursor-ew-resize; - // width: 100%; - // min-width: theme("spacing.3"); - // max-width: calc(100% - theme("spacing.3")); + @media (pointer: coarse) { + @apply w-2 h-12; + } + } + } - overflow: hidden; + &.vertical { + @apply flex items-center justify-center w-full py-2; - font-family: Consolas, "Courier New", monospace; - font-weight: normal; - font-size: 14px; - font-feature-settings: "liga" 0, "calt" 0; - line-height: 19px; - letter-spacing: 0px; + .drag-handle { + @apply w-12 h-1 rounded-full; + @apply bg-slate-500/30 hover:bg-gray-600/40 dark:hover:bg-gray-400/40 cursor-ns-resize; - .monaco-hover-content h3 { - @apply text-lg font-bold; + @media (pointer: coarse) { + @apply w-12 h-2; + } + } } } -.flex-wrapper.loaded .app { - resize: horizontal; +.app { + @apply relative block w-full; + height: 170px; + + @screen sm { + height: 100%; + } - @screen lt-sm { - resize: vertical; + .editor-container { + @apply bg-white border border-gray-300; + @apply dark:bg-elevated dark:border-gray-700; + @apply rounded-lg shadow-lg; + @apply relative block w-full; + height: 100%; + + padding-top: 15px; + padding-bottom: 15px; + + font-family: Consolas, "Courier New", monospace; + font-weight: normal; + font-size: 14px; + font-feature-settings: "liga" 0, "calt" 0; + line-height: 19px; + letter-spacing: 0px; + + .monaco-hover-content h3 { + @apply text-lg font-bold; + } } } @@ -86,17 +100,41 @@ --spacing: calc(theme("spacing.10") + env(safe-area-inset-right) + env(safe-area-inset-left)); } - min-width: 25px; - max-width: calc(theme("screens.lg") - theme("spacing.3") - 25px - var(--spacing)); + min-height: 80px; + min-width: 200px; + // max-width: calc(theme("screens.lg") - theme("spacing.3") - 25px - var(--spacing)); } -.app#output { - resize: none; - height: 100%; +.app#console { + height: 140px; + flex: 1 1 0%; + @screen sm { + height: 100%; + } + + pre.console { + @apply h-full relative; + max-height: 100%; + @apply flex flex-col; + } + + pre.console code { + @apply overflow-auto overscroll-y-contain relative; + } + + .console-btns { + @apply flex flex-wrap p-2 gap-2; + .btn { + @apply mr-0; + } + .icon { + @apply text-sm; + } + } } .info-pane { - @apply flex w-full lt-sm:flex-col align-middle gap-2 lt-sm:gap-3; + @apply flex w-full lt-sm:flex-col gap-2 lt-sm:gap-3; flex-wrap: nowrap; #bundle-time { @@ -110,13 +148,12 @@ } .action-btns-overflow { - @apply py-1; + @apply flex-grow py-1; overflow-x: auto; - width: 100%; } .action-btns { - @apply flex w-full align-middle gap-2; + @apply flex flex-grow align-middle gap-2; position: relative; } @@ -186,7 +223,7 @@ animation: spin 1s linear infinite; } -.dark .app { +.dark .app .editor-container { background-color: #0d1117; border: 1px solid #30363D; } @@ -265,8 +302,8 @@ opacity: 1; } -.app:hover .editor-btns, -.app:focus-within .editor-btns { +.app .editor-container:hover .editor-btns, +.app .editor-container:focus-within .editor-btns { transition: opacity ease-out 0.5s; opacity: 1; pointer-events: none; diff --git a/src/css/components/_search.scss b/src/css/components/_search.scss index f889c745..a9d1f7f2 100644 --- a/src/css/components/_search.scss +++ b/src/css/components/_search.scss @@ -5,7 +5,7 @@ // @apply bg-gray-200 dark:bg-quaternary; @apply focus-within:ring-4 focus-within:ring-blue-500 focus-within:ring-opacity-50; @apply bg-white border border-gray-300; - @apply dark:bg-elevated dark:border-gray-700; + @apply dark:bg-black dark:border-gray-700; @apply flex items-center pl-4 rounded-lg; @@ -29,7 +29,7 @@ } .search-container { - @apply mb-5; + // @apply mb-5; } .search-container, diff --git a/src/pug/index.pug b/src/pug/index.pug index 9ccbf56d..46c6a836 100644 --- a/src/pug/index.pug +++ b/src/pug/index.pug @@ -21,18 +21,21 @@ block content i.icon clear .search-results-container - .flex.w-full.gap-2 - .info-pane - .flex-grow#bundle-time Bundled in ... + + .container.editor-section(class="!max-w-screen-lg relative !pt-0 pb-6") + .container.info-pane + .tab-btns.flex.flex-nowrap + .action-btns + button.btn.tab-style.input-btn.active(type="button") Input + button.btn.tab-style.output-btn(type="button") Output + + + .action-btns-overflow.flex.flex-grow .flex-grow - .action-btns-overflow - .action-btns - .flex-grow - button.btn#run(type='button') Run - button.btn.btn-share#share(type='button') Share - .file-size(title="Ungzipped Bundled size -> Gzipped Bundle size") Wait... - - .container(class="!max-w-screen-lg relative pb-6") + .action-btns.justify-end + button.btn#run(type='button') Run + button.btn.btn-share#share(type='button') Share + .file-size(title="Ungzipped Bundled size -> Gzipped Bundle size") Wait... .flex-wrapper mixin editor-btns .editor-btns&attributes(attributes) @@ -63,39 +66,45 @@ block content path(d='M2.75 5a.75.75 0 0 0 0 1.5h18.5a.75.75 0 0 0 0-1.5H2.75ZM2.75 11.5a.75.75 0 0 0 0 1.5H19a2.5 2.5 0 0 1 0 5h-4.44l.72-.72a.75.75 0 1 0-1.06-1.06l-2 2a.75.75 0 0 0 0 1.06l2 2a.75.75 0 1 0 1.06-1.06l-.72-.72H19a4 4 0 0 0 0-8H2.75Z') path(d='M2 18.75a.75.75 0 0 1 .75-.75h6.5a.75.75 0 0 1 0 1.5h-6.5a.75.75 0 0 1-.75-.75Z') block - .app#input - .center-container - .loading - #editor - +editor-btns - .input-file-size 0 Kb - - .app#output - .center-container - .loading - #editor - +editor-btns + + .editor-container + .center-container + .loading + #editor + +editor-btns - .container - .console-btns.flex.items-center.pt-4 - h3#console Console - .flex-grow - .flex.flex-wrap.gap-2 - button.btn.console-to-bottom-btn(type="button" title="Scroll to Bottom" class="text-xl flex items-center justify-center border border-gray-300 dark:border-gray-600") - svg.icon.text-xl(xmlns='http://www.w3.org/2000/svg', width='24', height='24', fill='none', viewbox='0 0 24 24') - path(d='M19.79 13.267a.75.75 0 0 0-1.086-1.034l-5.954 6.251V3.75a.75.75 0 1 0-1.5 0v14.734l-5.955-6.251a.75.75 0 0 0-1.086 1.034l7.067 7.42c.16.168.366.268.58.3a.753.753 0 0 0 .29-.001.995.995 0 0 0 .578-.3l7.067-7.419Z', fill='currentColor') - button.btn.fold-unfold-console-btn(type="button" title="Fold/Unfold Console Lines" class="text-xl flex items-center justify-center border border-gray-300 dark:border-gray-600") - svg.icon.text-xl(xmlns='http://www.w3.org/2000/svg', width='24', height='24', fill='none', viewbox='0 0 24 24') - path(d='M13.22 6.781a.75.75 0 0 1-.073-.976l.073-.085 2.367-2.37a.77.77 0 0 1 .664-.35c.252 0 .475.109.611.276l.053.075 2.367 2.37.073.084a.75.75 0 0 1 .007.882l-.08.094-.084.073a.75.75 0 0 1-.883.007l-.094-.08L17 5.56v3.784l-.007.089c-.05.32-.363.567-.743.567s-.694-.247-.743-.567l-.007-.09V5.56l-1.22 1.221-.084.073a.75.75 0 0 1-.976-.073ZM13.223 17.219a.75.75 0 0 1 .976-.073l.084.073 1.22 1.221v-3.784c0-.362.336-.656.75-.656.38 0 .693.247.743.567l.007.09v3.783l1.221-1.221a.75.75 0 0 1 .977-.073l.084.073a.75.75 0 0 1 .073.976l-.073.084-2.367 2.37a.77.77 0 0 1-.664.351.77.77 0 0 1-.664-.35l-2.367-2.37a.75.75 0 0 1 0-1.061ZM6.25 3.992A2.25 2.25 0 0 0 4 6.242v11.5a2.25 2.25 0 0 0 2.25 2.25h4a.75.75 0 0 0 0-1.5h-4a.75.75 0 0 1-.75-.75v-11.5a.75.75 0 0 1 .75-.75h4a.75.75 0 0 0 0-1.5h-4Z', fill='currentColor') - button.btn.clear-console-btn(type="button" title="Clear Console" class="text-xl flex items-center justify-center border border-gray-300 dark:border-gray-600") - svg.icon.text-xl(xmlns='http://www.w3.org/2000/svg', width='24', height='24', fill='none', viewbox='0 0 24 24') - path(d='M12 1.75a3.25 3.25 0 0 1 3.245 3.066L15.25 5h5.25a.75.75 0 0 1 .102 1.493L20.5 6.5h-.796l-1.28 13.02a2.75 2.75 0 0 1-2.561 2.474l-.176.006H8.313a2.75 2.75 0 0 1-2.714-2.307l-.023-.174L4.295 6.5H3.5a.75.75 0 0 1-.743-.648L2.75 5.75a.75.75 0 0 1 .648-.743L3.5 5h5.25A3.25 3.25 0 0 1 12 1.75Zm6.197 4.75H5.802l1.267 12.872a1.25 1.25 0 0 0 1.117 1.122l.127.006h7.374c.6 0 1.109-.425 1.225-1.002l.02-.126L18.196 6.5ZM13.75 9.25a.75.75 0 0 1 .743.648L14.5 10v7a.75.75 0 0 1-1.493.102L13 17v-7a.75.75 0 0 1 .75-.75Zm-3.5 0a.75.75 0 0 1 .743.648L11 10v7a.75.75 0 0 1-1.493.102L9.5 17v-7a.75.75 0 0 1 .75-.75Zm1.75-6a1.75 1.75 0 0 0-1.744 1.606L10.25 5h3.5A1.75 1.75 0 0 0 12 3.25Z', fill='currentColor') + .drag-section.dynamic + .drag-handle + + .app#console + pre.console.pt-0(class="leading-[0]") + .console-btns + p.tab-style.text-sm#console Console + .flex-grow + .action-btns-overflow + .flex.flex-nowrap.action-btns.gap-1 + button.btn.console-to-top-btn(type="button" title="Scroll to Top" class="flex items-center justify-center border border-gray-300 dark:border-gray-600") + svg.icon(xmlns='http://www.w3.org/2000/svg', width='24', height='24', fill='none', viewbox='0 0 24 24') + path(d='M4.21 10.733a.75.75 0 0 0 1.086 1.034l5.954-6.251V20.25a.75.75 0 0 0 1.5 0V5.516l5.955 6.251a.75.75 0 0 0 1.086-1.034l-7.067-7.42a.995.995 0 0 0-.58-.3.754.754 0 0 0-.29.001.995.995 0 0 0-.578.3L4.21 10.733Z', fill='currentColor') + button.btn.console-to-bottom-btn(type="button" title="Scroll to Bottom" class="flex items-center justify-center border border-gray-300 dark:border-gray-600") + svg.icon(xmlns='http://www.w3.org/2000/svg', width='24', height='24', fill='none', viewbox='0 0 24 24') + path(d='M19.79 13.267a.75.75 0 0 0-1.086-1.034l-5.954 6.251V3.75a.75.75 0 1 0-1.5 0v14.734l-5.955-6.251a.75.75 0 0 0-1.086 1.034l7.067 7.42c.16.168.366.268.58.3a.753.753 0 0 0 .29-.001.995.995 0 0 0 .578-.3l7.067-7.419Z', fill='currentColor') + button.btn.fold-unfold-console-btn(type="button" title="Fold/Unfold Console Lines" class="flex items-center justify-center border border-gray-300 dark:border-gray-600") + svg.icon(xmlns='http://www.w3.org/2000/svg', width='24', height='24', fill='none', viewbox='0 0 24 24') + path(d='M13.22 6.781a.75.75 0 0 1-.073-.976l.073-.085 2.367-2.37a.77.77 0 0 1 .664-.35c.252 0 .475.109.611.276l.053.075 2.367 2.37.073.084a.75.75 0 0 1 .007.882l-.08.094-.084.073a.75.75 0 0 1-.883.007l-.094-.08L17 5.56v3.784l-.007.089c-.05.32-.363.567-.743.567s-.694-.247-.743-.567l-.007-.09V5.56l-1.22 1.221-.084.073a.75.75 0 0 1-.976-.073ZM13.223 17.219a.75.75 0 0 1 .976-.073l.084.073 1.22 1.221v-3.784c0-.362.336-.656.75-.656.38 0 .693.247.743.567l.007.09v3.783l1.221-1.221a.75.75 0 0 1 .977-.073l.084.073a.75.75 0 0 1 .073.976l-.073.084-2.367 2.37a.77.77 0 0 1-.664.351.77.77 0 0 1-.664-.35l-2.367-2.37a.75.75 0 0 1 0-1.061ZM6.25 3.992A2.25 2.25 0 0 0 4 6.242v11.5a2.25 2.25 0 0 0 2.25 2.25h4a.75.75 0 0 0 0-1.5h-4a.75.75 0 0 1-.75-.75v-11.5a.75.75 0 0 1 .75-.75h4a.75.75 0 0 0 0-1.5h-4Z', fill='currentColor') + button.btn.clear-console-btn(type="button" title="Clear Console" class="flex items-center justify-center border border-gray-300 dark:border-gray-600") + svg.icon(xmlns='http://www.w3.org/2000/svg', width='24', height='24', fill='none', viewbox='0 0 24 24') + path(d='M12 1.75a3.25 3.25 0 0 1 3.245 3.066L15.25 5h5.25a.75.75 0 0 1 .102 1.493L20.5 6.5h-.796l-1.28 13.02a2.75 2.75 0 0 1-2.561 2.474l-.176.006H8.313a2.75 2.75 0 0 1-2.714-2.307l-.023-.174L4.295 6.5H3.5a.75.75 0 0 1-.743-.648L2.75 5.75a.75.75 0 0 1 .648-.743L3.5 5h5.25A3.25 3.25 0 0 1 12 1.75Zm6.197 4.75H5.802l1.267 12.872a1.25 1.25 0 0 0 1.117 1.122l.127.006h7.374c.6 0 1.109-.425 1.225-1.002l.02-.126L18.196 6.5ZM13.75 9.25a.75.75 0 0 1 .743.648L14.5 10v7a.75.75 0 0 1-1.493.102L13 17v-7a.75.75 0 0 1 .75-.75Zm-3.5 0a.75.75 0 0 1 .743.648L11 10v7a.75.75 0 0 1-1.493.102L9.5 17v-7a.75.75 0 0 1 .75-.75Zm1.75-6a1.75 1.75 0 0 0-1.744 1.606L10.25 5h3.5A1.75 1.75 0 0 0 12 3.25Z', fill='currentColor') - - pre.pt-0 - code.console.p-2(class="resize-y max-h-72 min-h-10 overscroll-y-contain") - span.hljs-literal No logs... + code.p-2(class="leading-normal min-h-10 no-highlight") + .py-3 + .content + p.px-4.hljs-literal No logs... + + + .drag-section.vertical#handle-2 + .drag-handle .container h2#usage Usage diff --git a/src/ts/components/Console.tsx b/src/ts/components/Console.tsx index 0b903e80..60e9f543 100644 --- a/src/ts/components/Console.tsx +++ b/src/ts/components/Console.tsx @@ -10,7 +10,7 @@ export const Console = ({ parentEl }: { parentEl: HTMLElement }) => { if (parentEl) { parentEl?.addEventListener("scroll", debounce((e) => { setStickToBottom(parentEl.scrollTop + parentEl.clientHeight >= parentEl.scrollHeight - 50); - }, 10)); + }, 50), { passive: true }); } createEffect(() => { @@ -19,16 +19,22 @@ export const Console = ({ parentEl }: { parentEl: HTMLElement }) => { } return getLogs(); }); - + return ( - No logs...}> + +
+

No logs...

+
+ + }> {({ title, message, type }, index) => { let styleType = { "error": "bg-red-400/20 border border-red-400/70 text-red-500/90 dark:text-red-300/90 rounded-md", "warn": "bg-yellow-400/20 border border-yellow-400/70 text-yellow-500/90 dark:text-yellow-300/90 rounded-md" }; - let staticClassName = "whitespace-normal overflow-auto overscroll-x-contain "; + let staticClassName = "whitespace-normal overflow-auto overscroll-x-contain "; let [getClassName, setClassName] = createSignal(staticClassName); createEffect(() => { setClassName(staticClassName + (styleType[type ?? "default"] ?? (Math.abs(index() - len() - 1) > 2 ? " border-b border-gray-300/60 dark:border-gray-600/60" : ""))); diff --git a/src/ts/index.ts b/src/ts/index.ts index 6d9b05a2..4a596796 100644 --- a/src/ts/index.ts +++ b/src/ts/index.ts @@ -27,6 +27,7 @@ import * as Monaco from "./modules/monaco"; import type { editor as Editor } from "monaco-editor"; import type { App, HistoryManager, IHistoryItem } from "@okikio/native"; +import Module from "module"; export let oldShareURL = new URL(String(document.location)); export const BundleEvents = new EventEmitter(); @@ -151,20 +152,21 @@ BundleEvents.on({ // Load all heavy main content export const build = (app: App) => { let RunBtn = document.querySelector("#run"); - let bundleTime = document.querySelector("#bundle-time"); + // let bundleTime = document.querySelector("#bundle-time"); fileSizeEl = fileSizeEl ?? document.querySelector(".file-size"); let editor: Editor.IStandaloneCodeEditor; - let output: Editor.IStandaloneCodeEditor; + let inputModel: Editor.ITextModel; + let outputModel: Editor.ITextModel; // bundles using esbuild and returns the result BundleEvents.on({ bundle() { if (!initialized) return; - value = `` + editor?.getValue(); + value = `` + inputModel?.getValue(); fileSizeEl.innerHTML = `
`; - bundleTime.textContent = `Bundled in ...`; + // bundleTime.textContent = `Bundled in ...`; // if (!isInitial) setLogs?.([]); start = Date.now(); @@ -173,32 +175,45 @@ export const build = (app: App) => { result(details) { let { size, content } = details; - output?.setValue?.(content); - bundleTime.textContent = `Bundled ${timeFormatter.format( - (Date.now() - start) / 1000, - "seconds" - )}`; + outputModel?.setValue?.(content); + // bundleTime.textContent = `Bundled ${timeFormatter.format( + // (Date.now() - start) / 1000, + // "seconds" + // )}`; + + setLogs([ + ...getLogs(), + { + title: `⌛ Bundled ${timeFormatter.format( + (Date.now() - start) / 1000, + "seconds" + )}`, + message: "" + } + ]); fileSizeEl.textContent = `` + size; } }); let historyManager = app.get("HistoryManager") as HistoryManager; let replaceState = (url) => { - let { last } = historyManager; - let state = { - ...last, - url: url.toString() - } + if (url) { + let { last } = historyManager; + let state = { + ...last, + url: url.toString() + } - historyManager.states.pop(); - historyManager.states.push({ ...state }); + historyManager.states.pop(); + historyManager.states.push({ ...state }); - let item: IHistoryItem = { - index: historyManager.pointer, - states: [...historyManager.states] - }; + let item: IHistoryItem = { + index: historyManager.pointer, + states: [...historyManager.states] + }; - window.history.replaceState(item, "", state.url); + window.history.replaceState(item, "", state.url); + } } let pushState = (url) => { @@ -238,9 +253,8 @@ export const build = (app: App) => { }); const { languages } = Monaco; - const getShareableURL = async (editor: typeof output) => { + const getShareableURL = async (model: typeof inputModel) => { try { - const model = editor.getModel(); const worker = await languages.typescript.getTypeScriptWorker(); const thisWorker = await worker(model.uri); @@ -251,9 +265,10 @@ export const build = (app: App) => { } }; - const editorBtns = (editor: typeof output, reset: string) => { + const editorBtns = (editor: Editor.IStandaloneCodeEditor) => { let el = editor.getDomNode(); - let parentEl = el?.closest(".app").querySelector(".editor-btns"); + let app = el?.closest(".app"); + let parentEl = app.querySelector(".editor-btns"); if (parentEl) { let btnContainer = parentEl.querySelector(".editor-btn-container"); let hideBtn = parentEl.querySelector(".hide-btns"); @@ -291,8 +306,12 @@ export const build = (app: App) => { }); resetBtn.addEventListener("click", () => { - editor.setValue(reset); - if (editor != output) { + editor.setValue( + editor.getModel() == inputModel ? [ + '// Click Run for the Bundled, Minified & Gzipped package size', + 'export * from "@okikio/animate";' + ].join("\n") : `// Output`); + if (editor.getModel() != outputModel) { isInitial = true; } }); @@ -330,79 +349,48 @@ export const build = (app: App) => { editor.updateOptions({ wordWrap }); }); } + + let editorTabs = document.querySelector(".tab-btns"); + if (editorTabs) { + let inputEditorBtn = editorTabs.querySelector(".input-btn"); + let outputEditorBtn = editorTabs.querySelector(".output-btn"); + inputEditorBtn.addEventListener("click", () => { + outputEditorBtn.classList.remove("active"); + inputEditorBtn.classList.add("active"); + editor?.setModel(inputModel); + }); + outputEditorBtn.addEventListener("click", () => { + inputEditorBtn.classList.remove("active"); + outputEditorBtn.classList.add("active"); + editor?.setModel(outputModel); + }); + } }; // Build the Code Editor - [editor, output] = Monaco.build(oldShareURL); + [editor, inputModel, outputModel] = Monaco.build(oldShareURL); FadeLoadingScreen.play(); // Fade away the loading screen await FadeLoadingScreen; - [editor.getDomNode(), output.getDomNode()].forEach((el) => { - el?.parentElement?.classList.add("show"); - }); + editor.getDomNode()?.parentElement?.classList.add("show"); // Add editor buttons to both editors - editorBtns( - editor, - [ - '// Click Run for the Bundled, Minified & Gzipped package size', - 'export * from "@okikio/animate";' - ].join("\n") - ); - editorBtns(output, `// Output`); + editorBtns(editor); FadeLoadingScreen.stop(); loadingContainerEl.forEach((x) => x?.remove()); flexWrapper.classList.add("loaded"); - - const allEditorBtns = Array.from( - document.querySelectorAll(".editor-btns") - ); - if (allEditorBtns) { - allEditorBtns?.[1].classList.add("delay"); - setTimeout(() => { - allEditorBtns?.[1].classList.remove("delay"); - }, 1600); - } - BundleEvents.emit("loaded"); loadingContainerEl = null; FadeLoadingScreen = null; - let el = editor.getDomNode(); - let parentEl = el?.closest(".app").querySelector(".editor-btns"); - let inputSizeEl = parentEl.querySelector(".input-file-size") as HTMLDivElement; - let calculated = false; - const setInputFileSize = () => { - if (parentEl) { - inputSizeEl && (inputSizeEl.textContent = prettyBytes(encode(editor.getValue()).byteLength)); - calculated = true; - } - } - - setInputFileSize(); - editor.onDidChangeModelContent( - debounce((e) => { - if (parentEl && calculated) { - inputSizeEl && (inputSizeEl.innerHTML = `
`); - calculated = false; - } - }, 100) - ); - - editor.onDidChangeModelContent( - debounce((e) => { - setInputFileSize(); - }, 500) - ); - editor.onDidChangeModelContent( debounce((e) => { (async () => { - replaceState(await getShareableURL(editor)); + replaceState(await getShareableURL(inputModel)); isInitial = false; })(); }, 1000) @@ -423,7 +411,7 @@ export const build = (app: App) => { await navigator.share({ title: 'bundle', text: '', - url: await getShareableURL(editor), + url: await getShareableURL(inputModel), }); shareBtn.innerText = "Shared!"; @@ -431,7 +419,7 @@ export const build = (app: App) => { shareBtn.innerText = shareBtnValue; }, 600); } else { - shareInput.value = await getShareableURL(editor); + shareInput.value = await getShareableURL(inputModel); shareInput.select(); document.execCommand("copy"); @@ -450,8 +438,8 @@ export const build = (app: App) => { // Listen to events for the results ResultEvents.on("add-module", (v) => { - value = isInitial ? "// Click Run for the Bundled + Minified + Gzipped package size" : `` + editor?.getValue(); - editor.setValue((value + "\n" + v).trim()); + value = isInitial ? "// Click Run for the Bundled + Minified + Gzipped package size" : `` + inputModel?.getValue(); + inputModel?.setValue((value + "\n" + v).trim()); }); RunBtn.addEventListener("click", () => { @@ -459,7 +447,7 @@ export const build = (app: App) => { if (!initialized) fileSizeEl.textContent = `Wait!`; BundleEvents.emit("bundle"); - pushState(await getShareableURL(editor)); + pushState(await getShareableURL(inputModel)); })(); }); })(); @@ -531,10 +519,154 @@ export const InitialRender = (shareURL: URL) => { }); })(); + // Drag handle - Resiable split editors + (() => { + // Based on the tutorial at https://htmldom.dev/create-resizable-split-views/ + // Honestly, I am surprised that native dragging doesn't work for this use case + const dragSection = document.querySelector(".drag-section") as HTMLElement; + const dragHandle = dragSection.querySelector(".drag-handle") as HTMLElement; + + const parentEl = dragSection.parentElement as HTMLElement; + const leftSide = dragSection.previousElementSibling as HTMLElement; + const rightSide = dragSection.nextElementSibling as HTMLElement; + + // The current position of mouse + let x = 0; + let y = 0; + + // Width & Height of left side + let leftWidth = 0; + let leftHeight = 0; + + let parentRect = parentEl.getBoundingClientRect(); + let parentWidth = parentRect.width; + let parentHeight = parentRect.height; + + window.matchMedia("(min-width: 640px)") + .addEventListener("change", (e) => { + leftSide.style.removeProperty(e.matches ? 'height' : 'width'); + }); + let drag = (e: MouseEvent) => { + // How far the mouse has been moved + const dx = e.clientX - x; + const dy = e.clientY - y; + + if (window.matchMedia("(min-width: 640px)").matches) { + const newLeftWidth = ((leftWidth + dx) * 100) / parentWidth; + leftSide.style.width = `${newLeftWidth}%`; + document.body.style.cursor = 'col-resize'; + } else { + const newLeftHeight = ((leftHeight + dy) * 100) / parentHeight; + leftSide.style.height = `${newLeftHeight}%`; + document.body.style.cursor = 'row-resize'; + } + + leftSide.style.userSelect = 'none'; + leftSide.style.pointerEvents = 'none'; + + rightSide.style.userSelect = 'none'; + rightSide.style.pointerEvents = 'none'; + } + + let stopDrag = () => { + dragHandle.style.removeProperty('cursor'); + document.body.style.removeProperty('cursor'); + + leftSide.style.removeProperty('user-select'); + leftSide.style.removeProperty('pointer-events'); + + rightSide.style.removeProperty('user-select'); + rightSide.style.removeProperty('pointer-events'); + + document.removeEventListener('pointermove', drag); + document.removeEventListener('pointerup', stopDrag); + } + + // Handle the mousedown event + // that's triggered when user drags the resizer + const pointerDown = (e: MouseEvent) => { + // Get the current mouse position + x = e.clientX; + y = e.clientY; + + let { width, height } = leftSide.getBoundingClientRect(); + leftWidth = width; + leftHeight = height; + + // Attach the listeners to `document` + document.addEventListener('pointermove', drag); + document.addEventListener('pointerup', stopDrag); + }; + + dragHandle.addEventListener('pointerdown', pointerDown); + + window.addEventListener('resize', debounce(() => { + parentRect = parentEl.getBoundingClientRect(); + parentWidth = parentRect.width; + parentHeight = parentRect.height; + }, 50)); + + new ResizeObserver(debounce(() => { + parentRect = parentEl.getBoundingClientRect(); + parentWidth = parentRect.width; + parentHeight = parentRect.height; + }, 50)).observe(parentEl); + })(); + + // Drag handle - Resizable Full height + (() => { + // Based on the tutorial at https://htmldom.dev/create-resizable-split-views/ + // Honestly, I am surprised that native dragging doesn't work for this use case + const dragSection = document.querySelector(".drag-section#handle-2") as HTMLElement; + const dragHandle = dragSection.querySelector(".drag-handle") as HTMLElement; + const targetEl = document.querySelector(".flex-wrapper") as HTMLElement; + + // The current position of mouse + let y = 0; + + // Height of left side + let height = 0; + let drag = (e: MouseEvent) => { + // How far the mouse has been moved + const dy = e.clientY - y; + const newHeight = height + dy; + targetEl.style.height = `${newHeight}px`; + document.body.style.cursor = 'row-resize'; + + targetEl.style.userSelect = 'none'; + targetEl.style.pointerEvents = 'none'; + } + + let stopDrag = () => { + dragHandle.style.removeProperty('cursor'); + document.body.style.removeProperty('cursor'); + + targetEl.style.removeProperty('user-select'); + targetEl.style.removeProperty('pointer-events'); + + document.removeEventListener('pointermove', drag); + document.removeEventListener('pointerup', stopDrag); + } + + // Handle the mousedown event + // that's triggered when user drags the resizer + const pointerDown = (e: MouseEvent) => { + // Get the current mouse position + y = e.clientY; + height = targetEl.getBoundingClientRect().height; + + // Attach the listeners to `document` + document.addEventListener('pointermove', drag); + document.addEventListener('pointerup', stopDrag); + }; + + dragHandle.addEventListener('pointerdown', pointerDown); + })(); + // Console solidjs component (async () => { const ConsoleEl = document.querySelector( - ".console" + ".console code" ) as HTMLElement; if (ConsoleEl) { ConsoleEl.innerHTML = ""; @@ -560,6 +692,13 @@ export const InitialRender = (shareURL: URL) => { ConsoleEl.scrollTo(0, ConsoleEl.scrollHeight); } }); + + const scrollUpBtn = document.querySelector(".console-btns .console-to-top-btn"); + scrollUpBtn?.addEventListener("click", () => { + if (ConsoleEl) { + ConsoleEl.scrollTo(0, 0); + } + }); })(); // countapi-js hit counter. It counts the number of time the website is loaded diff --git a/src/ts/modules/monaco.ts b/src/ts/modules/monaco.ts index 010c13f2..1398d613 100644 --- a/src/ts/modules/monaco.ts +++ b/src/ts/modules/monaco.ts @@ -108,7 +108,7 @@ export const TS_WORKER = new WebWorker(TYPESCRIPT_WORKER_URL, { name: "ts-worker } as Environment; export { languages, Editor, Uri }; -export const build = (oldShareURL: URL) => { +export const build = (oldShareURL: URL): [Editor.IStandaloneCodeEditor, Editor.ITextModel, Editor.ITextModel] => { const initialValue = parseSearchQuery(oldShareURL) || [ @@ -117,13 +117,7 @@ export const build = (oldShareURL: URL) => { ].join("\n"); let inputEl = document.querySelector(".app#input #editor") as HTMLElement; - let outputEl = document.querySelector(".app#output #editor") as HTMLElement; - inputEl.textContent = ""; - outputEl.textContent = ""; - - let inputEditor: Editor.IStandaloneCodeEditor; - let outputEditor: Editor.IStandaloneCodeEditor; // @ts-ignore Editor.defineTheme("dark", GithubDark); @@ -134,8 +128,20 @@ export const build = (oldShareURL: URL) => { // Basically android and monaco is pretty bad, this makes it less bad // See https://github.com/microsoft/pxt/pull/7099 for this, and the long // read is in https://github.com/microsoft/monaco-editor/issues/563 - const isAndroid = navigator && /android/i.test(navigator.userAgent) + const isAndroid = navigator && /android/i.test(navigator.userAgent); + let inputModel = Editor.createModel( + initialValue, + "typescript", + Uri.parse("file://input.ts") + ); + let outputModel = Editor.createModel( + `// Output`, + "typescript", + Uri.parse("file://output.ts") + ); + let editorOpts: Editor.IStandaloneEditorConstructionOptions = { + model: null, // @ts-ignore bracketPairColorization: { enabled: true, @@ -143,11 +149,6 @@ export const build = (oldShareURL: URL) => { parameterHints: { enabled: true, }, - model: Editor.createModel( - initialValue, - "typescript", - Uri.parse("file://input.ts") - ), quickSuggestions: { other: !isAndroid, comments: !isAndroid, @@ -182,15 +183,8 @@ export const build = (oldShareURL: URL) => { lineNumbers: "on", }; - inputEditor = Editor.create(inputEl, editorOpts); - outputEditor = Editor.create(outputEl, { - ...editorOpts, - model: Editor.createModel( - `// Output`, - "typescript", - Uri.parse("file://output.ts") - ), - }); + let editor = Editor.create(inputEl, editorOpts); + editor.setModel(inputModel); document.addEventListener("theme-change", () => { let theme = themeGet(); @@ -249,7 +243,6 @@ export const build = (oldShareURL: URL) => { // (?:(?:import|export|require)(?:\s?(.*)?\s?)(?:from\s+|\((?:\s+)?)["']([^"']+)["'])\)? const IMPORTS_REXPORTS_REQUIRE_REGEX = /(?:(?:import|export|require)(?:.)*?(?:from\s+|\((?:\s+)?)["']([^"']+)["'])\)?/g; - const FetchCache = new Set(); languages.registerHoverProvider("typescript", { provideHover(model, position) { @@ -317,5 +310,5 @@ export const build = (oldShareURL: URL) => { }, }); - return [inputEditor, outputEditor]; + return [editor, inputModel, outputModel]; }; diff --git a/src/ts/plugins/cdn.ts b/src/ts/plugins/cdn.ts index 497b4a1d..33c9b9dc 100644 --- a/src/ts/plugins/cdn.ts +++ b/src/ts/plugins/cdn.ts @@ -37,9 +37,9 @@ export const CDN_RESOLVE = (host?: string): (args: OnResolveArgs) => OnResolveRe pluginData: { pkg } }; } - } else if (("dependencies" in pkg || "devDependencies" in pkg) && !/\S+@\S+/.test(args.path)) { - let { devDependencies = {}, dependencies = {} } = pkg; - let deps = Object.assign({}, devDependencies, dependencies); + } else if (("dependencies" in pkg || "devDependencies" in pkg || "peerDependencies" in pkg) && !/\S+@\S+/.test(args.path)) { + let { devDependencies = {}, dependencies = {}, peerDependencies = {} } = pkg; + let deps = Object.assign({}, devDependencies, peerDependencies, dependencies); let keys = Object.keys(deps); if (keys.includes(args.path)) { diff --git a/src/ts/workers/esbuild.ts b/src/ts/workers/esbuild.ts index 019c7eba..e756b57a 100644 --- a/src/ts/workers/esbuild.ts +++ b/src/ts/workers/esbuild.ts @@ -36,7 +36,7 @@ export const initEvent = new EventEmitter(); // I didn't even know this was exported by esbuild, great job @egoist export const createNotice = async (errors: PartialMessage[], kind: "error" | "warning" = "error", color = true) => { let notices = await formatMessages(errors, { color, kind }); - return notices.map((msg) => !color ? msg : ansi(msg.replace(/(\s+)(\d+)(\s+)\│/, "\n$1$2$3│"))); + return notices.map((msg) => !color ? msg : ansi(msg.replace(/(\s+)(\d+)(\s+)\│/g, "\n$1$2$3│"))); } export const start = async (port) => { @@ -121,7 +121,7 @@ export const start = async (port) => { treeShaking: true, incremental: false, target: ["esnext"], - logLevel: 'silent',// 'info', + logLevel: 'info', write: false, outfile: "/bundle.js", platform: "browser",