`
+}
+
+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("
+
+
+ `
+ }
+}
+
+/** 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..51cc6567b 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -1,8 +1,12 @@
+---
+title: "@ota-meshi/eslint-plugin-svelte"
+---
+
# Introduction
`@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](./playground/README.md).
+You can check on the [Online DEMO](./playground.md).
::: **_WORKS IN PROGRESS_** :::
@@ -38,14 +42,14 @@ The [svelte-eslint-parser] and the `@ota-meshi/eslint-plugin-svelte` can not be
## :book: Usage
-See [User Guide](./user-guide/README.md).
+See [User Guide](./user-guide.md).
## :white_check_mark: Rules
-See [Available Rules](./rules/README.md).
+See [Available Rules](./rules.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..1cd89c7e7
--- /dev/null
+++ b/docs/__layout.svelte
@@ -0,0 +1,6 @@
+
+
+
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.md
similarity index 59%
rename from docs/playground/README.md
rename to docs/playground.md
index cfd2c1f88..ff3a9945b 100644
--- a/docs/playground/README.md
+++ b/docs/playground.md
@@ -1,11 +1,12 @@
---
pageClass: "playground"
+hiddenMenu: true
---
# Playground
-
+
-The playground is [here](https://ota-meshi.github.io/eslint-plugin-svelte/playground/)!!
+The playground is [here](https://ota-meshi.github.io/eslint-plugin-svelte/README)!!
-
+
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.md b/docs/rules.md
new file mode 100644
index 000000000..049be17b6
--- /dev/null
+++ b/docs/rules.md
@@ -0,0 +1,73 @@
+---
+sidebarDepth: 0
+---
+
+# Available Rules
+
+The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) automatically fixes problems reported by rules which have a wrench :wrench: below.
+The rules with the following star :star: are included in the `plugin:@ota-meshi/svelte/recommended` config.
+
+
+
+## Possible Errors
+
+These rules relate to possible syntax or logic errors in Svelte code:
+
+| Rule ID | Description | |
+|:--------|:------------|:---|
+| [@ota-meshi/svelte/no-dupe-else-if-blocks](./rules/no-dupe-else-if-blocks.md) | disallow duplicate conditions in `{#if}` / `{:else if}` chains | :star: |
+| [@ota-meshi/svelte/no-dynamic-slot-name](./rules/no-dynamic-slot-name.md) | disallow dynamic slot name | :star::wrench: |
+| [@ota-meshi/svelte/no-not-function-handler](./rules/no-not-function-handler.md) | disallow use of not function in event handler | :star: |
+| [@ota-meshi/svelte/no-object-in-text-mustaches](./rules/no-object-in-text-mustaches.md) | disallow objects in text mustache interpolation | :star: |
+| [@ota-meshi/svelte/valid-compile](./rules/valid-compile.md) | disallow warnings when compiling. | :star: |
+
+## Security Vulnerability
+
+These rules relate to security vulnerabilities in Svelte code:
+
+| Rule ID | Description | |
+|:--------|:------------|:---|
+| [@ota-meshi/svelte/no-at-html-tags](./rules/no-at-html-tags.md) | disallow use of `{@html}` to prevent XSS attack | :star: |
+| [@ota-meshi/svelte/no-target-blank](./rules/no-target-blank.md) | disallow `target="_blank"` attribute without `rel="noopener noreferrer"` | |
+
+## Best Practices
+
+These rules relate to better ways of doing things to help you avoid problems:
+
+| Rule ID | Description | |
+|:--------|:------------|:---|
+| [@ota-meshi/svelte/button-has-type](./rules/button-has-type.md) | disallow usage of button without an explicit type attribute | |
+| [@ota-meshi/svelte/no-at-debug-tags](./rules/no-at-debug-tags.md) | disallow the use of `{@debug}` | :star: |
+| [@ota-meshi/svelte/no-useless-mustaches](./rules/no-useless-mustaches.md) | disallow unnecessary mustache interpolations | :wrench: |
+
+## Stylistic Issues
+
+These rules relate to style guidelines, and are therefore quite subjective:
+
+| Rule ID | Description | |
+|:--------|:------------|:---|
+| [@ota-meshi/svelte/first-attribute-linebreak](./rules/first-attribute-linebreak.md) | enforce the location of first attribute | :wrench: |
+| [@ota-meshi/svelte/html-quotes](./rules/html-quotes.md) | enforce quotes style of HTML attributes | :wrench: |
+| [@ota-meshi/svelte/indent](./rules/indent.md) | enforce consistent indentation | :wrench: |
+| [@ota-meshi/svelte/max-attributes-per-line](./rules/max-attributes-per-line.md) | enforce the maximum number of attributes per line | :wrench: |
+| [@ota-meshi/svelte/mustache-spacing](./rules/mustache-spacing.md) | enforce unified spacing in mustache | :wrench: |
+| [@ota-meshi/svelte/prefer-class-directive](./rules/prefer-class-directive.md) | require class directives instead of ternary expressions | :wrench: |
+| [@ota-meshi/svelte/shorthand-attribute](./rules/shorthand-attribute.md) | enforce use of shorthand syntax in attribute | :wrench: |
+| [@ota-meshi/svelte/spaced-html-comment](./rules/spaced-html-comment.md) | enforce consistent spacing after the `` in a HTML comment | :wrench: |
+
+## Extension Rules
+
+These rules extend the rules provided by ESLint itself to work well in Svelte:
+
+| Rule ID | Description | |
+|:--------|:------------|:---|
+| [@ota-meshi/svelte/no-inner-declarations](./rules/no-inner-declarations.md) | disallow variable or `function` declarations in nested blocks | :star: |
+
+## System
+
+These rules relate to this plugin works:
+
+| Rule ID | Description | |
+|:--------|:------------|:---|
+| [@ota-meshi/svelte/comment-directive](./rules/comment-directive.md) | support comment-directives in HTML template | :star: |
+| [@ota-meshi/svelte/system](./rules/system.md) | system rule for working this plugin | :star: |
diff --git a/docs/rules/README.md b/docs/rules/README.md
deleted file mode 100644
index 47b1abf66..000000000
--- a/docs/rules/README.md
+++ /dev/null
@@ -1,73 +0,0 @@
----
-sidebarDepth: 0
----
-
-# Available Rules
-
-The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) automatically fixes problems reported by rules which have a wrench :wrench: below.
-The rules with the following star :star: are included in the `plugin:@ota-meshi/svelte/recommended` config.
-
-
-
-## Possible Errors
-
-These rules relate to possible syntax or logic errors in Svelte code:
-
-| Rule ID | Description | |
-|:--------|:------------|:---|
-| [@ota-meshi/svelte/no-dupe-else-if-blocks](./no-dupe-else-if-blocks.md) | disallow duplicate conditions in `{#if}` / `{:else if}` chains | :star: |
-| [@ota-meshi/svelte/no-dynamic-slot-name](./no-dynamic-slot-name.md) | disallow dynamic slot name | :star::wrench: |
-| [@ota-meshi/svelte/no-not-function-handler](./no-not-function-handler.md) | disallow use of not function in event handler | :star: |
-| [@ota-meshi/svelte/no-object-in-text-mustaches](./no-object-in-text-mustaches.md) | disallow objects in text mustache interpolation | :star: |
-| [@ota-meshi/svelte/valid-compile](./valid-compile.md) | disallow warnings when compiling. | :star: |
-
-## Security Vulnerability
-
-These rules relate to security vulnerabilities in Svelte code:
-
-| Rule ID | Description | |
-|:--------|:------------|:---|
-| [@ota-meshi/svelte/no-at-html-tags](./no-at-html-tags.md) | disallow use of `{@html}` to prevent XSS attack | :star: |
-| [@ota-meshi/svelte/no-target-blank](./no-target-blank.md) | disallow `target="_blank"` attribute without `rel="noopener noreferrer"` | |
-
-## Best Practices
-
-These rules relate to better ways of doing things to help you avoid problems:
-
-| Rule ID | Description | |
-|:--------|:------------|:---|
-| [@ota-meshi/svelte/button-has-type](./button-has-type.md) | disallow usage of button without an explicit type attribute | |
-| [@ota-meshi/svelte/no-at-debug-tags](./no-at-debug-tags.md) | disallow the use of `{@debug}` | :star: |
-| [@ota-meshi/svelte/no-useless-mustaches](./no-useless-mustaches.md) | disallow unnecessary mustache interpolations | :wrench: |
-
-## Stylistic Issues
-
-These rules relate to style guidelines, and are therefore quite subjective:
-
-| Rule ID | Description | |
-|:--------|:------------|:---|
-| [@ota-meshi/svelte/first-attribute-linebreak](./first-attribute-linebreak.md) | enforce the location of first attribute | :wrench: |
-| [@ota-meshi/svelte/html-quotes](./html-quotes.md) | enforce quotes style of HTML attributes | :wrench: |
-| [@ota-meshi/svelte/indent](./indent.md) | enforce consistent indentation | :wrench: |
-| [@ota-meshi/svelte/max-attributes-per-line](./max-attributes-per-line.md) | enforce the maximum number of attributes per line | :wrench: |
-| [@ota-meshi/svelte/mustache-spacing](./mustache-spacing.md) | enforce unified spacing in mustache | :wrench: |
-| [@ota-meshi/svelte/prefer-class-directive](./prefer-class-directive.md) | require class directives instead of ternary expressions | :wrench: |
-| [@ota-meshi/svelte/shorthand-attribute](./shorthand-attribute.md) | enforce use of shorthand syntax in attribute | :wrench: |
-| [@ota-meshi/svelte/spaced-html-comment](./spaced-html-comment.md) | enforce consistent spacing after the `` in a HTML comment | :wrench: |
-
-## Extension Rules
-
-These rules extend the rules provided by ESLint itself to work well in Svelte:
-
-| Rule ID | Description | |
-|:--------|:------------|:---|
-| [@ota-meshi/svelte/no-inner-declarations](./no-inner-declarations.md) | disallow variable or `function` declarations in nested blocks | :star: |
-
-## System
-
-These rules relate to this plugin works:
-
-| Rule ID | Description | |
-|:--------|:------------|:---|
-| [@ota-meshi/svelte/comment-directive](./comment-directive.md) | support comment-directives in HTML template | :star: |
-| [@ota-meshi/svelte/system](./system.md) | system rule for working this plugin | :star: |
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
```
-
+
## :wrench: Options
diff --git a/docs/rules/no-object-in-text-mustaches.md b/docs/rules/no-object-in-text-mustaches.md
index 4c096423b..e9a9f8ce1 100644
--- a/docs/rules/no-object-in-text-mustaches.md
+++ b/docs/rules/no-object-in-text-mustaches.md
@@ -17,7 +17,7 @@ since: "v0.5.0"
This rule disallows the use of objects in text mustache interpolation.
When you use an object for text interpolation, it is drawn as `[object Object]`. It's almost always a mistake. You may have written a lot of unnecessary curly braces.
-
+
@@ -36,7 +36,7 @@ When you use an object for text interpolation, it is drawn as `[object Object]`.
```
-
+
## :wrench: Options
diff --git a/docs/rules/no-target-blank.md b/docs/rules/no-target-blank.md
index 43873fc3c..bd42a39c0 100644
--- a/docs/rules/no-target-blank.md
+++ b/docs/rules/no-target-blank.md
@@ -14,7 +14,7 @@ since: "v0.0.4"
This rule disallows using `target="_blank"` attribute without `rel="noopener noreferrer"` to avoid a security vulnerability([see here for more details](https://mathiasbynens.github.io/rel-noopener/)).
-
+
@@ -30,7 +30,7 @@ This rule disallows using `target="_blank"` attribute without `rel="noopener nor
link
```
-
+
## :wrench: Options
@@ -51,7 +51,7 @@ This rule disallows using `target="_blank"` attribute without `rel="noopener nor
### `{ allowReferrer: false }` (default)
-
+
@@ -67,11 +67,11 @@ This rule disallows using `target="_blank"` attribute without `rel="noopener nor
link
```
-
+
### `{ allowReferrer: true }`
-
+
@@ -87,11 +87,11 @@ This rule disallows using `target="_blank"` attribute without `rel="noopener nor
link
```
-
+
### `{ "enforceDynamicLinks": "always" }` (default)
-
+
@@ -107,11 +107,11 @@ This rule disallows using `target="_blank"` attribute without `rel="noopener nor
link
```
-
+
### `{ "enforceDynamicLinks": "never" }`
-
+
@@ -127,7 +127,7 @@ This rule disallows using `target="_blank"` attribute without `rel="noopener nor
link
```
-
+
## :rocket: Version
diff --git a/docs/rules/no-useless-mustaches.md b/docs/rules/no-useless-mustaches.md
index fc776e9de..44fb1cce8 100644
--- a/docs/rules/no-useless-mustaches.md
+++ b/docs/rules/no-useless-mustaches.md
@@ -17,7 +17,7 @@ since: "v0.0.4"
This rule reports mustache interpolation with a string literal value.
The mustache interpolation with a string literal value can be changed to a static contents.
-
+
@@ -38,7 +38,7 @@ Lorem ipsum {foo}
```
-
+
## :wrench: Options
@@ -59,7 +59,7 @@ Lorem ipsum {foo}
### `"ignoreIncludesComment": true`
-
+
@@ -75,11 +75,11 @@ Lorem ipsum {foo}
```
-
+
### `"ignoreStringEscape": true`
-
+
```svelte
@@ -87,7 +87,7 @@ Lorem ipsum {foo}
```
-
+
## :rocket: Version
diff --git a/docs/rules/prefer-class-directive.md b/docs/rules/prefer-class-directive.md
index 4d5b29c4b..7cd683172 100644
--- a/docs/rules/prefer-class-directive.md
+++ b/docs/rules/prefer-class-directive.md
@@ -16,7 +16,7 @@ since: "v0.0.1"
This rule aims to replace a class with ternary operator with the class directive.
-
+
@@ -32,7 +32,7 @@ This rule aims to replace a class with ternary operator with the class directive
```
-
+
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/docs/user-guide/README.md b/docs/user-guide.md
similarity index 98%
rename from docs/user-guide/README.md
rename to docs/user-guide.md
index 0b6be57c5..f7e63ef82 100644
--- a/docs/user-guide/README.md
+++ b/docs/user-guide.md
@@ -42,7 +42,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](../rules/README.md) to get the `rules` that this plugin provides.
+See [the rule list](./rules.md) to get the `rules` that this plugin provides.
::: warning ❗ Attention
diff --git a/package.json b/package.json
index 1baa0e718..961dc7fd6 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",
+ "docs:watch": "svelte-kit dev",
+ "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",
+ "pre_docs:watch": "npm run build:ts",
+ "_docs:watch": "vuepress dev --debug docs",
+ "_docs:build": "vuepress build docs --no-cache",
"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/src/utils/index.ts b/src/utils/index.ts
index 6ce7d340c..febe653f3 100644
--- a/src/utils/index.ts
+++ b/src/utils/index.ts
@@ -14,7 +14,7 @@ export function createRule(
...rule.meta,
docs: {
...rule.meta.docs,
- url: `https://ota-meshi.github.io/eslint-plugin-svelte/rules/${ruleName}.html`,
+ url: `https://ota-meshi.github.io/eslint-plugin-svelte/rules/${ruleName}`,
ruleId: `@ota-meshi/svelte/${ruleName}`,
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