From 542d4351f715571e82e2888dfeb48ab63734bfdf Mon Sep 17 00:00:00 2001 From: yosuke ota Date: Fri, 3 Dec 2021 09:57:11 +0900 Subject: [PATCH 01/10] Replace website with sveltekit --- .eslintignore | 5 + .eslintrc.js | 6 + .github/workflows/GHPages.yml | 2 +- .gitignore | 5 + .vscode/settings.json | 3 +- docs-svelte-kit/.eslintrc.cjs | 7 + docs-svelte-kit/build-system/build.js | 74 +++++ docs-svelte-kit/build-system/src/eslint.mjs | 6 + docs-svelte-kit/shim/module.mjs | 7 + docs-svelte-kit/shim/os.mjs | 7 + docs-svelte-kit/shim/path.mjs | 10 + docs-svelte-kit/shim/url.mjs | 7 + docs-svelte-kit/src/.eslintrc.js | 9 + docs-svelte-kit/src/app.css | 107 +++++++ docs-svelte-kit/src/app.html | 13 + docs-svelte-kit/src/hooks.js | 4 + .../src/lib/components/ESLintCodeBlock.svelte | 76 +++++ .../lib/components/ESLintPlayground.svelte | 208 +++++++++++++ .../src/lib/eslint/ESLintEditor.svelte | 255 ++++++++++++++++ .../src/lib/eslint/MonacoEditor.svelte | 280 ++++++++++++++++++ .../src/lib/eslint/RulesSettings.svelte | 192 ++++++++++++ .../src/lib/eslint/scripts/json.js | 81 +++++ .../src/lib/eslint/scripts/linter.js | 100 +++++++ .../src/lib/eslint/scripts/monaco-loader.js | 61 ++++ .../lib/eslint/scripts/state/deserialize.js | 48 +++ .../src/lib/eslint/scripts/state/index.js | 2 + .../src/lib/eslint/scripts/state/serialize.js | 45 +++ docs-svelte-kit/src/lib/footer/Footer.svelte | 152 ++++++++++ docs-svelte-kit/src/lib/header/Header.svelte | 157 ++++++++++ docs-svelte-kit/src/lib/header/logo.svg | 28 ++ .../src/lib/header/svelte-logo.svg | 1 + .../src/lib/markdown/Markdown.svelte | 42 +++ .../src/lib/sidemenu/SideMenu.svelte | 32 ++ .../src/lib/sidemenu/UlMenu.svelte | 87 ++++++ docs-svelte-kit/src/lib/utils.js | 103 +++++++ docs-svelte-kit/src/site.css | 90 ++++++ docs-svelte-kit/static/favicon.png | Bin 0 -> 1571 bytes docs-svelte-kit/tools/highlight.mjs | 53 ++++ .../markdown-it-auto-inject-components.mjs | 54 ++++ .../tools/markdown-it-container-option.mjs | 37 +++ .../tools/markdown-it-markdown.mjs | 110 +++++++ .../tools/markdown-it-replace-link.mjs | 47 +++ docs-svelte-kit/tools/markdown-it-title.mjs | 35 +++ .../tools/vite-plugin-svelte-md-option.mjs | 37 +++ docs/.eslintrc.js | 1 + ...int-code-block.vue => ESLintCodeBlock.vue} | 0 ...yground-block.vue => ESLintPlayground.vue} | 2 +- docs/README.md | 6 +- docs/__layout.svelte | 9 + docs/index.svelte | 5 + docs/playground/README.md | 5 +- docs/prettier.config.js | 7 - docs/rules/button-has-type.md | 4 +- docs/rules/comment-directive.md | 8 +- docs/rules/first-attribute-linebreak.md | 4 +- docs/rules/html-quotes.md | 4 +- docs/rules/indent.md | 4 +- docs/rules/max-attributes-per-line.md | 4 +- docs/rules/mustache-spacing.md | 4 +- docs/rules/no-at-debug-tags.md | 4 +- docs/rules/no-at-html-tags.md | 4 +- docs/rules/no-dupe-else-if-blocks.md | 8 +- docs/rules/no-dynamic-slot-name.md | 4 +- docs/rules/no-inner-declarations.md | 4 +- docs/rules/no-not-function-handler.md | 4 +- docs/rules/no-object-in-text-mustaches.md | 4 +- docs/rules/no-target-blank.md | 20 +- docs/rules/no-useless-mustaches.md | 12 +- docs/rules/prefer-class-directive.md | 4 +- docs/rules/shorthand-attribute.md | 4 +- docs/rules/spaced-html-comment.md | 4 +- docs/rules/valid-compile.md | 8 +- package.json | 26 +- src/rules/indent-helpers/offset-context.ts | 2 +- src/rules/valid-compile.ts | 9 +- src/utils/eslint-core.ts | 4 +- svelte-kit-import-hook.mjs | 99 +++++++ svelte.config.esm.mjs | 60 ++++ svelte.config.js | 28 ++ tools/new-rule.ts | 4 +- tools/update-docs.ts | 10 +- tools/update-readme.ts | 62 ++-- 82 files changed, 3025 insertions(+), 115 deletions(-) create mode 100644 docs-svelte-kit/.eslintrc.cjs create mode 100644 docs-svelte-kit/build-system/build.js create mode 100644 docs-svelte-kit/build-system/src/eslint.mjs create mode 100644 docs-svelte-kit/shim/module.mjs create mode 100644 docs-svelte-kit/shim/os.mjs create mode 100644 docs-svelte-kit/shim/path.mjs create mode 100644 docs-svelte-kit/shim/url.mjs create mode 100644 docs-svelte-kit/src/.eslintrc.js create mode 100644 docs-svelte-kit/src/app.css create mode 100644 docs-svelte-kit/src/app.html create mode 100644 docs-svelte-kit/src/hooks.js create mode 100644 docs-svelte-kit/src/lib/components/ESLintCodeBlock.svelte create mode 100644 docs-svelte-kit/src/lib/components/ESLintPlayground.svelte create mode 100644 docs-svelte-kit/src/lib/eslint/ESLintEditor.svelte create mode 100644 docs-svelte-kit/src/lib/eslint/MonacoEditor.svelte create mode 100644 docs-svelte-kit/src/lib/eslint/RulesSettings.svelte create mode 100644 docs-svelte-kit/src/lib/eslint/scripts/json.js create mode 100644 docs-svelte-kit/src/lib/eslint/scripts/linter.js create mode 100644 docs-svelte-kit/src/lib/eslint/scripts/monaco-loader.js create mode 100644 docs-svelte-kit/src/lib/eslint/scripts/state/deserialize.js create mode 100644 docs-svelte-kit/src/lib/eslint/scripts/state/index.js create mode 100644 docs-svelte-kit/src/lib/eslint/scripts/state/serialize.js create mode 100644 docs-svelte-kit/src/lib/footer/Footer.svelte create mode 100644 docs-svelte-kit/src/lib/header/Header.svelte create mode 100644 docs-svelte-kit/src/lib/header/logo.svg create mode 100644 docs-svelte-kit/src/lib/header/svelte-logo.svg create mode 100644 docs-svelte-kit/src/lib/markdown/Markdown.svelte create mode 100644 docs-svelte-kit/src/lib/sidemenu/SideMenu.svelte create mode 100644 docs-svelte-kit/src/lib/sidemenu/UlMenu.svelte create mode 100644 docs-svelte-kit/src/lib/utils.js create mode 100644 docs-svelte-kit/src/site.css create mode 100644 docs-svelte-kit/static/favicon.png create mode 100644 docs-svelte-kit/tools/highlight.mjs create mode 100644 docs-svelte-kit/tools/markdown-it-auto-inject-components.mjs create mode 100644 docs-svelte-kit/tools/markdown-it-container-option.mjs create mode 100644 docs-svelte-kit/tools/markdown-it-markdown.mjs create mode 100644 docs-svelte-kit/tools/markdown-it-replace-link.mjs create mode 100644 docs-svelte-kit/tools/markdown-it-title.mjs create mode 100644 docs-svelte-kit/tools/vite-plugin-svelte-md-option.mjs rename docs/.vuepress/components/{eslint-code-block.vue => ESLintCodeBlock.vue} (100%) rename docs/.vuepress/components/{playground-block.vue => ESLintPlayground.vue} (99%) create mode 100644 docs/__layout.svelte create mode 100644 docs/index.svelte delete mode 100644 docs/prettier.config.js create mode 100644 svelte-kit-import-hook.mjs create mode 100644 svelte.config.esm.mjs create mode 100644 svelte.config.js diff --git a/.eslintignore b/.eslintignore index 94c64cfa6..797ba184c 100644 --- a/.eslintignore +++ b/.eslintignore @@ -11,3 +11,8 @@ /tests/fixtures/rules/indent/invalid/ts-v5 /tests/fixtures/rules/valid-compile/invalid/ts /tests/fixtures/rules/valid-compile/valid/ts +/.svelte-kit +/svelte.config-dist.js +/build +/docs-svelte-kit/shim/eslint.mjs +/docs-svelte-kit/shim/assert.mjs diff --git a/.eslintrc.js b/.eslintrc.js index cdae6b49c..46cdc5e93 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -35,6 +35,12 @@ module.exports = { ], }, overrides: [ + { + files: ["*.mjs"], + parserOptions: { + sourceType: "module", + }, + }, { files: ["*.svelte"], parser: "svelte-eslint-parser", diff --git a/.github/workflows/GHPages.yml b/.github/workflows/GHPages.yml index e781a4383..3ab2aaafe 100644 --- a/.github/workflows/GHPages.yml +++ b/.github/workflows/GHPages.yml @@ -19,5 +19,5 @@ jobs: uses: peaceiris/actions-gh-pages@v3 with: github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: ./docs/.vuepress/dist + publish_dir: ./build force_orphan: true diff --git a/.gitignore b/.gitignore index a4aefc168..ea2cde7d8 100644 --- a/.gitignore +++ b/.gitignore @@ -105,3 +105,8 @@ dist ## repo /lib +/.svelte-kit +/build +/svelte.config-dist.js +/docs-svelte-kit/shim/eslint.mjs +/docs-svelte-kit/shim/assert.mjs diff --git a/.vscode/settings.json b/.vscode/settings.json index bd2658d84..90a7e03b7 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -16,5 +16,6 @@ "editor.codeActionsOnSave": { "source.fixAll": true, "source.fixAll.stylelint": true - } + }, + "svelte.plugin.typescript.diagnostics.enable": false } diff --git a/docs-svelte-kit/.eslintrc.cjs b/docs-svelte-kit/.eslintrc.cjs new file mode 100644 index 000000000..a19bb9f26 --- /dev/null +++ b/docs-svelte-kit/.eslintrc.cjs @@ -0,0 +1,7 @@ +// eslint-disable-next-line no-undef -- ignore +module.exports = { + extends: ["plugin:@ota-meshi/svelte/recommended"], + parserOptions: { + sourceType: "module", + }, +} diff --git a/docs-svelte-kit/build-system/build.js b/docs-svelte-kit/build-system/build.js new file mode 100644 index 000000000..9cba5f0ea --- /dev/null +++ b/docs-svelte-kit/build-system/build.js @@ -0,0 +1,74 @@ +const esbuild = require("esbuild") +const path = require("path") +const fs = require("fs") +// const babelCore = require("@babel/core") +// const t = require("@babel/types") + +build( + require.resolve("./src/eslint.mjs"), + path.join(__dirname, "../shim/eslint.mjs"), + ["assert"], +) +build( + require.resolve("../../node_modules/assert"), + path.join(__dirname, "../shim/assert.mjs"), +) + +/** build */ +function build(input, out, injects = []) { + console.log(`build@ ${input}`) + let code = bundle(input, injects) + code = transform(code, injects) + fs.writeFileSync(out, code, "utf8") +} + +/** bundle */ +function bundle(entryPoint, externals) { + const result = esbuild.buildSync({ + entryPoints: [entryPoint], + format: "esm", + bundle: true, + external: ["path", ...externals], + write: false, + }) + + return `${result.outputFiles[0].text}` +} + +/** transform code */ +function transform(code, injects) { + // const newCode = babelCore.transformSync(code, { + // babelrc: false, + // plugins: [ + // { + // visitor: { + // CallExpression(path) { + // const callee = path.get("callee") + // if ( + // callee.type === "Identifier" && + // callee.node.name === "__require" + // ) { + // callee.replaceWith(t.identifier("__$$$require")) + // } + // }, + // }, + // }, + // ], + // }) + return ` +${injects + .map((inject) => `import $inject_${inject}$ from '${inject}';`) + .join("\n")} +const $_injects_$ = {${injects + .map((inject) => `${inject}:$inject_${inject}$`) + .join(",\n")}}; +const process = { + env: {}, + cwd: () => undefined, +} +function require(module, ...args) { + return $_injects_$[module] || {} +} +${code} +` +} diff --git a/docs-svelte-kit/build-system/src/eslint.mjs b/docs-svelte-kit/build-system/src/eslint.mjs new file mode 100644 index 000000000..636e4ebae --- /dev/null +++ b/docs-svelte-kit/build-system/src/eslint.mjs @@ -0,0 +1,6 @@ +/* eslint require-jsdoc:0 -- shim */ + +import * as all from "../../../node_modules/eslint/lib/linter/linter.js" +const Linter = all.Linter +export { Linter } +export default { Linter } diff --git a/docs-svelte-kit/shim/module.mjs b/docs-svelte-kit/shim/module.mjs new file mode 100644 index 000000000..6f5e094c7 --- /dev/null +++ b/docs-svelte-kit/shim/module.mjs @@ -0,0 +1,7 @@ +/* eslint require-jsdoc:0 -- shim */ +function createRequire() { + return () => null +} + +export { createRequire } +export default { createRequire } diff --git a/docs-svelte-kit/shim/os.mjs b/docs-svelte-kit/shim/os.mjs new file mode 100644 index 000000000..9dcde3629 --- /dev/null +++ b/docs-svelte-kit/shim/os.mjs @@ -0,0 +1,7 @@ +/* eslint require-jsdoc:0 -- shim */ +function platform() { + return "" +} + +export { platform } +export default { platform } diff --git a/docs-svelte-kit/shim/path.mjs b/docs-svelte-kit/shim/path.mjs new file mode 100644 index 000000000..6f5f54949 --- /dev/null +++ b/docs-svelte-kit/shim/path.mjs @@ -0,0 +1,10 @@ +/* eslint require-jsdoc:0 -- shim */ + +function dirname(p) { + return p.split("/").slice(0, -1).join("/") || p +} + +const posix = { dirname } +posix.posix = posix +export { dirname, posix } +export default posix diff --git a/docs-svelte-kit/shim/url.mjs b/docs-svelte-kit/shim/url.mjs new file mode 100644 index 000000000..2085270e2 --- /dev/null +++ b/docs-svelte-kit/shim/url.mjs @@ -0,0 +1,7 @@ +/* eslint require-jsdoc:0 -- shim */ +function fileURLToPath(p) { + return p +} + +export { fileURLToPath } +export default { fileURLToPath } diff --git a/docs-svelte-kit/src/.eslintrc.js b/docs-svelte-kit/src/.eslintrc.js new file mode 100644 index 000000000..457395cc5 --- /dev/null +++ b/docs-svelte-kit/src/.eslintrc.js @@ -0,0 +1,9 @@ +module.exports = { + parserOptions: { + sourceType: "module", + }, + rules: { + "node/no-unsupported-features/es-syntax": "off", + "require-jsdoc": "off", + }, +} diff --git a/docs-svelte-kit/src/app.css b/docs-svelte-kit/src/app.css new file mode 100644 index 000000000..20debf773 --- /dev/null +++ b/docs-svelte-kit/src/app.css @@ -0,0 +1,107 @@ +@import "@fontsource/fira-mono"; + +:root { + font-family: Arial, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, + Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; + --font-mono: "Fira Mono", monospace; + --pure-white: #ffffff; + --primary-color: #b9c6d2; + --secondary-color: #d0dde9; + --tertiary-color: #edf0f8; + --accent-color: #ff3e00; + --heading-color: rgba(0, 0, 0, 0.7); + --text-color: #444444; + --background-without-opacity: rgba(255, 255, 255, 0.7); + --column-width: 42rem; + --column-margin-top: 4rem; +} + +body { + min-height: 100vh; + margin: 0; + background-color: var(--primary-color); + background: linear-gradient( + 180deg, + var(--primary-color) 0%, + var(--secondary-color) 10.45%, + var(--tertiary-color) 41.35% + ); +} + +body::before { + content: ""; + width: 80vw; + height: 100vh; + position: absolute; + top: 0; + left: 10vw; + z-index: -1; + background: radial-gradient( + 50% 50% at 50% 50%, + var(--pure-white) 0%, + rgba(255, 255, 255, 0) 100% + ); + opacity: 0.05; +} + +#svelte { + min-height: 100vh; + display: flex; + flex-direction: column; +} + +h1, +h2, +p { + font-weight: 400; + color: var(--heading-color); +} + +p { + line-height: 1.5; +} + +a { + color: var(--accent-color); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +h1 { + font-size: 2rem; + text-align: center; +} + +h2 { + font-size: 1rem; +} + +pre { + font-size: 16px; + font-family: var(--font-mono); + background-color: rgba(255, 255, 255, 0.45); + border-radius: 3px; + box-shadow: 2px 2px 6px rgb(255 255 255 / 25%); + padding: 0.5em; + overflow-x: auto; + color: var(--text-color); +} + +input, +button { + font-size: inherit; + font-family: inherit; +} + +button:focus:not(:focus-visible) { + outline: none; +} + +@media (min-width: 720px) { + h1 { + font-size: 2.4rem; + } +} diff --git a/docs-svelte-kit/src/app.html b/docs-svelte-kit/src/app.html new file mode 100644 index 000000000..4be94d08f --- /dev/null +++ b/docs-svelte-kit/src/app.html @@ -0,0 +1,13 @@ + + + + + + + + %svelte.head% + + +
%svelte.body%
+ + diff --git a/docs-svelte-kit/src/hooks.js b/docs-svelte-kit/src/hooks.js new file mode 100644 index 000000000..eff633b99 --- /dev/null +++ b/docs-svelte-kit/src/hooks.js @@ -0,0 +1,4 @@ +export async function handle({ request, resolve }) { + const response = await resolve(request) + return response +} diff --git a/docs-svelte-kit/src/lib/components/ESLintCodeBlock.svelte b/docs-svelte-kit/src/lib/components/ESLintCodeBlock.svelte new file mode 100644 index 000000000..3f6553a62 --- /dev/null +++ b/docs-svelte-kit/src/lib/components/ESLintCodeBlock.svelte @@ -0,0 +1,76 @@ + + +
+ +
+ +
+ +
+ {#if fix} + + {/if} + {time} +
+
+ + diff --git a/docs-svelte-kit/src/lib/components/ESLintPlayground.svelte b/docs-svelte-kit/src/lib/components/ESLintPlayground.svelte new file mode 100644 index 000000000..241e2b941 --- /dev/null +++ b/docs-svelte-kit/src/lib/components/ESLintPlayground.svelte @@ -0,0 +1,208 @@ + + +
+
+ {time} +
+
+ +
+ +
+
    + {#each messages as msg, i (`${msg.line}:${msg.column}:${msg.ruleId}@${i}`)} +
  1. + [{msg.line}:{msg.column}]: + {msg.message} ( + {msg.ruleId} + ) +
  2. + {/each} +
+
+
+
+
+ + diff --git a/docs-svelte-kit/src/lib/eslint/ESLintEditor.svelte b/docs-svelte-kit/src/lib/eslint/ESLintEditor.svelte new file mode 100644 index 000000000..71ffa8bda --- /dev/null +++ b/docs-svelte-kit/src/lib/eslint/ESLintEditor.svelte @@ -0,0 +1,255 @@ + + +
+ +
+ {#if showApplyFix} + + {/if} +
+
+ + diff --git a/docs-svelte-kit/src/lib/eslint/MonacoEditor.svelte b/docs-svelte-kit/src/lib/eslint/MonacoEditor.svelte new file mode 100644 index 000000000..adc2a606b --- /dev/null +++ b/docs-svelte-kit/src/lib/eslint/MonacoEditor.svelte @@ -0,0 +1,280 @@ + + + + +{#await loading} + {#if started} +
+ {/if} +{:then} +
+{/await} + + diff --git a/docs-svelte-kit/src/lib/eslint/RulesSettings.svelte b/docs-svelte-kit/src/lib/eslint/RulesSettings.svelte new file mode 100644 index 000000000..7a47ae5f4 --- /dev/null +++ b/docs-svelte-kit/src/lib/eslint/RulesSettings.svelte @@ -0,0 +1,192 @@ + + +
+
    + {#each categories as category (category.title)} + {#if category.rules.length} +
  • + +
    + +
    + + {#if !categoryState[category.title].close} +
      + {#each category.rules as rule (rule.ruleId)} +
    • + + +
    • + {/each} +
    + {/if} +
  • + {/if} + {/each} +
+
+ + diff --git a/docs-svelte-kit/src/lib/eslint/scripts/json.js b/docs-svelte-kit/src/lib/eslint/scripts/json.js new file mode 100644 index 000000000..60c58881d --- /dev/null +++ b/docs-svelte-kit/src/lib/eslint/scripts/json.js @@ -0,0 +1,81 @@ +export function processJsonValue(options, ctx, value) { + const type = typeof value + if ( + type === "string" || + type === "number" || + type === "boolean" || + value === null + ) { + ctx.appendText(JSON.stringify(value)) + return + } else if (type !== "object") { + ctx.appendText('"?"') + return + } + if (Array.isArray(value)) { + ctx.appendText("[\n").indent() + const arr = [...value] + while (arr.length) { + ctx.appendIndent() + const e = arr.shift() + processJsonValue(options, ctx, e) + if (arr.length) { + ctx.appendText(",") + } + ctx.appendText("\n") + } + ctx.outdent().appendIndent().appendText("]") + } else { + let entries = Object.entries(value) + const valueIsNode = isNode(value) + if (valueIsNode) { + ctx.pushNode(value) + const typeEntry = entries.find(([key]) => key === "type") + const locEntries = options.showLocations + ? entries.filter(([key]) => key === "loc" || key === "range") + : [] + entries = entries.filter( + ([key]) => + key !== "type" && + key !== "loc" && + key !== "range" && + key !== "parent" && + !( + (key === "start" || key === "end") && + typeof value.start === "number" + ), + ) + if (typeEntry) entries.unshift(typeEntry) + entries.push(...locEntries) + } + ctx.appendText("{\n").indent() + while (entries.length) { + const [key, val] = entries.shift() + ctx.appendIndent() + processJsonValue(options, ctx, key) + ctx.appendText(": ") + processJsonValue(options, ctx, val) + if (entries.length) { + ctx.appendText(",") + } + ctx.appendText("\n") + } + ctx.outdent().appendIndent().appendText("}") + + if (valueIsNode) { + ctx.popNode() + } + } +} + +/** + * Check if given value is node + */ +function isNode(value) { + return ( + value != null && + Array.isArray(value.range) && + "loc" in value && + "type" in value + ) +} diff --git a/docs-svelte-kit/src/lib/eslint/scripts/linter.js b/docs-svelte-kit/src/lib/eslint/scripts/linter.js new file mode 100644 index 000000000..7210d2a85 --- /dev/null +++ b/docs-svelte-kit/src/lib/eslint/scripts/linter.js @@ -0,0 +1,100 @@ +// eslint-disable-next-line node/file-extension-in-import -- ignore +import { rules as pluginRules } from "../../../../../src/utils/rules.ts" +import { Linter } from "eslint" +import * as svelteEslintParser from "svelte-eslint-parser" + +const linter = new Linter() + +export const categories = [ + { + title: "Possible Errors", + rules: [], + }, + { + title: "Security Vulnerability", + rules: [], + }, + { + title: "Best Practices", + rules: [], + }, + { + title: "Stylistic Issues", + rules: [], + }, + { + title: "Extension Rules", + rules: [], + }, + { + title: "System", + rules: [], + }, + { + type: "problem", + title: "Possible Errors (CORE)", + rules: [], + }, + { + type: "suggestion", + title: "Suggestions (CORE)", + rules: [], + }, + { + type: "layout", + title: "Layout & Formatting (CORE)", + rules: [], + }, +] +export const DEFAULT_RULES_CONFIG = {} + +const rules = [] +for (const rule of pluginRules) { + if (rule.meta.deprecated) { + continue + } + const data = { + ruleId: rule.meta.docs.ruleId, + rule, + url: rule.meta.docs.url, + } + rules.push(data) + const category = rule.meta.docs.category + categories.find((c) => c.title === category).rules.push(data) + + if (rule.meta.docs.recommended) { + DEFAULT_RULES_CONFIG[rule.meta.docs.ruleId] = "error" + } +} + +for (const [ruleId, rule] of linter.getRules()) { + if (rule.meta.deprecated) { + continue + } + const data = { + ruleId, + rule, + url: rule.meta.docs.url, + } + rules.push(data) + const type = rule.meta.type + categories.find((c) => c.type === type).rules.push(data) + + if (rule.meta.docs.recommended) { + DEFAULT_RULES_CONFIG[ruleId] = "error" + } +} +/** get url */ +export function getURL(ruleId) { + return linter.getRules().get(ruleId)?.meta.docs.url ?? "" +} + +export function createLinter() { + const linter = new Linter() + linter.defineParser("svelte-eslint-parser", svelteEslintParser) + for (const rule of pluginRules) { + linter.defineRule(rule.meta.docs.ruleId, rule) + } + + return linter +} diff --git a/docs-svelte-kit/src/lib/eslint/scripts/monaco-loader.js b/docs-svelte-kit/src/lib/eslint/scripts/monaco-loader.js new file mode 100644 index 000000000..d12b46064 --- /dev/null +++ b/docs-svelte-kit/src/lib/eslint/scripts/monaco-loader.js @@ -0,0 +1,61 @@ +async function setupMonaco() { + if (typeof window !== "undefined") { + const monacoScript = + Array.from(document.head.querySelectorAll("script")).find( + (script) => + script.src && + script.src.includes("monaco") && + script.src.includes("vs/loader"), + ) || (await appendMonacoEditorScript()) + window.require.config({ + paths: { + vs: monacoScript.src.replace(/\/vs\/.*$/u, "/vs"), + }, + "vs/nls": { + availableLanguages: { + "*": "ja", + }, + }, + }) + } +} + +function appendMonacoEditorScript() { + return new Promise((resolve) => { + const script = document.createElement("script") + script.src = + "https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.26.1/min/vs/loader.min.js" + script.onload = () => { + script.onload = null + + watch() + + function watch() { + if (window.require) { + resolve(script) + return + } + setTimeout(watch, 200) + } + } + document.head.append(script) + }) +} + +let setupedMonaco = null +let editorLoaded = null + +export async function loadMonacoEditor() { + await (setupedMonaco || (setupedMonaco = setupMonaco())) + return ( + editorLoaded || + (editorLoaded = new Promise((resolve) => { + if (typeof window !== "undefined") { + // eslint-disable-next-line node/no-missing-require -- ignore + window.require(["vs/editor/editor.main"], (r) => { + resolve(r) + }) + } + })) + ) +} diff --git a/docs-svelte-kit/src/lib/eslint/scripts/state/deserialize.js b/docs-svelte-kit/src/lib/eslint/scripts/state/deserialize.js new file mode 100644 index 000000000..8ea46f7d5 --- /dev/null +++ b/docs-svelte-kit/src/lib/eslint/scripts/state/deserialize.js @@ -0,0 +1,48 @@ +import pako from "pako" + +/** + * Deserialize a given serialized string then update this object. + * @param {string} serializedString A serialized string. + * @returns {object} The deserialized state. + */ +export function deserializeState(serializedString) { + const state = { + code: undefined, + rules: undefined, + } + + if (serializedString === "") { + return state + } + + try { + const compressedString = window.atob(serializedString) + const uint8Arr = pako.inflate( + Uint8Array.from(compressedString, (c) => c.charCodeAt(0)), + ) + + const jsonText = new TextDecoder().decode(uint8Arr) + const json = JSON.parse(jsonText) + + if (typeof json === "object" && json != null) { + if (typeof json.code === "string") { + state.code = json.code + } + if (json.useEslintPluginSvelte3 === true) { + state.useEslintPluginSvelte3 = true + } + + if (typeof json.rules === "object" && json.rules != null) { + state.rules = {} + for (const id of Object.keys(json.rules)) { + state.rules[id] = json.rules[id] === 2 ? "error" : "off" + } + } + } + } catch (error) { + // eslint-disable-next-line no-console -- Demo + console.error(error) + } + + return state +} diff --git a/docs-svelte-kit/src/lib/eslint/scripts/state/index.js b/docs-svelte-kit/src/lib/eslint/scripts/state/index.js new file mode 100644 index 000000000..60b1ca055 --- /dev/null +++ b/docs-svelte-kit/src/lib/eslint/scripts/state/index.js @@ -0,0 +1,2 @@ +export * from "./deserialize" +export * from "./serialize" diff --git a/docs-svelte-kit/src/lib/eslint/scripts/state/serialize.js b/docs-svelte-kit/src/lib/eslint/scripts/state/serialize.js new file mode 100644 index 000000000..17e5796ff --- /dev/null +++ b/docs-svelte-kit/src/lib/eslint/scripts/state/serialize.js @@ -0,0 +1,45 @@ +import pako from "pako" + +/** + * Get only enabled rules to make the serialized data smaller. + * @param {object} allRules The rule settings. + * @returns {object} The rule settings for the enabled rules. + */ +function getEnabledRules(allRules) { + return Object.keys(allRules).reduce((map, id) => { + if (allRules[id] === "error") { + map[id] = 2 + } + return map + }, {}) +} + +/** + * Serialize a given state as a base64 string. + * @param {State} state The state to serialize. + * @returns {string} The serialized string. + */ +export function serializeState(state) { + const saveData = { + code: state.code, + rules: state.rules ? getEnabledRules(state.rules) : undefined, + useEslintPluginSvelte3: state.useEslintPluginSvelte3, + } + const jsonString = JSON.stringify(saveData) + + const uint8Arr = new TextEncoder().encode(jsonString) + const compressedString = String.fromCharCode(...pako.deflate(uint8Arr)) + const base64 = + (typeof window !== "undefined" && window.btoa(compressedString)) || + compressedString + + // eslint-disable-next-line no-console -- Demo + console.log( + `The compress rate of serialized string: ${( + (100 * base64.length) / + jsonString.length + ).toFixed(1)}% (${jsonString.length}B → ${base64.length}B)`, + ) + + return base64 +} diff --git a/docs-svelte-kit/src/lib/footer/Footer.svelte b/docs-svelte-kit/src/lib/footer/Footer.svelte new file mode 100644 index 000000000..6680335ef --- /dev/null +++ b/docs-svelte-kit/src/lib/footer/Footer.svelte @@ -0,0 +1,152 @@ + + +
+ + + +
+ + diff --git a/docs-svelte-kit/src/lib/header/Header.svelte b/docs-svelte-kit/src/lib/header/Header.svelte new file mode 100644 index 000000000..7f90ee598 --- /dev/null +++ b/docs-svelte-kit/src/lib/header/Header.svelte @@ -0,0 +1,157 @@ + + +
+
+ + Logo + +
+ + + + +
+ + diff --git a/docs-svelte-kit/src/lib/header/logo.svg b/docs-svelte-kit/src/lib/header/logo.svg new file mode 100644 index 000000000..77da6e4bd --- /dev/null +++ b/docs-svelte-kit/src/lib/header/logo.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + diff --git a/docs-svelte-kit/src/lib/header/svelte-logo.svg b/docs-svelte-kit/src/lib/header/svelte-logo.svg new file mode 100644 index 000000000..49492a83c --- /dev/null +++ b/docs-svelte-kit/src/lib/header/svelte-logo.svg @@ -0,0 +1 @@ +svelte-logo \ No newline at end of file diff --git a/docs-svelte-kit/src/lib/markdown/Markdown.svelte b/docs-svelte-kit/src/lib/markdown/Markdown.svelte new file mode 100644 index 000000000..d5af3e349 --- /dev/null +++ b/docs-svelte-kit/src/lib/markdown/Markdown.svelte @@ -0,0 +1,42 @@ + + +{#if !frontmatter.hiddenMenu} + +{/if} +
+
+ +
+
+
+ + diff --git a/docs-svelte-kit/src/lib/sidemenu/SideMenu.svelte b/docs-svelte-kit/src/lib/sidemenu/SideMenu.svelte new file mode 100644 index 000000000..f679432ee --- /dev/null +++ b/docs-svelte-kit/src/lib/sidemenu/SideMenu.svelte @@ -0,0 +1,32 @@ + + + + + diff --git a/docs-svelte-kit/src/lib/sidemenu/UlMenu.svelte b/docs-svelte-kit/src/lib/sidemenu/UlMenu.svelte new file mode 100644 index 000000000..1f3c218fa --- /dev/null +++ b/docs-svelte-kit/src/lib/sidemenu/UlMenu.svelte @@ -0,0 +1,87 @@ + + + + + diff --git a/docs-svelte-kit/src/lib/utils.js b/docs-svelte-kit/src/lib/utils.js new file mode 100644 index 000000000..6557ac331 --- /dev/null +++ b/docs-svelte-kit/src/lib/utils.js @@ -0,0 +1,103 @@ +// eslint-disable-next-line node/file-extension-in-import -- ignore +import { rules } from "../../../src/utils/rules.ts" +import { readable, writable } from "svelte/store" +// eslint-disable-next-line node/no-missing-import -- ignore +import { page } from "$app/stores" + +const svelteRules = rules.filter((rule) => !rule.meta.deprecated) + +const categories = [ + "Possible Errors", + "Security Vulnerability", + "Best Practices", + "Stylistic Issues", + "Extension Rules", + "System", +] +svelteRules.forEach((rule) => { + if (!categories.includes(rule.meta.docs.category)) { + throw new Error(`missing categories:${rule.meta.docs.category}`) + } +}) + +const categoryRules = categories.map((cat) => { + return { + title: cat, + children: svelteRules + .filter((rule) => rule.meta.docs.category === cat) + .map((rule) => { + return { + title: rule.meta.docs.ruleId, + path: `/rules/${rule.meta.docs.ruleName}`, + } + }), + } +}) +const SIDE_MENU = { + "/rules": [ + { path: "/", title: "Introduction" }, + { path: "/user-guide/README", title: "User Guide" }, + { + path: "/rules/README", + title: "Available Rules", + children: categoryRules, + }, + ], + "/": [ + { path: "/", title: "Introduction" }, + { path: "/user-guide/README", title: "User Guide" }, + { path: "/rules/README", title: "Available Rules" }, + ], +} + +export function isActive(path, $page) { + return normalizePath($page.path) === normalizePath(path) +} + +export function normalizePath(path) { + return path === "/" ? "/README" : path +} + +export const tocStore = writable([]) + +export const menuItems = readable([], function start(set) { + let pageData = {} + let tocData = { children: [] } + const pageUnsubscriber = page.subscribe(($page) => { + pageData = $page + set(generateMenu(pageData, tocData)) + }) + const tocUnsubscriber = tocStore.subscribe((toc) => { + tocData = toc + set(generateMenu(pageData, tocData)) + }) + + return function stop() { + pageUnsubscriber() + tocUnsubscriber() + } +}) + +function generateMenu($page, toc) { + const result = [] + const [, menus] = + Object.entries(SIDE_MENU).find(([k]) => $page.path.startsWith(k)) || + SIDE_MENU["/"] + for (const { path, title, children } of menus) { + const active = isActive(path, $page) + if (active) { + for (const item of toc.children) { + result.push({ + ...item, + path, + title, + children: children || item.children, + }) + } + } else { + result.push({ path, title, children }) + } + } + + return result +} diff --git a/docs-svelte-kit/src/site.css b/docs-svelte-kit/src/site.css new file mode 100644 index 000000000..2c774d6ab --- /dev/null +++ b/docs-svelte-kit/src/site.css @@ -0,0 +1,90 @@ +@import "prismjs/themes/prism"; + +h3, +h4, +h5, +h6 { + font-weight: 400; + color: var(--heading-color); +} + +h2 { + font-size: 1.2rem; +} +h3, +h4, +h5, +h6 { + font-size: 1rem; +} + +.custom-block .custom-block-title { + font-weight: 600; + margin-bottom: -0.4rem; +} + +.custom-block.danger, +.custom-block.tip, +.custom-block.warning { + padding: 0.1rem 1.5rem; + border-left-width: 0.5rem; + border-left-style: solid; + margin: 1rem 0; +} + +.custom-block.tip { + background-color: #f3f5f7; + border-color: #42b983; +} + +.custom-block.warning { + background-color: rgba(255, 229, 100, 0.3); + border-color: #e7c000; + color: #6b5900; +} + +.custom-block.warning .custom-block-title { + color: #b29400; +} + +.custom-block.warning a { + color: #2c3e50; +} + +.custom-block.danger { + background-color: #ffe6e6; + border-color: #c00; + color: #4d0000; +} + +.custom-block.danger .custom-block-title { + color: #900; +} + +.custom-block.danger a { + color: #2c3e50; +} + +.custom-block.details { + display: block; + position: relative; + border-radius: 2px; + margin: 1.6em 0; + padding: 1.6em; + background-color: #eee; +} + +.custom-block.details h4 { + margin-top: 0; +} + +.custom-block.details figure:last-child, +.custom-block.details p:last-child { + margin-bottom: 0; + padding-bottom: 0; +} + +.custom-block.details summary { + outline: none; + cursor: pointer; +} diff --git a/docs-svelte-kit/static/favicon.png b/docs-svelte-kit/static/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..825b9e65af7c104cfb07089bb28659393b4f2097 GIT binary patch literal 1571 zcmV+;2Hg3HP)Px)-AP12RCwC$UE6KzI1p6{F2N z1VK2vi|pOpn{~#djwYcWXTI_im_u^TJgMZ4JMOsSj!0ma>B?-(Hr@X&W@|R-$}W@Z zgj#$x=!~7LGqHW?IO8+*oE1MyDp!G=L0#^lUx?;!fXv@l^6SvTnf^ac{5OurzC#ZMYc20lI%HhX816AYVs1T3heS1*WaWH z%;x>)-J}YB5#CLzU@GBR6sXYrD>Vw(Fmt#|JP;+}<#6b63Ike{Fuo!?M{yEffez;| zp!PfsuaC)>h>-AdbnwN13g*1LowNjT5?+lFVd#9$!8Z9HA|$*6dQ8EHLu}U|obW6f z2%uGv?vr=KNq7YYa2Roj;|zooo<)lf=&2yxM@e`kM$CmCR#x>gI>I|*Ubr({5Y^rb zghxQU22N}F51}^yfDSt786oMTc!W&V;d?76)9KXX1 z+6Okem(d}YXmmOiZq$!IPk5t8nnS{%?+vDFz3BevmFNgpIod~R{>@#@5x9zJKEHLHv!gHeK~n)Ld!M8DB|Kfe%~123&Hz1Z(86nU7*G5chmyDe ziV7$pB7pJ=96hpxHv9rCR29%bLOXlKU<_13_M8x)6;P8E1Kz6G<&P?$P^%c!M5`2` zfY2zg;VK5~^>TJGQzc+33-n~gKt{{of8GzUkWmU110IgI0DLxRIM>0US|TsM=L|@F z0Bun8U!cRB7-2apz=y-7*UxOxz@Z0)@QM)9wSGki1AZ38ceG7Q72z5`i;i=J`ILzL z@iUO?SBBG-0cQuo+an4TsLy-g-x;8P4UVwk|D8{W@U1Zi z!M)+jqy@nQ$p?5tsHp-6J304Q={v-B>66$P0IDx&YT(`IcZ~bZfmn11#rXd7<5s}y zBi9eim&zQc0Dk|2>$bs0PnLmDfMP5lcXRY&cvJ=zKxI^f0%-d$tD!`LBf9^jMSYUA zI8U?CWdY@}cRq6{5~y+)#h1!*-HcGW@+gZ4B};0OnC~`xQOyH19z*TA!!BJ%9s0V3F?CAJ{hTd#*tf+ur-W9MOURF-@B77_-OshsY}6 zOXRY=5%C^*26z?l)1=$bz30!so5tfABdSYzO+H=CpV~aaUefmjvfZ3Ttu9W&W3Iu6 zROlh0MFA5h;my}8lB0tAV-Rvc2Zs_CCSJnx@d`**$idgy-iMob4dJWWw|21b4NB=LfsYp0Aeh{Ov)yztQi;eL4y5 zMi>8^SzKqk8~k?UiQK^^-5d8c%bV?$F8%X~czyiaKCI2=UH${ + lang === "text" ? escapeHtml(code) : code + }` +} + +const EXTENSION_MAPPINGS = { + vue: "markup", + html: "markup", + svelte: "svelte", + sv: "svelte", + md: "markdown", + rb: "ruby", + ts: "typescript", + py: "python", + sh: "bash", + yml: "yaml", + styl: "stylus", + kt: "kotlin", + rs: "rust", +} + +export default (str, lang) => { + if (!lang) { + return wrapPre(str, "text") + } + let normalLang = lang.toLowerCase() + const rawLang = lang + + normalLang = EXTENSION_MAPPINGS[normalLang] || normalLang + + if (!prism.languages[normalLang]) { + try { + loadLanguages([normalLang]) + } catch { + // ignore + } + } + if (prism.languages[normalLang]) { + const code = prism.highlight(str, prism.languages[normalLang], normalLang) + return wrapPre(code, rawLang) + } + return wrapPre(str, "text") +} diff --git a/docs-svelte-kit/tools/markdown-it-auto-inject-components.mjs b/docs-svelte-kit/tools/markdown-it-auto-inject-components.mjs new file mode 100644 index 000000000..0e5c2b1cb --- /dev/null +++ b/docs-svelte-kit/tools/markdown-it-auto-inject-components.mjs @@ -0,0 +1,54 @@ +/** + * @param {import('markdown-it')} md + */ +export default (md) => { + md.core.ruler.push("auto_inject_components", (state) => { + const injected = new Set(extractInjectedComponents(state.tokens)) + for (const component of new Set( + extractComponents(state.tokens, injected), + )) { + const newToken = new state.Token("auto_inject_component") + newToken.content = `` + state.tokens.unshift(newToken) + } + + /** Extract imported components */ + function* extractInjectedComponents(tokens) { + for (const token of tokens) { + if ( + (token.type === "html_inline" || token.type === "html_block") && + token.content.trim().startsWith(" { + return tokens[idx].content + } +} diff --git a/docs-svelte-kit/tools/markdown-it-container-option.mjs b/docs-svelte-kit/tools/markdown-it-container-option.mjs new file mode 100644 index 000000000..f8dff94f1 --- /dev/null +++ b/docs-svelte-kit/tools/markdown-it-container-option.mjs @@ -0,0 +1,37 @@ +/** + * Generate markdown-it-container option + * @see https://github.com/markdown-it/markdown-it-container + */ +export default (type, defaultTitle = type.toUpperCase()) => { + return { + render(tokens, index) { + const token = tokens[index] + + if (token.nesting === 1) { + // `before` tag + + // resolve info (title) + let title = token.info.trim().slice(type.length).trim() + + if (!title) { + title = defaultTitle + } + // render + if (type === "details") { + return `
${ + title ? `${title}` : "" + }\n` + } + return `
${ + title ? `

${title}

` : "" + }\n` + } + // `after` tag + // render + if (type === "details") { + return `
\n` + } + return "
\n" + }, + } +} diff --git a/docs-svelte-kit/tools/markdown-it-markdown.mjs b/docs-svelte-kit/tools/markdown-it-markdown.mjs new file mode 100644 index 000000000..f4599705c --- /dev/null +++ b/docs-svelte-kit/tools/markdown-it-markdown.mjs @@ -0,0 +1,110 @@ +import path from "path" +import spawn from "cross-spawn" + +class TOCRenderer { + constructor(name) { + const item = { children: [] } + this.tree = item + this.stack = { item, level: 1, upper: null } + this.name = name + } + + addMenu(level, id, title) { + if (this.stack.level < level) { + const parent = this.stack.item + const item = parent.children[parent.children.length - 1] + if (item) { + this.stack = { item, level, upper: this.stack } + } + } + while (level < this.stack.level && this.stack.upper) { + this.stack = this.stack.upper + } + const item = { level, id, title, children: [] } + this.stack.item.children.push(item) + } + + toc() { + return this.tree + } +} +/** + * @param {import('markdown-it')} md + */ +export default (md) => { + md.core.ruler.push("custom_markdown", (state) => { + const tokens = state.tokens + tokens.unshift(new state.Token("custom_markdown_open")) + tokens.push(new state.Token("custom_markdown_close")) + }) + // eslint-disable-next-line camelcase -- ignore + md.renderer.rules.custom_markdown_close = () => `` + // eslint-disable-next-line camelcase -- ignore + md.renderer.rules.custom_markdown_open = ( + tokens, + _idx, + _options, + env, + _self, + ) => { + const name = path.basename(env.id).replace(/\.md$/, "") + const renderer = new TOCRenderer(name) + for (let idx = 0; idx < tokens.length; idx++) { + const token = tokens[idx] + + if (token.type !== "heading_open") { + continue + } + let level = Number(token.tag.substr(1)) + if (level > 3) { + continue + } + // Aggregate the next token children text. + const title = tokens[idx + 1].children + .filter( + (token) => + token.type === "text" || + token.type === "emoji" || + token.type === "code_inline", + ) + .reduce((acc, t) => acc + t.content, "") + + let slug = token.attrGet("id") + renderer.addMenu(level, slug, title) + } + + const fileInfo = {} + const timestamp = getGitLastUpdatedTimestamp(env.id) + if (timestamp) { + fileInfo.timestamp = timestamp + fileInfo.lastUpdated = new Date(timestamp).toLocaleString() + } + return ` + + + ` + } +} + +/** Get last updated timestamp */ +function getGitLastUpdatedTimestamp(filePath) { + let lastUpdated + try { + lastUpdated = + parseInt( + spawn + .sync("git", ["log", "-1", "--format=%at", path.basename(filePath)], { + cwd: path.dirname(filePath), + }) + .stdout.toString("utf-8"), + 10, + ) * 1000 + } catch { + /* do not handle for now */ + } + return lastUpdated +} diff --git a/docs-svelte-kit/tools/markdown-it-replace-link.mjs b/docs-svelte-kit/tools/markdown-it-replace-link.mjs new file mode 100644 index 000000000..c0bd9670a --- /dev/null +++ b/docs-svelte-kit/tools/markdown-it-replace-link.mjs @@ -0,0 +1,47 @@ +// eslint-disable-next-line eslint-comments/disable-enable-pair -- ignore +/* eslint-disable camelcase -- ignore */ +// markdown-it plugin for: +// 1. adding target="_blank" to external links +// 2. converting internal links to remove .md +import path from "path" + +export default (md) => { + md.renderer.rules.link_open = (tokens, idx, options, env, self) => { + const token = tokens[idx] + const hrefIndex = token.attrIndex("href") + if (hrefIndex >= 0) { + const link = token.attrs[hrefIndex] + const href = link[1] + if (/^https?:/.test(href)) { + const proxyToken = { + ...token, + attrs: [...token.attrs, ["target", "_blank"]], + } + return self.renderToken([proxyToken], 0, options) + } else if (/\.md(?:#.*)?$/.test(href)) { + const proxyToken = { + ...token, + attrs: [ + ...token.attrs.slice(0, hrefIndex - 1), + [link[0], href.replace(/\.md$/, "").replace(/\.md(#.*)$/, `$1`)], + ...token.attrs.slice(hrefIndex + 1), + ], + } + return self.renderToken([proxyToken], 0, options) + } else if (/^#.*$/.test(href)) { + // Avoid build error + const name = path.basename(env.id).replace(/\.md$/, "") + const proxyToken = { + ...token, + attrs: [ + ...token.attrs.slice(0, hrefIndex - 1), + [link[0], name + href], + ...token.attrs.slice(hrefIndex + 1), + ], + } + return self.renderToken([proxyToken], 0, options) + } + } + return self.renderToken(tokens, idx, options) + } +} diff --git a/docs-svelte-kit/tools/markdown-it-title.mjs b/docs-svelte-kit/tools/markdown-it-title.mjs new file mode 100644 index 000000000..25bda4644 --- /dev/null +++ b/docs-svelte-kit/tools/markdown-it-title.mjs @@ -0,0 +1,35 @@ +/** + * @param {import('markdown-it')} md + */ +export default (md) => { + const headingOpen = md.renderer.rules.heading_open + // eslint-disable-next-line camelcase -- ignore + md.renderer.rules.heading_open = (tokens, idx, options, env, self) => { + const head = headingOpen + ? headingOpen(tokens, idx, options, env, self) + : self.renderToken(tokens, idx, options) + const token = tokens[idx] + let level = Number(token.tag.substr(1)) + if (level > 1) { + return head + } + const title = tokens[idx + 1].children + .filter( + (token) => + token.type === "text" || + token.type === "emoji" || + token.type === "code_inline", + ) + .reduce((acc, t) => acc + t.content, "") + .trim() + return `${head} + + + {#if !frontmatter.title} + ${title} + + {/if} + +` + } +} diff --git a/docs-svelte-kit/tools/vite-plugin-svelte-md-option.mjs b/docs-svelte-kit/tools/vite-plugin-svelte-md-option.mjs new file mode 100644 index 000000000..b1dd62cbb --- /dev/null +++ b/docs-svelte-kit/tools/vite-plugin-svelte-md-option.mjs @@ -0,0 +1,37 @@ +import highlight from "./highlight.mjs" +import replaceLinkPlugin from "./markdown-it-replace-link.mjs" +import emojiPlugin from "markdown-it-emoji" +import anchorPlugin from "markdown-it-anchor" +import containerPlugin from "markdown-it-container" +import autoInjectComponentsPlugin from "./markdown-it-auto-inject-components.mjs" +import titlePlugin from "./markdown-it-title.mjs" +import markdownPlugin from "./markdown-it-markdown.mjs" +import containerPluginOption from "./markdown-it-container-option.mjs" +import slugify from "@sindresorhus/slugify" + +export default { + wrapperClasses: [], + markdownItOptions: { + highlight, + }, + markdownItUses: [ + replaceLinkPlugin, + emojiPlugin, + [ + anchorPlugin, + { + slugify, + permalink: true, + permalinkBefore: true, + permalinkSymbol: "#", + }, + ], + autoInjectComponentsPlugin, + titlePlugin, + markdownPlugin, + [containerPlugin, "tip", containerPluginOption("tip")], + [containerPlugin, "warning", containerPluginOption("warning")], + [containerPlugin, "danger", containerPluginOption("danger", "warning")], + [containerPlugin, "details", containerPluginOption("details")], + ], +} diff --git a/docs/.eslintrc.js b/docs/.eslintrc.js index bffa6c507..5191ade56 100644 --- a/docs/.eslintrc.js +++ b/docs/.eslintrc.js @@ -1,6 +1,7 @@ "use strict" module.exports = { + extends: ["plugin:@ota-meshi/svelte/recommended"], rules: { "eslint-comments/require-description": "off", "prettier/prettier": "off", diff --git a/docs/.vuepress/components/eslint-code-block.vue b/docs/.vuepress/components/ESLintCodeBlock.vue similarity index 100% rename from docs/.vuepress/components/eslint-code-block.vue rename to docs/.vuepress/components/ESLintCodeBlock.vue diff --git a/docs/.vuepress/components/playground-block.vue b/docs/.vuepress/components/ESLintPlayground.vue similarity index 99% rename from docs/.vuepress/components/playground-block.vue rename to docs/.vuepress/components/ESLintPlayground.vue index ec8cdc9dd..53113e431 100644 --- a/docs/.vuepress/components/playground-block.vue +++ b/docs/.vuepress/components/ESLintPlayground.vue @@ -94,7 +94,7 @@ const DEFAULT_CODE = ` export default { - name: "PlaygroundBlock", + name: "ESLintPlayground", components: { PgEditor, RulesSettings, SnsBar }, data() { const serializedString = diff --git a/docs/README.md b/docs/README.md index 0ebafd55c..c08cc7bcd 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,3 +1,7 @@ +--- +title: "@ota-meshi/eslint-plugin-svelte" +--- + # Introduction `@ota-meshi/eslint-plugin-svelte` is ESLint plugin for Svelte. @@ -46,6 +50,6 @@ See [Available Rules](./rules/README.md). ## :lock: License -See the [LICENSE](LICENSE) file for license rights and limitations (MIT). +See the [LICENSE](https://github.com/ota-meshi/eslint-plugin-svelte/blob/main/LICENSE) file for license rights and limitations (MIT). [svelte]: https://svelte.dev/ diff --git a/docs/__layout.svelte b/docs/__layout.svelte new file mode 100644 index 000000000..ffcc4c604 --- /dev/null +++ b/docs/__layout.svelte @@ -0,0 +1,9 @@ + + +
+ + diff --git a/docs/index.svelte b/docs/index.svelte new file mode 100644 index 000000000..ef64e395a --- /dev/null +++ b/docs/index.svelte @@ -0,0 +1,5 @@ + + + diff --git a/docs/playground/README.md b/docs/playground/README.md index cfd2c1f88..9a7156e17 100644 --- a/docs/playground/README.md +++ b/docs/playground/README.md @@ -1,11 +1,12 @@ --- pageClass: "playground" +hiddenMenu: true --- # Playground - + The playground is [here](https://ota-meshi.github.io/eslint-plugin-svelte/playground/)!! - + diff --git a/docs/prettier.config.js b/docs/prettier.config.js deleted file mode 100644 index 5d78cdc2b..000000000 --- a/docs/prettier.config.js +++ /dev/null @@ -1,7 +0,0 @@ -"use strict" - -module.exports = { - tabWidth: 2, - semi: false, - trailingComma: "all", -} diff --git a/docs/rules/button-has-type.md b/docs/rules/button-has-type.md index 2175c103c..c7f1a985a 100644 --- a/docs/rules/button-has-type.md +++ b/docs/rules/button-has-type.md @@ -14,7 +14,7 @@ since: "v0.0.4" This rule aims to warn if no type or an invalid type is used on a button type attribute. - + @@ -34,7 +34,7 @@ This rule aims to warn if no type or an invalid type is used on a button type at ``` - + ## :wrench: Options diff --git a/docs/rules/comment-directive.md b/docs/rules/comment-directive.md index 5b3bff622..54f3ec154 100644 --- a/docs/rules/comment-directive.md +++ b/docs/rules/comment-directive.md @@ -30,7 +30,7 @@ ESLint doesn't provide any API to enhance `eslint-disable` functionality and ESL This rule sends all `eslint-disable`-like comments to the post-process of the `.svelte` file processor, then the post-process removes the reported errors in disabled areas. - + @@ -43,11 +43,11 @@ This rule sends all `eslint-disable`-like comments to the post-process of the `. ``` - + The `eslint-disable`-like comments can include descriptions to explain why the comment is necessary. The description must occur after the directive and is separated from the directive by two or more consecutive `-` characters. For example: - + @@ -60,7 +60,7 @@ The `eslint-disable`-like comments can include descriptions to explain why the c ``` - + ## :wrench: Options diff --git a/docs/rules/first-attribute-linebreak.md b/docs/rules/first-attribute-linebreak.md index 71359bb94..c0887b8ef 100644 --- a/docs/rules/first-attribute-linebreak.md +++ b/docs/rules/first-attribute-linebreak.md @@ -16,7 +16,7 @@ since: "v0.6.0" This rule aims to enforce a consistent location for the first attribute. - + @@ -44,7 +44,7 @@ This rule aims to enforce a consistent location for the first attribute. - + ## :wrench: Options diff --git a/docs/rules/html-quotes.md b/docs/rules/html-quotes.md index 66463906b..a74f71c2b 100644 --- a/docs/rules/html-quotes.md +++ b/docs/rules/html-quotes.md @@ -22,7 +22,7 @@ You can choose quotes of HTML attributes from: This rule enforces the quotes style of HTML attributes. - + @@ -43,7 +43,7 @@ This rule enforces the quotes style of HTML attributes. - + ## :wrench: Options diff --git a/docs/rules/indent.md b/docs/rules/indent.md index 2c58b194c..6d6104664 100644 --- a/docs/rules/indent.md +++ b/docs/rules/indent.md @@ -19,7 +19,7 @@ This rule enforces a consistent indentation style in `.svelte`. The default styl - This rule checks all tags, also all expressions in directives and mustaches. - In the expressions, this rule supports ECMAScript 2021 syntaxes and some TypeScript syntaxes. It ignores unknown AST nodes, but it might be confused by non-standard syntaxes. - + @@ -51,7 +51,7 @@ CLICK ME! - + ::: warning Note This rule only checks `.svelte` files and does not interfere with other `.js` files. Unfortunately the default `indent` rule when turned on will try to lint both, so in order to make them complementary you can use `overrides` setting and disable `indent` rule on `.svelte` files: diff --git a/docs/rules/max-attributes-per-line.md b/docs/rules/max-attributes-per-line.md index 5eba30368..297e80366 100644 --- a/docs/rules/max-attributes-per-line.md +++ b/docs/rules/max-attributes-per-line.md @@ -22,7 +22,7 @@ An attribute is considered to be in a new line when there is a line break betwee There is a configurable number of attributes that are acceptable in one-line case (default 1), as well as how many attributes are acceptable per line in multi-line case (default 1). - + @@ -58,7 +58,7 @@ There is a configurable number of attributes that are acceptable in one-line cas ``` - + ## :wrench: Options diff --git a/docs/rules/mustache-spacing.md b/docs/rules/mustache-spacing.md index 0f21c6332..25a86fe72 100644 --- a/docs/rules/mustache-spacing.md +++ b/docs/rules/mustache-spacing.md @@ -16,7 +16,7 @@ since: "v0.15.0" This rule aims at enforcing unified spacing in mustaches. - + @@ -57,7 +57,7 @@ This rule aims at enforcing unified spacing in mustaches. { #key id }...{ /key } ``` - + diff --git a/docs/rules/no-at-debug-tags.md b/docs/rules/no-at-debug-tags.md index 286f95af2..96a564f5e 100644 --- a/docs/rules/no-at-debug-tags.md +++ b/docs/rules/no-at-debug-tags.md @@ -18,7 +18,7 @@ This rule reports all uses of `{@debug}`. The `{@debug}` should be removed when you no longer need it after you use it for debugging. - + @@ -33,7 +33,7 @@ The `{@debug}` should be removed when you no longer need it after you use it for {@debug} ``` - + ## :wrench: Options diff --git a/docs/rules/no-at-html-tags.md b/docs/rules/no-at-html-tags.md index 6eed1c104..7ac24660d 100644 --- a/docs/rules/no-at-html-tags.md +++ b/docs/rules/no-at-html-tags.md @@ -16,7 +16,7 @@ since: "v0.0.1" This rule reports all uses of `{@html}` in order to reduce the risk of injecting potentially unsafe / unescaped html into the browser leading to Cross-Site Scripting (XSS) attacks. - + @@ -32,7 +32,7 @@ This rule reports all uses of `{@html}` in order to reduce the risk of injecting {@html foo} ``` - + ## :wrench: Options diff --git a/docs/rules/no-dupe-else-if-blocks.md b/docs/rules/no-dupe-else-if-blocks.md index e35b797fd..e16340c7d 100644 --- a/docs/rules/no-dupe-else-if-blocks.md +++ b/docs/rules/no-dupe-else-if-blocks.md @@ -16,7 +16,7 @@ since: "v0.0.1" This rule disallows duplicate conditions in the same `{#if}` / `{:else if}` chain. - + @@ -55,11 +55,11 @@ This rule disallows duplicate conditions in the same `{#if}` / `{:else if}` chai {/if} ``` - + This rule can also detect some cases where the conditions are not identical, but the branch can never execute due to the logic of `||` and `&&` operators. - + @@ -110,7 +110,7 @@ This rule can also detect some cases where the conditions are not identical, but {/if} ``` - + ## :wrench: Options diff --git a/docs/rules/no-dynamic-slot-name.md b/docs/rules/no-dynamic-slot-name.md index 0af8215b2..31dc34033 100644 --- a/docs/rules/no-dynamic-slot-name.md +++ b/docs/rules/no-dynamic-slot-name.md @@ -20,7 +20,7 @@ Dynamic `` names are not allowed in Svelte, so you must use static names. The auto-fix of this rule can be replaced with a static `` name if the expression given to the `` name is static and resolvable. - + @@ -37,7 +37,7 @@ The auto-fix of this rule can be replaced with a static `` name if the exp ``` - + ## :wrench: Options diff --git a/docs/rules/no-inner-declarations.md b/docs/rules/no-inner-declarations.md index dc60c8fe1..4d8bf06f6 100644 --- a/docs/rules/no-inner-declarations.md +++ b/docs/rules/no-inner-declarations.md @@ -21,7 +21,7 @@ This rule supports [svelte-eslint-parser]'s AST. [svelte-eslint-parser]: https://github.com/ota-meshi/svelte-eslint-parser - + @@ -43,7 +43,7 @@ This rule supports [svelte-eslint-parser]'s AST. ``` - + ## :wrench: Options diff --git a/docs/rules/no-not-function-handler.md b/docs/rules/no-not-function-handler.md index 6678fa801..d5da17556 100644 --- a/docs/rules/no-not-function-handler.md +++ b/docs/rules/no-not-function-handler.md @@ -17,7 +17,7 @@ since: "v0.5.0" This rule reports where you used not function value in event handlers. If you use a non-function value for the event handler, it event handler will not be called. It's almost always a mistake. You may have written a lot of unnecessary curly braces. - + @@ -43,7 +43,7 @@ If you use a non-function value for the event handler, it event handler will not ``` - + You cannot enforce this style by using [prettier-plugin-svelte]. That is, this rule does not conflict with [prettier-plugin-svelte] and can be used with [prettier-plugin-svelte]. diff --git a/docs/rules/shorthand-attribute.md b/docs/rules/shorthand-attribute.md index 59766cbf0..4d6606a68 100644 --- a/docs/rules/shorthand-attribute.md +++ b/docs/rules/shorthand-attribute.md @@ -16,7 +16,7 @@ since: "v0.5.0" This rule enforces the use of the shorthand syntax in attribute. - + @@ -35,7 +35,7 @@ This rule enforces the use of the shorthand syntax in attribute. - + ## :wrench: Options diff --git a/docs/rules/spaced-html-comment.md b/docs/rules/spaced-html-comment.md index 444cb659d..f24181d0b 100644 --- a/docs/rules/spaced-html-comment.md +++ b/docs/rules/spaced-html-comment.md @@ -16,7 +16,7 @@ since: "v0.0.1" This rule will enforce consistency of spacing after the start of a comment ``. - + @@ -30,7 +30,7 @@ This rule will enforce consistency of spacing after the start of a comment ` ``` - + You cannot enforce this style by using [prettier-plugin-svelte]. That is, this rule does not conflict with [prettier-plugin-svelte] and can be used with [prettier-plugin-svelte]. diff --git a/docs/rules/valid-compile.md b/docs/rules/valid-compile.md index 5eb17bcba..6bc9c4cf2 100644 --- a/docs/rules/valid-compile.md +++ b/docs/rules/valid-compile.md @@ -16,7 +16,7 @@ since: "v0.7.0" This rule uses Svelte compiler to check the source code. - + @@ -33,7 +33,7 @@ This rule uses Svelte compiler to check the source code. ``` - + Note that we exclude reports for some checks, such as `missing-declaration`, and `dynamic-slot-name`, which you can check with different ESLint rules. @@ -52,7 +52,7 @@ Note that we exclude reports for some checks, such as `missing-declaration`, and - `ignoreWarnings` ... If set to `true`, ignores any warnings other than fatal errors reported by the svelte compiler. - + @@ -66,7 +66,7 @@ Note that we exclude reports for some checks, such as `missing-declaration`, and ``` - + ## :rocket: Version diff --git a/package.json b/package.json index 1baa0e718..c3d0641d8 100644 --- a/package.json +++ b/package.json @@ -25,9 +25,12 @@ "eslint-fix": "eslint . --fix", "update": "ts-node --transpile-only ./tools/update.ts && npm run eslint-fix && npm run test", "new": "ts-node --transpile-only ./tools/new-rule.ts", - "predocs:watch": "npm run build:ts", - "docs:watch": "vuepress dev --debug docs", - "docs:build": "vuepress build docs --no-cache", + "pre_docs:watch": "npm run build:ts", + "_docs:watch": "vuepress dev --debug docs", + "docs:watch": "svelte-kit dev", + "_docs:build": "vuepress build docs --no-cache", + "docs:build": "node --experimental-loader ./svelte-kit-import-hook.mjs node_modules/@sveltejs/kit/svelte-kit.js build", + "docs:preview": "node --experimental-loader ./svelte-kit-import-hook.mjs node_modules/@sveltejs/kit/svelte-kit.js preview", "preversion": "npm test && git add .", "version": "env-cmd -e version npm run update && git add ." }, @@ -64,7 +67,14 @@ } }, "devDependencies": { + "@babel/core": "^7.16.0", + "@babel/types": "^7.16.0", + "@fontsource/fira-mono": "^4.5.0", "@ota-meshi/eslint-plugin": "^0.10.0", + "@ota-meshi/eslint-plugin-svelte": "^0.16.0", + "@sindresorhus/slugify": "^2.1.0", + "@sveltejs/adapter-static": "^1.0.0-next.21", + "@sveltejs/kit": "^1.0.0-next.201", "@types/eslint": "^8.0.0", "@types/eslint-scope": "^3.7.0", "@types/eslint-visitor-keys": "^1.0.0", @@ -74,6 +84,9 @@ "@typescript-eslint/parser": "^5.4.1-0", "@typescript-eslint/parser-v4": "npm:@typescript-eslint/parser@4", "env-cmd": "^10.1.0", + "esbuild": "^0.14.1", + "esbuild-register": "^3.2.0", + "escape-html": "^1.0.3", "eslint": "^8.0.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-eslint-comments": "^3.2.0", @@ -90,17 +103,24 @@ "estree-walker": "^3.0.0", "locate-character": "^2.0.5", "magic-string": "^0.25.7", + "markdown-it-anchor": "^8.4.1", + "markdown-it-container": "^3.0.0", + "markdown-it-emoji": "^2.0.0", "mocha": "^9.0.0", "nyc": "^15.1.0", "pako": "^2.0.3", + "pirates": "^4.0.1", "prettier": "^2.2.1", "prettier-plugin-svelte": "^2.2.0", + "prism-svelte": "^0.4.7", + "prismjs": "^1.25.0", "semver": "^7.3.5", "stylelint": "^14.0.0", "stylelint-config-standard": "^24.0.0", "svelte": "^3.37.0", "ts-node": "^10.0.0", "typescript": "^4.5.2", + "vite-plugin-svelte-md": "^0.1.3", "vue-eslint-editor": "^1.1.0", "vue-eslint-parser": "^8.0.0", "vuepress": "^1.8.2" diff --git a/src/rules/indent-helpers/offset-context.ts b/src/rules/indent-helpers/offset-context.ts index fe776ce74..4a4788bfa 100644 --- a/src/rules/indent-helpers/offset-context.ts +++ b/src/rules/indent-helpers/offset-context.ts @@ -318,7 +318,7 @@ export class OffsetCalculator { if (offsetInfo == null) { continue } - offsetInfo.expectedIndent ??= expectedIndent + offsetInfo.expectedIndent = offsetInfo.expectedIndent ?? expectedIndent } } } diff --git a/src/rules/valid-compile.ts b/src/rules/valid-compile.ts index 237b79eb2..ceba8d63c 100644 --- a/src/rules/valid-compile.ts +++ b/src/rules/valid-compile.ts @@ -203,8 +203,8 @@ export default createRule("valid-compile", { this.mapIndexes.push({ range: [codeStart, this.code.length], remap: (index) => { - outputLocs ??= new LinesAndColumns(outputText) - inputLocs ??= new LinesAndColumns(inputText) + outputLocs = outputLocs ?? new LinesAndColumns(outputText) + inputLocs = inputLocs ?? new LinesAndColumns(inputText) const outputCodePos = outputLocs.getLocFromIndex(index - codeStart) const inputCodePos = remapPosition(outputCodePos) return inputLocs.getIndexFromLoc(inputCodePos) + start @@ -216,7 +216,8 @@ export default createRule("valid-compile", { line: number column: number } { - decoded ??= decode(JSON.parse(output.sourceMapText!).mappings) + decoded = + decoded ?? decode(JSON.parse(output.sourceMapText!).mappings) const lineMaps = decoded[pos.line - 1] @@ -277,7 +278,7 @@ export default createRule("valid-compile", { } } { const mapIndexes = this.mapIndexes - const locs = (this.locs ??= new LinesAndColumns(this.code)) + const locs = (this.locs = this.locs ?? new LinesAndColumns(this.code)) let start: | { line: number diff --git a/src/utils/eslint-core.ts b/src/utils/eslint-core.ts index 7d9be9d17..5450ba28d 100644 --- a/src/utils/eslint-core.ts +++ b/src/utils/eslint-core.ts @@ -2,6 +2,7 @@ import type { RuleListener, RuleContext, RuleModule } from "../types" import type * as ESTree from "estree" import type { AST as SvAST } from "svelte-eslint-parser" +import { Linter } from "eslint" /** * Define the wrapped core rule. @@ -82,8 +83,7 @@ export function getCoreRule(ruleName: string): RuleModule { if (ruleMap) { map = ruleMap } else { - // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires -- load eslint - ruleMap = map = new (require("eslint").Linter)().getRules() + ruleMap = map = (new Linter() as any).getRules() } return map.get(ruleName)! } diff --git a/svelte-kit-import-hook.mjs b/svelte-kit-import-hook.mjs new file mode 100644 index 000000000..aa564d2e4 --- /dev/null +++ b/svelte-kit-import-hook.mjs @@ -0,0 +1,99 @@ +/* !! This project can't be ESM yet, so hack it to get sveltekit to work. !! */ +import babelCore from "@babel/core" +import * as t from "@babel/types" + +import pirates from "pirates" + +pirates.addHook(transform, { + exts: [".js", ".mjs"], +}) + +/** transform code */ +function transform(code, _filename) { + if (code.includes("import(")) { + let transformed = false + const newCode = babelCore.transformSync(code, { + babelrc: false, + plugins: [ + { + visitor: { + CallExpression(path) { + const callee = path.get("callee") + if (callee.type === "Import") { + callee.replaceWith(t.identifier("$$$import")) + transformed = true + } + }, + }, + }, + ], + }) + if (!transformed) { + return code + } + return `${newCode.code} +async function $$$import(module, ...args) { + const m = await import(module) + return ________adjustModule(m) +} +function ________adjustModule(m) { + const keys = Object.keys(m); + if(m.default && keys.length === 1 && keys[0] === 'default' && typeof m.default === 'object') { + const result = { + default: ________adjustModule(m.default) + } + for (const key of Object.keys(m.default)) { + if (typeof m.default[key] === 'function') { + result[key] = (...args) => m.default[key](...args); + } else { + result[key] = m.default[key] + } + } + return result + } + return m +} +` + } + + return code +} + +/** + * @param {string} url + * @param {{ + * format: string, + * }} context If resolve settled with a `format`, that value is included here. + * @param {Function} defaultLoad + * @returns {Promise<{ + * format: !string, + * source: !(string | ArrayBuffer | SharedArrayBuffer | Uint8Array), + * }>} + */ +export async function load(url, context, defaultLoad) { + const result = await defaultLoad(url, context, defaultLoad) + return { + format: result.format, + source: transform(`${result.source}`), + } +} + +/** + * @param {!(string | SharedArrayBuffer | Uint8Array)} source + * @param {{ + * format: string, + * url: string, + * }} context + * @param {Function} defaultTransformSource + * @returns {Promise<{ source: !(string | SharedArrayBuffer | Uint8Array) }>} + */ +export async function transformSource(source, context, defaultTransformSource) { + const result = await defaultTransformSource( + source, + context, + defaultTransformSource, + ) + return { + source: transform(`${result.source}`), + } +} diff --git a/svelte.config.esm.mjs b/svelte.config.esm.mjs new file mode 100644 index 000000000..e1158d52d --- /dev/null +++ b/svelte.config.esm.mjs @@ -0,0 +1,60 @@ +/* global __dirname -- __dirname */ +import staticAdapter from "@sveltejs/adapter-static" +import path from "path" +import svelteMd from "vite-plugin-svelte-md" +import svelteMdOption from "./docs-svelte-kit/tools/vite-plugin-svelte-md-option.mjs" + +import "./docs-svelte-kit/build-system/build.js" + +const dirname = + typeof __dirname !== "undefined" + ? __dirname + : (() => { + const metaUrl = Function(`return import.meta.url`)() + return path.dirname(new URL(metaUrl).pathname) + })() +/** @type {import('@sveltejs/kit').Config} */ +const config = { + compilerOptions: { + preserveWhitespace: true, + }, + extensions: [".svelte", ".md"], + kit: { + paths: { + base: "/eslint-plugin-svelte", + }, + adapter: staticAdapter({ + // default options are shown + pages: "build", + assets: "build", + }), + + // hydrate the
element in src/app.html + target: "#svelte", + files: { + routes: path.join(dirname, "./docs"), + template: path.join(dirname, "./docs-svelte-kit/src/app.html"), + hooks: path.join(dirname, "./docs-svelte-kit/src/hooks"), + lib: path.join(dirname, "./docs-svelte-kit/src/lib"), + assets: path.join(dirname, "./docs-svelte-kit/statics"), + }, + + vite: { + server: { + fs: { strict: false }, + }, + resolve: { + alias: { + eslint: path.join(dirname, "./docs-svelte-kit/shim/eslint.mjs"), + assert: path.join(dirname, "./docs-svelte-kit/shim/assert.mjs"), + module: path.join(dirname, "./docs-svelte-kit/shim/module.mjs"), + path: path.join(dirname, "./docs-svelte-kit/shim/path.mjs"), + url: path.join(dirname, "./docs-svelte-kit/shim/url.mjs"), + os: path.join(dirname, "./docs-svelte-kit/shim/os.mjs"), + }, + }, + plugins: [svelteMd(svelteMdOption)], + }, + }, +} +export default config diff --git a/svelte.config.js b/svelte.config.js new file mode 100644 index 000000000..b42d75340 --- /dev/null +++ b/svelte.config.js @@ -0,0 +1,28 @@ +"use strict" + +/* !! This project can't be ESM yet, so hack it to get sveltekit to work. !! */ +const esbuild = require("esbuild") +const path = require("path") + +esbuild.buildSync({ + entryPoints: [require.resolve("./svelte.config.esm.mjs")], + outfile: path.join(__dirname, "./svelte.config-dist.js"), + format: "cjs", + bundle: true, + external: [ + "path", + "cross-spawn", + "prismjs", + "./docs-svelte-kit/build-system/build.js", + ], +}) +const { register } = require("esbuild-register/dist/node") +register({ + format: "cjs", + extensions: [".js", ".mjs", ".cjs", ".ts"], +}) + +/* eslint node/no-missing-require: 0 -- ignore */ +const config = require("./svelte.config-dist.js").default + +module.exports = config diff --git a/tools/new-rule.ts b/tools/new-rule.ts index 9d9644fc0..6ae1dd327 100644 --- a/tools/new-rule.ts +++ b/tools/new-rule.ts @@ -80,7 +80,7 @@ tester.run("${ruleId}", rule as any, loadTestCases("${ruleId}")) This rule reports ???. - + @@ -95,7 +95,7 @@ This rule reports ???. \`\`\` - + ## :wrench: Options diff --git a/tools/update-docs.ts b/tools/update-docs.ts index e73d43b78..90adfb3da 100644 --- a/tools/update-docs.ts +++ b/tools/update-docs.ts @@ -167,7 +167,7 @@ ${ const { meta } = this.rule this.content = this.content.replace( - //gu, + //gu, (_t, str) => { const ps = str .split(/\s+/u) @@ -176,7 +176,7 @@ ${ if (meta.fixable) { ps.unshift("fix") } - ps.unshift("` }, ) @@ -186,12 +186,12 @@ ${ public adjustCodeBlocks() { // Adjust the necessary blank lines before and after the code block so that GitHub can recognize `.md`. this.content = this.content.replace( - /()\n+```/gu, + /()\n+```/gu, "$1\n\n```", ) this.content = this.content.replace( - /```\n+<\/eslint-code-block>/gu, - "```\n\n", + /```\n+<\/ESLintCodeBlock>/gu, + "```\n\n", ) return this } diff --git a/tools/update-readme.ts b/tools/update-readme.ts index 5db0a80b1..5c72ba069 100644 --- a/tools/update-readme.ts +++ b/tools/update-readme.ts @@ -23,31 +23,39 @@ const docsReadmeFilePath = path.resolve(__dirname, "../docs/README.md") fs.writeFileSync( docsReadmeFilePath, - newReadme - .replace("# @ota-meshi/eslint-plugin-svelte\n", "# Introduction\n") - .replace( - /[\s\S]*/u, - "See [Available Rules](./rules/README.md).", - ) - .replace( - /[\s\S]*/u, - "See [User Guide](./user-guide/README.md).", - ) - .replace(/[\s\S]*?/gu, "") - .replace( - // eslint-disable-next-line regexp/no-super-linear-backtracking -- ignore - /\(https:\/\/ota-meshi.github.io\/eslint-plugin-svelte(.*?)([^/]*\.html)?\)/gu, - (_ptn, c1: string, c2: string) => { - let result = `(.${c1}` - if (c2) { - result += - c2 === "index.html" ? "README.md" : c2.replace(/\.html$/, ".md") - } else { - result += "README.md" - } - result += ")" - return result - }, - ) - .replace(/\n{3,}/gu, "\n\n"), + `--- +title: "@ota-meshi/eslint-plugin-svelte" +--- + +${newReadme + .replace("# @ota-meshi/eslint-plugin-svelte\n", "# Introduction\n") + .replace( + /[\s\S]*/u, + "See [Available Rules](./rules/README.md).", + ) + .replace( + /[\s\S]*/u, + "See [User Guide](./user-guide/README.md).", + ) + .replace(/[\s\S]*?/gu, "") + .replace( + // eslint-disable-next-line regexp/no-super-linear-backtracking -- ignore + /\(https:\/\/ota-meshi.github.io\/eslint-plugin-svelte(.*?)([^/]*\.html)?\)/gu, + (_ptn, c1: string, c2: string) => { + let result = `(.${c1}` + if (c2) { + result += + c2 === "index.html" ? "README.md" : c2.replace(/\.html$/, ".md") + } else { + result += "README.md" + } + result += ")" + return result + }, + ) + .replace( + "[LICENSE](LICENSE)", + "[LICENSE](https://github.com/ota-meshi/eslint-plugin-svelte/blob/main/LICENSE)", + ) + .replace(/\n{3,}/gu, "\n\n")}`, ) From 5ebcb1c5192de7230929dd23a4ce8d8f4d84f5df Mon Sep 17 00:00:00 2001 From: yosuke ota Date: Sat, 4 Dec 2021 22:02:30 +0900 Subject: [PATCH 02/10] update wf --- .github/workflows/GHPages.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/GHPages.yml b/.github/workflows/GHPages.yml index 3ab2aaafe..740f7eb16 100644 --- a/.github/workflows/GHPages.yml +++ b/.github/workflows/GHPages.yml @@ -1,6 +1,7 @@ name: GHPages on: + workflow_dispatch: null push: branches: [main] From 079e8c67d7187f0b1465186c144b07d88f16333a Mon Sep 17 00:00:00 2001 From: yosuke ota Date: Sun, 5 Dec 2021 13:13:00 +0900 Subject: [PATCH 03/10] Update style --- docs-svelte-kit/src/lib/footer/Footer.svelte | 7 +- docs-svelte-kit/src/lib/header/Header.svelte | 86 +++++++++++++++++-- .../src/lib/markdown/Markdown.svelte | 19 +++- .../src/lib/sidemenu/SideMenu.svelte | 25 +++++- .../src/lib/sidemenu/UlMenu.svelte | 4 +- docs-svelte-kit/src/lib/utils.js | 2 + docs-svelte-kit/src/site.css | 55 +++++++++++- docs/__layout.svelte | 3 - 8 files changed, 178 insertions(+), 23 deletions(-) diff --git a/docs-svelte-kit/src/lib/footer/Footer.svelte b/docs-svelte-kit/src/lib/footer/Footer.svelte index 6680335ef..8b7a626fa 100644 --- a/docs-svelte-kit/src/lib/footer/Footer.svelte +++ b/docs-svelte-kit/src/lib/footer/Footer.svelte @@ -103,7 +103,7 @@ display: flex; } .footer-move { - border-top: 1px solid rgba(255, 255, 255, 0.7); + border-top: 1px solid var(--background-without-opacity); width: 100%; padding: 1rem; box-sizing: border-box; @@ -131,6 +131,11 @@ padding-left: 16.4rem; } } + @media (max-width: 719px) { + footer:not(.hidden-menu) { + padding-left: 0; + } + } footer { display: flex; diff --git a/docs-svelte-kit/src/lib/header/Header.svelte b/docs-svelte-kit/src/lib/header/Header.svelte index 7f90ee598..fa028de4c 100644 --- a/docs-svelte-kit/src/lib/header/Header.svelte +++ b/docs-svelte-kit/src/lib/header/Header.svelte @@ -1,13 +1,33 @@
@@ -30,6 +50,11 @@ Playground + @@ -72,7 +97,8 @@ height: 3em; } - .corner a { + .corner a, + .sidebar-button { display: flex; align-items: center; justify-content: center; @@ -80,26 +106,64 @@ height: 100%; } + .sidebar-button, + .nav-title { + display: none; + } + @media (max-width: 719px) { + .sidebar-button { + display: flex; + } + .corner .home-link { + display: none; + } + .nav-title { + display: flex; + background: var(--background-without-opacity); + max-width: calc(100vw - 170px); + } + .nav-title a { + height: 3rem; + object-fit: contain; + font-size: 0.5rem; + } + .nav-title img { + width: 2rem; + height: 2rem; + object-fit: contain; + } + nav ul { + display: none; + } + } + .corner img { width: 2em; height: 2em; object-fit: contain; } + .corner svg { + width: 2rem; + height: 2rem; + object-fit: contain; + } + .corner path { + fill: var(--heading-color); + } nav { display: flex; justify-content: center; - --background: rgba(255, 255, 255, 0.7); } - svg { + nav svg { width: 2em; height: 3em; display: block; } - path { - fill: var(--background); + nav path { + fill: var(--background-without-opacity); } ul { @@ -111,7 +175,7 @@ justify-content: center; align-items: center; list-style: none; - background: var(--background); + background: var(--background-without-opacity); background-size: contain; } @@ -150,8 +214,14 @@ color: var(--accent-color); } + .home-link, + .sidebar-button { + background: var(--background-without-opacity); + border-bottom-right-radius: 20%; + } + .github-link { - background: rgba(255, 255, 255, 0.7); + background: var(--background-without-opacity); border-bottom-left-radius: 20%; } diff --git a/docs-svelte-kit/src/lib/markdown/Markdown.svelte b/docs-svelte-kit/src/lib/markdown/Markdown.svelte index d5af3e349..eeeaf85f3 100644 --- a/docs-svelte-kit/src/lib/markdown/Markdown.svelte +++ b/docs-svelte-kit/src/lib/markdown/Markdown.svelte @@ -1,4 +1,5 @@ -{#if !frontmatter.hiddenMenu} - -{/if} +
+ + +
@@ -28,6 +36,11 @@ padding-left: 16.4rem; } } + @media (max-width: 719px) { + main:not(.hidden-menu) { + padding-left: 0; + } + } main .main-content { flex: 1; diff --git a/docs-svelte-kit/src/lib/sidemenu/SideMenu.svelte b/docs-svelte-kit/src/lib/sidemenu/SideMenu.svelte index f679432ee..512988203 100644 --- a/docs-svelte-kit/src/lib/sidemenu/SideMenu.svelte +++ b/docs-svelte-kit/src/lib/sidemenu/SideMenu.svelte @@ -1,11 +1,16 @@ - +{#if !hiddenMenu || sidebarOpen} + +{/if} diff --git a/docs-svelte-kit/src/lib/sidemenu/UlMenu.svelte b/docs-svelte-kit/src/lib/sidemenu/UlMenu.svelte index 1f3c218fa..8a187fd1c 100644 --- a/docs-svelte-kit/src/lib/sidemenu/UlMenu.svelte +++ b/docs-svelte-kit/src/lib/sidemenu/UlMenu.svelte @@ -80,8 +80,8 @@ height: 0; position: absolute; top: calc(50% - var(--size)); - left: 0; + right: 0; border: var(--size) solid transparent; - border-left: var(--size) solid var(--accent-color); + border-right: var(--size) solid var(--accent-color); } diff --git a/docs-svelte-kit/src/lib/utils.js b/docs-svelte-kit/src/lib/utils.js index 6557ac331..fe0d0fa0c 100644 --- a/docs-svelte-kit/src/lib/utils.js +++ b/docs-svelte-kit/src/lib/utils.js @@ -42,11 +42,13 @@ const SIDE_MENU = { title: "Available Rules", children: categoryRules, }, + { path: "/playground/README", title: "Playground" }, ], "/": [ { path: "/", title: "Introduction" }, { path: "/user-guide/README", title: "User Guide" }, { path: "/rules/README", title: "Available Rules" }, + { path: "/playground/README", title: "Playground" }, ], } diff --git a/docs-svelte-kit/src/site.css b/docs-svelte-kit/src/site.css index 2c774d6ab..f53478171 100644 --- a/docs-svelte-kit/src/site.css +++ b/docs-svelte-kit/src/site.css @@ -1,4 +1,53 @@ -@import "prismjs/themes/prism"; +/* @import "prismjs/themes/prism"; */ +@import "prismjs/themes/prism-tomorrow"; + +/* theme */ +:root { + --primary-color: #ffffff; + --secondary-color: #ffffff; + --tertiary-color: #edf0f8; + --background-without-opacity: rgba(255, 255, 255, 0.95); +} + +/*** markdown ***/ + +:not(pre) > code { + padding: 0.4rem; + margin: 0 0.2rem; + top: -0.1rem; + background: #e5eef5; + position: relative; + border-radius: 0.3em; + white-space: nowrap; + color: #444; + -webkit-font-smoothing: initial; +} + +blockquote { + padding: 1rem; + color: #09f; + border: 1px solid #40b3ff; + margin: 1.6rem 2.4rem 2.4rem; + padding: 0.5rem 2.4rem; + border-radius: 0.4rem; +} +blockquote p { + color: #09f; +} + +table { + margin: 0 0 2em; + width: 100%; + font-size: var(--h5); +} +td, +th { + text-align: left; + border-bottom: 1px solid rgba(0 0 0 / 0.1); + padding: 0.4rem 0.8rem 0.4rem 0; +} + +/* header */ h3, h4, @@ -18,6 +67,8 @@ h6 { font-size: 1rem; } +/*** custom container ***/ + .custom-block .custom-block-title { font-weight: 600; margin-bottom: -0.4rem; @@ -27,7 +78,7 @@ h6 { .custom-block.tip, .custom-block.warning { padding: 0.1rem 1.5rem; - border-left-width: 0.5rem; + border-left-width: 4px; border-left-style: solid; margin: 1rem 0; } diff --git a/docs/__layout.svelte b/docs/__layout.svelte index ffcc4c604..1cd89c7e7 100644 --- a/docs/__layout.svelte +++ b/docs/__layout.svelte @@ -1,9 +1,6 @@ -
- From f2e675fc4bcce0a9248f137698c7a6606f3ddebd Mon Sep 17 00:00:00 2001 From: yosuke ota Date: Sun, 5 Dec 2021 13:23:15 +0900 Subject: [PATCH 04/10] update docs --- README.md | 44 +++++++++++++++++++++--------------------- tools/update-readme.ts | 3 +-- 2 files changed, 23 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index a35aff50a..588b6bfd0 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,7 @@ This plugin provides configs: - `plugin:@ota-meshi/svelte/base` ... Configuration to enable correct Svelte parsing. - `plugin:@ota-meshi/svelte/recommended` ... Above, plus rules to prevent errors or unintended behavior. -See [the rule list](https://ota-meshi.github.io/eslint-plugin-svelte/rules/) to get the `rules` that this plugin provides. +See [the rule list](https://ota-meshi.github.io/eslint-plugin-svelte/rules/README) to get the `rules` that this plugin provides. ::: warning ❗ Attention @@ -247,11 +247,11 @@ These rules relate to possible syntax or logic errors in Svelte code: | Rule ID | Description | | |:--------|:------------|:---| -| [@ota-meshi/svelte/no-dupe-else-if-blocks](https://ota-meshi.github.io/eslint-plugin-svelte/rules/no-dupe-else-if-blocks.html) | disallow duplicate conditions in `{#if}` / `{:else if}` chains | :star: | -| [@ota-meshi/svelte/no-dynamic-slot-name](https://ota-meshi.github.io/eslint-plugin-svelte/rules/no-dynamic-slot-name.html) | disallow dynamic slot name | :star::wrench: | -| [@ota-meshi/svelte/no-not-function-handler](https://ota-meshi.github.io/eslint-plugin-svelte/rules/no-not-function-handler.html) | disallow use of not function in event handler | :star: | -| [@ota-meshi/svelte/no-object-in-text-mustaches](https://ota-meshi.github.io/eslint-plugin-svelte/rules/no-object-in-text-mustaches.html) | disallow objects in text mustache interpolation | :star: | -| [@ota-meshi/svelte/valid-compile](https://ota-meshi.github.io/eslint-plugin-svelte/rules/valid-compile.html) | disallow warnings when compiling. | :star: | +| [@ota-meshi/svelte/no-dupe-else-if-blocks](https://ota-meshi.github.io/eslint-plugin-svelte/rules/no-dupe-else-if-blocks) | disallow duplicate conditions in `{#if}` / `{:else if}` chains | :star: | +| [@ota-meshi/svelte/no-dynamic-slot-name](https://ota-meshi.github.io/eslint-plugin-svelte/rules/no-dynamic-slot-name) | disallow dynamic slot name | :star::wrench: | +| [@ota-meshi/svelte/no-not-function-handler](https://ota-meshi.github.io/eslint-plugin-svelte/rules/no-not-function-handler) | disallow use of not function in event handler | :star: | +| [@ota-meshi/svelte/no-object-in-text-mustaches](https://ota-meshi.github.io/eslint-plugin-svelte/rules/no-object-in-text-mustaches) | disallow objects in text mustache interpolation | :star: | +| [@ota-meshi/svelte/valid-compile](https://ota-meshi.github.io/eslint-plugin-svelte/rules/valid-compile) | disallow warnings when compiling. | :star: | ## Security Vulnerability @@ -259,8 +259,8 @@ These rules relate to security vulnerabilities in Svelte code: | Rule ID | Description | | |:--------|:------------|:---| -| [@ota-meshi/svelte/no-at-html-tags](https://ota-meshi.github.io/eslint-plugin-svelte/rules/no-at-html-tags.html) | disallow use of `{@html}` to prevent XSS attack | :star: | -| [@ota-meshi/svelte/no-target-blank](https://ota-meshi.github.io/eslint-plugin-svelte/rules/no-target-blank.html) | disallow `target="_blank"` attribute without `rel="noopener noreferrer"` | | +| [@ota-meshi/svelte/no-at-html-tags](https://ota-meshi.github.io/eslint-plugin-svelte/rules/no-at-html-tags) | disallow use of `{@html}` to prevent XSS attack | :star: | +| [@ota-meshi/svelte/no-target-blank](https://ota-meshi.github.io/eslint-plugin-svelte/rules/no-target-blank) | disallow `target="_blank"` attribute without `rel="noopener noreferrer"` | | ## Best Practices @@ -268,9 +268,9 @@ These rules relate to better ways of doing things to help you avoid problems: | Rule ID | Description | | |:--------|:------------|:---| -| [@ota-meshi/svelte/button-has-type](https://ota-meshi.github.io/eslint-plugin-svelte/rules/button-has-type.html) | disallow usage of button without an explicit type attribute | | -| [@ota-meshi/svelte/no-at-debug-tags](https://ota-meshi.github.io/eslint-plugin-svelte/rules/no-at-debug-tags.html) | disallow the use of `{@debug}` | :star: | -| [@ota-meshi/svelte/no-useless-mustaches](https://ota-meshi.github.io/eslint-plugin-svelte/rules/no-useless-mustaches.html) | disallow unnecessary mustache interpolations | :wrench: | +| [@ota-meshi/svelte/button-has-type](https://ota-meshi.github.io/eslint-plugin-svelte/rules/button-has-type) | disallow usage of button without an explicit type attribute | | +| [@ota-meshi/svelte/no-at-debug-tags](https://ota-meshi.github.io/eslint-plugin-svelte/rules/no-at-debug-tags) | disallow the use of `{@debug}` | :star: | +| [@ota-meshi/svelte/no-useless-mustaches](https://ota-meshi.github.io/eslint-plugin-svelte/rules/no-useless-mustaches) | disallow unnecessary mustache interpolations | :wrench: | ## Stylistic Issues @@ -278,14 +278,14 @@ These rules relate to style guidelines, and are therefore quite subjective: | Rule ID | Description | | |:--------|:------------|:---| -| [@ota-meshi/svelte/first-attribute-linebreak](https://ota-meshi.github.io/eslint-plugin-svelte/rules/first-attribute-linebreak.html) | enforce the location of first attribute | :wrench: | -| [@ota-meshi/svelte/html-quotes](https://ota-meshi.github.io/eslint-plugin-svelte/rules/html-quotes.html) | enforce quotes style of HTML attributes | :wrench: | -| [@ota-meshi/svelte/indent](https://ota-meshi.github.io/eslint-plugin-svelte/rules/indent.html) | enforce consistent indentation | :wrench: | -| [@ota-meshi/svelte/max-attributes-per-line](https://ota-meshi.github.io/eslint-plugin-svelte/rules/max-attributes-per-line.html) | enforce the maximum number of attributes per line | :wrench: | -| [@ota-meshi/svelte/mustache-spacing](https://ota-meshi.github.io/eslint-plugin-svelte/rules/mustache-spacing.html) | enforce unified spacing in mustache | :wrench: | -| [@ota-meshi/svelte/prefer-class-directive](https://ota-meshi.github.io/eslint-plugin-svelte/rules/prefer-class-directive.html) | require class directives instead of ternary expressions | :wrench: | -| [@ota-meshi/svelte/shorthand-attribute](https://ota-meshi.github.io/eslint-plugin-svelte/rules/shorthand-attribute.html) | enforce use of shorthand syntax in attribute | :wrench: | -| [@ota-meshi/svelte/spaced-html-comment](https://ota-meshi.github.io/eslint-plugin-svelte/rules/spaced-html-comment.html) | enforce consistent spacing after the `` in a HTML comment | :wrench: | +| [@ota-meshi/svelte/first-attribute-linebreak](https://ota-meshi.github.io/eslint-plugin-svelte/rules/first-attribute-linebreak) | enforce the location of first attribute | :wrench: | +| [@ota-meshi/svelte/html-quotes](https://ota-meshi.github.io/eslint-plugin-svelte/rules/html-quotes) | enforce quotes style of HTML attributes | :wrench: | +| [@ota-meshi/svelte/indent](https://ota-meshi.github.io/eslint-plugin-svelte/rules/indent) | enforce consistent indentation | :wrench: | +| [@ota-meshi/svelte/max-attributes-per-line](https://ota-meshi.github.io/eslint-plugin-svelte/rules/max-attributes-per-line) | enforce the maximum number of attributes per line | :wrench: | +| [@ota-meshi/svelte/mustache-spacing](https://ota-meshi.github.io/eslint-plugin-svelte/rules/mustache-spacing) | enforce unified spacing in mustache | :wrench: | +| [@ota-meshi/svelte/prefer-class-directive](https://ota-meshi.github.io/eslint-plugin-svelte/rules/prefer-class-directive) | require class directives instead of ternary expressions | :wrench: | +| [@ota-meshi/svelte/shorthand-attribute](https://ota-meshi.github.io/eslint-plugin-svelte/rules/shorthand-attribute) | enforce use of shorthand syntax in attribute | :wrench: | +| [@ota-meshi/svelte/spaced-html-comment](https://ota-meshi.github.io/eslint-plugin-svelte/rules/spaced-html-comment) | enforce consistent spacing after the `` in a HTML comment | :wrench: | ## Extension Rules @@ -293,7 +293,7 @@ These rules extend the rules provided by ESLint itself to work well in Svelte: | Rule ID | Description | | |:--------|:------------|:---| -| [@ota-meshi/svelte/no-inner-declarations](https://ota-meshi.github.io/eslint-plugin-svelte/rules/no-inner-declarations.html) | disallow variable or `function` declarations in nested blocks | :star: | +| [@ota-meshi/svelte/no-inner-declarations](https://ota-meshi.github.io/eslint-plugin-svelte/rules/no-inner-declarations) | disallow variable or `function` declarations in nested blocks | :star: | ## System @@ -301,8 +301,8 @@ These rules relate to this plugin works: | Rule ID | Description | | |:--------|:------------|:---| -| [@ota-meshi/svelte/comment-directive](https://ota-meshi.github.io/eslint-plugin-svelte/rules/comment-directive.html) | support comment-directives in HTML template | :star: | -| [@ota-meshi/svelte/system](https://ota-meshi.github.io/eslint-plugin-svelte/rules/system.html) | system rule for working this plugin | :star: | +| [@ota-meshi/svelte/comment-directive](https://ota-meshi.github.io/eslint-plugin-svelte/rules/comment-directive) | support comment-directives in HTML template | :star: | +| [@ota-meshi/svelte/system](https://ota-meshi.github.io/eslint-plugin-svelte/rules/system) | system rule for working this plugin | :star: | diff --git a/tools/update-readme.ts b/tools/update-readme.ts index 5c72ba069..649ac76ed 100644 --- a/tools/update-readme.ts +++ b/tools/update-readme.ts @@ -3,8 +3,7 @@ import fs from "fs" import renderRulesTableContent from "./render-rules" const insertText = `\n${renderRulesTableContent( - (name) => - `https://ota-meshi.github.io/eslint-plugin-svelte/rules/${name}.html`, + (name) => `https://ota-meshi.github.io/eslint-plugin-svelte/rules/${name}`, )}\n` const readmeFilePath = path.resolve(__dirname, "../README.md") From db0fce055655327f243ce33a41f1c181968e4298 Mon Sep 17 00:00:00 2001 From: yosuke ota Date: Sun, 5 Dec 2021 13:39:50 +0900 Subject: [PATCH 05/10] update paths --- README.md | 4 +- docs-svelte-kit/src/lib/footer/Footer.svelte | 6 +- docs-svelte-kit/src/lib/header/Header.svelte | 12 ++-- docs-svelte-kit/src/lib/utils.js | 12 ++-- docs/README.md | 6 +- docs/{playground/README.md => playground.md} | 2 +- docs/rules.md | 73 ++++++++++++++++++++ docs/rules/README.md | 73 -------------------- docs/{user-guide/README.md => user-guide.md} | 2 +- src/utils/index.ts | 2 +- tools/render-rules.ts | 2 +- tools/update-docs-rules-index.ts | 2 +- tools/update-readme.ts | 6 +- 13 files changed, 103 insertions(+), 99 deletions(-) rename docs/{playground/README.md => playground.md} (87%) create mode 100644 docs/rules.md delete mode 100644 docs/rules/README.md rename docs/{user-guide/README.md => user-guide.md} (98%) diff --git a/README.md b/README.md index 588b6bfd0..6b27f16b0 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ `@ota-meshi/eslint-plugin-svelte` is ESLint plugin for Svelte. It provides many unique check rules by using the template AST. -You can check on the [Online DEMO](https://ota-meshi.github.io/eslint-plugin-svelte/playground/). +You can check on the [Online DEMO](https://ota-meshi.github.io/eslint-plugin-svelte/playground). ::: **_WORKS IN PROGRESS_** ::: @@ -85,7 +85,7 @@ This plugin provides configs: - `plugin:@ota-meshi/svelte/base` ... Configuration to enable correct Svelte parsing. - `plugin:@ota-meshi/svelte/recommended` ... Above, plus rules to prevent errors or unintended behavior. -See [the rule list](https://ota-meshi.github.io/eslint-plugin-svelte/rules/README) to get the `rules` that this plugin provides. +See [the rule list](https://ota-meshi.github.io/eslint-plugin-svelte/rules) to get the `rules` that this plugin provides. ::: warning ❗ Attention diff --git a/docs-svelte-kit/src/lib/footer/Footer.svelte b/docs-svelte-kit/src/lib/footer/Footer.svelte index 8b7a626fa..30c7c41bc 100644 --- a/docs-svelte-kit/src/lib/footer/Footer.svelte +++ b/docs-svelte-kit/src/lib/footer/Footer.svelte @@ -42,7 +42,11 @@