vite-plugin-bemoji 1.0.0-beta.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.
Files changed (2) hide show
  1. package/package.json +14 -0
  2. package/src/index.js +103 -0
package/package.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "vite-plugin-bemoji",
3
+ "version": "1.0.0-beta.1",
4
+ "description": "Vite plugin for BEMoji — transforms emoji class names in HTML, JSX, TSX, and Vue templates.",
5
+ "main": "src/index.js",
6
+ "scripts": {
7
+ "test": "vitest run --passWithNoTests"
8
+ },
9
+ "keywords": ["vite-plugin", "bemoji", "css", "emoji", "bem", "vite"],
10
+ "license": "MIT",
11
+ "peerDependencies": {
12
+ "vite": ">=4.0.0"
13
+ }
14
+ }
package/src/index.js ADDED
@@ -0,0 +1,103 @@
1
+ /**
2
+ * vite-plugin-bemoji
3
+ *
4
+ * Vite plugin that transforms readable BEM class names to emoji throughout your
5
+ * source files (HTML, JSX, TSX, Vue) at build time.
6
+ *
7
+ * Usage:
8
+ * // vite.config.ts
9
+ * import bemoji from 'vite-plugin-bemoji';
10
+ *
11
+ * export default {
12
+ * plugins: [
13
+ * bemoji({
14
+ * config: './bemoji.config.js',
15
+ * include: ['**\/*.{tsx,jsx,vue,html}'],
16
+ * })
17
+ * ]
18
+ * }
19
+ */
20
+
21
+ import { loadConfig, encode } from '../../core/src/resolver.js';
22
+ import { createFilter } from 'vite';
23
+
24
+ // Matches className="..." or class="..." attribute values
25
+ // Handles bracket shorthand: className="[card] [card__image--featured]"
26
+ const CLASS_ATTR_PATTERN = /(?:class|className)=["']([^"']+)["']/g;
27
+ const BRACKET_CLASS_REGEX = /\[([^\]]+)\]/g;
28
+
29
+ function transformClassString(classStr, config) {
30
+ return classStr.replace(BRACKET_CLASS_REGEX, (_, readable) => {
31
+ return encode(readable, config);
32
+ });
33
+ }
34
+
35
+ export default function bemojiPlugin(opts = {}) {
36
+ const userConfig = opts.config ?? {};
37
+ let config;
38
+
39
+ const filter = createFilter(
40
+ opts.include ?? ['**/*.{html,jsx,tsx,vue,svelte}'],
41
+ opts.exclude ?? ['node_modules/**']
42
+ );
43
+
44
+ return {
45
+ name: 'vite-plugin-bemoji',
46
+
47
+ configResolved() {
48
+ config = loadConfig(
49
+ typeof userConfig === 'string'
50
+ ? {} // In production: loadConfig(require(userConfig))
51
+ : userConfig
52
+ );
53
+ },
54
+
55
+ /**
56
+ * Transform HTML template class attributes.
57
+ * This runs on raw HTML files.
58
+ */
59
+ transformIndexHtml(html) {
60
+ return html.replace(CLASS_ATTR_PATTERN, (match, classStr) => {
61
+ const transformed = transformClassString(classStr, config);
62
+ return match.replace(classStr, transformed);
63
+ });
64
+ },
65
+
66
+ /**
67
+ * Transform JSX/TSX/Vue source files.
68
+ * Finds className and class attribute values and transforms them.
69
+ */
70
+ transform(code, id) {
71
+ if (!filter(id)) return null;
72
+
73
+ let transformed = code;
74
+ let hasChanges = false;
75
+
76
+ transformed = transformed.replace(CLASS_ATTR_PATTERN, (match, classStr) => {
77
+ const newClassStr = transformClassString(classStr, config);
78
+ if (newClassStr !== classStr) {
79
+ hasChanges = true;
80
+ return match.replace(classStr, newClassStr);
81
+ }
82
+ return match;
83
+ });
84
+
85
+ if (!hasChanges) return null;
86
+
87
+ return {
88
+ code: transformed,
89
+ map: null, // Source maps can be added here
90
+ };
91
+ },
92
+
93
+ /**
94
+ * Handle HMR — re-apply transforms when config changes.
95
+ */
96
+ handleHotUpdate({ file, server }) {
97
+ if (file.endsWith('bemoji.config.js') || file.endsWith('bemoji.config.ts')) {
98
+ config = loadConfig({});
99
+ server.ws.send({ type: 'full-reload' });
100
+ }
101
+ },
102
+ };
103
+ }