@birdycom/omniacss-migrate 0.11.2 → 0.12.1
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 +4 -3
- package/package.json +6 -3
- package/src/entry.css +8 -0
- package/src/index.mjs +1 -0
- package/src/postcss.mjs +8 -5
- package/src/project.mjs +1 -1
- package/src/setup.mjs +21 -10
- package/src/utilities.mjs +2 -1
- package/src/vite.mjs +1 -1
package/README.md
CHANGED
|
@@ -31,9 +31,10 @@ export default defineConfig({ plugins: [laravel({ input: ["resources/css/app.css
|
|
|
31
31
|
```
|
|
32
32
|
|
|
33
33
|
```css
|
|
34
|
-
/* resources/css/app.css:
|
|
34
|
+
/* resources/css/app.css: the entry, under our own name (setup --write renames @import "tailwindcss" to it): */
|
|
35
|
+
@import "@birdycom/omniacss-migrate";
|
|
36
|
+
/* the Tailwind forms keep working too: */
|
|
35
37
|
@import "tailwindcss";
|
|
36
|
-
/* or */
|
|
37
38
|
@tailwind base; @tailwind components; @tailwind utilities;
|
|
38
39
|
```
|
|
39
40
|
|
|
@@ -47,7 +48,7 @@ export default { plugins: [omniaMigrate({ content: ["resources/views/**/*.blade.
|
|
|
47
48
|
|
|
48
49
|
## What the plugin does
|
|
49
50
|
|
|
50
|
-
- Replaces `@import "tailwindcss"` / `@tailwind base|components|utilities` with Omnia core (tokens + the Omnia classes you use), a small base reset and the compat CSS for the classes it finds in your content.
|
|
51
|
+
- Replaces `@import "@birdycom/omniacss-migrate"` / `@import "tailwindcss"` / `@tailwind base|components|utilities` with Omnia core (tokens + the Omnia classes you use), a small base reset and the compat CSS for the classes it finds in your content.
|
|
51
52
|
- Expands `@apply` (with variants, `!important`, and your own classes), `theme(colors.red.500)`, `--spacing(4)`, `@theme`, `@custom-variant`, `@variant`, `@source`, `@source inline("…")`; ignores `@plugin` and `@config`.
|
|
52
53
|
- Reads `tailwind.config.{js,cjs,mjs}` (`darkMode`, `theme.colors`/`extend.colors`, `fontFamily`, `borderRadius`, `spacing`, `boxShadow`, `screens`, `container`, `prefix`, `important`) and your `@theme` blocks.
|
|
53
54
|
- Output is wrapped in cascade layers `omnia, theme, base, components, utilities`.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@birdycom/omniacss-migrate",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.1",
|
|
4
4
|
"description": "Switch a Laravel / Vue / React project from Tailwind CSS to OmniaCSS and keep your class names (PostCSS + Vite plugin, scan, setup, codemod), or convert a Bootstrap 3/4/5 site to OmniaCSS + OmniaUI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -32,7 +32,10 @@
|
|
|
32
32
|
"omniacss-migrate": "./bin/omniacss-migrate.mjs"
|
|
33
33
|
},
|
|
34
34
|
"exports": {
|
|
35
|
-
".":
|
|
35
|
+
".": {
|
|
36
|
+
"style": "./src/entry.css",
|
|
37
|
+
"default": "./src/index.mjs"
|
|
38
|
+
},
|
|
36
39
|
"./postcss": "./src/postcss.mjs",
|
|
37
40
|
"./vite": "./src/vite.mjs",
|
|
38
41
|
"./cli": "./src/cli.mjs",
|
|
@@ -51,7 +54,7 @@
|
|
|
51
54
|
"build:colors": "node scripts/build-color-map.mjs"
|
|
52
55
|
},
|
|
53
56
|
"dependencies": {
|
|
54
|
-
"@birdycom/omniacss": "^0.
|
|
57
|
+
"@birdycom/omniacss": "^0.12.1",
|
|
55
58
|
"postcss": "^8.5.3"
|
|
56
59
|
},
|
|
57
60
|
"publishConfig": {
|
package/src/entry.css
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/* File: packages/migrate/src/entry.css
|
|
2
|
+
What `@import "@birdycom/omniacss-migrate";` resolves to when a bundler inlines the import itself (Vite with the
|
|
3
|
+
PostCSS plugin in postcss.config.js). The plugin replaces these directives with OmniaCSS core + compat CSS.
|
|
4
|
+
With the Vite plugin the import never gets this far: it is compiled before Vite looks at it.
|
|
5
|
+
Author: Serge Cools | Framework: OmniaCSS */
|
|
6
|
+
@tailwind base;
|
|
7
|
+
@tailwind components;
|
|
8
|
+
@tailwind utilities;
|
package/src/index.mjs
CHANGED
|
@@ -8,5 +8,6 @@ export { runCodemod, formatCodemod } from "./codemod.mjs";
|
|
|
8
8
|
export { planSetup, applySetup, formatPlan } from "./setup.mjs";
|
|
9
9
|
export { loadProject, themeFromConfig } from "./project.mjs";
|
|
10
10
|
export { COLOR_MAP } from "./values.mjs";
|
|
11
|
+
export { loadOmniaIndex, nativeFor } from "./native.mjs";
|
|
11
12
|
export { default as postcss } from "./postcss.mjs";
|
|
12
13
|
export { default as vite } from "./vite.mjs";
|
package/src/postcss.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// File: packages/migrate/src/postcss.mjs
|
|
2
2
|
// PostCSS plugin "keep your classes": replaces the framework directives in your CSS
|
|
3
|
-
// @import "tailwindcss"; / @tailwind base|components|utilities;
|
|
3
|
+
// @import "tailwindcss"; / @import "@birdycom/omniacss-migrate"; / @tailwind base|components|utilities;
|
|
4
4
|
// with OmniaCSS core + compat CSS for the classes found in your content, and expands @apply, theme() and @theme.
|
|
5
5
|
//
|
|
6
6
|
// // postcss.config.js
|
|
@@ -21,7 +21,8 @@ import { buildCoreCss } from "./core.mjs";
|
|
|
21
21
|
import { COLOR_MAP } from "./values.mjs";
|
|
22
22
|
import { applyVariant } from "./variants.mjs";
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
// `@import "tailwindcss"`, or the same entry under our own name, so a project can drop every Tailwind mention.
|
|
25
|
+
const TW_IMPORT = /^["'](?:tailwindcss|@birdycom\/omniacss-migrate)(?:\/(theme|preflight|utilities|base|components)(?:\.css)?)?["']/;
|
|
25
26
|
const fileTokenCache = new Map();
|
|
26
27
|
|
|
27
28
|
/** Default content globs when none are given. */
|
|
@@ -197,7 +198,8 @@ export default function omniaMigrate(options = {}) {
|
|
|
197
198
|
pieces.core = options.core === false ? "" : await buildCoreCss({ candidates, compatCss, exclude, cwd, layer: layers ? "omnia" : false, mode: options.core === "tokens" ? "tokens" : true });
|
|
198
199
|
pieces.utilities = wrap("utilities", compatCss);
|
|
199
200
|
const all = [pieces.order, pieces.theme, pieces.preflight, pieces.core, pieces.utilities];
|
|
200
|
-
|
|
201
|
+
// `from`: the stylesheet being built, so Vite resolves url() in the generated CSS against it (no "did not pass from" warning).
|
|
202
|
+
const mk = (css) => postcss.parse(css, { from: result.opts.from }).nodes;
|
|
201
203
|
const place = (at, css) => { const nodes = css ? mk(css) : []; if (nodes.length) at.replaceWith(nodes); else at.remove(); };
|
|
202
204
|
|
|
203
205
|
for (const at of twImports) {
|
|
@@ -293,7 +295,8 @@ function expandApply(at, ctx, classIndex, usedKeyframes, result) {
|
|
|
293
295
|
else extras.push(rule);
|
|
294
296
|
}
|
|
295
297
|
}
|
|
296
|
-
|
|
298
|
+
// `source` of the @apply: Vite resolves url() in these declarations against the file they are written in.
|
|
299
|
+
const nodes = inline.map(([prop, value, imp]) => postcss.decl({ prop, value, important: !!imp, source: at.source }));
|
|
297
300
|
if (nodes.length) at.replaceWith(nodes); else at.remove();
|
|
298
301
|
if (!extras.length) return;
|
|
299
302
|
const flat = parent.parent && parent.parent.type !== "rule";
|
|
@@ -302,7 +305,7 @@ function expandApply(at, ctx, classIndex, usedKeyframes, result) {
|
|
|
302
305
|
const sels = flat ? x.selectors.flatMap((s) => parent.selectors.map((ps) => s.replace(/&/g, ps))) : x.selectors;
|
|
303
306
|
let css = `${sels.join(",\n")} {\n${x.decls.map(([p, v]) => ` ${p}: ${v};`).join("\n")}\n}`;
|
|
304
307
|
for (let i = x.media.length - 1; i >= 0; i--) css = `${x.media[i]} {\n${css}\n}`;
|
|
305
|
-
const parsed = postcss.parse(css, { from:
|
|
308
|
+
const parsed = postcss.parse(css, { from: at.source?.input.file ?? result.opts.from }).nodes;
|
|
306
309
|
if (flat) { for (const n of parsed) { anchor.after(n); anchor = n; } } else parent.append(parsed);
|
|
307
310
|
}
|
|
308
311
|
}
|
package/src/project.mjs
CHANGED
|
@@ -146,7 +146,7 @@ export async function loadProject(dir, overrides = {}) {
|
|
|
146
146
|
for (const f of info.cssFiles) {
|
|
147
147
|
const css = await fs.readFile(f, "utf8").catch(() => "");
|
|
148
148
|
for (const [k, v] of parseThemeBlocks(css)) info.themeVars.set(k, v);
|
|
149
|
-
if (/@import\s+["']tailwindcss/.test(css) || /@theme\b/.test(css)) info.tailwindVersion ||= 4;
|
|
149
|
+
if (/@import\s+["'](?:tailwindcss|@birdycom\/omniacss-migrate)/.test(css) || /@theme\b/.test(css)) info.tailwindVersion ||= 4;
|
|
150
150
|
if (/@tailwind\s+(base|utilities|components)/.test(css)) info.tailwindVersion ||= 3;
|
|
151
151
|
const cv = css.match(/@custom-variant\s+dark\s*\(([^;]*)\)\s*;/);
|
|
152
152
|
if (cv) {
|
package/src/setup.mjs
CHANGED
|
@@ -5,12 +5,14 @@
|
|
|
5
5
|
|
|
6
6
|
import fs from "node:fs/promises";
|
|
7
7
|
import path from "node:path";
|
|
8
|
+
import { createRequire } from "node:module";
|
|
8
9
|
import { loadProject, loadTailwindConfig, themeFromConfig, findFiles } from "./project.mjs";
|
|
9
10
|
import { createContext } from "./resolve.mjs";
|
|
10
11
|
|
|
11
12
|
const TW_PKGS = ["tailwindcss", "@tailwindcss/vite", "@tailwindcss/postcss"];
|
|
12
13
|
const TW_NAME = "(?:@tailwindcss\\/vite|@tailwindcss\\/postcss|tailwindcss)";
|
|
13
|
-
|
|
14
|
+
// The range written into the project: this package's own version, so it never goes stale.
|
|
15
|
+
const VERSION = `^${createRequire(import.meta.url)("../package.json").version}`;
|
|
14
16
|
|
|
15
17
|
const read = (f) => fs.readFile(f, "utf8").catch(() => null);
|
|
16
18
|
|
|
@@ -147,10 +149,17 @@ export async function planSetup(dir, { keepBrandColors = false } = {}) {
|
|
|
147
149
|
let entryDone = false;
|
|
148
150
|
for (const f of cssFiles) {
|
|
149
151
|
const before = await read(f);
|
|
150
|
-
if (!/@import\s+["']tailwindcss|@tailwind\s+(base|utilities)/.test(before)) continue;
|
|
152
|
+
if (!/@import\s+["'](?:tailwindcss|@birdycom\/omniacss-migrate)|@tailwind\s+(base|utilities)/.test(before)) continue;
|
|
151
153
|
detected.css.push(path.relative(dir, f));
|
|
152
|
-
|
|
154
|
+
// `@import "tailwindcss"` -> `@import "@birdycom/omniacss-migrate"` (same entry, no Tailwind name left).
|
|
155
|
+
// The v3 `@tailwind …` directives stay: they may sit mid-file, where an @import is not allowed.
|
|
156
|
+
const renamed = before.replace(/(@import\s+)(["'])tailwindcss((?:\/[\w.-]+)?)\2/g, "$1$2@birdycom/omniacss-migrate$3$2");
|
|
157
|
+
const isEntry = !entryDone;
|
|
153
158
|
entryDone = true;
|
|
159
|
+
if (!isEntry) {
|
|
160
|
+
if (renamed !== before) changes.push({ file: f, before, after: renamed, note: 'rename @import "tailwindcss" to @import "@birdycom/omniacss-migrate"' });
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
154
163
|
const add = [];
|
|
155
164
|
if (loaded?.config) {
|
|
156
165
|
const t = themeFromConfig(loaded.config, createContext({}), { keepColors: keepBrandColors });
|
|
@@ -165,15 +174,17 @@ export async function planSetup(dir, { keepBrandColors = false } = {}) {
|
|
|
165
174
|
if ((dm === "class" || dm === "selector") && !/@custom-variant\s+dark/.test(before)) add.push("@custom-variant dark (&:where(.dark, .dark *));");
|
|
166
175
|
}
|
|
167
176
|
if (add.length) {
|
|
168
|
-
const re = /^(@import\s+["']
|
|
169
|
-
const m =
|
|
170
|
-
const eol =
|
|
171
|
-
const after = m ?
|
|
172
|
-
changes.push({ file: f, before, after, note:
|
|
173
|
-
} else
|
|
177
|
+
const re = /^(@import\s+["']@birdycom\/omniacss-migrate["'][^;\n]*;|@tailwind\s+utilities;)[ \t]*\r?\n/m;
|
|
178
|
+
const m = renamed.match(re);
|
|
179
|
+
const eol = renamed.includes("\r\n") ? "\r\n" : "\n";
|
|
180
|
+
const after = m ? renamed.replace(re, `${m[0]}${eol}${add.join(eol)}${eol}`) : renamed + eol + add.join(eol) + eol;
|
|
181
|
+
changes.push({ file: f, before, after, note: `carry tailwind.config theme into CSS (@theme) and dark mode variant${renamed !== before ? '; rename @import "tailwindcss"' : ""}` });
|
|
182
|
+
} else if (renamed !== before) {
|
|
183
|
+
changes.push({ file: f, before, after: renamed, note: 'rename @import "tailwindcss" to @import "@birdycom/omniacss-migrate" (the plugin handles it)' });
|
|
184
|
+
} else notes.push(`${path.relative(dir, f)}: the directives (@import "@birdycom/omniacss-migrate" / @tailwind …) are handled by the plugin; no change needed.`);
|
|
174
185
|
if (/@plugin\s+['"]@iconify/.test(before)) notes.push("`@plugin '@iconify/...'` is ignored by the plugin (icon-[...] classes are not generated).");
|
|
175
186
|
}
|
|
176
|
-
if (!detected.css.length) notes.push("No CSS file with Tailwind directives found. The plugin works on `@import \"tailwindcss\"` or `@tailwind base/components/utilities`.");
|
|
187
|
+
if (!detected.css.length) notes.push("No CSS file with Tailwind directives found. The plugin works on `@import \"@birdycom/omniacss-migrate\"`, `@import \"tailwindcss\"` or `@tailwind base/components/utilities`.");
|
|
177
188
|
commands.push("npm uninstall " + (removed.join(" ") || "tailwindcss @tailwindcss/vite"));
|
|
178
189
|
commands.push("npm install -D @birdycom/omniacss-migrate");
|
|
179
190
|
return { changes, notes, commands, detected };
|
package/src/utilities.mjs
CHANGED
|
@@ -262,6 +262,7 @@ const SIDE = { t: "top", r: "right", b: "bottom", l: "left", s: "inline-start",
|
|
|
262
262
|
function boxHandler(prop) {
|
|
263
263
|
// m, mx, my, mt … (margin / padding / scroll-margin / scroll-padding)
|
|
264
264
|
return (u, root) => {
|
|
265
|
+
// The side after the root: "mt" -> "t", "scroll-mt" -> "t", "scroll-p" -> "".
|
|
265
266
|
const key = root.slice(prefixLen(prop));
|
|
266
267
|
const v = sp(u, u.value, { keywords: { auto: "auto" }, fractions: false });
|
|
267
268
|
if (v == null) return null;
|
|
@@ -275,7 +276,7 @@ function boxHandler(prop) {
|
|
|
275
276
|
return null;
|
|
276
277
|
};
|
|
277
278
|
}
|
|
278
|
-
const prefixLen = (prop) => ({ margin: 1, padding: 1, "scroll-margin":
|
|
279
|
+
const prefixLen = (prop) => ({ margin: 1, padding: 1, "scroll-margin": 8, "scroll-padding": 8 })[prop];
|
|
279
280
|
|
|
280
281
|
function insetHandler(prop) {
|
|
281
282
|
return (u) => {
|
package/src/vite.mjs
CHANGED
|
@@ -60,7 +60,7 @@ export default function omniaMigrate(options = {}) {
|
|
|
60
60
|
async transform(code, id) {
|
|
61
61
|
const file = id.split("?")[0];
|
|
62
62
|
if (!/\.(css|pcss|postcss)$/.test(file)) return null;
|
|
63
|
-
if (!/@import\s+["']tailwindcss|@tailwind\s+\w+|@apply\s|@theme\b/.test(code)) return null;
|
|
63
|
+
if (!/@import\s+["'](?:tailwindcss|@birdycom\/omniacss-migrate)|@tailwind\s+\w+|@apply\s|@theme\b/.test(code)) return null;
|
|
64
64
|
const result = await postcss([omniaMigratePostcss({ cwd: root, ...options })]).process(code, { from: file, map: false });
|
|
65
65
|
for (const m of result.messages) if (m.type === "dependency" && m.file) this.addWatchFile(m.file);
|
|
66
66
|
return { code: result.css, map: null };
|