wechat
ihzero 2023-09-04 17:08:58 +08:00
parent 7eb7e05bf4
commit 18708200b3
16 changed files with 12145 additions and 2 deletions

View File

@ -96,9 +96,10 @@
"jest": "^25.4.0",
"mini-types": "*",
"miniprogram-api-typings": "*",
"node-sass": "^4.14.1",
"postcss-comment": "^2.0.0",
"sass-loader": "^10.1.1",
"postcss-windicss": "file:src/vendor/postcss-windicss",
"sass": "^1.43.4",
"sass-loader": "^8.0.2",
"stylus": "^0.54.8",
"stylus-loader": "^3.0.2",
"vue-template-compiler": "^2.6.11"

View File

@ -1,8 +1,10 @@
const path = require('path')
const webpack = require('webpack')
const config = {
parser: require('postcss-comment'),
plugins: [
require('postcss-windicss')({}),
require('postcss-import')({
resolve (id, basedir, importOptions) {
if (id.startsWith('~@/')) {

5
src/vendor/README.md vendored 100644
View File

@ -0,0 +1,5 @@
## Project setup
```
自定义插件
```

View File

@ -0,0 +1,2 @@
dist
node_modules

View File

@ -0,0 +1,8 @@
{
"env": {
"jest": true
},
"extends": ["@antfu"],
"plugins": ["jest"],
"rules": {}
}

View File

@ -0,0 +1,84 @@
# Created by .ignore support plugin (hsz.mobi)
### Node template
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# We use pnpm instead of npm in this project.
package-lock.json
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
# parcel-bundler cache (https://parceljs.org/)
.cache
# next.js build output
.next
# nuxt.js build output
.nuxt
# Nuxt generate
!dist
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless
# IDE
.idea

View File

@ -0,0 +1,3 @@
declare const postcss = true;
export { postcss };

View File

@ -0,0 +1,172 @@
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }var __defProp = Object.defineProperty;
var __defProps = Object.defineProperties;
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp.call(b, prop))
__defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b)) {
if (__propIsEnum.call(b, prop))
__defNormalProp(a, prop, b[prop]);
}
return a;
};
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
// src/index.ts
var _exithook = require('exit-hook'); var _exithook2 = _interopRequireDefault(_exithook);
var _postcss = require('postcss');
var _pluginutils = require('@windicss/plugin-utils');
// src/dev.ts
var _fs = require('fs');
var _chokidar = require('chokidar'); var _chokidar2 = _interopRequireDefault(_chokidar);
// src/utils.ts
async function touch(path, mode = "utime") {
if (mode === "utime")
return await touchUtime(path);
else
return await touchInsert(path);
}
var TOUCH_REG = /\/\*\s*windicss-touch:.*\*\//;
async function touchInsert(path) {
let css = await _fs.promises.readFile(path, "utf-8");
const banner = `/* windicss-touch: ${Date.now()} */`;
let replaced = false;
css = css.replace(TOUCH_REG, () => {
replaced = true;
return banner;
});
if (!replaced)
css = `${banner}
${css}`;
await _fs.promises.writeFile(path, css, "utf-8");
}
async function touchUtime(path) {
return new Promise((resolve, reject) => {
const time = new Date();
_fs.utimes.call(void 0, path, time, time, (err) => {
if (err) {
return _fs.open.call(void 0, path, "w", (err2, fd) => {
if (err2)
return reject(err2);
_fs.close.call(void 0, fd, (err3) => err3 ? reject(err3) : resolve(fd));
});
}
resolve(false);
});
});
}
// src/context.ts
var _debug2 = require('debug'); var _debug3 = _interopRequireDefault(_debug2);
var context = {};
var isDev = process.env.NODE_ENV === "development";
var debug = _debug3.default.call(void 0, "postcss-windicss");
// src/dev.ts
var watcher;
function shutdownWatcher() {
if (watcher) {
debug("shutting down watcher");
watcher.close();
watcher = void 0;
}
}
async function startDevWatcher(options = {}) {
shutdownWatcher();
debug("starting dev watcher");
const utils = context.utils;
await utils.ensureInit();
const {
touchMode = "utime"
} = options;
watcher = _chokidar2.default.watch(utils.options.scanOptions.include, {
ignored: utils.options.scanOptions.exclude,
ignoreInitial: true
});
if (utils.configFilePath)
watcher.add(utils.configFilePath);
watcher.on("change", async (path) => {
if (path === context.entry)
return;
if (path === utils.configFilePath) {
debug("reload config", utils.configFilePath);
utils.init();
return;
}
debug("update from", path);
await utils.extractFile(await _fs.promises.readFile(path, "utf-8"));
if (context.entry)
touch(context.entry, touchMode);
});
if (context.entry)
touch(context.entry, touchMode);
}
// src/index.ts
var plugin = (options) => {
if (!context.utils) {
context.utils = _pluginutils.createUtils.call(void 0, __spreadProps(__spreadValues({}, options), {
onOptionsResolved() {
if (isDev)
setTimeout(() => startDevWatcher(options));
}
}), {
name: "postcss-windicss"
});
if (isDev)
_exithook2.default.call(void 0, shutdownWatcher);
debug(isDev ? "development mode" : "production mode");
}
const utils = context.utils;
return (root) => {
const promiseArray = [];
root.walkAtRules((atRule) => {
var _a;
const entry = (_a = atRule.root().source) == null ? void 0 : _a.input.from;
if (atRule.name === "windicss") {
context.entry = entry;
promiseArray.push(utils.generateCSS().then((data) => {
atRule.replaceWith(_postcss.parse.call(void 0, data));
}));
} else if (["apply"].includes(atRule.name)) {
const rule = atRule.parent;
if (!rule)
return;
promiseArray.push(utils.ensureInit().then(() => {
const css = rule.toString();
const transformed = css ? utils.transformCSS(css, entry || "") : void 0;
if (transformed)
rule.replaceWith(_postcss.parse.call(void 0, transformed));
}));
} else if (["screen", "variants"].includes(atRule.name)) {
promiseArray.push(utils.ensureInit().then(() => {
const css = atRule.toString();
const transformed = css ? utils.transformCSS(css, entry || "") : void 0;
if (transformed)
atRule.replaceWith(_postcss.parse.call(void 0, transformed));
}));
}
});
root.walkDecls((decl) => {
const match = decl.value.match(/^\s*theme\((['"])(.*)\1\)\s*$/);
if (match && match[2])
decl.value = utils.processor.theme(match[2]).toString();
});
return Promise.all(promiseArray);
};
};
var postcss = true;
plugin.postcss = true;
module.exports = _postcss.plugin.call(void 0, "postcss-windicss", plugin);
exports.postcss = postcss;

View File

@ -0,0 +1,12 @@
module.exports = {
roots: [
'<rootDir>/test',
],
testMatch: [
'**/__tests__/**/*.+(ts|tsx|js)',
'**/?(*.)+(spec|test).+(ts|tsx|js)',
],
transform: {
'^.+\\.(ts|tsx)$': 'ts-jest',
},
}

View File

@ -0,0 +1,48 @@
{
"name": "postcss-windicss",
"version": "1.0.0",
"keywords": [
"postcss",
"postcss-plugin",
"windicss"
],
"files": [
"dist"
],
"scripts": {
"prepublishOnly": "npm run build",
"dev": "npm run build -- --watch",
"build": "tsup src/index.ts --format cjs --dts",
"release": "bumpp --commit --push --tag",
"lint": "eslint \"{src,test}/**/*.ts\"",
"lint:fix": "npm run lint -- --fix",
"test": "jest"
},
"dependencies": {
"@windicss/plugin-utils": "^0.16.0",
"chokidar": "^3.5.1",
"debug": "^4.3.2",
"exit-hook": "^2.2.1",
"windicss": "^3.0.12"
},
"peerDependencies": {
"postcss": "^7.0.0"
},
"devDependencies": {
"@antfu/eslint-config": "^0.6.5",
"@antfu/ni": "^0.7.0",
"@types/debug": "^4.1.5",
"@types/jest": "^26.0.23",
"@types/node": "^15.6.1",
"bumpp": "^6.0.6",
"eslint": "^7.27.0",
"eslint-plugin-jest": "^24.3.6",
"esno": "^0.5.0",
"git-ensure": "^0.1.0",
"jest": "^27.0.1",
"postcss": "^7.0.39",
"ts-jest": "^27.0.1",
"tsup": "^4.11.1",
"typescript": "^4.3.2"
}
}

View File

@ -0,0 +1,27 @@
import { WindiPluginUtils, WindiPluginUtilsOptions } from '@windicss/plugin-utils'
import _debug from 'debug'
export interface WindiPostCSSPluginOptions extends WindiPluginUtilsOptions {
/**
* By default, this plugin "touches" your css entry by updating the file's
* "updated time" (utime) to trigger the hot reload without changing its content.
*
* It should work most of the time. But for some tools, they might also compare
* the file's content to avoid unnecessary hot reloads. In that cases, you will
* need to specify this option to "insert-comment" to get proper style updates with
* those tools.
*
* @default 'utime'
*/
touchMode?: 'utime' | 'insert-comment'
}
export interface Context {
entry?: string
utils?: WindiPluginUtils
}
export const context: Context = {}
export const isDev = process.env.NODE_ENV === 'development'
export const debug = _debug('postcss-windicss')

View File

@ -0,0 +1,54 @@
import { promises as fs } from 'fs'
import chokidar, { FSWatcher } from 'chokidar'
import { touch } from './utils'
import { context, debug, WindiPostCSSPluginOptions } from './context'
let watcher: FSWatcher | undefined
export function shutdownWatcher() {
if (watcher) {
debug('shutting down watcher')
watcher.close()
watcher = undefined
}
}
export async function startDevWatcher(options: WindiPostCSSPluginOptions = {}) {
shutdownWatcher()
debug('starting dev watcher')
const utils = context.utils!
await utils.ensureInit()
const {
touchMode = 'utime',
} = options
watcher = chokidar
.watch(utils.options.scanOptions.include, {
ignored: utils.options.scanOptions.exclude,
ignoreInitial: true,
})
if (utils.configFilePath)
watcher.add(utils.configFilePath)
watcher
.on('change', async(path) => {
if (path === context.entry)
return
if (path === utils.configFilePath) {
debug('reload config', utils.configFilePath)
utils.init()
return
}
debug('update from', path)
await utils!.extractFile(await fs.readFile(path, 'utf-8'))
if (context.entry)
touch(context.entry, touchMode)
})
if (context.entry)
touch(context.entry, touchMode)
}

View File

@ -0,0 +1,115 @@
import exitHook from 'exit-hook'
import { parse, plugin as PostcssPlugin } from 'postcss'
import { createUtils } from '@windicss/plugin-utils'
// import type { Plugin } from 'postcss'
import { shutdownWatcher, startDevWatcher } from './dev'
import { context, debug, isDev, WindiPostCSSPluginOptions } from './context'
const plugin = (options: WindiPostCSSPluginOptions): any => {
if (!context.utils) {
context.utils = createUtils({
...options,
onOptionsResolved() {
if (isDev)
setTimeout(() => startDevWatcher(options))
},
}, {
name: 'postcss-windicss',
})
if (isDev)
exitHook(shutdownWatcher)
debug(isDev ? 'development mode' : 'production mode')
}
const utils = context.utils
return (root) => {
const promiseArray: any[] = []
root.walkAtRules((atRule) => {
const entry = atRule.root().source?.input.from
if (atRule.name === 'windicss') {
context.entry = entry
promiseArray.push(utils.generateCSS().then((data) => {
atRule.replaceWith(parse(data))
}))
// atRule.replaceWith(parse(await utils.generateCSS()))
}
// @apply
else if (['apply'].includes(atRule.name)) {
const rule = atRule.parent!
if (!rule)
return
// await utils.ensureInit()
promiseArray.push(utils.ensureInit().then(() => {
const css = rule.toString()
const transformed = css ? utils.transformCSS(css, entry || '') : undefined
if (transformed)
rule.replaceWith(parse(transformed))
}))
}
// @screen, @variants
else if (['screen', 'variants'].includes(atRule.name)) {
// await utils.ensureInit()
promiseArray.push(utils.ensureInit().then(() => {
const css = atRule.toString()
const transformed = css ? utils.transformCSS(css, entry || '') : undefined
if (transformed)
atRule.replaceWith(parse(transformed))
}))
}
})
root.walkDecls((decl) => {
// We work with each `decl` object here.
const match = decl.value.match(/^\s*theme\((['"])(.*)\1\)\s*$/)
if (match && match[2])
decl.value = (utils.processor.theme(match[2]) as any).toString()
})
return Promise.all(promiseArray)
}
// return {
// postcssPlugin: 'postcss-windicss',
// async AtRule(atRule) {
// const entry = atRule.root().source?.input.from
// if (atRule.name === 'windicss') {
// context.entry = entry
// atRule.replaceWith(parse(await utils.generateCSS()))
// }
// // @apply
// else if (['apply'].includes(atRule.name)) {
// const rule = atRule.parent!
// if (!rule)
// return
// await utils.ensureInit()
// const css = rule.toString()
// const transformed = css ? utils.transformCSS(css, entry || '') : undefined
// if (transformed)
// rule.replaceWith(parse(transformed))
// }
// // @screen, @variants
// else if (['screen', 'variants'].includes(atRule.name)) {
// await utils.ensureInit()
// const css = atRule.toString()
// const transformed = css ? utils.transformCSS(css, entry || '') : undefined
// if (transformed)
// atRule.replaceWith(parse(transformed))
// }
// },
// Declaration(decl) {
// // theme()
// const match = decl.value.match(/^\s*theme\((['"])(.*)\1\)\s*$/)
// if (match && match[2])
// decl.value = (utils.processor.theme(match[2]) as any).toString()
// },
// }
}
export const postcss = true
plugin.postcss = true
module.exports = PostcssPlugin('postcss-windicss', plugin)

View File

@ -0,0 +1,39 @@
import { promises as fs, utimes, open, close } from 'fs'
export async function touch(path: string, mode: 'utime' | 'insert-comment' = 'utime') {
if (mode === 'utime')
return await touchUtime(path)
else
return await touchInsert(path)
}
const TOUCH_REG = /\/\*\s*windicss-touch:.*\*\//
export async function touchInsert(path: string) {
let css = await fs.readFile(path, 'utf-8')
const banner = `/* windicss-touch: ${Date.now()} */`
let replaced = false
css = css.replace(TOUCH_REG, () => {
replaced = true
return banner
})
if (!replaced)
css = `${banner}\n${css}`
await fs.writeFile(path, css, 'utf-8')
}
export async function touchUtime(path: string) {
return new Promise((resolve, reject) => {
const time = new Date()
utimes(path, time, time, (err) => {
if (err) {
return open(path, 'w', (err, fd) => {
if (err)
return reject(err)
close(fd, err => (err ? reject(err) : resolve(fd)))
})
}
resolve(false)
})
})
}

View File

@ -0,0 +1,12 @@
{
"compilerOptions": {
"target": "es2017",
"module": "esnext",
"lib": ["esnext"],
"moduleResolution": "node",
"esModuleInterop": true,
"strict": false,
"strictNullChecks": true,
"resolveJsonModule": true
}
}

11559
yarn.lock 100644

File diff suppressed because it is too large Load Diff