Coder Social home page Coder Social logo

vite-plugin-stylelint's Introduction

Hi there. I'm ModyQyW. 👋🏻

I'm a front-end developer using Vue and React (mostly Vue 😝). I'm also a TypeScript full-stack developer (mostly CRUD 🤣). I keep learning to make myself better. You can check out my GitHub profile, my website, or my resume to learn more about me.

Please consider sponsor me if you think my work are valuable. 🤩

Please consider hire me for your project and pay me by the hour if you find some of my work experience may do a great help. 🥹

ModyQyW's github stats ModyQyW's Top Langs

vite-plugin-stylelint's People

Contributors

gxmari007 avatar indexxuan avatar modyqyw avatar ricardogobbosouza avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

Forkers

hawtinzeng

vite-plugin-stylelint's Issues

Update prettier to v3

Clear and concise description of the problem

Update prettier to v3

Suggested solution

Update prettier to v3

Alternative

No response

Additional context

No response

Validations

  • Follow our Code of Conduct
  • Check that there isn't already an issue that request the same feature to avoid creating a duplicate.

Lint some files twice

The plugin gets two kinds of id in transform hook.

First kind of id:

  • /Users/wurui/Documents/libraries/vite-plugin-stylelint/examples/vue/src/tailwind.css
  • /Users/wurui/Documents/libraries/vite-plugin-stylelint/examples/vue/src/components/hello-world.vue

Second kind of id (with ? and type=style following):

  • /Users/wurui/Documents/libraries/vite-plugin-stylelint/examples/vue/src/components/hello-world.vue?vue&type=style&index=0&scoped=071dd9ae&lang.css

The plugins will receive two kinds of id when first start and receive a second kind when update a vue file. So, the plugin logs twice for hello-world.vue when first start and logs once when update hello-world.vue.

I think we can distinguish between different files. For .vue files (maybe .svelte files too), lint when receiving a second kine of id. For other files, lint when receiving a first kind of id.

It will be launched in v4.2.0 likely. Please be patient. Thanks.

Vite 5 semver in `peerDependencies`

描述问题

Now that Vite ^5.0.0 is released, probably the peerDependencies should be updated:

from:

    "vite": "^2.0.0 || ^3.0.0 || ^4.0.0 || 5.0.0-0"

to:

    "vite": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0"

复现

n/a

系统信息

n/a

使用的包管理器

npm

核对

  • 遵循我们的 行为准则
  • 检查是否已经有一个报告相同错误的问题,以避免重复创建。
  • 这是一个具体的错误。请开启 GitHub 讨论你的疑问。
  • 所提供的复现是这个问题的 最小复现

Wrong `StylelintPluginOptions` type

Describe the bug

Argument of type '{ fix: boolean; include: string[]; }' is not assignable to parameter of type 'StylelintPluginOptions'.
  Object literal may only specify known properties, and 'fix' does not exist in type 'StylelintPluginOptions'.ts(2345)

Reproduction

In nuxt.config.ts file (Nuxt 3):

export default defineNuxtConfig({
	// ...
	vite: {
		plugins: [
			stylelint({
				fix: true,
			}),
		],
	}
});

image

System Info

系统信息

System:
    OS: Windows 10 10.0.22000
    CPU: (8) x64 Intel(R) Core(TM) i5-8300H CPU @ 2.30GHz
    Memory: 6.33 GB / 15.88 GB
  Binaries:
    Node: 16.11.0 - C:\Program Files\nodejs\node.EXE
    Yarn: 1.22.19 - ~\AppData\Roaming\npm\yarn.CMD
    npm: 8.0.0 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Edge: Spartan (44.22000.120.0), Chromium (107.0.1418.24)
    Internet Explorer: 11.0.22000.120

Used Package Manager

yarn

Validations

  • Follow our Code of Conduct
  • Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
  • Check that this is a concrete bug. For Q&A, please open a GitHub Discussion instead.
  • The provided reproduction is a minimal reproducible of the bug.

The plugin doesn't report the source of synax error

Describe the bug 描述问题

The plugin doesn't report the source of synax error .
But ,it's ok when i use CLI.

不知道来源,就不知道改哪里了。

Reproduction 复现

This is my console when use plugin.

 WARN  19:06:27 [vite] warning: Unexpected empty block (block-no-empty)                                                                                                       19:06:27  
  Plugin: vite:stylelint

This is my console when use Cli.

G:\PHPproject\eslint>npx stylelint src/app.vue
npm WARN config global `--global`, `--local` are deprecated. Use `--location=global` instead.

src/app.vue
 17:6  ‼  Unexpected empty block   block-no-empty

Cli状态下是有错误出处的。

System Info 系统信息

window10

Used Package Manager 使用的包管理器

yarn

Validations 核对

  • Follow our Code of Conduct 遵循我们的 行为准则
  • Check that there isn't already an issue that reports the same bug to avoid creating a duplicate. 检查是否已经有一个报告相同错误的问题,以避免重复创建。
  • Check that this is a concrete bug. For Q&A, please open a GitHub Discussion instead. 这是一个具体的错误。如有疑问,请 打开GitHub 讨论。
  • The provided reproduction is a minimal reproducible of the bug. 所提供的复现是这个问题的 最小复现

Passing `context` to `lintFiles` when enable `chokidar` breaks the build

I apologize that I may not have expressed my opinion correctly and completely before. And sorry I am late in response.

Normally, enabling lintInWorker would only show errors and warnings in the console, but otherwise in the console and the browser.

Now, with chokidar enabled and lintInWorker disabled, I can't pass the context to the function (see https://github.com/ModyQyW/vite-plugin-stylelint/blob/v5.1.1/src/index.ts#L78-L98 comments) because it causes an error and just quits the Vite process. This leads to the problem mentioned in nuxt-modules/stylelint#89, where the plugin only displays error and warning messages in the console, not in the browser.

I don't think adding an option called failOnError solves this problem. To fix this, we need to pass the context and avoid the error.

I think we only need to quit the process if the lintOnStart option is enabled and an error is checked, which would request the user to deal with the error that exists first to avoid caching issues ⬇️, which is exactly what this plugin currently behaves like.

image

Originally posted by @ModyQyW in #50 (comment)

nuxt 3 vs vite-plugin-stylelint 4.0.0

Describe the bug

for a reason I don't understand vite-plugin-stylelint 4.0.0 crashes nuxt 3 on start while 3.3.3 works fine

ERROR  Cannot start nuxt:  Cannot read properties of undefined (reading 'formatters')
at formatError (/home/amery/projects/xxxx/node_modules/.pnpm/[email protected][email protected]/node_modules/vite/dist/node/chunks/dep-5605cfa4.js:40281:46)
  at Context.error (/home/amery/projects/xxxx/node_modules/.pnpm/[email protected][email protected]/node_modules/vite/dist/node/chunks/dep-5605cfa4.js:40277:19)
  at L (/home/amery/projects/xxxx/node_modules/vite-plugin-stylelint/dist/index.js:2:1208)
  at async Context.buildStart (/home/amery/projects/xxx/node_modules/.pnpm/[email protected]_r2tgf73irdyaz3c772gabqao7i/node_modules/vite-plugin-stylelint/dist/index.js:2:2031)
  at async Promise.all (index 5)
  at async hookParallel (/home/amery/projects/xxxx/node_modules/.pnpm/[email protected][email protected]/node_modules/vite/dist/node/chunks/dep-5605cfa4.js:40168:9)
  at async Object.buildStart (/home/amery/projects/xxxx/node_modules/.pnpm/[email protected][email protected]/node_modules/vite/dist/node/chunks/dep-5605cfa4.js:40439:13)
  at async /home/amery/projects/xxxx/node_modules/.pnpm/[email protected][email protected]/node_modules/vite/dist/node/chunks/dep-5605cfa4.js:62181:13
  at async Module.createServer (/home/amery/projects/xxxx/node_modules/.pnpm/[email protected][email protected]/node_modules/vite/dist/node/chunks/dep-5605cfa4.js:62206:9)
  at async buildClient (/home/amery/projects/xxxx/node_modules/.pnpm/@[email protected]_qj7x6gp3rczsq4mh5nosxx3oaq/node_modules/@nuxt/vite-builder/dist/shared/vite-builder.1c88b3ee.mjs:299:24)

Reproduction

My integration is very simple, nuxt.config.ts looks like this:

import StylelintPlugin from "vite-plugin-stylelint";

const autoFix: boolean = false;

export default defineNuxtConfig({
  [...]

  vite: {
    server: {
      strictPort: true,
    },

    plugins: [
      StylelintPlugin({
        fix: autoFix,
      }),
    ],
  },
});

### System Info

