diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 000000000..e69de29bb diff --git a/CONTRIBUTORS.svg b/CONTRIBUTORS.svg new file mode 100644 index 000000000..ab5a08dde --- /dev/null +++ b/CONTRIBUTORS.svg @@ -0,0 +1,14 @@ + + + + + + + + \ No newline at end of file diff --git a/css/copy.css b/css/copy.css new file mode 100644 index 000000000..c4b309362 --- /dev/null +++ b/css/copy.css @@ -0,0 +1,49 @@ +markdown-style pre > .copied, +markdown-style [class*='language-'] .copied { + display: flex; + position: absolute; + cursor: pointer; + color: #a5afbb; + top: 6px; + right: 6px; + border-radius: 5px; + background: #82828226; + padding: 6px; + font-size: 12px; + transition: all 0.3s; + z-index: 10; +} +markdown-style pre > .copied:not(.active), +markdown-style [class*='language-'] .copied:not(.active) { + visibility: hidden; +} +markdown-style pre:hover > .copied, +markdown-style [class*='language-']:hover .copied { + visibility: visible; +} +markdown-style pre:hover > .copied:hover, +markdown-style [class*='language-']:hover .copied:hover { + background: #4caf50; + color: #fff; +} +markdown-style [class*='language-']:hover .copied:active, +markdown-style pre > .copied.active { + background: #2e9b33; + color: #fff; +} +markdown-style pre > .copied .octicon-copy, +markdown-style [class*='language-'] .copied .octicon-copy { + display: block; +} +markdown-style pre > .copied .octicon-check, +markdown-style [class*='language-'] .copied .octicon-check { + display: none; +} +markdown-style pre > .active .octicon-copy, +markdown-style [class*='language-'] .active .octicon-copy { + display: none; +} +markdown-style pre > .active .octicon-check, +markdown-style [class*='language-'] .active .octicon-check { + display: block; +} diff --git a/css/demo-preview.css b/css/demo-preview.css new file mode 100644 index 000000000..cc8a25e5e --- /dev/null +++ b/css/demo-preview.css @@ -0,0 +1,62 @@ +.idoc-demo-warpper { + overflow: hidden; + min-height: 60px; + margin-bottom: 16px; +} + +div.idoc-demo-warpper { + position: relative; + background-color: var(--color-canvas-subtle); + border-radius: 6px; +} + +div.idoc-demo-warpper > pre { + padding: 16px; + overflow: auto; + display: block; + margin-bottom: 0 !important; + height: 100%; +} + +div.idoc-demo-previw { + padding: 10px; + font-size: initial; + line-height: initial; + line-height: initial; + font-family: initial; + overflow: auto; +} +.idoc-demo-previw { + border: 0; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + width: 100%; + background-color: var(--color-canvas-subtle); + border: 1px solid var(--color-border-default); + border-radius: 6px; + z-index: 9; + transition: left 0.3s cubic-bezier(1, 0, 1, 0); +} + +.idoc-demo-previw.ishiden { + left: -100%; +} +button.idoc-toggle-previw { + user-select: none; + position: absolute; + z-index: 10; + border: transparent; + background-color: var(--color-border-default); + cursor: pointer; + font-size: 12px; + padding: 2px 5px; + border-radius: 3px; + bottom: 5px; + right: 5px; +} +button.idoc-toggle-previw:hover { + color: var(--color-theme-text); +} diff --git a/css/main.css b/css/main.css new file mode 100644 index 000000000..edff54f90 --- /dev/null +++ b/css/main.css @@ -0,0 +1,253 @@ +[data-color-mode*='dark'], +[data-color-mode*='dark'] body { + --color-header-bg: #3a3a3a8f; + --color-header-border: #21262d; + --color-hover: #ffffff1c; + --color-hoc-bg: #fffefe08; +} + +[data-color-mode*='light'], +[data-color-mode*='light'] body { + --color-header-bg: #ffffff52; + --color-header-border: #d3d3d3; + --color-hover: #0000001a; + --color-hoc-bg: #00000008; +} + +*, +:after, +:before { + box-sizing: border-box; +} + +html { + scroll-behavior: smooth; +} + +body { + margin: 0; + font-size: 14px; + font-family: -apple-system, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji'; +} + +a { + text-decoration: none; + color: var(--color-accent-fg); +} +a:hover { + text-decoration: underline; +} + +.warpper { + max-width: 960px; + margin: 0 auto; +} + +markdown-style { + min-height: 60vh; + grid-area: main; + margin-bottom: 18px !important; +} +markdown-style img { + background-color: transparent !important; +} + +.warpper-content { + padding: 0 20px; + padding-top: 32px; + margin-top: 48px; + display: grid; + grid-template-columns: minmax(0, 3.5fr) minmax(0, 15rem); + grid-template-areas: 'main toc'; + grid-gap: 18px; + gap: 18px; +} +.warpper-content.sidebar { + grid-template-columns: 180px minmax(0, 3.5fr) minmax(0, 15rem); + grid-template-areas: 'sidebar main toc'; +} +.warpper-content.notocs { + grid-template-columns: minmax(0, 3.5fr); + grid-template-areas: 'main'; +} +.warpper-content.sidebar.notocs { + grid-template-columns: 180px minmax(0, 3.5fr); + grid-template-areas: 'sidebar main'; +} + +nav.tocs .is-position-fixed { + top: 58px !important; + max-height: calc(100% - 68px); +} +nav.tocs { + position: relative; + grid-area: toc; +} +nav.tocs p { + color: var(--color-fg-muted); + margin-bottom: 0; +} +nav.tocs a { + color: var(--color-fg-muted); + display: block; + padding: 0 5px; +} +nav.tocs .inner { + padding: 10px 10px 10px 10px; + background-color: var(--color-hoc-bg); + max-width: 240px; + width: 240px; +} + +a.gototop { + position: fixed; + bottom: 10px; + right: 10px; + display: inline-block; + background: var(--color-theme-text); + padding: 5px; + border-radius: 5px; + z-index: 9999; + color: var(--color-theme-bg); + font-size: 10px; + opacity: 0; + transition: all 0.3s; +} +a.gototop:hover { + opacity: 1; +} + +.header { + position: fixed; + width: 100%; + background: var(--color-header-bg); + backdrop-filter: saturate(180%) blur(0.4rem); + background-color: var(--color-header-bg); + border-bottom: 1px solid var(--color-header-border); + z-index: 99; + top: 0; +} + +.header .inner { + display: flex; + justify-content: space-between; + min-height: 45px; + padding-left: 10px; + padding-right: 10px; +} +.header .logo { + font-weight: bold; + display: flex; + color: var(--color-theme-text); + align-items: center; +} +.header .logo:hover { + text-decoration: none; +} +.header .logo .title { + padding-left: 8px; + display: flex; +} +.header .logo .title sup { + margin-top: -5px; + font-weight: normal; + color: var(--color-fg-subtle); +} +.header .logo img, +.header .logo svg { + height: 26px; + display: block; +} + +.header .content { + display: flex; + align-items: center; +} + +.header .menu { + padding: 0; + margin: 0; + display: flex; + list-style: none; + padding-right: 10px; +} +.header .menu li { + display: flex; + align-items: center; +} +.header a { + color: var(--color-theme-text); + font-weight: bold; +} +.header .menu a { + padding: 3px 7px; + font-size: 14px; + border-radius: 2px; +} +.header .menu a.active { + background-color: var(--color-hover); +} + +.header .github { + width: 18px; + height: 18px; + margin-right: 8px; +} + +section.article-footer { + display: flex; + align-items: center; + font-size: 14px; + justify-content: space-between; + margin-top: 12px; +} + +section.article-footer a { + display: flex; + align-items: center; +} + +section.article-footer .edit-button { + padding-right: 8px; +} +section.article-footer .edit-button svg { + height: 15px; + margin-right: 6px; +} + +section.article-footer .atime { + font-size: 12px; + color: var(--color-fg-muted); + margin-top: 2px; +} + +.previous { + display: flex; + align-items: center; + justify-content: space-between; + grid-gap: 12px; + gap: 12px; + background-color: var(--color-canvas-subtle); + padding: 10px; + font-size: 14px; + border-radius: 5px; + margin-top: 26px; +} +.previous a { + display: flex; + align-items: center; +} +.previous a.prev svg { + margin-right: 3px; +} +.previous a.next svg { + margin-left: 3px; +} + +.footer { + text-align: center; + border-top: 1px solid var(--color-header-border); + padding: 32px 0 110px 0; + color: var(--color-fg-muted); + font-size: 14px; +} diff --git a/css/media.css b/css/media.css new file mode 100644 index 000000000..da524359e --- /dev/null +++ b/css/media.css @@ -0,0 +1,52 @@ +@media only screen and (min-width: 1024px) { + footer.article-footer, + .warpper { + max-width: 1200px; + } +} + +@media screen and (max-width: 900px) { + .warpper-content { + grid-template-columns: minmax(0, 3.5fr); + grid-template-areas: 'main'; + } + .warpper-content.sidebar { + grid-template-areas: 'sidebar main'; + grid-template-columns: 180px minmax(0, 41rem); + } + nav.tocs { + display: none; + } +} + +@media screen and (max-width: 600px) { + .warpper-content { + grid-template-columns: minmax(0, 3.5fr); + grid-template-areas: 'main'; + } + .warpper-content.sidebar { + grid-template-areas: 'main'; + grid-template-columns: minmax(0, 41rem); + } + nav.tocs, + .sidebar-border { + display: none; + } +} + +@media print { + .header, + nav.tocs, + section.article-footer, + .sidebar-border, + .previous, + .footer, + a.gototop { + display: none; + } + .warpper-content { + margin: 0; + padding: 0; + display: initial; + } +} diff --git a/css/sidebar.css b/css/sidebar.css new file mode 100644 index 000000000..11a6999fe --- /dev/null +++ b/css/sidebar.css @@ -0,0 +1,41 @@ +.sidebar-border { + border-right: 1px solid var(--color-border-muted); +} +aside.sidebar { + min-width: 160px; + margin-left: -5px; + padding-bottom: 20px; + padding-right: 6px; + position: -webkit-sticky; + position: sticky; + top: 56px; + grid-area: sidebar; + overflow: auto; + max-height: calc(100vh - 56px); + padding-bottom: 36px; +} +aside.sidebar label:first-child { + padding-top: 0 !important; +} +aside.sidebar a:first-child { + margin-top: 0 !important; +} +aside.sidebar label { + font-size: 12px; + padding: 5px 0 3px 0; + display: block; + padding-left: 5px !important; +} +aside.sidebar a.active { + color: var(--color-prettylights-syntax-markup-inserted-text); + background-color: var(--color-hover); +} +aside.sidebar a { + display: block; + padding: 3px 5px 3px 5px; + border-radius: 3px; + margin: 3px 0; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; +} diff --git a/css/tocbot.css b/css/tocbot.css new file mode 100644 index 000000000..3c374ce6e --- /dev/null +++ b/css/tocbot.css @@ -0,0 +1,52 @@ +.tocs { + line-height: 26px; +} +nav.tocs > .inner { + position: sticky; + top: 56px; + overflow: auto; + max-height: calc(100vh - 56px); +} +nav.tocs .inner > .tocs-list { + overflow: hidden; + position: relative; +} +.tocs .tocs-list li { + list-style: none; +} +.tocs-list { + margin: 0; + padding-left: 10px; +} +.tocs-list.is-collapsed { + max-height: 0; + overflow: hidden; + transition: max-height 0.3s cubic-bezier(0, 1, 0, 1); +} +.tocs-list.is-collapsed.is-open { + max-height: 9999px; + transition: max-height 0.3s cubic-bezier(1, 0, 1, 0); +} + +.tocs-link { + height: 100%; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; +} +.tocs-link::before { + background-color: var(--color-border-default); + content: ' '; + display: inline-block; + height: inherit; + left: 0; + margin-top: -1px; + position: absolute; + width: 2px; +} +.tocs-link.is-active-link { + font-weight: 700; +} +.tocs-link.is-active-link::before { + background-color: #54bc4b; +} diff --git a/index.html b/index.html new file mode 100644 index 000000000..55203cf02 --- /dev/null +++ b/index.html @@ -0,0 +1,524 @@ + + + + + + + TSBB 4.0.0 + + + + + + + + + + + + + + top +
+
+
+ + + + +
+
+
+
+ +

tsbb

+

Build & Deploy +NPM Downloads +Open in unpkg +npm version

+

+ Quick Start · + Example · + Command Help · + npm · + License +

+

TSBB is a CLI tool that enables the development, testing, and publishing of modern TypeScript Node.js projects with zero configuration needed.

+

TypeScript + Babel = TSBB

+

Features

+ +

Quick Start

+

You will need Node.js installed on your system.

+
$ yarn create tsbb [appName]
+# or npm
+$ npm create tsbb@latest my-app -- -e express
+# --- Example name ------┴ˇˇˇˇˇ
+# or npx
+$ npx create-tsbb@latest my-app -e koa
+
+# npm 7+, extra double-dash is needed:
+$ npm init tsbb my-app -- --example typenexus
+# npm 6.x
+$ npm init tsbb my-app --example typenexus
+
+$ cd my-project
+
+$ npm run watch # Listen compile .ts files.
+$ npm run build # compile .ts files.
+$ npm start
+
+

Example

+

create-tsbb initialize the project from one of the examples:

+
$ npx create-tsbb my-app -e <Example Name>
+# --- E.g: ----------------┴ˇˇˇˇˇˇˇˇˇˇˇˇˇˇ
+# npx create-tsbb my-app -e Basic
+
+

You can download the following examples directly. Download page.

+ +

TypeScript Project

+

To configure the tsconfig.json properly, you must first define either the include or files field(s) to specify which files need to be compiled. Once you've done that, you can then specify the outDir for the output directory in the configuration.

+
{
+  "$schema": "http://json.schemastore.org/tsconfig",
+  "compilerOptions": {
+    "module": "commonjs",
+    "target": "esnext",
+    "outDir": "./lib",
+    "strict": true,
+    "skipLibCheck": true
+  },
+  "include": ["src/**/*"],
+  "exclude": [
+    "node_modules",
+    "**/*.spec.ts"
+  ]
+}
+
+

After completing tsconfig.jso configuration, you can configure scripts in package.json:

+
{
+  "scripts": {
+    "watch": "tsbb watch",
+    "build": "tsbb build"
+  },
+  "devDependencies": {
+    "tsbb": "*"
+  }
+}
+
+

Babel Project

+

Adding the parameter --use-babel to your project enables babel to compile and output cjs/esm files simultaneously, while ts is only needed for type output.

+
$ tsbb build "src/*ts" --use-babel
+
+

You can change the built-in settings of Babel by adding a .babelrc configuration file. Additionally, you can modify the Babel configurations for esm and cjs separately through environment variables. Please refer to the example below:

+
{
+  "env": {
+    "cjs": {
+      "presets": ["@babel/preset-typescript"]
+    },
+    "esm": {
+      "presets": ["@babel/preset-env", {
+        "modules": false,
+        "loose": true,
+        "targets": {
+          "esmodules": true,
+        },
+      }]
+    }
+  } 
+}
+
+

At compile time, specify the environment variable --envName='xxx' to enable reading of relevant configurations from the settings. This environment variable can also be customized.

+
{
+  "env": {
+    "xxx": { ... }
+  } 
+}
+
+

Command Help

+

Below is a help of commands you might find useful.

+

tsbb

+
▶ tsbb --help
+
+Usage: tsbb <command>
+
+Commands:
+
+  tsbb build [source…] [options]   Build your project once and exit.
+  tsbb watch [source…] [options]   Recompile files on changes.
+  tsbb test [options]              Run jest test runner in watch mode.
+
+Options:[build|watch]
+
+  --use-babel                Use Babel.(works in babel)
+  --source-maps              Enables the generation of sourcemap files.(works in babel)
+  --env-name                 The current active environment used during configuration loading.(works in babel)
+  --esm                      Output "esm" directory.(works in babel)
+  --cjs                      Output "cjs" directory.(works in babel)
+
+Options:
+
+  --version, -v              Show version number
+  --help, -h                 Show help
+
+Examples:
+
+  $ tsbb build src/*.ts                    Build your project.
+  $ tsbb build src/main.ts src/good.ts     Specify the entry directory.
+  $ tsbb build src/*.ts --use-babel --no-source-maps   No ".js.map" file is generated. (works in babel)
+  $ tsbb watch src/*.ts --use-babel --cjs ./cjs        Watch Output directory.
+  $ tsbb build src/*.ts --use-babel --esm ./es         Output directory.
+  $ tsbb build src/*.ts --use-babel --use-vue          To add Vue JSX support.
+  $ tsbb test                              Run test suites related
+  $ tsbb test --coverage --bail            Test coverage information should be collected
+
+  Copyright 2023
+
+
+

tsbb create

+

Please use create-tsbb to create an example.

+

tsbb test

+

Runs the test watcher (Jest) in an interactive mode.

+
$ tsbb test                          Run test suites related
+$ tsbb test --coverage --no-color    Test coverage information should be collected
+
+
export declare type Argv = Arguments<Partial<{
+  all: boolean;
+  automock: boolean;
+  bail: boolean | number;
+  cache: boolean;
+  cacheDirectory: string;
+  changedFilesWithAncestor: boolean;
+  changedSince: string;
+  ci: boolean;
+  clearCache: boolean;
+  clearMocks: boolean;
+  collectCoverage: boolean;
+  collectCoverageFrom: string;
+  collectCoverageOnlyFrom: Array<string>;
+  color: boolean;
+  colors: boolean;
+  config: string;
+  coverage: boolean;
+  coverageDirectory: string;
+  coveragePathIgnorePatterns: Array<string>;
+  coverageReporters: Array<string>;
+  coverageThreshold: string;
+  debug: boolean;
+  env: string;
+  expand: boolean;
+  findRelatedTests: boolean;
+  forceExit: boolean;
+  globals: string;
+  globalSetup: string | null | undefined;
+  globalTeardown: string | null | undefined;
+  haste: string;
+  init: boolean;
+  injectGlobals: boolean;
+  json: boolean;
+  lastCommit: boolean;
+  logHeapUsage: boolean;
+  maxWorkers: number | string;
+  moduleDirectories: Array<string>;
+  moduleFileExtensions: Array<string>;
+  moduleNameMapper: string;
+  modulePathIgnorePatterns: Array<string>;
+  modulePaths: Array<string>;
+  noStackTrace: boolean;
+  notify: boolean;
+  notifyMode: string;
+  onlyChanged: boolean;
+  onlyFailures: boolean;
+  outputFile: string;
+  preset: string | null | undefined;
+  projects: Array<string>;
+  prettierPath: string | null | undefined;
+  resetMocks: boolean;
+  resetModules: boolean;
+  resolver: string | null | undefined;
+  restoreMocks: boolean;
+  rootDir: string;
+  roots: Array<string>;
+  runInBand: boolean;
+  selectProjects: Array<string>;
+  setupFiles: Array<string>;
+  setupFilesAfterEnv: Array<string>;
+  showConfig: boolean;
+  silent: boolean;
+  snapshotSerializers: Array<string>;
+  testEnvironment: string;
+  testFailureExitCode: string | null | undefined;
+  testMatch: Array<string>;
+  testNamePattern: string;
+  testPathIgnorePatterns: Array<string>;
+  testPathPattern: Array<string>;
+  testRegex: string | Array<string>;
+  testResultsProcessor: string;
+  testRunner: string;
+  testSequencer: string;
+  testURL: string;
+  testTimeout: number | null | undefined;
+  timers: string;
+  transform: string;
+  transformIgnorePatterns: Array<string>;
+  unmockedModulePathPatterns: Array<string> | null | undefined;
+  updateSnapshot: boolean;
+  useStderr: boolean;
+  verbose: boolean;
+  version: boolean;
+  watch: boolean;
+  watchAll: boolean;
+  watchman: boolean;
+  watchPathIgnorePatterns: Array<string>;
+}>>;
+
+

Development

+
$ npm i
+$ npm run build
+
+

Contributors

+

As always, thanks to our amazing contributors!

+

Made with github-action-contributors.

+

License

+

MIT © Kenny Wong

+
+ +
+ + + + + diff --git a/js/copy.js b/js/copy.js new file mode 100644 index 000000000..a3fe52dff --- /dev/null +++ b/js/copy.js @@ -0,0 +1,40 @@ +/** + * https://github.com/uiwjs/copy-to-clipboard/blob/master/src/main.js + */ +function copyTextToClipboard(text, cb) { + const el = document.createElement('textarea'); + el.value = text; + el.setAttribute('readonly', ''); + el.style = { + position: 'absolute', + left: '-9999px', + } + document.body.appendChild(el); + const selected = document.getSelection().rangeCount > 0 ? document.getSelection().getRangeAt(0) : false; + el.select(); + let isCopy = false; + try { + const successful = document.execCommand('copy'); + isCopy = !!successful; + } catch (err) { + isCopy = false; + } + document.body.removeChild(el); + if (selected && document.getSelection) { + document.getSelection().removeAllRanges(); + document.getSelection().addRange(selected); + } + cb && cb(isCopy); +}; + +function copied(target, str) { + target.classList.add('active'); + const input = target.parentElement.querySelector('input'); + if (input) { + copyTextToClipboard(input.value || '', function() { + setTimeout(() => { + target.classList.remove('active'); + }, 2000); + }); + } +} \ No newline at end of file diff --git a/js/dark-mode.js b/js/dark-mode.js new file mode 100644 index 000000000..50a01653e --- /dev/null +++ b/js/dark-mode.js @@ -0,0 +1,162 @@ +/** + * @package @wcj/dark-mode@1.0.14 + * Web Component that toggles dark mode 🌒 + * Github: https://github.com/jaywcjlove/dark-mode.git + * Website: https://jaywcjlove.github.io/dark-mode + * + * Licensed under the MIT license. + * @license Copyright © 2022. Licensed under the MIT License + * @author kenny wong + */ +const t = document; +const e = '_dark_mode_theme_'; +const s = 'permanent'; +const o = 'colorschemechange'; +const i = 'permanentcolorscheme'; +const h = 'light'; +const r = 'dark'; +const n = (t, e, s = e) => { + Object.defineProperty(t, s, { + enumerable: true, + get() { + const t = this.getAttribute(e); + return t === null ? '' : t; + }, + set(t) { + this.setAttribute(e, t); + }, + }); +}; +const c = (t, e, s = e) => { + Object.defineProperty(t, s, { + enumerable: true, + get() { + return this.hasAttribute(e); + }, + set(t) { + if (t) { + this.setAttribute(e, ''); + } else { + this.removeAttribute(e); + } + }, + }); +}; +class a extends HTMLElement { + static get observedAttributes() { + return ['mode', h, r, s]; + } + LOCAL_NANE = e; + constructor() { + super(); + this.t(); + } + connectedCallback() { + n(this, 'mode'); + n(this, r); + n(this, h); + c(this, s); + const a = localStorage.getItem(e); + if (a && [h, r].includes(a)) { + this.mode = a; + this.permanent = true; + } + if (this.permanent && !a) { + localStorage.setItem(e, this.mode); + } + const l = [h, r].includes(a); + if (this.permanent && a) { + this.o(); + } else { + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + this.mode = r; + this.o(); + } + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: light)').matches) { + this.mode = h; + this.o(); + } + } + if (!this.permanent && !l) { + window.matchMedia('(prefers-color-scheme: light)').onchange = (t) => { + this.mode = t.matches ? h : r; + this.o(); + }; + window.matchMedia('(prefers-color-scheme: dark)').onchange = (t) => { + this.mode = t.matches ? r : h; + this.o(); + }; + } + const d = new MutationObserver((s, h) => { + this.mode = t.documentElement.dataset.colorMode; + if (this.permanent && l) { + localStorage.setItem(e, this.mode); + this.i(i, { permanent: this.permanent }); + } + this.h(); + this.i(o, { colorScheme: this.mode }); + }); + d.observe(t.documentElement, { attributes: true }); + this.i(o, { colorScheme: this.mode }); + this.h(); + } + attributeChangedCallback(t, s, o) { + if (t === 'mode' && s !== o && [h, r].includes(o)) { + const t = localStorage.getItem(e); + if (this.mode === t) { + this.mode = o; + this.h(); + this.o(); + } else if (this.mode && this.mode !== t) { + this.h(); + this.o(); + } + } else if ((t === h || t === r) && s !== o) { + this.h(); + } + if (t === 'permanent' && typeof this.permanent === 'boolean') { + this.permanent ? localStorage.setItem(e, this.mode) : localStorage.removeItem(e); + } + } + o() { + t.documentElement.setAttribute('data-color-mode', this.mode); + } + h() { + this.icon.textContent = this.mode === h ? '🌒' : '🌞'; + this.text.textContent = this.mode === h ? this.getAttribute(r) : this.getAttribute(h); + } + t() { + var s = this.attachShadow({ mode: 'open' }); + this.label = t.createElement('span'); + this.label.setAttribute('class', 'wrapper'); + this.label.onclick = () => { + this.mode = this.mode === h ? r : h; + if (this.permanent) { + localStorage.setItem(e, this.mode); + } + this.o(); + this.h(); + }; + s.appendChild(this.label); + this.icon = t.createElement('span'); + this.label.appendChild(this.icon); + this.text = t.createElement('span'); + this.label.appendChild(this.text); + const o = `\n[data-color-mode*='dark'], [data-color-mode*='dark'] body {\n color-scheme: dark;\n --color-theme-bg: #0d1117;\n --color-theme-text: #c9d1d9;\n background-color: var(--color-theme-bg);\n color: var(--color-theme-text);\n}\n\n[data-color-mode*='light'], [data-color-mode*='light'] body {\n color-scheme: light;\n --color-theme-bg: #fff;\n --color-theme-text: #24292f;\n background-color: var(--color-theme-bg);\n color: var(--color-theme-text);\n}`; + const i = '_dark_mode_style_'; + const n = t.getElementById(i); + if (!n) { + var c = t.createElement('style'); + c.id = i; + c.textContent = o; + t.head.appendChild(c); + } + var a = t.createElement('style'); + a.textContent = `\n .wrapper { cursor: pointer; user-select: none; position: relative; }\n .wrapper > span + span { margin-left: .4rem; }\n `; + s.appendChild(a); + } + i(t, e) { + this.dispatchEvent(new CustomEvent(t, { bubbles: true, composed: true, detail: e })); + } +} +customElements.define('dark-mode', a); diff --git a/js/demo-preview.js b/js/demo-preview.js new file mode 100644 index 000000000..c96cf9fce --- /dev/null +++ b/js/demo-preview.js @@ -0,0 +1,31 @@ +const demo = document.querySelectorAll('.idoc-demo-warpper .idoc-demo-previw'); + +function getButton(elm, type = 'BUTTON') { + let btn; + do { + elm = elm.nextElementSibling + if (elm.tagName === type) { + btn = elm; + elm = undefined; + break; + } + } while (elm); + return btn; +} +if (demo && demo.length > 0) { + demo.forEach((item) => { + if (item.previousElementSibling && item.previousElementSibling.tagName === 'INPUT') { + const button = getButton(item); + if (button) { + button.innerHTML = item.classList.contains('ishiden') ? 'Preview' : 'Show Code'; + if (item.tagName === 'DIV') { + item.innerHTML = item.previousElementSibling.defaultValue + } + button.onclick = () => { + item.classList.toggle('ishiden'); + button.innerHTML = item.classList.contains('ishiden') ? 'Preview' : 'Show Code'; + } + } + } + }); +} \ No newline at end of file diff --git a/js/markdown-style.js b/js/markdown-style.js new file mode 100644 index 000000000..5d54bf231 --- /dev/null +++ b/js/markdown-style.js @@ -0,0 +1,1006 @@ +const octiconLinkStyle = ` +markdown-style h1:hover a.anchor .icon-link:before, +markdown-style h2:hover a.anchor .icon-link:before, +markdown-style h3:hover a.anchor .icon-link:before, +markdown-style h4:hover a.anchor .icon-link:before, +markdown-style h5:hover a.anchor .icon-link:before, +markdown-style h6:hover a.anchor .icon-link:before { + width: 16px; + height: 16px; + content: ' '; + display: inline-block; + background-color: currentColor; + -webkit-mask-image: url("data:image/svg+xml,"); + mask-image: url("data:image/svg+xml,"); +}`; + +const __TEMPLATE__ = document.createElement('template'); +__TEMPLATE__.innerHTML = ` + + +`; +class MarkdownStyle extends HTMLElement { + constructor() { + super(); + this.shadow = this.attachShadow({ mode: 'open' }); + this.shadow.appendChild(__TEMPLATE__.content.cloneNode(true)); + const style = Array.prototype.slice + .call(this.shadow.children) + .find((item) => item.tagName === 'STYLE'); + if (style) { + const id = '__MARKDOWN_STYLE__'; + const findStyle = document.getElementById(id); + if (!findStyle) { + style.id = id; + document.head.append(style); + } + } + } + get theme() { + const value = this.getAttribute('theme'); + return value === null ? '' : value; + } + set theme(name) { + this.setAttribute('theme', name); + } + connectedCallback() { + if (!this.theme) { + const { colorMode } = document.documentElement.dataset; + this.theme = colorMode; + const observer = new MutationObserver((mutationsList, observer) => { + this.theme = document.documentElement.dataset.colorMode; + }); + observer.observe(document.documentElement, { attributes: true }); + window.matchMedia('(prefers-color-scheme: light)').onchange = (event) => { + this.theme = event.matches ? 'light' : 'dark'; + }; + window.matchMedia('(prefers-color-scheme: dark)').onchange = (event) => { + this.theme = event.matches ? 'dark' : 'light'; + }; + } + } +} +customElements.define('markdown-style', MarkdownStyle); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/js/tocbot.js b/js/tocbot.js new file mode 100644 index 000000000..b6cebb1ec --- /dev/null +++ b/js/tocbot.js @@ -0,0 +1,128 @@ +;(() => { + function debounce(fn, delay = 1000) { + let time = null + function _debounce(...args) { + if (time !== null) clearTimeout(time); + time = setTimeout(() => fn.apply(this, args), delay) + } + return _debounce + } + + const scrollSmoothOffset = 56; + function updateScroll() { + const heading = document.getElementById(decodeURIComponent(location.hash.replace(/^#/, ''))); + if (heading) { + document.scrollingElement.scrollTop = heading.offsetTop - scrollSmoothOffset + 3; + } + } + + function preventClickHandle(selector) { + const mdContainer = document.querySelectorAll(selector); + if (mdContainer && mdContainer.length > 0) { + mdContainer.forEach((anchor) => { + anchor.addEventListener('click', (e) => { + e.preventDefault(); + location.hash = anchor.getAttribute('href'); + updateScroll(); + updateAnchor(); + tocsCollapse() + }); + }); + } + } + function tocButton() { + const tocElement = document.querySelector(`a.gototop`); + if (document.body.scrollTop > 50 || document.documentElement.scrollTop > 50) { + tocElement.style.opacity = 0.5; + } else { + tocElement.style.opacity = 0; + } + } + function scrollListener(evn) { + const anchors = document.querySelectorAll('markdown-style a.anchor[href*="#"][aria-hidden]'); + const scrollTop = evn && evn.target && evn.target.scrollingElement && evn.target.scrollingElement.scrollTop; + let element; + let index = 0; + anchors.forEach((anchor, idx) => { + if (anchor.offsetTop - scrollSmoothOffset < scrollTop || (idx === 0 && anchor.offsetTop > scrollTop)) { + element = anchor; + index = idx; + } + }); + tocButton(); + if (element) { + const tocElement = document.querySelector(`a.tocs-link[href='${decodeURIComponent(element.hash)}']`); + if (tocElement) { + updateAnchor(tocElement) + tocsCollapse(tocElement); + } else { + const first = document.querySelector('a.tocs-link[href*="#"]'); + if (index === 0 && first) { + updateAnchor(first); + tocsCollapse(first); + } + } + } + } + + document.addEventListener('scroll',debounce(scrollListener, 30), false); + + function updateAnchor(element) { + const anchorContainer = document.querySelectorAll('.tocs aside.inner.toc a.tocs-link'); + anchorContainer.forEach((tocanchor) => { + tocanchor.classList.remove('is-active-link'); + }); + const anchor = element || document.querySelector(`a.tocs-link[href='${decodeURIComponent(location.hash)}']`); + if (anchor) { + anchor.classList.add('is-active-link'); + } + } + + function tocsCollapse(element) { + const tocContainer = document.querySelector('nav.tocs > aside.inner.toc'); + if (element) { + tocContainer.scrollTop = element.offsetTop; + } + + const list = document.querySelectorAll('aside.toc ol.tocs-list'); + list.forEach((item) => { + item.classList.remove('is-open'); + }); + if (element && element.nextElementSibling) { + element.nextElementSibling.classList.add('is-open'); + } + isOpen(element); + } + + function isOpen(element) { + if (!element) { + element = document.querySelector(`a.tocs-link[href='${decodeURIComponent(location.hash)}']`); + } + if (element && element.parentElement && element.parentElement.tagName !== 'ASIDE' && !element.parentElement.classList.contains('toc')) { + isOpen(element.parentElement); + if (element.parentElement.classList.contains('is-collapsed')) { + element.parentElement.classList.add('is-open'); + } + } + } + + preventClickHandle('markdown-style a.anchor[href*="#"][aria-hidden]'); + preventClickHandle('.tocs aside.inner.toc a.tocs-link'); + + function updateSiderBarScroll() { + const siderBar = document.querySelector(".sidebar[role*='navigation']"); + const siderAnchor = document.querySelector(".sidebar[role*='navigation'] a[class*='active']"); + if (siderAnchor) { + siderBar.scrollTop = siderAnchor.offsetTop; + } + } + + const timer = setTimeout(() => { + updateSiderBarScroll(); + updateScroll(); + updateAnchor(); + tocsCollapse() + clearTimeout(timer); + }, 100); + +})(); \ No newline at end of file diff --git a/sitemap.txt b/sitemap.txt new file mode 100644 index 000000000..b8250e36c --- /dev/null +++ b/sitemap.txt @@ -0,0 +1 @@ +https://jaywcjlove.github.io/tsbb/index.html \ No newline at end of file