v-auto-color 1.0.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/.gitattributes ADDED
@@ -0,0 +1,2 @@
1
+ # Auto detect text files and perform LF normalization
2
+ * text=auto
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Zeki T. Luan
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,203 @@
1
+ # Vue-AutoColor
2
+
3
+ 一个兼容 vite/typescript/vue 环境的 node module,用于在 vite 编译时实现基于文本的自动颜色生成。相似的文本会返回相似的颜色,从而实现视觉上的一致性。
4
+
5
+ ## 功能特点
6
+
7
+ - **基于文本的颜色生成**:根据纯文本计算颜色,相似的文本返回相似的颜色
8
+ - **编译时优化**:在 vite 编译时预先计算已使用的颜色,降低运行时负载
9
+ - **运行时 fallback**:对于未预编译的颜色,在运行时自动生成并缓存
10
+ - **支持自定义配置**:可以配置颜色的色相范围、饱和度范围和亮度范围
11
+ - **TypeScript 支持**:完整的类型定义,提供良好的开发体验
12
+ - **Vue 兼容**:可以在 Vue 组件中轻松使用
13
+
14
+ ## 安装
15
+
16
+ ```bash
17
+ npm install v-auto-color
18
+ # 或
19
+ yarn add v-auto-color
20
+ # 或
21
+ pnpm add v-auto-color
22
+ ```
23
+
24
+ ## 使用方法
25
+
26
+ ### 1. 在 vite.config.ts 中配置插件
27
+
28
+ ```typescript
29
+ import { defineConfig } from 'vite';
30
+ import vue from '@vitejs/plugin-vue';
31
+ import { viteAutoColorPlugin } from 'v-auto-color';
32
+
33
+ export default defineConfig({
34
+ plugins: [
35
+ vue(),
36
+ viteAutoColorPlugin() // 启用 v-auto-color 插件
37
+ ],
38
+ });
39
+ ```
40
+
41
+ ### 2. 在代码中使用
42
+
43
+ ```typescript
44
+ import { useAutoColor } from 'v-auto-color';
45
+
46
+ // 使用默认配置
47
+ const colorSet1 = useAutoColor('set1');
48
+ const color1 = colorSet1.getColor('text');
49
+
50
+ // 使用自定义配置
51
+ const colorSet2 = useAutoColor({
52
+ category: 'set2',
53
+ hue: [180, 360], // 蓝色调范围
54
+ saturation: [60, 90],
55
+ lightness: [40, 70]
56
+ });
57
+ const color2 = colorSet2.getColor('text');
58
+ ```
59
+
60
+ ### 3. 在 Vue 组件中使用
61
+
62
+ ```vue
63
+ <template>
64
+ <div :style="`--color: ${colorSet1.getColor('text')}`">text</div>
65
+ </template>
66
+
67
+ <script setup lang="ts">
68
+ import { useAutoColor } from 'v-auto-color';
69
+
70
+ const colorSet1 = useAutoColor('set1');
71
+ </script>
72
+ ```
73
+
74
+ ## 配置选项
75
+
76
+ ### useAutoColor 配置
77
+
78
+ ```typescript
79
+ interface ColorConfig {
80
+ category?: string; // 颜色集类别,默认 'default'
81
+ hue?: [number, number]; // 色相范围,默认 [0, 360]
82
+ saturation?: [number, number]; // 饱和度范围,默认 [70, 100]
83
+ lightness?: [number, number]; // 亮度范围,默认 [40, 60]
84
+ }
85
+
86
+ // 两种使用方式
87
+ const colorSet1 = useAutoColor('category'); // 使用字符串作为类别
88
+ const colorSet2 = useAutoColor({ /* 完整配置 */ }); // 使用对象配置
89
+ ```
90
+
91
+ ## 性能优化
92
+
93
+ ### 编译时预计算
94
+
95
+ 插件会在 vite 编译时分析代码,提取所有 `useAutoColor` 和 `getColor` 的调用,预先计算出所有使用的颜色,并在构建时注入到代码中。这样在运行时,大部分颜色都可以直接从缓存中获取,无需重新计算。
96
+
97
+ ### 运行时缓存
98
+
99
+ 对于未在编译时预计算的颜色(例如动态生成的文本),插件会在运行时生成颜色并缓存起来,避免重复计算。
100
+
101
+ ### 哈希算法优化
102
+
103
+ 使用 MurmurHash3 算法计算文本哈希值,该算法具有以下特点:
104
+ - 计算速度快
105
+ - 分布均匀
106
+ - 碰撞率低
107
+
108
+ ## 工作原理
109
+
110
+ 1. **文本哈希**:使用 MurmurHash3 算法对文本进行哈希计算,得到一个数值
111
+ 2. **颜色生成**:根据哈希值计算 HSL 颜色,确保相似的文本返回相似的颜色
112
+ 3. **编译时分析**:在 vite 编译时分析代码,提取颜色使用情况
113
+ 4. **预计算颜色**:为提取的文本预先计算颜色
114
+ 5. **运行时使用**:在运行时优先使用预计算的颜色,未预计算的则动态生成
115
+
116
+ ## 示例
117
+
118
+ ### 基本示例
119
+
120
+ ```typescript
121
+ import { useAutoColor } from 'v-auto-color';
122
+
123
+ const colorSet = useAutoColor('default');
124
+
125
+ // 相似的文本会返回相似的颜色
126
+ const color1 = colorSet.getColor('hello');
127
+ const color2 = colorSet.getColor('hello world');
128
+ const color3 = colorSet.getColor('hello there');
129
+
130
+ console.log(color1); // 例如: hsl(120, 80%, 50%)
131
+ console.log(color2); // 例如: hsl(125, 75%, 45%)
132
+ console.log(color3); // 例如: hsl(115, 85%, 55%)
133
+ ```
134
+
135
+ ### Vue 组件示例
136
+
137
+ ```vue
138
+ <template>
139
+ <div class="tag-container">
140
+ <span
141
+ v-for="tag in tags"
142
+ :key="tag"
143
+ class="tag"
144
+ :style="`--tag-color: ${colorSet.getColor(tag)}`"
145
+ >
146
+ {{ tag }}
147
+ </span>
148
+ </div>
149
+ </template>
150
+
151
+ <script setup lang="ts">
152
+ import { useAutoColor } from 'v-auto-color';
153
+
154
+ const colorSet = useAutoColor('tags');
155
+ const tags = ['JavaScript', 'TypeScript', 'Vue', 'React', 'Node.js'];
156
+ </script>
157
+
158
+ <style scoped>
159
+ .tag {
160
+ display: inline-block;
161
+ padding: 4px 12px;
162
+ margin: 4px;
163
+ background-color: var(--tag-color);
164
+ color: white;
165
+ border-radius: 16px;
166
+ font-size: 14px;
167
+ }
168
+ </style>
169
+ ```
170
+
171
+ ## 常见问题
172
+
173
+ ### 颜色不一致
174
+
175
+ 如果发现相似的文本返回的颜色差异较大,可能是因为:
176
+ - 文本差异过大,导致哈希值差异较大
177
+ - 色相范围设置过小,导致颜色变化不明显
178
+
179
+ 可以尝试调整 `hue` 配置选项,扩大色相范围。
180
+
181
+ ### 性能问题
182
+
183
+ 对于大量动态文本的场景,建议:
184
+ - 尽可能在编译时确定文本内容,以便插件能够预计算颜色
185
+ - 对于动态生成的文本,可以考虑缓存结果,避免重复调用 `getColor`
186
+
187
+ ### 颜色质量
188
+
189
+ 如果生成的颜色质量不佳,可以调整配置选项:
190
+ - `saturation`:调整颜色的饱和度,值越高颜色越鲜艳
191
+ - `lightness`:调整颜色的亮度,值适中时颜色效果最好
192
+
193
+ ## 浏览器兼容性
194
+
195
+ 本插件生成的是标准的 HSL 颜色值,支持所有现代浏览器。对于 IE11 等旧浏览器,可能需要使用 HEX 颜色值的 polyfill。
196
+
197
+ ## 许可证
198
+
199
+ MIT License
200
+
201
+ ## 贡献
202
+
203
+ 欢迎提交 Issue 和 Pull Request!
@@ -0,0 +1,72 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
+
5
+ // src/core/hash.ts
6
+ function murmurHash3(text) {
7
+ let h1 = 3735928559;
8
+ const c1 = 3432918353;
9
+ const c2 = 461845907;
10
+ const r1 = 15;
11
+ const r2 = 13;
12
+ const m = 5;
13
+ const n = 3864292196;
14
+ let i = 0;
15
+ const length = text.length;
16
+ let k1 = 0;
17
+ while (i < length) {
18
+ const char = text.charCodeAt(i++);
19
+ k1 = k1 << 8 | char;
20
+ }
21
+ k1 = k1 * c1 >>> 0;
22
+ k1 = (k1 << r1 | k1 >>> 32 - r1) >>> 0;
23
+ k1 = k1 * c2 >>> 0;
24
+ h1 ^= k1;
25
+ h1 = (h1 << r2 | h1 >>> 32 - r2) >>> 0;
26
+ h1 = h1 * m + n >>> 0;
27
+ h1 ^= length;
28
+ h1 ^= h1 >>> 16;
29
+ h1 = h1 * 2246822507 >>> 0;
30
+ h1 ^= h1 >>> 13;
31
+ h1 = h1 * 3266489909 >>> 0;
32
+ h1 ^= h1 >>> 16;
33
+ return h1;
34
+ }
35
+ function getTextHash(text) {
36
+ return murmurHash3(text);
37
+ }
38
+
39
+ // src/core/color.ts
40
+ var ColorGenerator = class {
41
+ constructor(config = {}) {
42
+ __publicField(this, "config");
43
+ this.config = {
44
+ category: config.category || "default",
45
+ hue: config.hue || [0, 360],
46
+ saturation: config.saturation || [70, 100],
47
+ lightness: config.lightness || [40, 60]
48
+ };
49
+ }
50
+ // Generate color from hash value
51
+ generateColor(hash) {
52
+ const { hue, saturation, lightness } = this.config;
53
+ const hueRange = hue[1] - hue[0];
54
+ const calculatedHue = hue[0] + hash % hueRange;
55
+ const satRange = saturation[1] - saturation[0];
56
+ const calculatedSat = saturation[0] + (hash >> 8) % satRange;
57
+ const lightRange = lightness[1] - lightness[0];
58
+ const calculatedLight = lightness[0] + (hash >> 16) % lightRange;
59
+ return `hsl(${calculatedHue}, ${calculatedSat}%, ${calculatedLight}%)`;
60
+ }
61
+ // Get color for text (wrapper method)
62
+ getColor(text, hashFn) {
63
+ const hash = hashFn(text);
64
+ return this.generateColor(hash);
65
+ }
66
+ };
67
+
68
+ export {
69
+ __publicField,
70
+ getTextHash,
71
+ ColorGenerator
72
+ };
@@ -0,0 +1,18 @@
1
+ interface ColorConfig {
2
+ category?: string;
3
+ hue?: [number, number];
4
+ saturation?: [number, number];
5
+ lightness?: [number, number];
6
+ }
7
+
8
+ declare class ColorSet {
9
+ private config;
10
+ private generator;
11
+ private category;
12
+ constructor(config?: ColorConfig | string);
13
+ getColor(text: string): string;
14
+ }
15
+ declare function useAutoColor(config?: ColorConfig | string): ColorSet;
16
+ declare function __internal__setPrecomputedColors(colors: Record<string, Record<string, string>>): void;
17
+
18
+ export { type ColorConfig, ColorSet, __internal__setPrecomputedColors, useAutoColor };
@@ -0,0 +1,18 @@
1
+ interface ColorConfig {
2
+ category?: string;
3
+ hue?: [number, number];
4
+ saturation?: [number, number];
5
+ lightness?: [number, number];
6
+ }
7
+
8
+ declare class ColorSet {
9
+ private config;
10
+ private generator;
11
+ private category;
12
+ constructor(config?: ColorConfig | string);
13
+ getColor(text: string): string;
14
+ }
15
+ declare function useAutoColor(config?: ColorConfig | string): ColorSet;
16
+ declare function __internal__setPrecomputedColors(colors: Record<string, Record<string, string>>): void;
17
+
18
+ export { type ColorConfig, ColorSet, __internal__setPrecomputedColors, useAutoColor };
package/dist/index.js ADDED
@@ -0,0 +1,133 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
21
+
22
+ // src/index.ts
23
+ var index_exports = {};
24
+ __export(index_exports, {
25
+ ColorSet: () => ColorSet,
26
+ __internal__setPrecomputedColors: () => __internal__setPrecomputedColors,
27
+ useAutoColor: () => useAutoColor
28
+ });
29
+ module.exports = __toCommonJS(index_exports);
30
+
31
+ // src/core/hash.ts
32
+ function murmurHash3(text) {
33
+ let h1 = 3735928559;
34
+ const c1 = 3432918353;
35
+ const c2 = 461845907;
36
+ const r1 = 15;
37
+ const r2 = 13;
38
+ const m = 5;
39
+ const n = 3864292196;
40
+ let i = 0;
41
+ const length = text.length;
42
+ let k1 = 0;
43
+ while (i < length) {
44
+ const char = text.charCodeAt(i++);
45
+ k1 = k1 << 8 | char;
46
+ }
47
+ k1 = k1 * c1 >>> 0;
48
+ k1 = (k1 << r1 | k1 >>> 32 - r1) >>> 0;
49
+ k1 = k1 * c2 >>> 0;
50
+ h1 ^= k1;
51
+ h1 = (h1 << r2 | h1 >>> 32 - r2) >>> 0;
52
+ h1 = h1 * m + n >>> 0;
53
+ h1 ^= length;
54
+ h1 ^= h1 >>> 16;
55
+ h1 = h1 * 2246822507 >>> 0;
56
+ h1 ^= h1 >>> 13;
57
+ h1 = h1 * 3266489909 >>> 0;
58
+ h1 ^= h1 >>> 16;
59
+ return h1;
60
+ }
61
+ function getTextHash(text) {
62
+ return murmurHash3(text);
63
+ }
64
+
65
+ // src/core/color.ts
66
+ var ColorGenerator = class {
67
+ constructor(config = {}) {
68
+ __publicField(this, "config");
69
+ this.config = {
70
+ category: config.category || "default",
71
+ hue: config.hue || [0, 360],
72
+ saturation: config.saturation || [70, 100],
73
+ lightness: config.lightness || [40, 60]
74
+ };
75
+ }
76
+ // Generate color from hash value
77
+ generateColor(hash) {
78
+ const { hue, saturation, lightness } = this.config;
79
+ const hueRange = hue[1] - hue[0];
80
+ const calculatedHue = hue[0] + hash % hueRange;
81
+ const satRange = saturation[1] - saturation[0];
82
+ const calculatedSat = saturation[0] + (hash >> 8) % satRange;
83
+ const lightRange = lightness[1] - lightness[0];
84
+ const calculatedLight = lightness[0] + (hash >> 16) % lightRange;
85
+ return `hsl(${calculatedHue}, ${calculatedSat}%, ${calculatedLight}%)`;
86
+ }
87
+ // Get color for text (wrapper method)
88
+ getColor(text, hashFn) {
89
+ const hash = hashFn(text);
90
+ return this.generateColor(hash);
91
+ }
92
+ };
93
+
94
+ // src/index.ts
95
+ var precomputedColors = {};
96
+ var ColorSet = class {
97
+ constructor(config = "default") {
98
+ __publicField(this, "config");
99
+ __publicField(this, "generator");
100
+ __publicField(this, "category");
101
+ if (typeof config === "string") {
102
+ this.config = { category: config };
103
+ } else {
104
+ this.config = config;
105
+ }
106
+ this.category = this.config.category || "default";
107
+ this.generator = new ColorGenerator(this.config);
108
+ }
109
+ // Get color for text
110
+ getColor(text) {
111
+ if (precomputedColors[this.category] && precomputedColors[this.category][text]) {
112
+ return precomputedColors[this.category][text];
113
+ }
114
+ const color = this.generator.getColor(text, getTextHash);
115
+ if (!precomputedColors[this.category]) {
116
+ precomputedColors[this.category] = {};
117
+ }
118
+ precomputedColors[this.category][text] = color;
119
+ return color;
120
+ }
121
+ };
122
+ function useAutoColor(config = "default") {
123
+ return new ColorSet(config);
124
+ }
125
+ function __internal__setPrecomputedColors(colors) {
126
+ Object.assign(precomputedColors, colors);
127
+ }
128
+ // Annotate the CommonJS export names for ESM import in node:
129
+ 0 && (module.exports = {
130
+ ColorSet,
131
+ __internal__setPrecomputedColors,
132
+ useAutoColor
133
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,45 @@
1
+ import {
2
+ ColorGenerator,
3
+ __publicField,
4
+ getTextHash
5
+ } from "./chunk-GO6JHW6J.mjs";
6
+
7
+ // src/index.ts
8
+ var precomputedColors = {};
9
+ var ColorSet = class {
10
+ constructor(config = "default") {
11
+ __publicField(this, "config");
12
+ __publicField(this, "generator");
13
+ __publicField(this, "category");
14
+ if (typeof config === "string") {
15
+ this.config = { category: config };
16
+ } else {
17
+ this.config = config;
18
+ }
19
+ this.category = this.config.category || "default";
20
+ this.generator = new ColorGenerator(this.config);
21
+ }
22
+ // Get color for text
23
+ getColor(text) {
24
+ if (precomputedColors[this.category] && precomputedColors[this.category][text]) {
25
+ return precomputedColors[this.category][text];
26
+ }
27
+ const color = this.generator.getColor(text, getTextHash);
28
+ if (!precomputedColors[this.category]) {
29
+ precomputedColors[this.category] = {};
30
+ }
31
+ precomputedColors[this.category][text] = color;
32
+ return color;
33
+ }
34
+ };
35
+ function useAutoColor(config = "default") {
36
+ return new ColorSet(config);
37
+ }
38
+ function __internal__setPrecomputedColors(colors) {
39
+ Object.assign(precomputedColors, colors);
40
+ }
41
+ export {
42
+ ColorSet,
43
+ __internal__setPrecomputedColors,
44
+ useAutoColor
45
+ };
@@ -0,0 +1,5 @@
1
+ import { Plugin } from 'vite';
2
+
3
+ declare function viteAutoColorPlugin(): Plugin;
4
+
5
+ export { viteAutoColorPlugin as default, viteAutoColorPlugin };
@@ -0,0 +1,5 @@
1
+ import { Plugin } from 'vite';
2
+
3
+ declare function viteAutoColorPlugin(): Plugin;
4
+
5
+ export { viteAutoColorPlugin as default, viteAutoColorPlugin };
@@ -0,0 +1,158 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
21
+
22
+ // src/vite-plugin.ts
23
+ var vite_plugin_exports = {};
24
+ __export(vite_plugin_exports, {
25
+ default: () => vite_plugin_default,
26
+ viteAutoColorPlugin: () => viteAutoColorPlugin
27
+ });
28
+ module.exports = __toCommonJS(vite_plugin_exports);
29
+ var import_pluginutils = require("@rollup/pluginutils");
30
+
31
+ // src/core/hash.ts
32
+ function murmurHash3(text) {
33
+ let h1 = 3735928559;
34
+ const c1 = 3432918353;
35
+ const c2 = 461845907;
36
+ const r1 = 15;
37
+ const r2 = 13;
38
+ const m = 5;
39
+ const n = 3864292196;
40
+ let i = 0;
41
+ const length = text.length;
42
+ let k1 = 0;
43
+ while (i < length) {
44
+ const char = text.charCodeAt(i++);
45
+ k1 = k1 << 8 | char;
46
+ }
47
+ k1 = k1 * c1 >>> 0;
48
+ k1 = (k1 << r1 | k1 >>> 32 - r1) >>> 0;
49
+ k1 = k1 * c2 >>> 0;
50
+ h1 ^= k1;
51
+ h1 = (h1 << r2 | h1 >>> 32 - r2) >>> 0;
52
+ h1 = h1 * m + n >>> 0;
53
+ h1 ^= length;
54
+ h1 ^= h1 >>> 16;
55
+ h1 = h1 * 2246822507 >>> 0;
56
+ h1 ^= h1 >>> 13;
57
+ h1 = h1 * 3266489909 >>> 0;
58
+ h1 ^= h1 >>> 16;
59
+ return h1;
60
+ }
61
+ function getTextHash(text) {
62
+ return murmurHash3(text);
63
+ }
64
+
65
+ // src/core/color.ts
66
+ var ColorGenerator = class {
67
+ constructor(config = {}) {
68
+ __publicField(this, "config");
69
+ this.config = {
70
+ category: config.category || "default",
71
+ hue: config.hue || [0, 360],
72
+ saturation: config.saturation || [70, 100],
73
+ lightness: config.lightness || [40, 60]
74
+ };
75
+ }
76
+ // Generate color from hash value
77
+ generateColor(hash) {
78
+ const { hue, saturation, lightness } = this.config;
79
+ const hueRange = hue[1] - hue[0];
80
+ const calculatedHue = hue[0] + hash % hueRange;
81
+ const satRange = saturation[1] - saturation[0];
82
+ const calculatedSat = saturation[0] + (hash >> 8) % satRange;
83
+ const lightRange = lightness[1] - lightness[0];
84
+ const calculatedLight = lightness[0] + (hash >> 16) % lightRange;
85
+ return `hsl(${calculatedHue}, ${calculatedSat}%, ${calculatedLight}%)`;
86
+ }
87
+ // Get color for text (wrapper method)
88
+ getColor(text, hashFn) {
89
+ const hash = hashFn(text);
90
+ return this.generateColor(hash);
91
+ }
92
+ };
93
+
94
+ // src/vite-plugin.ts
95
+ function viteAutoColorPlugin() {
96
+ const filter = (0, import_pluginutils.createFilter)(["**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx", "**/*.vue"]);
97
+ const colorUsage = {};
98
+ return {
99
+ name: "v-auto-color",
100
+ // Analyze code during build
101
+ transform(code, id) {
102
+ if (!filter(id)) return null;
103
+ const useAutoColorRegex = /useAutoColor\s*\(\s*(?:(['"])([^'"]+)\1|\{[^}]*\})\s*\)/g;
104
+ const getColorRegex = /\.getColor\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
105
+ let match;
106
+ const colorSets = /* @__PURE__ */ new Set();
107
+ while ((match = useAutoColorRegex.exec(code)) !== null) {
108
+ let category = "default";
109
+ if (match[2]) {
110
+ category = match[2];
111
+ } else {
112
+ const configMatch = match[0].match(/category\s*:\s*['"]([^'"]+)['"]/);
113
+ if (configMatch) {
114
+ category = configMatch[1];
115
+ }
116
+ }
117
+ colorSets.add(category);
118
+ }
119
+ const texts = /* @__PURE__ */ new Set();
120
+ while ((match = getColorRegex.exec(code)) !== null) {
121
+ texts.add(match[1]);
122
+ }
123
+ colorSets.forEach((category) => {
124
+ if (!colorUsage[category]) {
125
+ colorUsage[category] = {};
126
+ }
127
+ texts.forEach((text) => {
128
+ const generator = new ColorGenerator({ category });
129
+ const color = generator.getColor(text, getTextHash);
130
+ colorUsage[category][text] = color;
131
+ });
132
+ });
133
+ return null;
134
+ },
135
+ // Generate precomputed colors module
136
+ generateBundle() {
137
+ const precomputedCode = `
138
+ import { __internal__setPrecomputedColors } from 'v-auto-color';
139
+ __internal__setPrecomputedColors(${JSON.stringify(colorUsage, null, 2)});
140
+ `;
141
+ this.emitFile({
142
+ type: "asset",
143
+ fileName: "v-auto-color-precomputed.js",
144
+ source: precomputedCode
145
+ });
146
+ this.emitFile({
147
+ type: "asset",
148
+ fileName: "v-auto-color-initializer.js",
149
+ source: `import "/v-auto-color-precomputed.js";`
150
+ });
151
+ }
152
+ };
153
+ }
154
+ var vite_plugin_default = viteAutoColorPlugin;
155
+ // Annotate the CommonJS export names for ESM import in node:
156
+ 0 && (module.exports = {
157
+ viteAutoColorPlugin
158
+ });
@@ -0,0 +1,71 @@
1
+ import {
2
+ ColorGenerator,
3
+ getTextHash
4
+ } from "./chunk-GO6JHW6J.mjs";
5
+
6
+ // src/vite-plugin.ts
7
+ import { createFilter } from "@rollup/pluginutils";
8
+ function viteAutoColorPlugin() {
9
+ const filter = createFilter(["**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx", "**/*.vue"]);
10
+ const colorUsage = {};
11
+ return {
12
+ name: "v-auto-color",
13
+ // Analyze code during build
14
+ transform(code, id) {
15
+ if (!filter(id)) return null;
16
+ const useAutoColorRegex = /useAutoColor\s*\(\s*(?:(['"])([^'"]+)\1|\{[^}]*\})\s*\)/g;
17
+ const getColorRegex = /\.getColor\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
18
+ let match;
19
+ const colorSets = /* @__PURE__ */ new Set();
20
+ while ((match = useAutoColorRegex.exec(code)) !== null) {
21
+ let category = "default";
22
+ if (match[2]) {
23
+ category = match[2];
24
+ } else {
25
+ const configMatch = match[0].match(/category\s*:\s*['"]([^'"]+)['"]/);
26
+ if (configMatch) {
27
+ category = configMatch[1];
28
+ }
29
+ }
30
+ colorSets.add(category);
31
+ }
32
+ const texts = /* @__PURE__ */ new Set();
33
+ while ((match = getColorRegex.exec(code)) !== null) {
34
+ texts.add(match[1]);
35
+ }
36
+ colorSets.forEach((category) => {
37
+ if (!colorUsage[category]) {
38
+ colorUsage[category] = {};
39
+ }
40
+ texts.forEach((text) => {
41
+ const generator = new ColorGenerator({ category });
42
+ const color = generator.getColor(text, getTextHash);
43
+ colorUsage[category][text] = color;
44
+ });
45
+ });
46
+ return null;
47
+ },
48
+ // Generate precomputed colors module
49
+ generateBundle() {
50
+ const precomputedCode = `
51
+ import { __internal__setPrecomputedColors } from 'v-auto-color';
52
+ __internal__setPrecomputedColors(${JSON.stringify(colorUsage, null, 2)});
53
+ `;
54
+ this.emitFile({
55
+ type: "asset",
56
+ fileName: "v-auto-color-precomputed.js",
57
+ source: precomputedCode
58
+ });
59
+ this.emitFile({
60
+ type: "asset",
61
+ fileName: "v-auto-color-initializer.js",
62
+ source: `import "/v-auto-color-precomputed.js";`
63
+ });
64
+ }
65
+ };
66
+ }
67
+ var vite_plugin_default = viteAutoColorPlugin;
68
+ export {
69
+ vite_plugin_default as default,
70
+ viteAutoColorPlugin
71
+ };
@@ -0,0 +1,77 @@
1
+ <template>
2
+ <div class="example-container">
3
+ <h1>v-auto-color 示例</h1>
4
+
5
+ <!-- 使用默认配置的颜色集 -->
6
+ <div class="color-set">
7
+ <h2>默认配置颜色集</h2>
8
+ <div
9
+ v-for="text in texts"
10
+ :key="text"
11
+ class="color-item"
12
+ :style="`--color: ${colorSet1.getColor(text)}`"
13
+ >
14
+ {{ text }}
15
+ </div>
16
+ </div>
17
+
18
+ <!-- 使用自定义配置的颜色集 -->
19
+ <div class="color-set">
20
+ <h2>自定义配置颜色集</h2>
21
+ <div
22
+ v-for="text in texts"
23
+ :key="text"
24
+ class="color-item"
25
+ :style="`--color: ${colorSet2.getColor(text)}`"
26
+ >
27
+ {{ text }}
28
+ </div>
29
+ </div>
30
+ </div>
31
+ </template>
32
+
33
+ <script setup lang="ts">
34
+ import { useAutoColor } from 'v-auto-color';
35
+
36
+ // 默认配置的颜色集
37
+ const colorSet1 = useAutoColor('set1');
38
+
39
+ // 自定义配置的颜色集
40
+ const colorSet2 = useAutoColor({
41
+ category: 'set2',
42
+ hue: [180, 360], // 蓝色调范围
43
+ saturation: [60, 90],
44
+ lightness: [40, 70]
45
+ });
46
+
47
+ // 测试文本
48
+ const texts = [
49
+ 'Hello World',
50
+ 'Test Text',
51
+ 'Another Example',
52
+ 'Similar Text',
53
+ 'Different Content'
54
+ ];
55
+ </script>
56
+
57
+ <style scoped>
58
+ .example-container {
59
+ max-width: 800px;
60
+ margin: 0 auto;
61
+ padding: 20px;
62
+ }
63
+
64
+ .color-set {
65
+ margin-bottom: 30px;
66
+ }
67
+
68
+ .color-item {
69
+ display: inline-block;
70
+ padding: 10px 20px;
71
+ margin: 5px;
72
+ background-color: var(--color);
73
+ color: white;
74
+ border-radius: 4px;
75
+ font-weight: bold;
76
+ }
77
+ </style>
@@ -0,0 +1,11 @@
1
+ import { defineConfig } from 'vite';
2
+ import vue from '@vitejs/plugin-vue';
3
+ import { viteAutoColorPlugin } from 'v-auto-color';
4
+
5
+ // https://vitejs.dev/config/
6
+ export default defineConfig({
7
+ plugins: [
8
+ vue(),
9
+ viteAutoColorPlugin() // 启用v-auto-color插件
10
+ ],
11
+ });
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "v-auto-color",
3
+ "version": "1.0.0",
4
+ "description": "Vite plugin for automatic color generation based on text similarity",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.mjs",
11
+ "require": "./dist/index.js",
12
+ "types": "./dist/index.d.ts"
13
+ }
14
+ },
15
+ "scripts": {
16
+ "build": "tsup src/index.ts src/vite-plugin.ts --format cjs,esm --dts",
17
+ "dev": "tsup src/index.ts src/vite-plugin.ts --format cjs,esm --dts --watch",
18
+ "typecheck": "tsc --noEmit"
19
+ },
20
+ "keywords": [
21
+ "vite",
22
+ "plugin",
23
+ "color",
24
+ "auto-color",
25
+ "text-similarity",
26
+ "vue",
27
+ "typescript"
28
+ ],
29
+ "author": "",
30
+ "license": "MIT",
31
+ "peerDependencies": {
32
+ "vite": "^4.0.0 || ^5.0.0"
33
+ },
34
+ "dependencies": {
35
+ "@rollup/pluginutils": "^5.0.2"
36
+ },
37
+ "devDependencies": {
38
+ "@types/node": "^18.19.3",
39
+ "tsup": "^8.0.1",
40
+ "typescript": "^5.3.3",
41
+ "vite": "^5.0.10"
42
+ }
43
+ }
@@ -0,0 +1,46 @@
1
+ // Color generation based on hash values
2
+ export interface ColorConfig {
3
+ category?: string;
4
+ hue?: [number, number];
5
+ saturation?: [number, number];
6
+ lightness?: [number, number];
7
+ }
8
+
9
+ export class ColorGenerator {
10
+ private config: Required<ColorConfig>;
11
+
12
+ constructor(config: ColorConfig = {}) {
13
+ this.config = {
14
+ category: config.category || 'default',
15
+ hue: config.hue || [0, 360],
16
+ saturation: config.saturation || [70, 100],
17
+ lightness: config.lightness || [40, 60]
18
+ };
19
+ }
20
+
21
+ // Generate color from hash value
22
+ generateColor(hash: number): string {
23
+ const { hue, saturation, lightness } = this.config;
24
+
25
+ // Calculate hue based on hash
26
+ const hueRange = hue[1] - hue[0];
27
+ const calculatedHue = hue[0] + (hash % hueRange);
28
+
29
+ // Calculate saturation based on hash
30
+ const satRange = saturation[1] - saturation[0];
31
+ const calculatedSat = saturation[0] + ((hash >> 8) % satRange);
32
+
33
+ // Calculate lightness based on hash
34
+ const lightRange = lightness[1] - lightness[0];
35
+ const calculatedLight = lightness[0] + ((hash >> 16) % lightRange);
36
+
37
+ // Return HSL color string
38
+ return `hsl(${calculatedHue}, ${calculatedSat}%, ${calculatedLight}%)`;
39
+ }
40
+
41
+ // Get color for text (wrapper method)
42
+ getColor(text: string, hashFn: (text: string) => number): string {
43
+ const hash = hashFn(text);
44
+ return this.generateColor(hash);
45
+ }
46
+ }
@@ -0,0 +1,44 @@
1
+ // MurmurHash3 implementation for text hashing
2
+ // Based on https://github.com/garycourt/murmurhash-js
3
+
4
+ export function murmurHash3(text: string): number {
5
+ let h1 = 0xdeadbeef; // Seed value
6
+ const c1 = 0xcc9e2d51;
7
+ const c2 = 0x1b873593;
8
+ const r1 = 15;
9
+ const r2 = 13;
10
+ const m = 5;
11
+ const n = 0xe6546b64;
12
+
13
+ let i = 0;
14
+ const length = text.length;
15
+ let k1 = 0;
16
+
17
+ while (i < length) {
18
+ const char = text.charCodeAt(i++);
19
+ k1 = (k1 << 8) | char;
20
+ }
21
+
22
+ k1 = (k1 * c1) >>> 0;
23
+ k1 = ((k1 << r1) | (k1 >>> (32 - r1))) >>> 0;
24
+ k1 = (k1 * c2) >>> 0;
25
+
26
+ h1 ^= k1;
27
+ h1 = ((h1 << r2) | (h1 >>> (32 - r2))) >>> 0;
28
+ h1 = (h1 * m + n) >>> 0;
29
+
30
+ // Finalization
31
+ h1 ^= length;
32
+ h1 ^= h1 >>> 16;
33
+ h1 = (h1 * 0x85ebca6b) >>> 0;
34
+ h1 ^= h1 >>> 13;
35
+ h1 = (h1 * 0xc2b2ae35) >>> 0;
36
+ h1 ^= h1 >>> 16;
37
+
38
+ return h1;
39
+ }
40
+
41
+ // Generate a hash from text
42
+ export function getTextHash(text: string): number {
43
+ return murmurHash3(text);
44
+ }
package/src/index.ts ADDED
@@ -0,0 +1,55 @@
1
+ import { getTextHash } from './core/hash';
2
+ import { ColorConfig, ColorGenerator } from './core/color';
3
+
4
+ // Precomputed colors cache (filled by Vite plugin at build time)
5
+ const precomputedColors: Record<string, Record<string, string>> = {};
6
+
7
+ // ColorSet class for managing color generation
8
+ export class ColorSet {
9
+ private config: ColorConfig;
10
+ private generator: ColorGenerator;
11
+ private category: string;
12
+
13
+ constructor(config: ColorConfig | string = 'default') {
14
+ if (typeof config === 'string') {
15
+ this.config = { category: config };
16
+ } else {
17
+ this.config = config;
18
+ }
19
+
20
+ this.category = this.config.category || 'default';
21
+ this.generator = new ColorGenerator(this.config);
22
+ }
23
+
24
+ // Get color for text
25
+ getColor(text: string): string {
26
+ // Check if color is precomputed
27
+ if (precomputedColors[this.category] && precomputedColors[this.category][text]) {
28
+ return precomputedColors[this.category][text];
29
+ }
30
+
31
+ // Generate color at runtime if not precomputed
32
+ const color = this.generator.getColor(text, getTextHash);
33
+
34
+ // Cache the generated color for future use
35
+ if (!precomputedColors[this.category]) {
36
+ precomputedColors[this.category] = {};
37
+ }
38
+ precomputedColors[this.category][text] = color;
39
+
40
+ return color;
41
+ }
42
+ }
43
+
44
+ // Main function to create ColorSet instances
45
+ export function useAutoColor(config: ColorConfig | string = 'default'): ColorSet {
46
+ return new ColorSet(config);
47
+ }
48
+
49
+ // Expose precomputed colors for Vite plugin to fill
50
+ export function __internal__setPrecomputedColors(colors: Record<string, Record<string, string>>): void {
51
+ Object.assign(precomputedColors, colors);
52
+ }
53
+
54
+ // Export types
55
+ export type { ColorConfig };
@@ -0,0 +1,91 @@
1
+ import { Plugin } from 'vite';
2
+ import { createFilter } from '@rollup/pluginutils';
3
+ import { getTextHash } from './core/hash';
4
+ import { ColorGenerator } from './core/color';
5
+
6
+ // Vite plugin for precomputing colors at build time
7
+ export function viteAutoColorPlugin(): Plugin {
8
+ const filter = createFilter(['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx', '**/*.vue']);
9
+
10
+ // Collected color usage data
11
+ const colorUsage: Record<string, Record<string, string>> = {};
12
+
13
+ return {
14
+ name: 'v-auto-color',
15
+
16
+ // Analyze code during build
17
+ transform(code, id) {
18
+ if (!filter(id)) return null;
19
+
20
+ // Extract useAutoColor calls and getColor calls
21
+ const useAutoColorRegex = /useAutoColor\s*\(\s*(?:(['"])([^'"]+)\1|\{[^}]*\})\s*\)/g;
22
+ const getColorRegex = /\.getColor\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
23
+
24
+ let match;
25
+ const colorSets = new Set<string>();
26
+
27
+ // Extract color set configurations
28
+ while ((match = useAutoColorRegex.exec(code)) !== null) {
29
+ let category = 'default';
30
+ if (match[2]) {
31
+ // String configuration
32
+ category = match[2];
33
+ } else {
34
+ // Object configuration - extract category
35
+ const configMatch = match[0].match(/category\s*:\s*['"]([^'"]+)['"]/);
36
+ if (configMatch) {
37
+ category = configMatch[1];
38
+ }
39
+ }
40
+ colorSets.add(category);
41
+ }
42
+
43
+ // Extract text parameters from getColor calls
44
+ const texts = new Set<string>();
45
+ while ((match = getColorRegex.exec(code)) !== null) {
46
+ texts.add(match[1]);
47
+ }
48
+
49
+ // Precompute colors for extracted texts
50
+ colorSets.forEach(category => {
51
+ if (!colorUsage[category]) {
52
+ colorUsage[category] = {};
53
+ }
54
+
55
+ texts.forEach(text => {
56
+ const generator = new ColorGenerator({ category });
57
+ const color = generator.getColor(text, getTextHash);
58
+ colorUsage[category][text] = color;
59
+ });
60
+ });
61
+
62
+ return null;
63
+ },
64
+
65
+ // Generate precomputed colors module
66
+ generateBundle() {
67
+ // Create precomputed colors code
68
+ const precomputedCode = `
69
+ import { __internal__setPrecomputedColors } from 'v-auto-color';
70
+ __internal__setPrecomputedColors(${JSON.stringify(colorUsage, null, 2)});
71
+ `;
72
+
73
+ // Add precomputed colors module to bundle
74
+ this.emitFile({
75
+ type: 'asset',
76
+ fileName: 'v-auto-color-precomputed.js',
77
+ source: precomputedCode
78
+ });
79
+
80
+ // Ensure the precomputed module is loaded before application code
81
+ this.emitFile({
82
+ type: 'asset',
83
+ fileName: 'v-auto-color-initializer.js',
84
+ source: `import "/v-auto-color-precomputed.js";`
85
+ });
86
+ }
87
+ };
88
+ }
89
+
90
+ // Export plugin
91
+ export default viteAutoColorPlugin;
package/tsconfig.json ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "useDefineForClassFields": true,
5
+ "module": "ESNext",
6
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
7
+ "skipLibCheck": true,
8
+
9
+ /* Bundler mode */
10
+ "moduleResolution": "bundler",
11
+ "allowImportingTsExtensions": true,
12
+ "resolveJsonModule": true,
13
+ "isolatedModules": true,
14
+ "noEmit": true,
15
+
16
+ /* Linting */
17
+ "strict": true,
18
+ "noUnusedLocals": true,
19
+ "noUnusedParameters": true,
20
+ "noFallthroughCasesInSwitch": true
21
+ },
22
+ "include": ["src"],
23
+ "references": [{ "path": "./tsconfig.node.json" }]
24
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "compilerOptions": {
3
+ "composite": true,
4
+ "skipLibCheck": true,
5
+ "module": "ESNext",
6
+ "moduleResolution": "bundler",
7
+ "allowSyntheticDefaultImports": true
8
+ },
9
+ "include": ["vite.config.ts"]
10
+ }