```Shell
$ pnpx envinfo --system --binaries --browsers
.../../../.pnpm-store/v3/tmp/dlx-21225   |   +1 +
.../../../.pnpm-store/v3/tmp/dlx-21225   | Progress: resolved 1, reused 1, downloaded 0, added 1, done

  System:
    OS: Linux 5.15 Ubuntu 22.04.1 LTS 22.04.1 LTS (Jammy Jellyfish)
    CPU: (8) x64 Intel(R) Core(TM) i7-8665U CPU @ 1.90GHz
    Memory: 13.78 GB / 31.02 GB
    Container: Yes
    Shell: 5.1.16 - /bin/bash
  Binaries:
    Node: 16.18.1 - /usr/bin/node
    Yarn: 1.22.19 - /usr/bin/yarn
    npm: 8.9.0 - ~/projects/xxx/bin/npm

$ pnpm list
Legend: production dependency, optional only, dev only

xxxx@22.12.1+dev /home/amery/projects/xxxx/web/client (PRIVATE)

dependencies:
@xxx/xx-types link:../../src/packages/types
@nuxtjs-alt/proxy 2.1.2
@pinia/nuxt 0.4.6
@popperjs/core 2.11.6
bootstrap link:../../../../github.com/amery/bootstrap-ssr
bootstrap-vue-3 link:../../../../github.com/amery/bootstrap-vue-3-ssr/packages/bootstrap-vue-3
pinia 2.0.28

devDependencies:
@nuxtjs/eslint-config-typescript 12.0.0  nuxt 3.0.0                               stylelint-config-recommended-vue 1.4.0   
eslint 8.29.0                            postcss-html 1.5.0                       stylelint-prettier 2.0.0                 
eslint-config-prettier 8.5.0             prettier 2.8.1                           typescript 4.9.4                         
eslint-plugin-prettier 4.2.1             sass 1.56.2                              vite-plugin-eslint 1.8.1                 
eslint-plugin-ssr-friendly 1.2.0         stylelint 14.16.0                        vite-plugin-stylelint 4.0.0              
eslint-plugin-vue 9.8.0                  stylelint-config-prettier 9.0.4          
npm-run-all 4.1.5                        stylelint-config-recommended-scss 8.0.0  

[22:54:17] [amery@d4902d6312b5(pts/0)client]$ pnpm info vite

vite@4.0.0 | MIT | deps: 5 | versions: 391
Native-ESM powered web dev build tool
https://github.com/vitejs/vite/tree/main/#readme

bin: vite

dist
.tarball: https://registry.npmjs.org/vite/-/vite-4.0.0.tgz
.shasum: b81b88349a06b2faaa53ae14cf96c942548e3454
.integrity: sha512-ynad+4kYs8Jcnn8J7SacS9vAbk7eMy0xWg6E7bAhS1s79TK+D7tVFGXVZ55S7RNLRROU1rxoKlvZ/qjaB41DGA==
.unpackedSize: 3.2 MB

dependencies:
esbuild: ^0.16.3 fsevents: ~2.3.2 postcss: ^8.4.19 resolve: ^1.22.1 rollup: ^3.7.0   

maintainers:
- soda <npm@haoqun.me>
- vitebot <vitejs.twitter@gmail.com>
- yyx990803 <yyx990803@gmail.com>
- patak <matias.capeletto@gmail.com>
- antfu <anthonyfu117@hotmail.com>

dist-tags:
alpha: 4.0.0-alpha.6  beta: 4.0.0-beta.7    latest: 4.0.0         

published yesterday by vitebot <vitejs.twitter@gmail.com>

Used Package Manager

pnpm

Validations

  • Follow our Code of Conduct
  • Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
  • Check that this is a concrete bug. For Q&A, please open a GitHub Discussion instead.
  • The provided reproduction is a minimal reproducible of the bug.

Svelte example

I use React and Vue mostly and know little about Svelte. Also, I have no more time to learn about Svelte. Welcome PR. :)

No filename or line number?

Describe the bug

error when starting dev server:
Error: Unexpected duplicate "display" (declaration-block-no-duplicate-properties)
    at formatError (/Users/whatever/Documents/company/project/node_modules/vite/dist/node/chunks/dep-689425f3.js:39080:46)
    at Context.error (/Users/whatever/Documents/company/project/node_modules/vite/dist/node/chunks/dep-689425f3.js:39076:19)
    at /Users/whatever/Documents/company/project/node_modules/vite-plugin-stylelint/dist/index.js:1:2047
    at async S (/Users/whatever/Documents/company/project/node_modules/vite-plugin-stylelint/dist/index.js:1:1627)
    at async Context.buildStart (/Users/whatever/Documents/company/project/node_modules/vite-plugin-stylelint/dist/index.js:1:2404)
    at async Promise.all (index 15)
    at async Object.buildStart (/Users/whatever/Documents/company/project/node_modules/vite/dist/node/chunks/dep-689425f3.js:39230:13)
    at async Server.httpServer.listen (/Users/whatever/Documents/company/project/node_modules/vite/dist/node/chunks/dep-689425f3.js:60350:21)

This output is completely garbled, even with sourcemaps inlined into my build. Why is there no filename or even a line number included in the report?

Reproduction

Use SFC syntax in Vite. Add issue to the styles.

<template>
...
</template>
<script setup lang="ts">
// ...
});
</script>
<style lang="scss">
// ... errors in here
</style>
// my vite config
  // Note: Only For Production Build
  build: {
    sourcemap: 'inline',
    lib: {
      entry: path.resolve(__dirname, 'src/entry.ts'),
      formats: ['cjs', 'umd'],
      name: 'connect',
      fileName: 'connect',
    },
    rollupOptions: {
      output: {
        assetFileNames: 'connect.[ext]',
      },
    },
  },

  plugins: [
    vue(),
    checker({
      vueTsc: true,
    }),
    eslint({
      fix: true,
      lintOnStart: true,
      include: ['src/**/*.js', 'src/**/*.ts', '**/*.vue'],
    }),
    StylelintPlugin({
      lintOnStart: true,
      fix: true,
    }),
  ],

System Info

System:
    OS: macOS 12.0.1
    CPU: (10) arm64 Apple M1 Max
    Memory: 3.63 GB / 64.00 GB
    Shell: 3.2.57 - /bin/bash
  Binaries:
    Node: 14.18.2 - ~/.nvm/versions/node/v14.18.2/bin/node
    Yarn: 1.22.17 - ~/.nvm/versions/node/v14.18.2/bin/yarn
    npm: 8.2.0 - ~/.nvm/versions/node/v14.18.2/bin/npm

Used Package Manager

yarn

Validations

  • Follow our Code of Conduct
  • Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
  • Check that this is a concrete bug. For Q&A, please open a GitHub Discussion instead.
  • The provided reproduction is a minimal reproducible of the bug.

Missing typescript definition for `fix` option

This option is not documented, but show in the first exemple.
Capture d’écran, le 2022-07-06 à 16 53 29

This option is not included in the type definition export.
Capture d’écran, le 2022-07-06 à 16 51 07

So if I try to use it, my app wont build and throw this error:

Argument of type '{ fix: boolean; }' is not assignable to parameter of type 'Options'. Object literal may only specify known properties, and 'fix' does not exist in type 'Options'.

Doesnt seem to work after buildStart

Describe the bug

I load up a simple app with a stylelint error (in this case I have added 0px as a value, so the Unexpected unit rule is triggered).
Saving the file after a change witht he error still there shows no console error. Adding a new styleint error into the file does not report any error.

On first load, I see an error in my console. If I create any other stylelint error, it will not output in my console.

If I start vite with no errors and then introduce one, it does not report any error.

Perhaps the issue is that I do not include any styles in my entry point at all?

I treat my scss as a seperate input:

build: {
	manifest: true,
	emptyOutDir: true,
	outDir: 'public',
	assetsDir: 'build',
	rollupOptions: {
		input: {
			js: `${env.VITE_SRC_DIR}/js/theme.js`,
			styles: `${env.VITE_SRC_DIR}/sass/style.scss`
		}
	}
},

Reproduction

This is my styleint config

{
    "extends": "stylelint-config-sass-guidelines",
    "rules": {
        "indentation": "tab",
        "string-quotes": null,
        "number-leading-zero": null,
        "no-missing-end-of-source-newline": null,
        "order/properties-alphabetical-order": null,
        "property-no-vendor-prefix": null,
        "max-nesting-depth": null,
        "selector-max-compound-selectors": 5,
        "selector-class-pattern": null,
        "selector-pseudo-element-colon-notation": "single",
        "declaration-property-value-disallowed-list": null,
        "color-named": [
            "never",
            {
                "ignore": ["inside-function"]
            }
        ],
        "selector-no-qualifying-type": [
            true,
            {
                "ignore": [
                    "attribute"
                ]
            }
        ]
    }
}

this is my plugin config:

stylelint({
	fix: false,
	include: ``${env.VITE_SRC_DIR}/sass/**/*.scss`,
	lintOnStart: false,
	lintInWorker: true
	// emitErrorAsWarning: true
})

And this is an offending scss file:

pre {
	margin-top: 0px;
	// top: 0px;
}

System Info

System:
    OS: Windows 10 10.0.22621
    CPU: (20) x64 12th Gen Intel(R) Core(TM) i7-12700KF
    Memory: 40.96 GB / 63.86 GB
  Binaries:
    Node: 16.14.0 - C:\Program Files\nodejs\node.EXE
    npm: 8.3.1 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Edge: Spartan (44.22621.963.0), Chromium (108.0.1462.76)
    Internet Explorer: 11.0.22621.1


### Used Package Manager

npm

### Validations

