@mochi-css/plugins 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +88 -0
- package/dist/index.d.mts +35 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.js +230 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +126 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +47 -0
package/README.md
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# 🧁 Mochi-CSS/plugins
|
|
2
|
+
|
|
3
|
+
This package is part of the [Mochi-CSS project](https://github.com/Niikelion/mochi-css).
|
|
4
|
+
It provides `createExtractorsPlugin` — the standard bridge between `StyleExtractor` instances and the `Builder` pipeline — along with re-exports of commonly needed builder types for plugin authors.
|
|
5
|
+
|
|
6
|
+
> **Note:** You only need this package when building custom integrations or writing plugins that wire extractors into the builder. Normal users configure extractors via `mochi.config.ts` using packages like `@mochi-css/vanilla/config`.
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm i @mochi-css/plugins --save-dev
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## `createExtractorsPlugin`
|
|
19
|
+
|
|
20
|
+
Packages a list of `StyleExtractor` instances as a `MochiPlugin`. When loaded, the plugin:
|
|
21
|
+
|
|
22
|
+
- Registers the analysis pipeline stages needed for the given extractors
|
|
23
|
+
- Registers a `sourceTransforms` hook that sets up per-build generators and injects them as eval-time globals
|
|
24
|
+
- Registers an `emitHook` that calls `generateStyles()` on each generator and emits CSS via `context.emitChunk()`; also applies any AST arg replacements returned by `getArgReplacements()`
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
import { createExtractorsPlugin } from "@mochi-css/plugins"
|
|
28
|
+
import { defaultExtractors } from "@mochi-css/builder"
|
|
29
|
+
import { FullContext } from "@mochi-css/config"
|
|
30
|
+
import { Builder, RolldownBundler, VmRunner } from "@mochi-css/builder"
|
|
31
|
+
|
|
32
|
+
const ctx = new FullContext(onDiagnostic)
|
|
33
|
+
createExtractorsPlugin(defaultExtractors).onLoad(ctx)
|
|
34
|
+
|
|
35
|
+
const builder = new Builder({
|
|
36
|
+
roots: ["./src"],
|
|
37
|
+
stages: [...ctx.stages.getAll()],
|
|
38
|
+
bundler: new RolldownBundler(),
|
|
39
|
+
runner: new VmRunner(),
|
|
40
|
+
sourceTransforms: [...ctx.sourceTransforms.getAll()],
|
|
41
|
+
emitHooks: [...ctx.emitHooks.getAll()],
|
|
42
|
+
emitDir: "./dist/mochi",
|
|
43
|
+
cleanup: () => ctx.cleanup.runAll(),
|
|
44
|
+
})
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
When integrations load `mochi.config.ts`, `createExtractorsPlugin` is typically called inside a higher-level plugin (e.g. the one returned by `@mochi-css/vanilla/config`'s `defineConfig`) — you don't need to call it manually.
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## `PluginContextCollector`
|
|
52
|
+
|
|
53
|
+
A lightweight alternative to `FullContext` (from `@mochi-css/config`) for collecting plugin hooks without the file pre-process pipeline. Useful for unit-testing plugins or building minimal integrations.
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
import { PluginContextCollector } from "@mochi-css/plugins"
|
|
57
|
+
|
|
58
|
+
const collector = new PluginContextCollector(onDiagnostic)
|
|
59
|
+
myPlugin.onLoad(collector)
|
|
60
|
+
|
|
61
|
+
const builder = new Builder({
|
|
62
|
+
stages: [...collector.getStages()],
|
|
63
|
+
sourceTransforms: [...collector.getSourceTransforms()],
|
|
64
|
+
emitHooks: [...collector.getEmitHooks()],
|
|
65
|
+
cleanup: () => collector.runCleanup(),
|
|
66
|
+
// ...
|
|
67
|
+
})
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
| Method | Returns |
|
|
71
|
+
|--------|---------|
|
|
72
|
+
| `getStages()` | `readonly StageDefinition[]` |
|
|
73
|
+
| `getSourceTransforms()` | `AstPostProcessor[]` |
|
|
74
|
+
| `getEmitHooks()` | `EmitHook[]` |
|
|
75
|
+
| `runCleanup()` | calls all registered cleanup functions |
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## Re-exports
|
|
80
|
+
|
|
81
|
+
This package re-exports the following types and utilities from `@mochi-css/builder` for convenience:
|
|
82
|
+
|
|
83
|
+
- `StyleExtractor`, `StyleGenerator`
|
|
84
|
+
- `AstPostProcessor`, `EmitHook`, `BuilderOptions`, `RootEntry`
|
|
85
|
+
- `StageDefinition`
|
|
86
|
+
- `createDefaultStages`, `defaultStages`
|
|
87
|
+
- All stage constructors and symbol constants (`ImportSpecStage`, `StyleExprStage`, etc.)
|
|
88
|
+
- `extractRelevantSymbols`
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { AstPostProcessor, AstPostProcessor as AstPostProcessor$1, BindingStage, BuilderOptions, CrossFileDerivedStage, DerivedExtractorStage, EmitHook, EmitHook as EmitHook$1, ImportSpecStage, OnDiagnostic, RootEntry, StageDefinition, StageDefinition as StageDefinition$1, StyleExprStage, StyleExtractor, StyleExtractor as StyleExtractor$1, StyleGenerator, createDefaultStages, defaultStages, extractRelevantSymbols, makeBindingStage, makeCrossFileDerivedStage, makeDerivedExtractorStage, makeImportSpecStage, makeStyleExprStage } from "@mochi-css/builder";
|
|
2
|
+
import { CleanupHookProvider, EmitHookProvider, MochiPlugin, PluginContext, SourceTransformHookProvider, StageHookProvider } from "@mochi-css/config";
|
|
3
|
+
|
|
4
|
+
//#region src/ExtractorsPlugin.d.ts
|
|
5
|
+
declare function getExtractorId(extractor: StyleExtractor$1): string;
|
|
6
|
+
declare function createExtractorsPlugin(extractors: StyleExtractor$1[]): MochiPlugin;
|
|
7
|
+
//#endregion
|
|
8
|
+
//#region src/PluginContextCollector.d.ts
|
|
9
|
+
/**
|
|
10
|
+
* A simple collector that implements {@link PluginContext} by gathering all registered
|
|
11
|
+
* hooks into arrays. Call {@link PluginContextCollector.getStages}, etc. after
|
|
12
|
+
* `plugin.onLoad(collector)` to extract the collected hooks for use in Builder.
|
|
13
|
+
*/
|
|
14
|
+
declare class PluginContextCollector implements PluginContext {
|
|
15
|
+
private readonly _stages;
|
|
16
|
+
private readonly _sourceTransforms;
|
|
17
|
+
private readonly _emitHooks;
|
|
18
|
+
private readonly _cleanupFns;
|
|
19
|
+
readonly filePreProcess: {
|
|
20
|
+
registerTransformation: (_t: unknown, _d: unknown) => void;
|
|
21
|
+
};
|
|
22
|
+
readonly stages: StageHookProvider;
|
|
23
|
+
readonly sourceTransforms: SourceTransformHookProvider;
|
|
24
|
+
readonly emitHooks: EmitHookProvider;
|
|
25
|
+
readonly cleanup: CleanupHookProvider;
|
|
26
|
+
readonly onDiagnostic: OnDiagnostic;
|
|
27
|
+
constructor(onDiagnostic?: OnDiagnostic);
|
|
28
|
+
getStages(): readonly StageDefinition$1<any[], any>[];
|
|
29
|
+
getSourceTransforms(): AstPostProcessor$1[];
|
|
30
|
+
getEmitHooks(): EmitHook$1[];
|
|
31
|
+
runCleanup(): void;
|
|
32
|
+
}
|
|
33
|
+
//#endregion
|
|
34
|
+
export { type AstPostProcessor, BindingStage, type BuilderOptions, CrossFileDerivedStage, DerivedExtractorStage, type EmitHook, ImportSpecStage, PluginContextCollector, type RootEntry, type StageDefinition, StyleExprStage, type StyleExtractor, type StyleGenerator, createDefaultStages, createExtractorsPlugin, defaultStages, extractRelevantSymbols, getExtractorId, makeBindingStage, makeCrossFileDerivedStage, makeDerivedExtractorStage, makeImportSpecStage, makeStyleExprStage };
|
|
35
|
+
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { AstPostProcessor, AstPostProcessor as AstPostProcessor$1, BindingStage, BuilderOptions, CrossFileDerivedStage, DerivedExtractorStage, EmitHook, EmitHook as EmitHook$1, ImportSpecStage, OnDiagnostic, RootEntry, StageDefinition, StageDefinition as StageDefinition$1, StyleExprStage, StyleExtractor, StyleExtractor as StyleExtractor$1, StyleGenerator, createDefaultStages, defaultStages, extractRelevantSymbols, makeBindingStage, makeCrossFileDerivedStage, makeDerivedExtractorStage, makeImportSpecStage, makeStyleExprStage } from "@mochi-css/builder";
|
|
2
|
+
import { CleanupHookProvider, EmitHookProvider, MochiPlugin, PluginContext, SourceTransformHookProvider, StageHookProvider } from "@mochi-css/config";
|
|
3
|
+
|
|
4
|
+
//#region src/ExtractorsPlugin.d.ts
|
|
5
|
+
declare function getExtractorId(extractor: StyleExtractor$1): string;
|
|
6
|
+
declare function createExtractorsPlugin(extractors: StyleExtractor$1[]): MochiPlugin;
|
|
7
|
+
//#endregion
|
|
8
|
+
//#region src/PluginContextCollector.d.ts
|
|
9
|
+
/**
|
|
10
|
+
* A simple collector that implements {@link PluginContext} by gathering all registered
|
|
11
|
+
* hooks into arrays. Call {@link PluginContextCollector.getStages}, etc. after
|
|
12
|
+
* `plugin.onLoad(collector)` to extract the collected hooks for use in Builder.
|
|
13
|
+
*/
|
|
14
|
+
declare class PluginContextCollector implements PluginContext {
|
|
15
|
+
private readonly _stages;
|
|
16
|
+
private readonly _sourceTransforms;
|
|
17
|
+
private readonly _emitHooks;
|
|
18
|
+
private readonly _cleanupFns;
|
|
19
|
+
readonly filePreProcess: {
|
|
20
|
+
registerTransformation: (_t: unknown, _d: unknown) => void;
|
|
21
|
+
};
|
|
22
|
+
readonly stages: StageHookProvider;
|
|
23
|
+
readonly sourceTransforms: SourceTransformHookProvider;
|
|
24
|
+
readonly emitHooks: EmitHookProvider;
|
|
25
|
+
readonly cleanup: CleanupHookProvider;
|
|
26
|
+
readonly onDiagnostic: OnDiagnostic;
|
|
27
|
+
constructor(onDiagnostic?: OnDiagnostic);
|
|
28
|
+
getStages(): readonly StageDefinition$1<any[], any>[];
|
|
29
|
+
getSourceTransforms(): AstPostProcessor$1[];
|
|
30
|
+
getEmitHooks(): EmitHook$1[];
|
|
31
|
+
runCleanup(): void;
|
|
32
|
+
}
|
|
33
|
+
//#endregion
|
|
34
|
+
export { type AstPostProcessor, BindingStage, type BuilderOptions, CrossFileDerivedStage, DerivedExtractorStage, type EmitHook, ImportSpecStage, PluginContextCollector, type RootEntry, type StageDefinition, StyleExprStage, type StyleExtractor, type StyleGenerator, createDefaultStages, createExtractorsPlugin, defaultStages, extractRelevantSymbols, getExtractorId, makeBindingStage, makeCrossFileDerivedStage, makeDerivedExtractorStage, makeImportSpecStage, makeStyleExprStage };
|
|
35
|
+
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
//#region rolldown:runtime
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
10
|
+
key = keys[i];
|
|
11
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
12
|
+
get: ((k) => from[k]).bind(null, key),
|
|
13
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
19
|
+
value: mod,
|
|
20
|
+
enumerable: true
|
|
21
|
+
}) : target, mod));
|
|
22
|
+
|
|
23
|
+
//#endregion
|
|
24
|
+
let __mochi_css_builder = require("@mochi-css/builder");
|
|
25
|
+
__mochi_css_builder = __toESM(__mochi_css_builder);
|
|
26
|
+
|
|
27
|
+
//#region src/ExtractorsPlugin.ts
|
|
28
|
+
function getExtractorId(extractor) {
|
|
29
|
+
return `${extractor.importPath}:${extractor.symbolName}`;
|
|
30
|
+
}
|
|
31
|
+
function wrapGenerator(generator, onDiagnostic) {
|
|
32
|
+
return (source, ...args) => {
|
|
33
|
+
try {
|
|
34
|
+
const subGenerators = generator.collectArgs(source, args);
|
|
35
|
+
const result = {};
|
|
36
|
+
for (const [name, subGen] of Object.entries(subGenerators ?? {})) result[name] = wrapGenerator(subGen, onDiagnostic);
|
|
37
|
+
return result;
|
|
38
|
+
} catch (err) {
|
|
39
|
+
const message = (0, __mochi_css_builder.getErrorMessage)(err);
|
|
40
|
+
onDiagnostic?.({
|
|
41
|
+
code: "MOCHI_EXEC",
|
|
42
|
+
message: `Failed to collect styles: ${message}`,
|
|
43
|
+
severity: "warning",
|
|
44
|
+
file: source
|
|
45
|
+
});
|
|
46
|
+
return {};
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function createExtractorsPlugin(extractors) {
|
|
51
|
+
return {
|
|
52
|
+
name: "mochi-extractor-plugin",
|
|
53
|
+
onLoad(ctx) {
|
|
54
|
+
let capturedGenerators = null;
|
|
55
|
+
const sourceTransform = (_index, context) => {
|
|
56
|
+
const generators = /* @__PURE__ */ new Map();
|
|
57
|
+
for (const extractor of extractors) {
|
|
58
|
+
const id = getExtractorId(extractor);
|
|
59
|
+
generators.set(id, extractor.startGeneration(ctx.onDiagnostic));
|
|
60
|
+
}
|
|
61
|
+
capturedGenerators = generators;
|
|
62
|
+
const extractorsObj = {};
|
|
63
|
+
for (const [id, gen] of generators) extractorsObj[id] = wrapGenerator(gen, ctx.onDiagnostic);
|
|
64
|
+
context.evaluator.setGlobal("extractors", extractorsObj);
|
|
65
|
+
};
|
|
66
|
+
const emitHook = async (index, context) => {
|
|
67
|
+
if (!capturedGenerators) return;
|
|
68
|
+
for (const [, generator] of capturedGenerators) {
|
|
69
|
+
const styles = await generator.generateStyles();
|
|
70
|
+
const replacements = generator.getArgReplacements?.() ?? [];
|
|
71
|
+
const replacementsBySource = /* @__PURE__ */ new Map();
|
|
72
|
+
for (const rep of replacements) {
|
|
73
|
+
const list = replacementsBySource.get(rep.source);
|
|
74
|
+
if (list) list.push({ expression: rep.expression });
|
|
75
|
+
else replacementsBySource.set(rep.source, [{ expression: rep.expression }]);
|
|
76
|
+
}
|
|
77
|
+
for (const [source, repList] of replacementsBySource) {
|
|
78
|
+
const fileInfo = index.files.find(([p]) => p === source)?.[1];
|
|
79
|
+
if (!fileInfo) continue;
|
|
80
|
+
for (const extractor of extractors) {
|
|
81
|
+
const callNodes = fileInfo.extractedCallExpressions.get(extractor);
|
|
82
|
+
if (callNodes?.length !== repList.length) continue;
|
|
83
|
+
for (let i = 0; i < callNodes.length; i++) {
|
|
84
|
+
const callNode = callNodes[i];
|
|
85
|
+
const rep = repList[i];
|
|
86
|
+
if (!callNode || !rep) continue;
|
|
87
|
+
callNode.arguments = [{ expression: rep.expression }];
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (styles.files) for (const [source, css] of Object.entries(styles.files)) context.emitChunk(source, css);
|
|
92
|
+
if (styles.global) context.emitChunk("global.css", styles.global);
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
for (const stage of (0, __mochi_css_builder.createDefaultStages)(extractors)) ctx.stages.register(stage);
|
|
96
|
+
ctx.sourceTransforms.register(sourceTransform);
|
|
97
|
+
ctx.emitHooks.register(emitHook);
|
|
98
|
+
ctx.cleanup.register(() => {
|
|
99
|
+
capturedGenerators = null;
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
//#endregion
|
|
106
|
+
//#region src/PluginContextCollector.ts
|
|
107
|
+
/**
|
|
108
|
+
* A simple collector that implements {@link PluginContext} by gathering all registered
|
|
109
|
+
* hooks into arrays. Call {@link PluginContextCollector.getStages}, etc. after
|
|
110
|
+
* `plugin.onLoad(collector)` to extract the collected hooks for use in Builder.
|
|
111
|
+
*/
|
|
112
|
+
var PluginContextCollector = class {
|
|
113
|
+
_stages = [];
|
|
114
|
+
_sourceTransforms = [];
|
|
115
|
+
_emitHooks = [];
|
|
116
|
+
_cleanupFns = [];
|
|
117
|
+
filePreProcess = { registerTransformation: (_t, _d) => {} };
|
|
118
|
+
stages = { register: (s) => {
|
|
119
|
+
this._stages.push(s);
|
|
120
|
+
} };
|
|
121
|
+
sourceTransforms = { register: (h) => {
|
|
122
|
+
this._sourceTransforms.push(h);
|
|
123
|
+
} };
|
|
124
|
+
emitHooks = { register: (h) => {
|
|
125
|
+
this._emitHooks.push(h);
|
|
126
|
+
} };
|
|
127
|
+
cleanup = { register: (fn) => {
|
|
128
|
+
this._cleanupFns.push(fn);
|
|
129
|
+
} };
|
|
130
|
+
onDiagnostic;
|
|
131
|
+
constructor(onDiagnostic) {
|
|
132
|
+
this.onDiagnostic = onDiagnostic ?? (() => {});
|
|
133
|
+
}
|
|
134
|
+
getStages() {
|
|
135
|
+
return [...this._stages];
|
|
136
|
+
}
|
|
137
|
+
getSourceTransforms() {
|
|
138
|
+
return [...this._sourceTransforms];
|
|
139
|
+
}
|
|
140
|
+
getEmitHooks() {
|
|
141
|
+
return [...this._emitHooks];
|
|
142
|
+
}
|
|
143
|
+
runCleanup() {
|
|
144
|
+
for (const fn of this._cleanupFns) fn();
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
//#endregion
|
|
149
|
+
Object.defineProperty(exports, 'BindingStage', {
|
|
150
|
+
enumerable: true,
|
|
151
|
+
get: function () {
|
|
152
|
+
return __mochi_css_builder.BindingStage;
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
Object.defineProperty(exports, 'CrossFileDerivedStage', {
|
|
156
|
+
enumerable: true,
|
|
157
|
+
get: function () {
|
|
158
|
+
return __mochi_css_builder.CrossFileDerivedStage;
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
Object.defineProperty(exports, 'DerivedExtractorStage', {
|
|
162
|
+
enumerable: true,
|
|
163
|
+
get: function () {
|
|
164
|
+
return __mochi_css_builder.DerivedExtractorStage;
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
Object.defineProperty(exports, 'ImportSpecStage', {
|
|
168
|
+
enumerable: true,
|
|
169
|
+
get: function () {
|
|
170
|
+
return __mochi_css_builder.ImportSpecStage;
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
exports.PluginContextCollector = PluginContextCollector;
|
|
174
|
+
Object.defineProperty(exports, 'StyleExprStage', {
|
|
175
|
+
enumerable: true,
|
|
176
|
+
get: function () {
|
|
177
|
+
return __mochi_css_builder.StyleExprStage;
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
Object.defineProperty(exports, 'createDefaultStages', {
|
|
181
|
+
enumerable: true,
|
|
182
|
+
get: function () {
|
|
183
|
+
return __mochi_css_builder.createDefaultStages;
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
exports.createExtractorsPlugin = createExtractorsPlugin;
|
|
187
|
+
Object.defineProperty(exports, 'defaultStages', {
|
|
188
|
+
enumerable: true,
|
|
189
|
+
get: function () {
|
|
190
|
+
return __mochi_css_builder.defaultStages;
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
Object.defineProperty(exports, 'extractRelevantSymbols', {
|
|
194
|
+
enumerable: true,
|
|
195
|
+
get: function () {
|
|
196
|
+
return __mochi_css_builder.extractRelevantSymbols;
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
exports.getExtractorId = getExtractorId;
|
|
200
|
+
Object.defineProperty(exports, 'makeBindingStage', {
|
|
201
|
+
enumerable: true,
|
|
202
|
+
get: function () {
|
|
203
|
+
return __mochi_css_builder.makeBindingStage;
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
Object.defineProperty(exports, 'makeCrossFileDerivedStage', {
|
|
207
|
+
enumerable: true,
|
|
208
|
+
get: function () {
|
|
209
|
+
return __mochi_css_builder.makeCrossFileDerivedStage;
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
Object.defineProperty(exports, 'makeDerivedExtractorStage', {
|
|
213
|
+
enumerable: true,
|
|
214
|
+
get: function () {
|
|
215
|
+
return __mochi_css_builder.makeDerivedExtractorStage;
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
Object.defineProperty(exports, 'makeImportSpecStage', {
|
|
219
|
+
enumerable: true,
|
|
220
|
+
get: function () {
|
|
221
|
+
return __mochi_css_builder.makeImportSpecStage;
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
Object.defineProperty(exports, 'makeStyleExprStage', {
|
|
225
|
+
enumerable: true,
|
|
226
|
+
get: function () {
|
|
227
|
+
return __mochi_css_builder.makeStyleExprStage;
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["result: Record<string, unknown>","capturedGenerators: Map<string, StyleGenerator> | null","sourceTransform: AstPostProcessor","extractorsObj: Record<\n string,\n (\n source: string,\n ...args: unknown[]\n ) => Record<string, unknown>\n >","emitHook: EmitHook"],"sources":["../src/ExtractorsPlugin.ts","../src/PluginContextCollector.ts"],"sourcesContent":["import type { AstPostProcessor, EmitHook } from \"@mochi-css/builder\";\nimport { createDefaultStages } from \"@mochi-css/builder\";\nimport type { StyleExtractor, StyleGenerator } from \"@mochi-css/builder\";\nimport { OnDiagnostic, getErrorMessage } from \"@mochi-css/builder\";\nimport type { MochiPlugin } from \"@mochi-css/config\";\nimport * as SWC from \"@swc/core\";\n\nexport function getExtractorId(extractor: StyleExtractor): string {\n return `${extractor.importPath}:${extractor.symbolName}`;\n}\n\nfunction wrapGenerator(\n generator: StyleGenerator,\n onDiagnostic: OnDiagnostic | undefined,\n): (source: string, ...args: unknown[]) => Record<string, unknown> {\n return (source: string, ...args: unknown[]) => {\n try {\n const subGenerators = generator.collectArgs(source, args);\n const result: Record<string, unknown> = {};\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n for (const [name, subGen] of Object.entries(subGenerators ?? {})) {\n result[name] = wrapGenerator(subGen, onDiagnostic);\n }\n return result;\n } catch (err) {\n const message = getErrorMessage(err);\n onDiagnostic?.({\n code: \"MOCHI_EXEC\",\n message: `Failed to collect styles: ${message}`,\n severity: \"warning\",\n file: source,\n });\n return {};\n }\n };\n}\n\nexport function createExtractorsPlugin(\n extractors: StyleExtractor[],\n): MochiPlugin {\n return {\n name: \"mochi-extractor-plugin\",\n onLoad(ctx) {\n let capturedGenerators: Map<string, StyleGenerator> | null = null;\n\n const sourceTransform: AstPostProcessor = (_index, context) => {\n const generators = new Map<string, StyleGenerator>();\n for (const extractor of extractors) {\n const id = getExtractorId(extractor);\n generators.set(\n id,\n extractor.startGeneration(ctx.onDiagnostic),\n );\n }\n capturedGenerators = generators;\n\n const extractorsObj: Record<\n string,\n (\n source: string,\n ...args: unknown[]\n ) => Record<string, unknown>\n > = {};\n for (const [id, gen] of generators) {\n extractorsObj[id] = wrapGenerator(gen, ctx.onDiagnostic);\n }\n context.evaluator.setGlobal(\"extractors\", extractorsObj);\n };\n\n const emitHook: EmitHook = async (index, context) => {\n if (!capturedGenerators) return;\n\n for (const [, generator] of capturedGenerators) {\n const styles = await generator.generateStyles();\n const replacements = generator.getArgReplacements?.() ?? [];\n\n const replacementsBySource = new Map<\n string,\n { expression: SWC.Expression }[]\n >();\n for (const rep of replacements) {\n const list = replacementsBySource.get(rep.source);\n if (list) {\n list.push({ expression: rep.expression });\n } else {\n replacementsBySource.set(rep.source, [\n { expression: rep.expression },\n ]);\n }\n }\n\n for (const [source, repList] of replacementsBySource) {\n const fileEntry = index.files.find(\n ([p]) => p === source,\n );\n const fileInfo = fileEntry?.[1];\n if (!fileInfo) continue;\n\n for (const extractor of extractors) {\n const callNodes =\n fileInfo.extractedCallExpressions.get(\n extractor,\n );\n if (callNodes?.length !== repList.length) continue;\n\n for (let i = 0; i < callNodes.length; i++) {\n const callNode = callNodes[i];\n const rep = repList[i];\n if (!callNode || !rep) continue;\n callNode.arguments = [\n { expression: rep.expression },\n ];\n }\n }\n }\n\n if (styles.files) {\n for (const [source, css] of Object.entries(\n styles.files,\n )) {\n context.emitChunk(source, css);\n }\n }\n if (styles.global) {\n context.emitChunk(\"global.css\", styles.global);\n }\n }\n };\n\n for (const stage of createDefaultStages(extractors)) {\n ctx.stages.register(stage);\n }\n ctx.sourceTransforms.register(sourceTransform);\n ctx.emitHooks.register(emitHook);\n ctx.cleanup.register(() => {\n capturedGenerators = null;\n });\n },\n };\n}\n","import type {\n PluginContext,\n SourceTransformHookProvider,\n StageHookProvider,\n EmitHookProvider,\n CleanupHookProvider,\n} from \"@mochi-css/config\";\nimport type {\n AstPostProcessor,\n EmitHook,\n OnDiagnostic,\n StageDefinition,\n} from \"@mochi-css/builder\";\n\n/**\n * A simple collector that implements {@link PluginContext} by gathering all registered\n * hooks into arrays. Call {@link PluginContextCollector.getStages}, etc. after\n * `plugin.onLoad(collector)` to extract the collected hooks for use in Builder.\n */\nexport class PluginContextCollector implements PluginContext {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private readonly _stages: StageDefinition<any[], any>[] = [];\n private readonly _sourceTransforms: AstPostProcessor[] = [];\n private readonly _emitHooks: EmitHook[] = [];\n private readonly _cleanupFns: (() => void)[] = [];\n\n readonly filePreProcess = {\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n registerTransformation: (_t: unknown, _d: unknown) => {},\n };\n\n readonly stages: StageHookProvider = {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n register: (s: StageDefinition<any[], any>) => {\n this._stages.push(s);\n },\n };\n\n readonly sourceTransforms: SourceTransformHookProvider = {\n register: (h: AstPostProcessor) => {\n this._sourceTransforms.push(h);\n },\n };\n\n readonly emitHooks: EmitHookProvider = {\n register: (h: EmitHook) => {\n this._emitHooks.push(h);\n },\n };\n\n readonly cleanup: CleanupHookProvider = {\n register: (fn: () => void) => {\n this._cleanupFns.push(fn);\n },\n };\n\n readonly onDiagnostic: OnDiagnostic;\n\n constructor(onDiagnostic?: OnDiagnostic) {\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n this.onDiagnostic = onDiagnostic ?? (() => {});\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n getStages(): readonly StageDefinition<any[], any>[] {\n return [...this._stages];\n }\n\n getSourceTransforms(): AstPostProcessor[] {\n return [...this._sourceTransforms];\n }\n\n getEmitHooks(): EmitHook[] {\n return [...this._emitHooks];\n }\n\n runCleanup(): void {\n for (const fn of this._cleanupFns) fn();\n }\n}\n"],"mappings":"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"}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { BindingStage, CrossFileDerivedStage, DerivedExtractorStage, ImportSpecStage, StyleExprStage, createDefaultStages, createDefaultStages as createDefaultStages$1, defaultStages, extractRelevantSymbols, getErrorMessage, makeBindingStage, makeCrossFileDerivedStage, makeDerivedExtractorStage, makeImportSpecStage, makeStyleExprStage } from "@mochi-css/builder";
|
|
2
|
+
|
|
3
|
+
//#region src/ExtractorsPlugin.ts
|
|
4
|
+
function getExtractorId(extractor) {
|
|
5
|
+
return `${extractor.importPath}:${extractor.symbolName}`;
|
|
6
|
+
}
|
|
7
|
+
function wrapGenerator(generator, onDiagnostic) {
|
|
8
|
+
return (source, ...args) => {
|
|
9
|
+
try {
|
|
10
|
+
const subGenerators = generator.collectArgs(source, args);
|
|
11
|
+
const result = {};
|
|
12
|
+
for (const [name, subGen] of Object.entries(subGenerators ?? {})) result[name] = wrapGenerator(subGen, onDiagnostic);
|
|
13
|
+
return result;
|
|
14
|
+
} catch (err) {
|
|
15
|
+
const message = getErrorMessage(err);
|
|
16
|
+
onDiagnostic?.({
|
|
17
|
+
code: "MOCHI_EXEC",
|
|
18
|
+
message: `Failed to collect styles: ${message}`,
|
|
19
|
+
severity: "warning",
|
|
20
|
+
file: source
|
|
21
|
+
});
|
|
22
|
+
return {};
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function createExtractorsPlugin(extractors) {
|
|
27
|
+
return {
|
|
28
|
+
name: "mochi-extractor-plugin",
|
|
29
|
+
onLoad(ctx) {
|
|
30
|
+
let capturedGenerators = null;
|
|
31
|
+
const sourceTransform = (_index, context) => {
|
|
32
|
+
const generators = /* @__PURE__ */ new Map();
|
|
33
|
+
for (const extractor of extractors) {
|
|
34
|
+
const id = getExtractorId(extractor);
|
|
35
|
+
generators.set(id, extractor.startGeneration(ctx.onDiagnostic));
|
|
36
|
+
}
|
|
37
|
+
capturedGenerators = generators;
|
|
38
|
+
const extractorsObj = {};
|
|
39
|
+
for (const [id, gen] of generators) extractorsObj[id] = wrapGenerator(gen, ctx.onDiagnostic);
|
|
40
|
+
context.evaluator.setGlobal("extractors", extractorsObj);
|
|
41
|
+
};
|
|
42
|
+
const emitHook = async (index, context) => {
|
|
43
|
+
if (!capturedGenerators) return;
|
|
44
|
+
for (const [, generator] of capturedGenerators) {
|
|
45
|
+
const styles = await generator.generateStyles();
|
|
46
|
+
const replacements = generator.getArgReplacements?.() ?? [];
|
|
47
|
+
const replacementsBySource = /* @__PURE__ */ new Map();
|
|
48
|
+
for (const rep of replacements) {
|
|
49
|
+
const list = replacementsBySource.get(rep.source);
|
|
50
|
+
if (list) list.push({ expression: rep.expression });
|
|
51
|
+
else replacementsBySource.set(rep.source, [{ expression: rep.expression }]);
|
|
52
|
+
}
|
|
53
|
+
for (const [source, repList] of replacementsBySource) {
|
|
54
|
+
const fileInfo = index.files.find(([p]) => p === source)?.[1];
|
|
55
|
+
if (!fileInfo) continue;
|
|
56
|
+
for (const extractor of extractors) {
|
|
57
|
+
const callNodes = fileInfo.extractedCallExpressions.get(extractor);
|
|
58
|
+
if (callNodes?.length !== repList.length) continue;
|
|
59
|
+
for (let i = 0; i < callNodes.length; i++) {
|
|
60
|
+
const callNode = callNodes[i];
|
|
61
|
+
const rep = repList[i];
|
|
62
|
+
if (!callNode || !rep) continue;
|
|
63
|
+
callNode.arguments = [{ expression: rep.expression }];
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (styles.files) for (const [source, css] of Object.entries(styles.files)) context.emitChunk(source, css);
|
|
68
|
+
if (styles.global) context.emitChunk("global.css", styles.global);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
for (const stage of createDefaultStages$1(extractors)) ctx.stages.register(stage);
|
|
72
|
+
ctx.sourceTransforms.register(sourceTransform);
|
|
73
|
+
ctx.emitHooks.register(emitHook);
|
|
74
|
+
ctx.cleanup.register(() => {
|
|
75
|
+
capturedGenerators = null;
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
//#endregion
|
|
82
|
+
//#region src/PluginContextCollector.ts
|
|
83
|
+
/**
|
|
84
|
+
* A simple collector that implements {@link PluginContext} by gathering all registered
|
|
85
|
+
* hooks into arrays. Call {@link PluginContextCollector.getStages}, etc. after
|
|
86
|
+
* `plugin.onLoad(collector)` to extract the collected hooks for use in Builder.
|
|
87
|
+
*/
|
|
88
|
+
var PluginContextCollector = class {
|
|
89
|
+
_stages = [];
|
|
90
|
+
_sourceTransforms = [];
|
|
91
|
+
_emitHooks = [];
|
|
92
|
+
_cleanupFns = [];
|
|
93
|
+
filePreProcess = { registerTransformation: (_t, _d) => {} };
|
|
94
|
+
stages = { register: (s) => {
|
|
95
|
+
this._stages.push(s);
|
|
96
|
+
} };
|
|
97
|
+
sourceTransforms = { register: (h) => {
|
|
98
|
+
this._sourceTransforms.push(h);
|
|
99
|
+
} };
|
|
100
|
+
emitHooks = { register: (h) => {
|
|
101
|
+
this._emitHooks.push(h);
|
|
102
|
+
} };
|
|
103
|
+
cleanup = { register: (fn) => {
|
|
104
|
+
this._cleanupFns.push(fn);
|
|
105
|
+
} };
|
|
106
|
+
onDiagnostic;
|
|
107
|
+
constructor(onDiagnostic) {
|
|
108
|
+
this.onDiagnostic = onDiagnostic ?? (() => {});
|
|
109
|
+
}
|
|
110
|
+
getStages() {
|
|
111
|
+
return [...this._stages];
|
|
112
|
+
}
|
|
113
|
+
getSourceTransforms() {
|
|
114
|
+
return [...this._sourceTransforms];
|
|
115
|
+
}
|
|
116
|
+
getEmitHooks() {
|
|
117
|
+
return [...this._emitHooks];
|
|
118
|
+
}
|
|
119
|
+
runCleanup() {
|
|
120
|
+
for (const fn of this._cleanupFns) fn();
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
//#endregion
|
|
125
|
+
export { BindingStage, CrossFileDerivedStage, DerivedExtractorStage, ImportSpecStage, PluginContextCollector, StyleExprStage, createDefaultStages, createExtractorsPlugin, defaultStages, extractRelevantSymbols, getExtractorId, makeBindingStage, makeCrossFileDerivedStage, makeDerivedExtractorStage, makeImportSpecStage, makeStyleExprStage };
|
|
126
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["result: Record<string, unknown>","capturedGenerators: Map<string, StyleGenerator> | null","sourceTransform: AstPostProcessor","extractorsObj: Record<\n string,\n (\n source: string,\n ...args: unknown[]\n ) => Record<string, unknown>\n >","emitHook: EmitHook","createDefaultStages"],"sources":["../src/ExtractorsPlugin.ts","../src/PluginContextCollector.ts"],"sourcesContent":["import type { AstPostProcessor, EmitHook } from \"@mochi-css/builder\";\nimport { createDefaultStages } from \"@mochi-css/builder\";\nimport type { StyleExtractor, StyleGenerator } from \"@mochi-css/builder\";\nimport { OnDiagnostic, getErrorMessage } from \"@mochi-css/builder\";\nimport type { MochiPlugin } from \"@mochi-css/config\";\nimport * as SWC from \"@swc/core\";\n\nexport function getExtractorId(extractor: StyleExtractor): string {\n return `${extractor.importPath}:${extractor.symbolName}`;\n}\n\nfunction wrapGenerator(\n generator: StyleGenerator,\n onDiagnostic: OnDiagnostic | undefined,\n): (source: string, ...args: unknown[]) => Record<string, unknown> {\n return (source: string, ...args: unknown[]) => {\n try {\n const subGenerators = generator.collectArgs(source, args);\n const result: Record<string, unknown> = {};\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n for (const [name, subGen] of Object.entries(subGenerators ?? {})) {\n result[name] = wrapGenerator(subGen, onDiagnostic);\n }\n return result;\n } catch (err) {\n const message = getErrorMessage(err);\n onDiagnostic?.({\n code: \"MOCHI_EXEC\",\n message: `Failed to collect styles: ${message}`,\n severity: \"warning\",\n file: source,\n });\n return {};\n }\n };\n}\n\nexport function createExtractorsPlugin(\n extractors: StyleExtractor[],\n): MochiPlugin {\n return {\n name: \"mochi-extractor-plugin\",\n onLoad(ctx) {\n let capturedGenerators: Map<string, StyleGenerator> | null = null;\n\n const sourceTransform: AstPostProcessor = (_index, context) => {\n const generators = new Map<string, StyleGenerator>();\n for (const extractor of extractors) {\n const id = getExtractorId(extractor);\n generators.set(\n id,\n extractor.startGeneration(ctx.onDiagnostic),\n );\n }\n capturedGenerators = generators;\n\n const extractorsObj: Record<\n string,\n (\n source: string,\n ...args: unknown[]\n ) => Record<string, unknown>\n > = {};\n for (const [id, gen] of generators) {\n extractorsObj[id] = wrapGenerator(gen, ctx.onDiagnostic);\n }\n context.evaluator.setGlobal(\"extractors\", extractorsObj);\n };\n\n const emitHook: EmitHook = async (index, context) => {\n if (!capturedGenerators) return;\n\n for (const [, generator] of capturedGenerators) {\n const styles = await generator.generateStyles();\n const replacements = generator.getArgReplacements?.() ?? [];\n\n const replacementsBySource = new Map<\n string,\n { expression: SWC.Expression }[]\n >();\n for (const rep of replacements) {\n const list = replacementsBySource.get(rep.source);\n if (list) {\n list.push({ expression: rep.expression });\n } else {\n replacementsBySource.set(rep.source, [\n { expression: rep.expression },\n ]);\n }\n }\n\n for (const [source, repList] of replacementsBySource) {\n const fileEntry = index.files.find(\n ([p]) => p === source,\n );\n const fileInfo = fileEntry?.[1];\n if (!fileInfo) continue;\n\n for (const extractor of extractors) {\n const callNodes =\n fileInfo.extractedCallExpressions.get(\n extractor,\n );\n if (callNodes?.length !== repList.length) continue;\n\n for (let i = 0; i < callNodes.length; i++) {\n const callNode = callNodes[i];\n const rep = repList[i];\n if (!callNode || !rep) continue;\n callNode.arguments = [\n { expression: rep.expression },\n ];\n }\n }\n }\n\n if (styles.files) {\n for (const [source, css] of Object.entries(\n styles.files,\n )) {\n context.emitChunk(source, css);\n }\n }\n if (styles.global) {\n context.emitChunk(\"global.css\", styles.global);\n }\n }\n };\n\n for (const stage of createDefaultStages(extractors)) {\n ctx.stages.register(stage);\n }\n ctx.sourceTransforms.register(sourceTransform);\n ctx.emitHooks.register(emitHook);\n ctx.cleanup.register(() => {\n capturedGenerators = null;\n });\n },\n };\n}\n","import type {\n PluginContext,\n SourceTransformHookProvider,\n StageHookProvider,\n EmitHookProvider,\n CleanupHookProvider,\n} from \"@mochi-css/config\";\nimport type {\n AstPostProcessor,\n EmitHook,\n OnDiagnostic,\n StageDefinition,\n} from \"@mochi-css/builder\";\n\n/**\n * A simple collector that implements {@link PluginContext} by gathering all registered\n * hooks into arrays. Call {@link PluginContextCollector.getStages}, etc. after\n * `plugin.onLoad(collector)` to extract the collected hooks for use in Builder.\n */\nexport class PluginContextCollector implements PluginContext {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private readonly _stages: StageDefinition<any[], any>[] = [];\n private readonly _sourceTransforms: AstPostProcessor[] = [];\n private readonly _emitHooks: EmitHook[] = [];\n private readonly _cleanupFns: (() => void)[] = [];\n\n readonly filePreProcess = {\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n registerTransformation: (_t: unknown, _d: unknown) => {},\n };\n\n readonly stages: StageHookProvider = {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n register: (s: StageDefinition<any[], any>) => {\n this._stages.push(s);\n },\n };\n\n readonly sourceTransforms: SourceTransformHookProvider = {\n register: (h: AstPostProcessor) => {\n this._sourceTransforms.push(h);\n },\n };\n\n readonly emitHooks: EmitHookProvider = {\n register: (h: EmitHook) => {\n this._emitHooks.push(h);\n },\n };\n\n readonly cleanup: CleanupHookProvider = {\n register: (fn: () => void) => {\n this._cleanupFns.push(fn);\n },\n };\n\n readonly onDiagnostic: OnDiagnostic;\n\n constructor(onDiagnostic?: OnDiagnostic) {\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n this.onDiagnostic = onDiagnostic ?? (() => {});\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n getStages(): readonly StageDefinition<any[], any>[] {\n return [...this._stages];\n }\n\n getSourceTransforms(): AstPostProcessor[] {\n return [...this._sourceTransforms];\n }\n\n getEmitHooks(): EmitHook[] {\n return [...this._emitHooks];\n }\n\n runCleanup(): void {\n for (const fn of this._cleanupFns) fn();\n }\n}\n"],"mappings":";;;AAOA,SAAgB,eAAe,WAAmC;AAC9D,QAAO,GAAG,UAAU,WAAW,GAAG,UAAU;;AAGhD,SAAS,cACL,WACA,cAC+D;AAC/D,SAAQ,QAAgB,GAAG,SAAoB;AAC3C,MAAI;GACA,MAAM,gBAAgB,UAAU,YAAY,QAAQ,KAAK;GACzD,MAAMA,SAAkC,EAAE;AAE1C,QAAK,MAAM,CAAC,MAAM,WAAW,OAAO,QAAQ,iBAAiB,EAAE,CAAC,CAC5D,QAAO,QAAQ,cAAc,QAAQ,aAAa;AAEtD,UAAO;WACF,KAAK;GACV,MAAM,UAAU,gBAAgB,IAAI;AACpC,kBAAe;IACX,MAAM;IACN,SAAS,6BAA6B;IACtC,UAAU;IACV,MAAM;IACT,CAAC;AACF,UAAO,EAAE;;;;AAKrB,SAAgB,uBACZ,YACW;AACX,QAAO;EACH,MAAM;EACN,OAAO,KAAK;GACR,IAAIC,qBAAyD;GAE7D,MAAMC,mBAAqC,QAAQ,YAAY;IAC3D,MAAM,6BAAa,IAAI,KAA6B;AACpD,SAAK,MAAM,aAAa,YAAY;KAChC,MAAM,KAAK,eAAe,UAAU;AACpC,gBAAW,IACP,IACA,UAAU,gBAAgB,IAAI,aAAa,CAC9C;;AAEL,yBAAqB;IAErB,MAAMC,gBAMF,EAAE;AACN,SAAK,MAAM,CAAC,IAAI,QAAQ,WACpB,eAAc,MAAM,cAAc,KAAK,IAAI,aAAa;AAE5D,YAAQ,UAAU,UAAU,cAAc,cAAc;;GAG5D,MAAMC,WAAqB,OAAO,OAAO,YAAY;AACjD,QAAI,CAAC,mBAAoB;AAEzB,SAAK,MAAM,GAAG,cAAc,oBAAoB;KAC5C,MAAM,SAAS,MAAM,UAAU,gBAAgB;KAC/C,MAAM,eAAe,UAAU,sBAAsB,IAAI,EAAE;KAE3D,MAAM,uCAAuB,IAAI,KAG9B;AACH,UAAK,MAAM,OAAO,cAAc;MAC5B,MAAM,OAAO,qBAAqB,IAAI,IAAI,OAAO;AACjD,UAAI,KACA,MAAK,KAAK,EAAE,YAAY,IAAI,YAAY,CAAC;UAEzC,sBAAqB,IAAI,IAAI,QAAQ,CACjC,EAAE,YAAY,IAAI,YAAY,CACjC,CAAC;;AAIV,UAAK,MAAM,CAAC,QAAQ,YAAY,sBAAsB;MAIlD,MAAM,WAHY,MAAM,MAAM,MACzB,CAAC,OAAO,MAAM,OAClB,GAC4B;AAC7B,UAAI,CAAC,SAAU;AAEf,WAAK,MAAM,aAAa,YAAY;OAChC,MAAM,YACF,SAAS,yBAAyB,IAC9B,UACH;AACL,WAAI,WAAW,WAAW,QAAQ,OAAQ;AAE1C,YAAK,IAAI,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;QACvC,MAAM,WAAW,UAAU;QAC3B,MAAM,MAAM,QAAQ;AACpB,YAAI,CAAC,YAAY,CAAC,IAAK;AACvB,iBAAS,YAAY,CACjB,EAAE,YAAY,IAAI,YAAY,CACjC;;;;AAKb,SAAI,OAAO,MACP,MAAK,MAAM,CAAC,QAAQ,QAAQ,OAAO,QAC/B,OAAO,MACV,CACG,SAAQ,UAAU,QAAQ,IAAI;AAGtC,SAAI,OAAO,OACP,SAAQ,UAAU,cAAc,OAAO,OAAO;;;AAK1D,QAAK,MAAM,SAASC,sBAAoB,WAAW,CAC/C,KAAI,OAAO,SAAS,MAAM;AAE9B,OAAI,iBAAiB,SAAS,gBAAgB;AAC9C,OAAI,UAAU,SAAS,SAAS;AAChC,OAAI,QAAQ,eAAe;AACvB,yBAAqB;KACvB;;EAET;;;;;;;;;;ACvHL,IAAa,yBAAb,MAA6D;CAEzD,AAAiB,UAAyC,EAAE;CAC5D,AAAiB,oBAAwC,EAAE;CAC3D,AAAiB,aAAyB,EAAE;CAC5C,AAAiB,cAA8B,EAAE;CAEjD,AAAS,iBAAiB,EAEtB,yBAAyB,IAAa,OAAgB,IACzD;CAED,AAAS,SAA4B,EAEjC,WAAW,MAAmC;AAC1C,OAAK,QAAQ,KAAK,EAAE;IAE3B;CAED,AAAS,mBAAgD,EACrD,WAAW,MAAwB;AAC/B,OAAK,kBAAkB,KAAK,EAAE;IAErC;CAED,AAAS,YAA8B,EACnC,WAAW,MAAgB;AACvB,OAAK,WAAW,KAAK,EAAE;IAE9B;CAED,AAAS,UAA+B,EACpC,WAAW,OAAmB;AAC1B,OAAK,YAAY,KAAK,GAAG;IAEhC;CAED,AAAS;CAET,YAAY,cAA6B;AAErC,OAAK,eAAe,uBAAuB;;CAI/C,YAAoD;AAChD,SAAO,CAAC,GAAG,KAAK,QAAQ;;CAG5B,sBAA0C;AACtC,SAAO,CAAC,GAAG,KAAK,kBAAkB;;CAGtC,eAA2B;AACvB,SAAO,CAAC,GAAG,KAAK,WAAW;;CAG/B,aAAmB;AACf,OAAK,MAAM,MAAM,KAAK,YAAa,KAAI"}
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mochi-css/plugins",
|
|
3
|
+
"repository": "git@github.com:Niikelion/mochi-css.git",
|
|
4
|
+
"version": "3.1.0",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"module": "dist/index.mjs",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"files": [
|
|
10
|
+
"/dist"
|
|
11
|
+
],
|
|
12
|
+
"exports": {
|
|
13
|
+
"import": {
|
|
14
|
+
"types": "./dist/index.d.mts",
|
|
15
|
+
"import": "./dist/index.mjs"
|
|
16
|
+
},
|
|
17
|
+
"require": {
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"require": "./dist/index.js"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "tsc --noEmit && tsdown",
|
|
24
|
+
"test": "vitest",
|
|
25
|
+
"coverage": "vitest run --coverage",
|
|
26
|
+
"lint": "eslint src",
|
|
27
|
+
"lint:fix": "eslint src --fix",
|
|
28
|
+
"format": "prettier --write ."
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@mochi-css/builder": "^4.0.0",
|
|
32
|
+
"@mochi-css/config": "^3.1.0",
|
|
33
|
+
"@swc/core": "^1.15.13"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@gamedev-sensei/ts-config": "^2.1.0",
|
|
37
|
+
"@gamedev-sensei/tsdown-config": "^2.1.0",
|
|
38
|
+
"@mochi-css/shared-config": "^2.0.0",
|
|
39
|
+
"@swc/types": "^0.1.25",
|
|
40
|
+
"@types/node": "^24.8.1",
|
|
41
|
+
"dedent": "^1.7.1",
|
|
42
|
+
"eslint": "^9.39.2",
|
|
43
|
+
"prettier": "^3.8.1",
|
|
44
|
+
"typescript": "^5.9.3",
|
|
45
|
+
"vitest": "^4.0.15"
|
|
46
|
+
}
|
|
47
|
+
}
|