Skip to content

Commit

Permalink
pkg: add @quasi-dev/browser-tailwind
Browse files Browse the repository at this point in the history
  • Loading branch information
KermanX committed Nov 11, 2023
1 parent 81875b4 commit 36c158b
Show file tree
Hide file tree
Showing 14 changed files with 352 additions and 85 deletions.
5 changes: 5 additions & 0 deletions packages/browser-tailwind/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Browser Tailwind

This package allows you to compile Tailwind CSS in the browser.

Some code is borrowed from https://github.com/tailwindlabs/tailwindcss/issues/9716.
30 changes: 30 additions & 0 deletions packages/browser-tailwind/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"name": "@quasi-dev/browser-tailwind",
"version": "0.0.0",
"description": "Compile Tailwind CSS in the browser",
"type": "module",
"private": true,
"scripts": {
"check": "tsc --noEmit",
"build": "vite build"
},
"main": "./dist/browser-tailwind.js",
"types": "./src/index.ts",
"exports": {
".": {
"default": "./dist/browser-tailwind.js",
"import": "./dist/browser-tailwind.js",
"types": "./src/index.ts"
}
},
"devDependencies": {
"@rollup/plugin-commonjs": "^25.0.7",
"@rollup/plugin-node-resolve": "^15.2.3",
"typescript": "^5.1.6",
"vite": "^4.4.8"
},
"dependencies": {
"postcss": "^8.4.31",
"tailwindcss": "^3.3.5"
}
}
56 changes: 56 additions & 0 deletions packages/browser-tailwind/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import postcss from "postcss";
import tailwindcss, { Config } from "tailwindcss";
import {
VIRTUAL_HTML_FILENAME,
VIRTUAL_SOURCE_PATH,
} from "./polyfill/constants";

//@ts-ignore
self.process = {
env: {},
};

export async function compileTailwindCSS(
cssInput: string,
htmlInput: string,
config: Config | {} = {},
plugins = [],
) {
// Tailwind scans the config.content for files to parse classNames -> set a virtual file here
if ("content" in config) {
self[VIRTUAL_HTML_FILENAME] = htmlInput;
config.content = [VIRTUAL_HTML_FILENAME];
}
return await postcss([
tailwindcss(config as Config),
formatNodes,
...plugins,
]).process(cssInput, {
from: VIRTUAL_SOURCE_PATH,
});
}

// https://github.com/tailwindlabs/tailwindcss/blob/315e3a2445d682b2da9ca93fda77252fe32879ff/src/cli.js#L26-L42
function formatNodes(root) {
indentRecursive(root);
if (root.first) {
root.first.raws.before = "";
}
}

function indentRecursive(node, indent = 0) {
node.each &&
node.each((child, i) => {
if (
!child.raws.before ||
!child.raws.before.trim() ||
child.raws.before.includes("\n")
) {
child.raws.before = `\n${
node.type !== "rule" && i > 0 ? "\n" : ""
}${" ".repeat(indent)}`;
}
child.raws.after = `\n${" ".repeat(indent)}`;
indentRecursive(child, indent + 1);
});
}
2 changes: 2 additions & 0 deletions packages/browser-tailwind/src/polyfill/colorette.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
//@ts-nocheck
export const options = { enabled: false };
6 changes: 6 additions & 0 deletions packages/browser-tailwind/src/polyfill/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
//@ts-nocheck
/**
* Dummy constant for Node like environment in Browser for lib depending on fs module, like PostCSS
*/
export const VIRTUAL_SOURCE_PATH = "/sourcePath";
export const VIRTUAL_HTML_FILENAME = "/htmlInput";
14 changes: 14 additions & 0 deletions packages/browser-tailwind/src/polyfill/fast-glob.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//@ts-nocheck
export default {
sync: (patterns) => [].concat(patterns),
escapePath: (path) => path,
generateTasks: (patterns) => [
{
dynamic: false,
base: '.',
negative: [],
positive: [].concat(patterns),
patterns: [].concat(patterns),
},
],
}
15 changes: 15 additions & 0 deletions packages/browser-tailwind/src/polyfill/fs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//@ts-nocheck
import { VIRTUAL_SOURCE_PATH } from "./constants";

let i = 0;
self.BUILD_ID = 0;

export default {
statSync: (id) => {
if (id === VIRTUAL_SOURCE_PATH) {
return { mtimeMs: self.BUILD_ID };
}
return { mtimeMs: ++i };
},
readFileSync: (id) => self[id] || "",
};
2 changes: 2 additions & 0 deletions packages/browser-tailwind/src/polyfill/glob-parent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
//@ts-nocheck
export default () => "";
2 changes: 2 additions & 0 deletions packages/browser-tailwind/src/polyfill/is-glob.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
//@ts-nocheck
export default () => false;
11 changes: 11 additions & 0 deletions packages/browser-tailwind/src/polyfill/path.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//@ts-nocheck
self.__dirname = "";
export default {
join: () => {
return "";
},
};

export const join = () => {
return "";
};
6 changes: 6 additions & 0 deletions packages/browser-tailwind/src/polyfill/url.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
//@ts-nocheck
export default {
parse() {
return new URL(location.href);
},
};
8 changes: 8 additions & 0 deletions packages/browser-tailwind/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"include": ["src"],
"compilerOptions": {
"module": "ESNext",
"moduleResolution": "Bundler",
"lib": ["ESNext", "DOM"],
}
}
50 changes: 50 additions & 0 deletions packages/browser-tailwind/vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { defineConfig } from "vite";
import commonjs from "@rollup/plugin-commonjs";
import resolve from "@rollup/plugin-node-resolve";

export default defineConfig({
plugins: [
commonjs(),
resolve(),
{
name: "helper",
enforce: "pre",
transform(code, id, options) {
const names = [
["declaration", "Declaration"],
["comment", "Comment"],
["container", "Container"],
["document", "Document"],
["at-rule", "AtRule"],
["root", "Root"],
["rule", "Rule"],
];
for (const name of names) {
if (id.endsWith(`postcss/lib/${name[0]}.js`)) {
console.log(`Removing ${name[1]} from ${id}`);
return code.replace(`${name[1]}.default = ${name[1]}`, "");
}
}
},
},
],
resolve: {
alias: {
colorette: "./src/polyfill/colorette.ts",
fs: "./src/polyfill/fs.ts",
path: "./src/polyfill/path.ts",
url: "./src/polyfill/url.ts",
"is-glob": "./src/polyfill/is-glob.ts",
"glob-parent": "./src/polyfill/glob-parent.ts",
"fast-glob": "./src/polyfill/fast-glob.ts",
},
},
build: {
lib: {
entry: "src/index.ts",
name: "BrowserTailwind",
formats: ["es"],
},
minify: false,
},
});
Loading

0 comments on commit 36c158b

Please sign in to comment.