- [X] Follow our [Code of Conduct](https://github.com/ModyQyW/.github/blob/main/CODE_OF_CONDUCT.md)
- [X] Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
- [X] Check that this is a concrete bug. For Q&A, please open a GitHub Discussion instead.
- [X] The provided reproduction is a [minimal reproducible](https://stackoverflow.com/help/minimal-reproducible-example) of the bug.

`output` is deprecated. Use `report` or `code` instead.

Describe the bug

The new version of stylelint shows that.
I think it's because of this line

const result = { ...linterResult };

Reproduction

Try to use it with stylelint@16

System Info

oh come on

Used Package Manager

pnpm

Validations

  • Follow our Code of Conduct
  • Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
  • Check that this is a concrete bug. For Q&A, please open a GitHub Discussion instead.
  • The provided reproduction is a minimal reproducible of the bug.

Update package for rollup v4 support

Describe the bug

Not compatible with rollup v4. Please update. Thank you.

─┬ vite-plugin-stylelint 5.1.1
  └── ✕ unmet peer rollup@"^2.0.0 || ^3.0.0": found 4.1.4

Reproduction

https://github.com/webdevnerdstuff/vuetify-color-picker-field

System Info

System:
    OS: macOS 13.5.2
    CPU: (10) arm64 Apple M1 Max
    Memory: 4.69 GB / 64.00 GB
    Shell: 3.2.57 - /bin/bash
  Binaries:
    Node: 20.4.0 - ~/.nvm/versions/node/v20.4.0/bin/node
    Yarn: 1.22.19 - ~/node_modules/.bin/yarn
    npm: 9.7.2 - ~/.nvm/versions/node/v20.4.0/bin/npm
    pnpm: 8.6.9 - ~/.nvm/versions/node/v20.4.0/bin/pnpm

Used Package Manager

pnpm

Validations

  • Follow our Code of Conduct
  • Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
  • Check that this is a concrete bug. For Q&A, please open a GitHub Discussion instead.
  • The provided reproduction is a minimal reproducible of the bug.

Error: Dynamic require of "tty" is not supported

描述问题

failed to load config from /home/ian/acte/roomzz-v1/admin_ts/vite.config.ts
error when starting dev server:
Error: Dynamic require of "tty" is not supported
at file:///home/ian/acte/roomzz-v1/admin_ts/node_modules/.pnpm/[email protected]_hdr6qhp2cp4t47liatlblyjedi/node_modules/vite-plugin-stylelint/dist/index.js:1:376
at file:///home/ian/acte/roomzz-v1/admin_ts/node_modules/.pnpm/[email protected]_hdr6qhp2cp4t47liatlblyjedi/node_modules/vite-plugin-stylelint/dist/index.js:1:853
at file:///home/ian/acte/roomzz-v1/admin_ts/node_modules/.pnpm/[email protected]_hdr6qhp2cp4t47liatlblyjedi/node_modules/vite-plugin-stylelint/dist/index.js:1:491
at file:///home/ian/acte/roomzz-v1/admin_ts/node_modules/.pnpm/[email protected]_hdr6qhp2cp4t47liatlblyjedi/node_modules/vite-plugin-stylelint/dist/index.js:1:2468
at ModuleJob.run (node:internal/modules/esm/module_job:193:25)
at async Promise.all (index 0)
at async ESMLoader.import (node:internal/modules/esm/loader:530:24)
at async loadConfigFromBundledFile (file:///home/ian/acte/roomzz-v1/admin_ts/node_modules/.pnpm/[email protected]_p56klvi3zg3u723wp3set4h7pe/node_modules/vite/dist/node/chunks/dep-2285ba4f.js:63052:21)
at async loadConfigFromFile (file:///home/ian/acte/roomzz-v1/admin_ts/node_modules/.pnpm/[email protected]_p56klvi3zg3u723wp3set4h7pe/node_modules/vite/dist/node/chunks/dep-2285ba4f.js:62937:28)
at async resolveConfig (file:///home/ian/acte/roomzz-v1/admin_ts/node_modules/.pnpm/[email protected]_p56klvi3zg3u723wp3set4h7pe/node_modules/vite/dist/node/chunks/dep-2285ba4f.js:62558:28)
 ELIFECYCLE  Command failed with exit code 1.

复现

my vite.config.ts setting is

import react from "@vitejs/plugin-react-swc";
import { resolve } from 'path';
import eslintPlugin from 'vite-plugin-eslint';
import stylelintPlugin from 'vite-plugin-stylelint';
import { defineConfig } from 'vitest/config';

export default defineConfig({
test: {
globals: true,
environment: 'happy-dom',
},
plugins: [
react(),
stylelintPlugin(),
eslintPlugin()
],
resolve: {
alias: {
src: resolve(__dirname, 'src'),
},
},
});

系统信息

System:
    OS: Linux 5.15 Ubuntu 22.04.1 LTS 22.04.1 LTS (Jammy Jellyfish)
    CPU: (8) x64 Intel(R) Core(TM) i5-8250U CPU @ 1.60GHz
    Memory: 5.60 GB / 7.69 GB
    Container: Yes
    Shell: 5.8.1 - /usr/bin/zsh
  Binaries:
    Node: 18.12.0 - ~/.local/share/pnpm/node
    npm: 8.19.2 - ~/.local/share/pnpm/npm

使用的包管理器

pnpm

核对

  • 遵循我们的 行为准则
  • 检查是否已经有一个报告相同错误的问题,以避免重复创建。
  • 这是一个具体的错误。请开启 GitHub 讨论你的疑问。
  • 所提供的复现是这个问题的 最小复现

Doesn't lint `@import` scss in Vue SFC <style> block

Importing a test.scss in that scope doesn't lint that test.scss still (it does compile!)

index.vue:

<style lang="scss" scoped>
@import "test";
</style>

test.scss:

.glorp {
  margin: 0;
  font-size: 40px;
      padding: 12px;
        clor: yellow;
}

test.scss DOES compile; but does NOT lint

Bare in mind: Running my linter via NPM does pickup the error:
script in package.json:
"lint:css": "stylelint ./**/*.{vue,scss} --fix",

npm run lint:css

> [email protected] lint:css
> stylelint ./**/*.{vue,scss} --fix


src/views/Home/test.scss
 5:9  ✖  Unexpected unknown property "clor"  property-no-unknown

Originally posted by @timenengwerda in #8 (comment)

SyntaxError: Named export 'formatters' not found

Describe the bug

file [email protected]_ngd3nnoldxv7gfhbrkt64hq3pu/node_modules/vite-plugin-stylelint/dist/index.mjs:2

var oe=Object.create;var vt=Object.defineProperty;var ie=Object.getOwnPropertyDescriptor;var ue=Object.getOwnPropertyNames;var ae=Object.getPrototypeOf,le=Object.prototype.hasOwnProperty;var nt=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(o,e)=>(typeof require<"u"?require:o)[e]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw new Error('Dynamic require of "'+t+'" is not supported')});var ce=(t,o)=>()=>(t&&(o=t(t=0)),o);var et=(t,o)=>()=>(o||t((o={exports:{}}).exports,o),o.exports);var pe=(t,o,e,c)=>{if(o&&typeof o=="object"||typeof o=="function")for(let a of ue(o))!le.call(t,a)&&a!==e&&vt(t,a,{get:()=>o[a],enumerable:!(c=ie(o,a))||c.enumerable});return t};var t=(t,o,e)=>(e=t!=null?oe(ae(t)):{},pe(o||!t||!t.__esModule?vt(e,"default",{value:t,enumerable:!0}):e,t));var k=ce(()=>{});var ot=et((or,wt)=>{"use strict";k();var fe=nt("path"),V="\\/",Ht=[^${V}],W="\.",he="\+",ye="\?",pt="\/",Ae="(?=.)",Ot="[^/]",Rt=(?:${pt}|$),Lt=(?:^|${pt}),gt=${W}{1,2}${Rt},e=(?!${W}),Re=(?!${Lt}${gt}),ge=(?!${W}{0,1}${Rt}),Ee=(?!${gt}),me=[^.${pt}],Se=${Ot}*?,Tt={DOT_LITERAL:W,PLUS_LITERAL:he,QMARK_LITERAL:ye,SLASH_LITERAL:pt,ONE_CHAR:Ae,QMARK:Ot,END_ANCHOR:Rt,DOTS_SLASH:gt,NO_DOT:e,NO_DOTS:Re,NO_DOT_SLASH:ge,NO_DOTS_SLASH:Ee,QMARK_NO_DOT:me,STAR:Se,START_ANCHOR:Lt},de={...Tt,SLASH_LITERAL:[${V}],QMARK:Ht,STAR:${Ht}*?,DOTS_SLASH:${W}{1,2}(?:[${V}]|$),NO_DOT:(?!${W}),NO_DOTS:(?!(?:^|[${V}])${W}{1,2}(?:[${V}]|$)),NO_DOT_SLASH:(?!${W}{0,1}(?:[${V}]|$)),NO_DOTS_SLASH:(?!${W}{1,2}(?:[${V}]|$)),QMARK_NO_DOT:[^.${V}],START_ANCHOR:(?:^|[${V}]),END_ANCHOR:(?:[${V}]|$)},$e={alnum:"a-zA-Z0-9",alpha:"a-zA-Z",ascii:"\x00-\x7F",blank:" \t",cntrl:"\x00-\x1F\x7F",digit:"0-9",graph:"\x21-\x7E",lower:"a-z",print:"\x20-\x7E
",punct:"\-!"#$%&'()\*+,./:;<=>?@[\]^
{|}~",space:" \\t\\r\\n\\v\\f",upper:"A-Z",word:"A-Za-z0-9_",xdigit:"A-Fa-f0-9"};wt.exports={MAX_LENGTH:1024*64,POSIX_REGEX_SOURCE:$e,REGEX_BACKSLASH:/\\(?![*+?^${}(|)[\]])/g,REGEX_NON_SPECIAL_CHARS:/^[^@![\].,$*+?^{}()|\\/]+/,REGEX_SPECIAL_CHARS:/[-*+?.^${}(|)[\]]/,REGEX_SPECIAL_CHARS_BACKREF:/(\\?)((\W)(\3*))/g,REGEX_SPECIAL_CHARS_GLOBAL:/([-*+?.^${}(|)[\]])/g,REGEX_REMOVE_BACKSLASH:/(?:\[.*?[^\\]\]|\\(?=.))/g,REPLACEMENTS:{"***":"*","**/**":"**","**/**/**":"**"},CHAR_0:48,CHAR_9:57,CHAR_UPPERCASE_A:65,CHAR_LOWERCASE_A:97,CHAR_UPPERCASE_Z:90,CHAR_LOWERCASE_Z:122,CHAR_LEFT_PARENTHESES:40,CHAR_RIGHT_PARENTHESES:41,CHAR_ASTERISK:42,CHAR_AMPERSAND:38,CHAR_AT:64,CHAR_BACKWARD_SLASH:92,CHAR_CARRIAGE_RETURN:13,CHAR_CIRCUMFLEX_ACCENT:94,CHAR_COLON:58,CHAR_COMMA:44,CHAR_DOT:46,CHAR_DOUBLE_QUOTE:34,CHAR_EQUAL:61,CHAR_EXCLAMATION_MARK:33,CHAR_FORM_FEED:12,CHAR_FORWARD_SLASH:47,CHAR_GRAVE_ACCENT:96,CHAR_HASH:35,CHAR_HYPHEN_MINUS:45,CHAR_LEFT_ANGLE_BRACKET:60,CHAR_LEFT_CURLY_BRACE:123,CHAR_LEFT_SQUARE_BRACKET:91,CHAR_LINE_FEED:10,CHAR_NO_BREAK_SPACE:160,CHAR_PERCENT:37,CHAR_PLUS:43,CHAR_QUESTION_MARK:63,CHAR_RIGHT_ANGLE_BRACKET:62,CHAR_RIGHT_CURLY_BRACE:125,CHAR_RIGHT_SQUARE_BRACKET:93,CHAR_SEMICOLON:59,CHAR_SINGLE_QUOTE:39,CHAR_SPACE:32,CHAR_TAB:9,CHAR_UNDERSCORE:95,CHAR_VERTICAL_LINE:124,CHAR_ZERO_WIDTH_NOBREAK_SPACE:65279,SEP:fe.sep,extglobChars(t){return{"!":{type:"negate",open:"(?:(?!(?:",close:))${t.STAR})},"?":{type:"qmark",open:"(?:",close:")?"},"+":{type:"plus",open:"(?:",close:")+"},"*":{type:"star",open:"(?:",close:")*"},"@":{type:"at",open:"(?:",close:")"}}},globChars(t){return t===!0?de:Tt}}});var ft=et(F=>{"use strict";k();var xe=nt("path"),be=process.platform==="win32",{REGEX_BACKSLASH:Ce,REGEX_REMOVE_BACKSLASH:ve,REGEX_SPECIAL_CHARS:He,REGEX_SPECIAL_CHARS_GLOBAL:Oe}=ot();F.isObject=t=>t!==null&&typeof t=="object"&&!Array.isArray(t);F.hasRegexChars=t=>He.test(t);F.isRegexChar=t=>t.length===1&&F.hasRegexChars(t);F.escapeRegex=t=>t.replace(Oe,"\\$1");F.toPosixSlashes=t=>t.replace(Ce,"/");F.removeBackslashes=t=>t.replace(ve,o=>o==="\\"?"":o);F.supportsLookbehinds=()=>{let t=process.version.slice(1).split(".").map(Number);return t.length===3&&t[0]>=9||t[0]===8&&t[1]>=10};F.isWindows=t=>t&&typeof t.windows=="boolean"?t.windows:be===!0||xe.sep==="\\";F.escapeLast=(t,o,e)=>{let c=t.lastIndexOf(o,e);return c===-1?t:t[c-1]==="\\"?F.escapeLast(t,o,c-1):${t.slice(0,c)}\${t.slice(c)}};F.removePrefix=(t,o={})=>{let e=t;return e.startsWith("./")&&(e=e.slice(2),o.prefix="./"),e};F.wrapOutput=(t,o={},e={})=>{let c=e.contains?"":"^",a=e.contains?"":"$",y=${c}(?:${t})${a};return o.negated===!0&&(y=(?:^(?!${y}).$)),y}});var Gt=et((lr,Ft)=>{"use strict";k();var kt=ft(),{CHAR_ASTERISK:Et,CHAR_AT:Le,CHAR_BACKWARD_SLASH:it,CHAR_COMMA:Te,CHAR_DOT:mt,CHAR_EXCLAMATION_MARK:St,CHAR_FORWARD_SLASH:Mt,CHAR_LEFT_CURLY_BRACE:dt,CHAR_LEFT_PARENTHESES:$t,CHAR_LEFT_SQUARE_BRACKET:we,CHAR_PLUS:ke,CHAR_QUESTION_MARK:It,CHAR_RIGHT_CURLY_BRACE:Ie,CHAR_RIGHT_PARENTHESES:Nt,CHAR_RIGHT_SQUARE_BRACKET:Ne}=ot(),Pt=t=>t===Mt||t===it,Dt=t=>{t.isPrefix!==!0&&(t.depth=t.isGlobstar?1/0:1)},Pe=(t,o)=>{let e=o||{},c=t.length-1,a=e.parts===!0||e.scanToEnd===!0,y=[],l=[],f=[],p=t,R=-1,A=0,E=0,v=!1,T=!1,d=!1,H=!1,z=!1,K=!1,U=!1,O=!1,q=!1,N=!1,Z=0,P,h,S={value:"",depth:0,isGlob:!1},I=()=>R>=c,n=()=>p.charCodeAt(R+1),b=()=>(P=h,p.charCodeAt(++R));for(;R<c;){h=b();let D;if(h===it){U=S.backslashes=!0,h=b(),h===dt&&(K=!0);continue}if(K===!0||h===dt){for(Z++;I()!==!0&&(h=b());){if(h===it){U=S.backslashes=!0,b();continue}if(h===dt){Z++;continue}if(K!==!0&&h===mt&&(h=b())===mt){if(v=S.isBrace=!0,d=S.isGlob=!0,N=!0,a===!0)continue;break}if(K!==!0&&h===Te){if(v=S.isBrace=!0,d=S.isGlob=!0,N=!0,a===!0)continue;break}if(h===Ie&&(Z--,Z===0)){K=!1,v=S.isBrace=!0,N=!0;break}}if(a===!0)continue;break}if(h===Mt){if(y.push(R),l.push(S),S={value:"",depth:0,isGlob:!1},N===!0)continue;if(P===mt&&R===A+1){A+=2;continue}E=R+1;continue}if(e.noext!==!0&&(h===ke||h===Le||h===Et||h===It||h===St)===!0&&n()===$t){if(d=S.isGlob=!0,H=S.isExtglob=!0,N=!0,h===St&&R===A&&(q=!0),a===!0){for(;I()!==!0&&(h=b());){if(h===it){U=S.backslashes=!0,h=b();continue}if(h===Nt){d=S.isGlob=!0,N=!0;break}}continue}break}if(h===Et){if(P===Et&&(z=S.isGlobstar=!0),d=S.isGlob=!0,N=!0,a===!0)continue;break}if(h===It){if(d=S.isGlob=!0,N=!0,a===!0)continue;break}if(h===we){for(;I()!==!0&&(D=b());){if(D===it){U=S.backslashes=!0,b();continue}if(D===Ne){T=S.isBracket=!0,d=S.isGlob=!0,N=!0;break}}if(a===!0)continue;break}if(e.nonegate!==!0&&h===St&&R===A){O=S.negated=!0,A++;continue}if(e.noparen!==!0&&h===$t){if(d=S.isGlob=!0,a===!0){for(;I()!==!0&&(h=b());){if(h===$t){U=S.backslashes=!0,h=b();continue}if(h===Nt){N=!0;break}}continue}break}if(d===!0){if(N=!0,a===!0)continue;break}}e.noext===!0&&(H=!1,d=!1);let $=p,Y="",r="";A>0&&(Y=p.slice(0,A),p=p.slice(A),E-=A),$&&d===!0&&E>0?($=p.slice(0,E),r=p.slice(E)):d===!0?($="",r=p):$=p,$&&$!==""&&$!=="/"&&$!==p&&Pt($.charCodeAt($.length-1))&&($=$.slice(0,-1)),e.unescape===!0&&(r&&(r=kt.removeBackslashes(r)),$&&U===!0&&($=kt.removeBackslashes($)));let s={prefix:Y,input:t,start:A,base:$,glob:r,isBrace:v,isBracket:T,isGlob:d,isExtglob:H,isGlobstar:z,negated:O,negatedExtglob:q};if(e.tokens===!0&&(s.maxDepth=0,Pt(h)||l.push(S),s.tokens=l),e.parts===!0||e.tokens===!0){let D;for(let m=0;m<y.length;m++){let X=D?D+1:A,Q=y[m],G=t.slice(X,Q);e.tokens&&(m===0&&A!==0?(l[m].isPrefix=!0,l[m].value=Y):l[m].value=G,Dt(l[m]),s.maxDepth+=l[m].depth),(m!==0||G!=="")&&f.push(G),D=Q}if(D&&D+1<t.length){let m=t.slice(D+1);f.push(m),e.tokens&&(l[l.length-1].value=m,Dt(l[l.length-1]),s.maxDepth+=l[l.length-1].depth)}s.slashes=y,s.parts=f}return s};Ft.exports=Pe});var Kt=et((pr,Ut)=>{"use strict";k();var ht=ot(),B=ft(),{MAX_LENGTH:yt,POSIX_REGEX_SOURCE:De,REGEX_NON_SPECIAL_CHARS:Me,REGEX_SPECIAL_CHARS_BACKREF:Fe,REPLACEMENTS:Bt}=ht,Ge=(t,o)=>{if(typeof o.expandRange=="function")return o.expandRange(...t,o);t.sort();let e=[${t.join("-")}];try{new RegExp(e)}catch{return t.map(a=>B.escapeRegex(a)).join("..")}return e},rt=(t,o)=>Missing ${t}: "${o}" - use "\\${o}" to match literal characters,xt=(t,o)=>{if(typeof t!="string")throw new TypeError("Expected a string");t=Bt[t]||t;let e={...o},c=typeof e.maxLength=="number"?Math.min(yt,e.maxLength):yt,a=t.length;if(a>c)throw new SyntaxError(Input length: ${a}, exceeds maximum allowed length: ${c});let y={type:"bos",value:"",output:e.prepend||""},l=[y],f=e.capture?"":"?:",p=B.isWindows(o),R=ht.globChars(p),A=ht.extglobChars(R),{DOT_LITERAL:E,PLUS_LITERAL:v,SLASH_LITERAL:T,ONE_CHAR:d,DOTS_SLASH:H,NO_DOT:z,NO_DOT_SLASH:K,NO_DOTS_SLASH:U,QMARK:O,QMARK_NO_DOT:q,STAR:N,START_ANCHOR:Z}=R,P=u=>(${f}(?:(?!${Z}${u.dot?H:E}).)?),h=e.dot?"":z,S=e.dot?O:q,I=e.bash===!0?P(e):N;e.capture&&(I=(${I})),typeof e.noext=="boolean"&&(e.noextglob=e.noext);let n={input:t,index:-1,start:0,dot:e.dot===!0,consumed:"",output:"",prefix:"",backtrack:!1,negated:!1,brackets:0,braces:0,parens:0,quotes:0,globstar:!1,tokens:l};t=B.removePrefix(t,n),a=t.length;let b=[],$=[],Y=[],r=y,s,D=()=>n.index===a-1,m=n.peek=(u=1)=>t[n.index+u],X=n.advance=()=>t[++n.index]||"",Q=()=>t.slice(n.index+1),G=(u="",x=0)=>{n.consumed+=u,n.index+=x},ut=u=>{n.output+=u.output!=null?u.output:u.value,G(u.value)},se=()=>{let u=1;for(;m()==="!"&&(m(2)!=="("||m(3)==="?");)X(),n.start++,u++;return u%2===0?!1:(n.negated=!0,n.start++,!0)},at=u=>{n[u]++,Y.push(u)},tt=u=>{n[u]--,Y.pop()},g=u=>{if(r.type==="globstar"){let x=n.braces>0&&(u.type==="comma"||u.type==="brace"),i=u.extglob===!0||b.length&&(u.type==="pipe"||u.type==="paren");u.type!=="slash"&&u.type!=="paren"&&!x&&!i&&(n.output=n.output.slice(0,-r.output.length),r.type="star",r.value="*",r.output=I,n.output+=r.output)}if(b.length&&u.type!=="paren"&&(b[b.length-1].inner+=u.value),(u.value||u.output)&&ut(u),r&&r.type==="text"&&u.type==="text"){r.value+=u.value,r.output=(r.output||"")+u.value;return}u.prev=r,l.push(u),r=u},lt=(u,x)=>{let i={...A[x],conditions:1,inner:""};i.prev=r,i.parens=n.parens,i.output=n.output;let _=(e.capture?"(":"")+i.open;at("parens"),g({type:u,value:x,output:n.output?"":d}),g({type:"paren",extglob:!0,value:X(),output:_}),b.push(i)},ne=u=>{let x=u.close+(e.capture?")":""),i;if(u.type==="negate"){let _=I;if(u.inner&&u.inner.length>1&&u.inner.includes("/")&&(_=P(e)),(_!==I||D()||/^\)+$/.test(Q()))&&(x=u.close=)$))${
}),u.inner.includes("*")&&(i=Q())&&/^\.[^\\/.]+$/.test(i)){let C=xt(i,{...o,fastpaths:!1}).output;x=u.close=)${C})${
})}u.prev.type==="bos"&&(n.negatedExtglob=!0)}g({type:"paren",extglob:!0,value:s,output:x}),tt("parens")};if(e.fastpaths!==!1&&!/(^[*!]|[/()[\]{}"])/.test(t)){let u=!1,x=t.replace(Fe,(i,_,C,M,w,At)=>M==="\\"?(u=!0,i):M==="?"?_?_+M+(w?O.repeat(w.length):""):At===0?S+(w?O.repeat(w.length):""):O.repeat(C.length):M==="."?E.repeat(C.length):M==="*"?_?_+M+(w?I:""):I:_?i:\${i});return u===!0&&(e.unescape===!0?x=x.replace(/\\/g,""):x=x.replace(/\\+/g,i=>i.length%2===0?"\\\\":i?"\\":"")),x===t&&e.contains===!0?(n.output=t,n):(n.output=B.wrapOutput(x,n,o),n)}for(;!D();){if(s=X(),s==="\0")continue;if(s==="\\"){let i=m();if(i==="/"&&e.bash!==!0||i==="."||i===";")continue;if(!i){s+="\\",g({type:"text",value:s});continue}let _=/^\\+/.exec(Q()),C=0;if(_&&_[0].length>2&&(C=_[0].length,n.index+=C,C%2!==0&&(s+="\\")),e.unescape===!0?s=X():s+=X(),n.brackets===0){g({type:"text",value:s});continue}}if(n.brackets>0&&(s!=="]"||r.value==="["||r.value==="[^")){if(e.posix!==!1&&s===":"){let i=r.value.slice(1);if(i.includes("[")&&(r.posix=!0,i.includes(":"))){let _=r.value.lastIndexOf("["),C=r.value.slice(0,_),M=r.value.slice(_+2),w=De[M];if(w){r.value=C+w,n.backtrack=!0,X(),!y.output&&l.indexOf(r)===1&&(y.output=d);continue}}}(s==="["&&m()!==":"||s==="-"&&m()==="]")&&(s=\${s}),s==="]"&&(r.value==="["||r.value==="[^")&&(s=\${s}),e.posix===!0&&s==="!"&&r.value==="["&&(s="^"),r.value+=s,ut({value:s});continue}if(n.quotes===1&&s!=='"'){s=B.escapeRegex(s),r.value+=s,ut({value:s});continue}if(s==='"'){n.quotes=n.quotes===1?0:1,e.keepQuotes===!0&&g({type:"text",value:s});continue}if(s==="("){at("parens"),g({type:"paren",value:s});continue}if(s===")"){if(n.parens===0&&e.strictBrackets===!0)throw new SyntaxError(rt("opening","("));let i=b[b.length-1];if(i&&n.parens===i.parens+1){ne(b.pop());continue}g({type:"paren",value:s,output:n.parens?")":"\\)"}),tt("parens");continue}if(s==="["){if(e.nobracket===!0||!Q().includes("]")){if(e.nobracket!==!0&&e.strictBrackets===!0)throw new SyntaxError(rt("closing","]"));s=\${s}}else at("brackets");g({type:"bracket",value:s});continue}if(s==="]"){if(e.nobracket===!0||r&&r.type==="bracket"&&r.value.length===1){g({type:"text",value:s,output:\${s}});continue}if(n.brackets===0){if(e.strictBrackets===!0)throw new SyntaxError(rt("opening","["));g({type:"text",value:s,output:\${s}});continue}tt("brackets");let i=r.value.slice(1);if(r.posix!==!0&&i[0]==="^"&&!i.includes("/")&&(s=/${s}),r.value+=s,ut({value:s}),e.literalBrackets===!1||B.hasRegexChars(i))continue;let _=B.escapeRegex(r.value);if(n.output=n.output.slice(0,-r.value.length),e.literalBrackets===!0){n.output+=_,r.value=_;continue}r.value=(${f}${_}|${r.value}),n.output+=r.value;continue}if(s==="{"&&e.nobrace!==!0){at("braces");let i={type:"brace",value:s,output:"(",outputIndex:n.output.length,tokensIndex:n.tokens.length};$.push(i),g(i);continue}if(s==="}"){let i=$[$.length-1];if(e.nobrace===!0||!i){g({type:"text",value:s,output:s});continue}let _=")";if(i.dots===!0){let C=l.slice(),M=[];for(let w=C.length-1;w>=0&&(l.pop(),C[w].type!=="brace");w--)C[w].type!=="dots"&&M.unshift(C[w].value);_=Ge(M,e),n.backtrack=!0}if(i.comma!==!0&&i.dots!==!0){let C=n.output.slice(0,i.outputIndex),M=n.tokens.slice(i.tokensIndex);i.value=i.output="\\{",s=_="\\}",n.output=C;for(let w of M)n.output+=w.output||w.value}g({type:"brace",value:s,output:_}),tt("braces"),$.pop();continue}if(s==="|"){b.length>0&&b[b.length-1].conditions++,g({type:"text",value:s});continue}if(s===","){let i=s,_=$[$.length-1];_&&Y[Y.length-1]==="braces"&&(_.comma=!0,i="|"),g({type:"comma",value:s,output:i});continue}if(s==="/"){if(r.type==="dot"&&n.index===n.start+1){n.start=n.index+1,n.consumed="",n.output="",l.pop(),r=y;continue}g({type:"slash",value:s,output:T});continue}if(s==="."){if(n.braces>0&&r.type==="dot"){r.value==="."&&(r.output=E);let i=$[$.length-1];r.type="dots",r.output+=s,r.value+=s,i.dots=!0;continue}if(n.braces+n.parens===0&&r.type!=="bos"&&r.type!=="slash"){g({type:"text",value:s,output:E});continue}g({type:"dot",value:s,output:E});continue}if(s==="?"){if(!(r&&r.value==="(")&&e.noextglob!==!0&&m()==="("&&m(2)!=="?"){lt("qmark",s);continue}if(r&&r.type==="paren"){let _=m(),C=s;if(_==="<"&&!B.supportsLookbehinds())throw new Error("Node.js v10 or higher is required for regex lookbehinds");(r.value==="("&&!/[!=<:]/.test(_)||_==="<"&&!/<([!=]|\w+>)/.test(Q()))&&(C=\${s}),g({type:"text",value:s,output:C});continue}if(e.dot!==!0&&(r.type==="slash"||r.type==="bos")){g({type:"qmark",value:s,output:q});continue}g({type:"qmark",value:s,output:O});continue}if(s==="!"){if(e.noextglob!==!0&&m()==="("&&(m(2)!=="?"||!/[!=<:]/.test(m(3)))){lt("negate",s);continue}if(e.nonegate!==!0&&n.index===0){se();continue}}if(s==="+"){if(e.noextglob!==!0&&m()==="("&&m(2)!=="?"){lt("plus",s);continue}if(r&&r.value==="("||e.regex===!1){g({type:"plus",value:s,output:v});continue}if(r&&(r.type==="bracket"||r.type==="paren"||r.type==="brace")||n.parens>0){g({type:"plus",value:s});continue}g({type:"plus",value:v});continue}if(s==="@"){if(e.noextglob!==!0&&m()==="("&&m(2)!=="?"){g({type:"at",extglob:!0,value:s,output:""});continue}g({type:"text",value:s});continue}if(s!=="*"){(s==="$"||s==="^")&&(s=\${s});let i=Me.exec(Q());i&&(s+=i[0],n.index+=i[0].length),g({type:"text",value:s});continue}if(r&&(r.type==="globstar"||r.star===!0)){r.type="star",r.star=!0,r.value+=s,r.output=I,n.backtrack=!0,n.globstar=!0,G(s);continue}let u=Q();if(e.noextglob!==!0&&/^\([^?]/.test(u)){lt("star",s);continue}if(r.type==="star"){if(e.noglobstar===!0){G(s);continue}let i=r.prev,_=i.prev,C=i.type==="slash"||i.type==="bos",M=_&&(_.type==="star"||_.type==="globstar");if(e.bash===!0&&(!C||u[0]&&u[0]!=="/")){g({type:"star",value:s,output:""});continue}let w=n.braces>0&&(i.type==="comma"||i.type==="brace"),At=b.length&&(i.type==="pipe"||i.type==="paren");if(!C&&i.type!=="paren"&&!w&&!At){g({type:"star",value:s,output:""});continue}for(;u.slice(0,3)==="/**";){let ct=t[n.index+4];if(ct&&ct!=="/")break;u=u.slice(3),G("/**",3)}if(i.type==="bos"&&D()){r.type="globstar",r.value+=s,r.output=P(e),n.output=r.output,n.globstar=!0,G(s);continue}if(i.type==="slash"&&i.prev.type!=="bos"&&!M&&D()){n.output=n.output.slice(0,-(i.output+r.output).length),i.output=(?:${i.output},r.type="globstar",r.output=P(e)+(e.strictSlashes?")":"|$)"),r.value+=s,n.globstar=!0,n.output+=i.output+r.output,G(s);continue}if(i.type==="slash"&&i.prev.type!=="bos"&&u[0]==="/"){let ct=u[1]!==void 0?"|$":"";n.output=n.output.slice(0,-(i.output+r.output).length),i.output=(?:${i.output},r.type="globstar",r.output=${P(e)}${T}|${T}${ct}),r.value+=s,n.output+=i.output+r.output,n.globstar=!0,G(s+X()),g({type:"slash",value:"/",output:""});continue}if(i.type==="bos"&&u[0]==="/"){r.type="globstar",r.value+=s,r.output=(?:^|${T}|${P(e)}${T}),n.output=r.output,n.globstar=!0,G(s+X()),g({type:"slash",value:"/",output:""});continue}n.output=n.output.slice(0,-r.output.length),r.type="globstar",r.output=P(e),r.value+=s,n.output+=r.output,n.globstar=!0,G(s);continue}let x={type:"star",value:s,output:I};if(e.bash===!0){x.output=".*?",(r.type==="bos"||r.type==="slash")&&(x.output=h+x.output),g(x);continue}if(r&&(r.type==="bracket"||r.type==="paren")&&e.regex===!0){x.output=s,g(x);continue}(n.index===n.start||r.type==="slash"||r.type==="dot")&&(r.type==="dot"?(n.output+=K,r.output+=K):e.dot===!0?(n.output+=U,r.output+=U):(n.output+=h,r.output+=h),m()!=="*"&&(n.output+=d,r.output+=d)),g(x)}for(;n.brackets>0;){if(e.strictBrackets===!0)throw new SyntaxError(rt("closing","]"));n.output=B.escapeLast(n.output,"["),tt("brackets")}for(;n.parens>0;){if(e.strictBrackets===!0)throw new SyntaxError(rt("closing",")"));n.output=B.escapeLast(n.output,"("),tt("parens")}for(;n.braces>0;){if(e.strictBrackets===!0)throw new SyntaxError(rt("closing","}"));n.output=B.escapeLast(n.output,"{"),tt("braces")}if(e.strictSlashes!==!0&&(r.type==="star"||r.type==="bracket")&&g({type:"maybe_slash",value:"",output:${T}?}),n.backtrack===!0){n.output="";for(let u of n.tokens)n.output+=u.output!=null?u.output:u.value,u.suffix&&(n.output+=u.suffix)}return n};xt.fastpaths=(t,o)=>{let e={...o},c=typeof e.maxLength=="number"?Math.min(yt,e.maxLength):yt,a=t.length;if(a>c)throw new SyntaxError(Input length: ${a}, exceeds maximum allowed length: ${c});t=Bt[t]||t;let y=B.isWindows(o),{DOT_LITERAL:l,SLASH_LITERAL:f,ONE_CHAR:p,DOTS_SLASH:R,NO_DOT:A,NO_DOTS:E,NO_DOTS_SLASH:v,STAR:T,START_ANCHOR:d}=ht.globChars(y),H=e.dot?E:A,z=e.dot?v:A,K=e.capture?"":"?:",U={negated:!1,prefix:""},O=e.bash===!0?".*?":T;e.capture&&(O=(${O}));let q=h=>h.noglobstar===!0?O:(${K}(?:(?!${d}${h.dot?R:l}).)?),N=h=>{switch(h){case"*":return${H}${p}${O};case".*":return${l}${p}${O};case"*.*":return${H}${O}${l}${p}${O};case"*/*":return${H}${O}${f}${p}${z}${O};case"**":return H+q(e);case"**/*":return(?:${H}${q(e)}${f})?${z}${p}${O};case"**/*.*":return(?:${H}${q(e)}${f})?${z}${O}${l}${p}${O};case"**/.*":return(?:${H}${q(e)}${f})?${l}${p}${O};default:{let S=/^(.*?)\.(\w+)$/.exec(h);if(!S)return;let I=N(S[1]);return I?I+l+S[2]:void 0}}},Z=B.removePrefix(t,U),P=N(Z);return P&&e.strictSlashes!==!0&&(P+=${f}?),P};Ut.exports=xt});var Xt=et((hr,qt)=>{"use strict";k();var Be=nt("path"),Ue=Gt(),bt=Kt(),Ct=ft(),Ke=ot(),qe=t=>t&&typeof t=="object"&&!Array.isArray(t),L=(t,o,e=!1)=>{if(Array.isArray(t)){let A=t.map(v=>L(v,o,e));return v=>{for(let T of A){let d=T(v);if(d)return d}return!1}}let c=qe(t)&&t.tokens&&t.input;if(t===""||typeof t!="string"&&!c)throw new TypeError("Expected pattern to be a non-empty string");let a=o||{},y=Ct.isWindows(o),l=c?L.compileRe(t,o):L.makeRe(t,o,!1,!0),f=l.state;delete l.state;let p=()=>!1;if(a.ignore){let A={...o,ignore:null,onMatch:null,onResult:null};p=L(a.ignore,A,e)}let R=(A,E=!1)=>{let{isMatch:v,match:T,output:d}=L.test(A,l,o,{glob:t,posix:y}),H={glob:t,state:f,regex:l,posix:y,input:A,output:d,match:T,isMatch:v};return typeof a.onResult=="function"&&a.onResult(H),v===!1?(H.isMatch=!1,E?H:!1):p(A)?(typeof a.onIgnore=="function"&&a.onIgnore(H),H.isMatch=!1,E?H:!1):(typeof a.onMatch=="function"&&a.onMatch(H),E?H:!0)};return e&&(R.state=f),R};L.test=(t,o,e,{glob:c,posix:a}={})=>{if(typeof t!="string")throw new TypeError("Expected input to be a string");if(t==="")return{isMatch:!1,output:""};let y=e||{},l=y.format||(a?Ct.toPosixSlashes:null),f=t===c,p=f&&l?l(t):t;return f===!1&&(p=l?l(t):t,f=p===c),(f===!1||y.capture===!0)&&(y.matchBase===!0||y.basename===!0?f=L.matchBase(t,o,e,a):f=o.exec(p)),{isMatch:Boolean(f),match:f,output:p}};L.matchBase=(t,o,e,c=Ct.isWindows(e))=>(o instanceof RegExp?o:L.makeRe(o,e)).test(Be.basename(t));L.isMatch=(t,o,e)=>L(o,e)(t);L.parse=(t,o)=>Array.isArray(t)?t.map(e=>L.parse(e,o)):bt(t,{...o,fastpaths:!1});L.scan=(t,o)=>Ue(t,o);L.compileRe=(t,o,e=!1,c=!1)=>{if(e===!0)return t.output;let a=o||{},y=a.contains?"":"^",l=a.contains?"":"$",f=${y}(?:${t.output})${l};t&&t.negated===!0&&(f=^(?!${f}).$);let p=L.toRegex(f,o);return c===!0&amp;&amp;(p.state=t),p};L.makeRe=(t,o={},e=!1,c=!1)=&gt;{if(!t||typeof t!="string")throw new TypeError("Expected a non-empty string");let a={negated:!1,fastpaths:!0};return o.fastpaths!==!1&amp;&amp;(t[0]==="."||t[0]==="*")&amp;&amp;(a.output=bt.fastpaths(t,o)),a.output||(a=bt(t,o)),L.compileRe(a,o,e,c)};L.toRegex=(t,o)=&gt;{try{let e=o||{};return new RegExp(t,e.flags||(e.nocase?"i":""))}catch(e){if(o&amp;&amp;o.debug===!0)throw e;return/$^/}};L.constants=Ke;qt.exports=L});var Vt=et((Ar,Qt)=&gt;{"use strict";k();Qt.exports=Xt()});k();k();var Zt=_t(Vt(),1);import{extname as gr,win32 as Xe,posix as zt,isAbsolute as Qe,resolve as Ve}from"path";function We(t){return Array.isArray(t)}function Wt(t){return We(t)?t:t==null?[]:[t]}var st=function(o){return o.split(Xe.sep).join(zt.sep)};function ze(t,o){if(o===!1||Qe(t)||t.startsWith("*"))return st(t);let e=st(Ve(o||"")).replace(/[-^$*+?.()|[\]{}]/g,"\\$&amp;");return zt.join(e,st(t))}var Yt=function(o,e,c){let a=c&amp;&amp;c.resolve,y=p=&gt;p instanceof RegExp?p:{test:R=&gt;{let A=ze(p,a);return(0,Zt.default)(A,{dot:!0})(R)}},l=Wt(o).map(y),f=Wt(e).map(y);return function(R){if(typeof R!="string"||/\0/.test(R))return!1;let A=st(R);for(let E=0;E&lt;f.length;++E)if(f[E].test(A))return!1;for(let E=0;E&lt;l.length;++E)if(l[E].test(A))return!0;return!l.length}},Ze="break case class catch const continue debugger default delete do else export extends finally for function if import in instanceof let new return super switch this throw try typeof var void while with yield enum await implements package protected static interface private public",Ye="arguments Infinity NaN undefined null true false eval uneval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent escape unescape Object Function Boolean Symbol Error EvalError InternalError RangeError ReferenceError SyntaxError TypeError URIError Number Math Date String RegExp Array Int8Array Uint8Array Uint8ClampedArray Int16Array Uint16Array Int32Array Uint32Array Float32Array Float64Array Map Set WeakMap WeakSet SIMD ArrayBuffer DataView JSON Promise Generator GeneratorFunction Reflect Proxy Intl",Je=new Set(${Ze} ${Ye}.split(" "));Je.add("");k();import{resolve as je}from"path";import{formatters as tr}from"stylelint";var Jt=t=>t.startsWith("virtual:")||t.startsWith("\0")||!t.includes("/"),jt=({cache:t,cacheLocation:o,include:e,exclude:c,stylelintPath:a,formatter:y,lintOnStart:l,emitError:f,emitErrorAsWarning:p,emitWarning:R,emitWarningAsError:A},{cacheDir:E})=>({cache:t!=null?t:!0,cacheLocation:o!=null?o:je(E,"vite-plugin-stylelint"),include:e!=null?e:["src/**/*.{css,scss,sass,less,styl,vue,svelte}"],exclude:c!=null?c:["node_modules","virtual:"],stylelintPath:a!=null?a:"stylelint",formatter:y!=null?y:"string",lintOnStart:l!=null?l:!1,emitError:f!=null?f:!0,emitErrorAsWarning:p!=null?p:!1,emitWarning:R!=null?R:!0,emitWarningAsError:A!=null?A:!1}),te=t=>Yt(t.include,t.exclude),er=t=>({...t,allowEmptyInput:!0,cache:t.cache,cacheLocation:t.cacheLocation,files:t.files}),ee=async(t,o)=>{var e;try{let a=(await Promise.resolve().then(()=>_t(nt(t.stylelintPath)))).default,y=typeof t.formatter=="string"?tr[t.formatter]:t.formatter;return{stylelint:a,formatter:y}}catch(c){console.log(""),o.error(${(e=c==null?void 0:c.message)!=null?e:"Failed to import Stylelint. Have you installed and configured correctly?"})}},re=(t,o,e)=>{let{emitError:c,emitErrorAsWarning:a,emitWarning:y,emitWarningAsError:l}=e;return async(f,p)=>await t.lint({...er(e),files:p}).then(async R=>{if(!R)return;R.results.filter(E=>!E.ignored).forEach(E=>{E.warnings.forEach(({severity:v})=>{let T=o([E],R);v==="error"&&c&&(a?f.warn(T):f.error(T)),v==="warning"&&y&&(l?f.error(T):f.warn(T))})})}).catch(R=>{var A;console.log(""),f.error(${(A=R==null?void 0:R.message)!=null?A:R})})};function rr(t={}){let o,e,c,a,y;return{name:"vite:stylelint",configResolved(l){o=jt(t,l),e=te(o)},async buildStart(){if(!c){let l=await ee(o,this);c=l.stylelint,a=l.formatter,y=re(c,a,o)}o.lintOnStart&&(console.log(""),this.warn("Stylelint is linting all files in the project because lintOnStart` is true. This will significantly slow down Vite."),await y(this,o.include))},async transform(l,f){let p=st(f).split("?")[0];return!e(p)||Jt(f)||await y(this,p),null}}}export{rr as default};

SyntaxError: Named export 'formatters' not found. The requested module 'stylelint' is a CommonJS module, which may not support all module.exports as named exports.

Reproduction

Step 1: Create a vite project by use pnpm create vite my-vue-app --template vue-ts, cd my-vue-app , and pnpm install
Step 2: pnpm install stylelint vite-plugin-stylelint@^3.1.0 -D
Step 3: in the vite.config.js file, set as follows:

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import StylelintPlugin from 'vite-plugin-stylelint';

export default defineConfig({
  plugins: [vue(),StylelintPlugin({fix:true})]
})

Step 4: pnpm run dev

Note: when replace the vite-plugin-stylelint@^3.1.0 by vite-plugin-stylelint@~3.0.10, the SyntaxError( Named export 'formatters' not found) does not occur

System Info

System:
    OS: Windows 10 10.0.19044
    CPU: (8) x64 Intel(R) Core(TM) i5-10210U CPU @ 1.60GHz   
    Memory: 7.50 GB / 15.84 GB
  Binaries:
    Node: 16.18.0 - C:\Program Files\nodejs\node.EXE
    Yarn: 1.22.19 - C:\Program Files (x86)\Yarn\bin\yarn.CMD 
    npm: 8.19.2 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Edge: Spartan (44.19041.1266.0), Chromium (107.0.1418.56)
    Internet Explorer: 11.0.19041.1566

Used Package Manager

pnpm

Validations

  • Follow our Code of Conduct
  • Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
  • Check that this is a concrete bug. For Q&A, please open a GitHub Discussion instead.
  • The provided reproduction is a minimal reproducible of the bug.

Switch to rollup and named export

Motivation

This plugin is using tsup to bundle for now. tsup is great. Bundling is fast with esbuild under the hood.

Dynamic require

I have stuck into dynamic require issues twice #16 #31.

how to fix dynamic require problem
// tsup.config.ts
import { defineConfig } from 'tsup';

export default defineConfig({
  ...,
  banner: ({ format }) => {
    if (format === 'esm') {
      return {
        // eslint-disable-next-line no-useless-escape
        js: `import {createRequire as __createRequire} from 'module';var require=__createRequire(import\.meta.url);`,
      };
    }
  },
});

The fix is simple. But I need to confirm if I need to add the fix, and the fix increases the package size.

Named export with default

module.exports.default is generated for now. But module.exports (default export) and module.exports.xxx (named export without default) are better to use.

Also, the fix is simple. But I have to add it everywhere. It is annoying.

how to fix module.exports.default problem
// tsup.config.ts
import { defineConfig } from 'tsup';

export default defineConfig({
  ...,
  footer: ({ format }) => {
    if (format === 'cjs') {
      return {
        js: `if (module.exports.default) module.exports = module.exports.default;`,
      };
    }
  },
});

Solutions

Dynamic require

This issue can be possibly solved by switching to another bundler.

There are some bundlers, such as webpack, rollup, unbuild and vite.

  • webpack is too complex to use and I don't want to spend much time on this.
  • unbuild is like tsup, but unbuild has less docs and minify issues.
  • vite library mode is based on rollup. So why not rollup directly?

I prefer rollup personally. Let me know if you have better choices.

Named export without default

We can keep named export with default, and add another named export with default. This is easy I think. Let me know if you have more ideas.

how does this plugin work with scss module?

the scss module source code is:
.myClassName {
background-color: grey;
}

the error I got while using this plugin:
[vite] Internal server error: Expected class selector to be kebab-case
Plugin: vite:stylelint
File: /home/ian/templates/react/src/components/MyComponent/style.module.scss
1 | ._myClassName_1x6hz_1 {
| ^
2 | background-color: grey;
3 | }
at formatError (/home/ian/templates/react/node_modules/.pnpm/[email protected][email protected]/node_modules/vite/dist/node/chunks/dep-59dc6e00.js:38663:46)
at TransformContext.error (/home/ian/templates/react/node_modules/.pnpm/[email protected][email protected]/node_modules/vite/dist/node/chunks/dep-59dc6e00.js:38659:19)
at /home/ian/templates/react/node_modules/.pnpm/[email protected]_wtr3vw7wiz4253njg4veakonmm/node_modules/vite-plugin-stylelint/dist/index.js:1:2442
at Array.forEach ()
at /home/ian/templates/react/node_modules/.pnpm/[email protected]_wtr3vw7wiz4253njg4veakonmm/node_modules/vite-plugin-stylelint/dist/index.js:1:2320
at Array.forEach ()
at /home/ian/templates/react/node_modules/.pnpm/[email protected]_wtr3vw7wiz4253njg4veakonmm/node_modules/vite-plugin-stylelint/dist/index.js:1:2275
at async TransformContext.transform (/home/ian/templates/react/node_modules/.pnpm/[email protected]_wtr3vw7wiz4253njg4veakonmm/node_modules/vite-plugin-stylelint/dist/index.js:1:2103)
at async Object.transform (/home/ian/templates/react/node_modules/.pnpm/[email protected][email protected]/node_modules/vite/dist/node/chunks/dep-59dc6e00.js:38900:30)
at async doTransform (/home/ian/templates/react/node_modules/.pnpm/[email protected][email protected]/node_modules/vite/dist/node/chunks/dep-59dc6e00.js:55857:29)

V4 roadmap

I am preparing v4 and I want your opinions and suggestions.

Async mode default

Maybe in v4, or in v5.

This plugin lints files synchronously for now and slows down Vite a lot. Vite means quick in French but this plugin breaks the meaning.

I want to add async mode and make it the default mode. This can make the plugin faster, without slowing down Vite. However, the async mode will most likely no longer stop the serve or build process. Since errors and warnings can be found in the IDE while developing, I don't think this is a serious problem.

In the meantime, you may want vite-plugin-checker.

Apply during serve default

Done

This plugin is invoked for both serve and build for now. Since almost everyone uses this plugin during serve, it is meaningless to apply this plugin during build.

cacheLocation update

Done

To be more out of box, cacheLocation defaults to .stylelintcache.

Support vite@4

Done

See Vite 4 discussion. Support vite@3 if possible, but drop vite@2.

Support stylelint@15

Maybe in a minor version since stylelint@15 is not released

See stylelint preparing 15.0.0. Support stylelint@14 if possible, but drop stylelint@13.

Require node >= 14.18

Done

See Node.js realease schedule.

ESM default

Done

node >= 14.18 has full support for esm. Can remove esm bundle banner too.

Scss errors are shown only after manual reload or .vue file change

I have a pretty vanilla Vite+Vue3+Eslint+Stylelint project running at the moment to see how the setup works.

I've got everything working properly now except for the stylelinter:

Whenever I make an inline scss error and save it; nothing happens. No error is shown in my terminal or my server HMR overlay.
Only after I refresh my browser manually the error is shown. When I fix the error HMR kicks back in and reloads my page without any issue.

Making another change in my .vue file seems to do the trick aswell to fire off the error belatedly.

Since it's pretty annoying to manually refresh or to make another change in my vue file I'd like stylelint to just show me my error right off the bat.

This is my .vue file with the faulty scss:

<template>
  <div class="glorp">
    <h1>Home index</h1>
  </div>
</template>
<script>
export default {
  name: 'HomeIndex',
};
</script>
<style lang="scss" scoped>
.glorp {
  background: #avc;
}
</style>

Obviously #avc is incorrect; so it shows me the warning(after refresh or other change):

Internal server error: Unexpected invalid hex color "#avc" (color-no-invalid-hex)

My vite.config.js (Located in root, I've tried turning off other plugins etc one-by-one without results)

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import eslintPlugin from 'vite-plugin-eslint';
import StylelintPlugin from 'vite-plugin-stylelint';
import babel from 'vite-plugin-babel';
import { fileURLToPath } from "url";

const esLintConfig = eslintPlugin({
  fix: true,
  cache: false // when cache is true modules are only linted once on startup and when fixed it won't check for errors in the entire file again
});

const styleLintConfig = StylelintPlugin({
  fix: true,
  cache: false
});

export default defineConfig({
  server: {
    host: true
  },
  plugins: [
    styleLintConfig,
    esLintConfig,
    babel(),
    vue(),
  ],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL("./src", import.meta.url)),
    },
  },
})

And my stylelint.config.js (located in root)

module.exports = {
  extends: [
    'stylelint-config-standard-scss', // Load the standard stylelint configuration
    'stylelint-config-recommended-vue',
    'stylelint-config-rational-order',
  ],
  plugins: [
    'stylelint-declaration-block-no-ignored-properties', // This plugin checks for ignored properties and throws error if so
  ],
};

And (for what it's worth) my package.json:

{
  "name": "piniata",
  "private": true,
  "version": "0.0.0",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview",
    "lint:css": "stylelint ./**/*.{vue,scss} --fix",
    "lint:js": "cross-env NODE_ENV=production eslint src --ext .js --ext .vue --fix"
  },
  "dependencies": {
    "vue": "^3.2.25",
    "vue-router": "^4.0.15"
  },
  "devDependencies": {
    "@vitejs/plugin-vue": "^2.3.3",
    "@vue/eslint-config-airbnb": "^6.0.0",
    "cross-env": "^7.0.3",
    "eslint-plugin-vue": "^8.7.1",
    "sass": "^1.51.0",
    "sass-loader": "^12.6.0",
    "stylelint": "^14.8.2",
    "stylelint-config-rational-order": "^0.1.2",
    "stylelint-config-recommended-vue": "^1.4.0",
    "stylelint-config-standard-scss": "^3.0.0",
    "stylelint-declaration-block-no-ignored-properties": "^2.5.0",
    "vite": "^2.9.9",
    "vite-plugin-babel": "^1.0.0",
    "vite-plugin-eslint": "^1.6.0",
    "vite-plugin-stylelint": "^2.2.2"
  }
}

As an aside: Importing .scss files in my .vue file or just having existing .scss files aren't even detected by my config at all (although it does function and compile properly)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.