xiangjsoncraft 1.0.5 → 1.1.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 +274 -125
- package/config.json +205 -10
- package/dist/xiangjsoncraft.cjs.js +97 -0
- package/dist/xiangjsoncraft.esm.js +94 -0
- package/dist/xiangjsoncraft.umd.js +92 -0
- package/package.json +29 -12
- package/renderJson.js +77 -23
- package/index.html +0 -19
package/README.md
CHANGED
|
@@ -1,148 +1,291 @@
|
|
|
1
|
-
|
|
1
|
+
# XiangJsonCraft
|
|
2
2
|

|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
4
|
+
XiangJsonCraft 是一个简单而强大的 JSON 配置与 HTML 页面渲染工具,由大学生董翔开发,专为前端开发者设计。通过简洁的 API,它允许你使用 JSON 配置文件来定义样式和内容,并将其应用到 HTML 页面中,实现动态页面的快速构建,做到样式、内容与代码的解耦管理。
|
|
5
|
+
|
|
6
|
+
## 🚀 最新更新 (v1.1.1)
|
|
7
|
+
基于 v1.1.0 核心功能完成**环境适配升级**,新增 CDN/本地双环境兼容能力,发布后可零成本实现本地开发、CDN 在线使用,同时优化渲染容错性,避免空配置、无效选择器导致的渲染异常。
|
|
8
|
+
|
|
9
|
+
### 核心更新
|
|
10
|
+
- **CDN/本地双环境适配**:自动识别运行环境,无需修改代码即可实现本地开发、CDN 在线调用
|
|
11
|
+
- **渲染容错优化**:过滤空样式、无效选择器,新增样式块创建判空,控制台错误提示更友好
|
|
12
|
+
- **打包格式完善**:提供 UMD/ES/CJS 三种打包格式,适配浏览器、前端框架、Node.js 全环境
|
|
13
|
+
- **使用体验升级**:新增 npm dev 脚本,一键启动开发服务器,快速验证开发效果
|
|
14
|
+
|
|
15
|
+
## ✨ 核心特性
|
|
16
|
+
- **简单易用**:仅需一行 API 调用,即可完成整个页面的样式和内容渲染
|
|
17
|
+
- **灵活配置**:通过单一 JSON 文件定义所有样式、文本、HTML 内容,支持按需修改
|
|
18
|
+
- **轻量级无依赖**:原生 JavaScript 开发,无任何第三方依赖,体积小巧,加载速度快
|
|
19
|
+
- **全面的 CSS 支持**:兼容所有 CSS 选择器(类、ID、伪类、伪元素、媒体查询等)
|
|
20
|
+
- **响应式设计友好**:直接通过 JSON 配置媒体查询,轻松实现多屏幕尺寸适配
|
|
21
|
+
- **双内容类型支持**:同时支持纯文本、HTML 片段动态注入,满足不同内容渲染需求
|
|
22
|
+
- **多环境适配**:支持本地模块化引入、CDN 全局调用,适配所有现代浏览器
|
|
23
|
+
- **高容错性**:自动过滤无效配置、空样式,避免单一配置错误导致整体渲染失败
|
|
24
|
+
|
|
25
|
+
## 📦 安装使用
|
|
26
|
+
### 1. npm 安装
|
|
18
27
|
```bash
|
|
19
|
-
npm
|
|
20
|
-
|
|
28
|
+
# npm
|
|
29
|
+
npm install xiangjsoncraft --save
|
|
21
30
|
|
|
22
|
-
|
|
31
|
+
# yarn
|
|
32
|
+
yarn add xiangjsoncraft
|
|
23
33
|
|
|
24
|
-
|
|
34
|
+
# pnpm
|
|
35
|
+
pnpm add xiangjsoncraft
|
|
36
|
+
```
|
|
25
37
|
|
|
26
|
-
|
|
38
|
+
### 2. CDN 在线使用(零安装)
|
|
39
|
+
无需本地安装,一行脚本引入即可全局调用,适合快速原型开发、静态页面使用:
|
|
40
|
+
```html
|
|
41
|
+
<!-- 引入UMD包,自动挂载全局变量 XiangJsonCraft -->
|
|
42
|
+
<script src="https://cdn.jsdelivr.net/npm/xiangjsoncraft@1.1.1/dist/xiangjsoncraft.umd.js"></script>
|
|
43
|
+
<!-- 直接调用核心方法,零配置渲染 -->
|
|
44
|
+
<script>
|
|
45
|
+
XiangJsonCraft.renderJsonStyles();
|
|
46
|
+
</script>
|
|
47
|
+
```
|
|
27
48
|
|
|
49
|
+
## ⚡ 快速开始
|
|
50
|
+
### 步骤1:创建 JSON 配置文件
|
|
51
|
+
在项目根目录/HTML 同级目录创建 `config.json`,定义页面的样式、文本及 HTML 内容,支持所有 CSS 选择器和媒体查询:
|
|
28
52
|
```json
|
|
29
53
|
{
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
54
|
+
"styles": {
|
|
55
|
+
"*": {
|
|
56
|
+
"margin": "0",
|
|
57
|
+
"padding": "0",
|
|
58
|
+
"boxSizing": "border-box"
|
|
59
|
+
},
|
|
60
|
+
"body": {
|
|
61
|
+
"fontFamily": "Arial, sans-serif",
|
|
62
|
+
"lineHeight": "1.6",
|
|
63
|
+
"color": "#333",
|
|
64
|
+
"backgroundColor": "#f9f9f9",
|
|
65
|
+
"padding": "2rem"
|
|
66
|
+
},
|
|
67
|
+
".header": {
|
|
68
|
+
"backgroundColor": "#2c3e50",
|
|
69
|
+
"color": "white",
|
|
70
|
+
"padding": "1.5rem",
|
|
71
|
+
"textAlign": "center",
|
|
72
|
+
"borderRadius": "8px",
|
|
73
|
+
"marginBottom": "2rem"
|
|
74
|
+
},
|
|
75
|
+
"nav ul": {
|
|
76
|
+
"display": "flex",
|
|
77
|
+
"listStyle": "none",
|
|
78
|
+
"justifyContent": "center",
|
|
79
|
+
"gap": "1.5rem",
|
|
80
|
+
"marginBottom": "2rem"
|
|
81
|
+
},
|
|
82
|
+
"nav a": {
|
|
83
|
+
"color": "#2c3e50",
|
|
84
|
+
"textDecoration": "none",
|
|
85
|
+
"fontSize": "1.1rem"
|
|
86
|
+
},
|
|
87
|
+
"nav a:hover": {
|
|
88
|
+
"color": "#f39c12",
|
|
89
|
+
"textDecoration": "underline"
|
|
90
|
+
},
|
|
91
|
+
".card": {
|
|
92
|
+
"background": "white",
|
|
93
|
+
"padding": "2rem",
|
|
94
|
+
"borderRadius": "8px",
|
|
95
|
+
"boxShadow": "0 2px 8px rgba(0,0,0,0.1)"
|
|
96
|
+
},
|
|
97
|
+
"@media (max-width: 768px)": {
|
|
98
|
+
"body": {
|
|
99
|
+
"padding": "1rem"
|
|
100
|
+
},
|
|
101
|
+
"nav ul": {
|
|
102
|
+
"flexDirection": "column",
|
|
103
|
+
"alignItems": "center",
|
|
104
|
+
"gap": "1rem"
|
|
105
|
+
}
|
|
50
106
|
}
|
|
107
|
+
},
|
|
108
|
+
"content": {
|
|
109
|
+
".header h1": {
|
|
110
|
+
"value": "XiangJsonCraft 演示页面",
|
|
111
|
+
"isHtml": false
|
|
112
|
+
},
|
|
113
|
+
".card h2": {
|
|
114
|
+
"value": "<span style='color:#2c3e50;'>JSON 配置渲染</span> 就是这么简单",
|
|
115
|
+
"isHtml": true
|
|
116
|
+
},
|
|
117
|
+
".card p": {
|
|
118
|
+
"value": "通过单个 JSON 文件定义所有样式和内容,一行代码完成页面渲染,实现代码与配置的解耦管理。",
|
|
119
|
+
"isHtml": false
|
|
120
|
+
}
|
|
121
|
+
}
|
|
51
122
|
}
|
|
52
123
|
```
|
|
53
124
|
|
|
54
|
-
### 2
|
|
55
|
-
|
|
56
|
-
然后,创建一个 HTML 页面 `index.html`,引入 JavaScript 文件:
|
|
57
|
-
|
|
125
|
+
### 步骤2:创建 HTML 页面
|
|
126
|
+
创建 `index.html`,引入渲染容器并调用核心 API,无需手写任何 CSS 样式:
|
|
58
127
|
```html
|
|
59
128
|
<!DOCTYPE html>
|
|
60
129
|
<html lang="en">
|
|
61
130
|
<head>
|
|
62
131
|
<meta charset="UTF-8">
|
|
63
132
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
64
|
-
<title>
|
|
65
|
-
|
|
133
|
+
<title>XiangJsonCraft 快速开始</title>
|
|
134
|
+
<!-- 动态样式块,渲染后的CSS会注入到这里 -->
|
|
135
|
+
<style id="dynamic-styles"></style>
|
|
66
136
|
</head>
|
|
67
137
|
<body>
|
|
68
|
-
|
|
69
|
-
|
|
138
|
+
<!-- 页面渲染容器,与config.json中的选择器匹配 -->
|
|
139
|
+
<header class="header">
|
|
140
|
+
<h1></h1>
|
|
70
141
|
</header>
|
|
71
|
-
|
|
142
|
+
<nav>
|
|
143
|
+
<ul>
|
|
144
|
+
<li><a href="#">首页</a></li>
|
|
145
|
+
<li><a href="#">文档</a></li>
|
|
146
|
+
<li><a href="#">示例</a></li>
|
|
147
|
+
</ul>
|
|
148
|
+
</nav>
|
|
149
|
+
<div class="card">
|
|
150
|
+
<h2></h2>
|
|
151
|
+
<p></p>
|
|
152
|
+
</div>
|
|
153
|
+
|
|
154
|
+
<!-- 方式1:本地模块化引入(推荐,适合项目开发) -->
|
|
72
155
|
<script type="module">
|
|
73
|
-
import {
|
|
74
|
-
|
|
156
|
+
import { renderJsonStyles } from './renderJson.js';
|
|
157
|
+
// 一行调用,完成所有样式和内容渲染
|
|
158
|
+
renderJsonStyles();
|
|
75
159
|
</script>
|
|
160
|
+
|
|
161
|
+
<!-- 方式2:CDN全局调用(注释方式1,打开此注释即可) -->
|
|
162
|
+
<!-- <script src="https://cdn.jsdelivr.net/npm/xiangjsoncraft@1.1.1/dist/xiangjsoncraft.umd.js"></script>
|
|
163
|
+
<script>
|
|
164
|
+
XiangJsonCraft.renderJsonStyles();
|
|
165
|
+
</script> -->
|
|
76
166
|
</body>
|
|
77
167
|
</html>
|
|
78
168
|
```
|
|
79
169
|
|
|
80
|
-
### 3
|
|
170
|
+
### 步骤3:开发运行
|
|
171
|
+
```bash
|
|
172
|
+
# 安装开发依赖(首次使用)
|
|
173
|
+
npm install
|
|
81
174
|
|
|
82
|
-
|
|
175
|
+
# 打包生成多格式文件(UMD/ES/CJS)
|
|
176
|
+
npm run build
|
|
83
177
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
String.prototype.replaceCamelCase = function (separator = '-') {
|
|
87
|
-
return this.replace(/[A-Z]/g, function (match) {
|
|
88
|
-
return separator + match.toLowerCase();
|
|
89
|
-
});
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
// 封装 JSON 渲染函数
|
|
93
|
-
function renderJson() {
|
|
94
|
-
// 使用 fetch API 获取 JSON 文件
|
|
95
|
-
fetch('./config.json')
|
|
96
|
-
.then(response => {
|
|
97
|
-
// 检查响应是否成功
|
|
98
|
-
if (!response.ok) {
|
|
99
|
-
throw new Error('网络响应失败');
|
|
100
|
-
}
|
|
101
|
-
// 将响应转换为 JSON 格式
|
|
102
|
-
return response.json();
|
|
103
|
-
})
|
|
104
|
-
.then(config => {
|
|
105
|
-
// 动态创建样式表
|
|
106
|
-
const styleBlock = document.getElementById('style-block');
|
|
107
|
-
styleBlock.innerHTML = `
|
|
108
|
-
* { ${Object.entries(config.styles.body).map(([key, value]) => `${key}: ${value};`).join(' ')} }
|
|
109
|
-
header { ${Object.entries(config.styles.header).map(([key, value]) => `${key.replaceCamelCase()}: ${value};`).join(' ')} }
|
|
110
|
-
header p { ${Object.entries(config.styles.headerP).map(([key, value]) => `${key}: ${value};`).join(' ')} }
|
|
111
|
-
`;
|
|
112
|
-
|
|
113
|
-
// 动态设置内容
|
|
114
|
-
document.getElementById('header-text').innerText = config.content.headerText;
|
|
115
|
-
})
|
|
116
|
-
.catch(error => {
|
|
117
|
-
console.error('获取 JSON 文件时出错:', error);
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// 导出渲染函数
|
|
122
|
-
export { renderJson };
|
|
178
|
+
# 启动开发服务器,一键预览效果
|
|
179
|
+
npm run dev
|
|
123
180
|
```
|
|
181
|
+
在浏览器中访问 `http://localhost:3000`,即可看到由 JSON 配置渲染的完整页面。
|
|
124
182
|
|
|
125
|
-
|
|
183
|
+
## 📚 API 文档
|
|
184
|
+
### `renderJsonStyles()`
|
|
185
|
+
**核心渲染方法**,无入参,执行后自动完成以下操作:
|
|
186
|
+
1. 自动识别运行环境(本地/CDN),加载对应路径的 `config.json` 配置文件
|
|
187
|
+
2. 解析配置中的 `styles` 节点,生成标准 CSS 样式并注入到页面头部的 `#dynamic-styles` 样式块
|
|
188
|
+
3. 解析配置中的 `content` 节点,根据 `isHtml` 标识,向匹配的 DOM 节点注入纯文本/HTML 内容
|
|
189
|
+
4. 控制台输出渲染成功提示,若配置异常则输出友好的错误信息
|
|
126
190
|
|
|
127
|
-
|
|
191
|
+
#### 调用方式
|
|
192
|
+
```javascript
|
|
193
|
+
// 方式1:ES6模块化引入(本地开发/前端框架)
|
|
194
|
+
import { renderJsonStyles } from 'xiangjsoncraft';
|
|
195
|
+
renderJsonStyles();
|
|
128
196
|
|
|
129
|
-
|
|
197
|
+
// 方式2:CDN全局调用(静态页面/快速开发)
|
|
198
|
+
XiangJsonCraft.renderJsonStyles();
|
|
199
|
+
```
|
|
130
200
|
|
|
131
|
-
|
|
201
|
+
## ⚙️ 配置文件说明
|
|
202
|
+
配置文件为标准 JSON 格式,核心包含 `styles` 和 `content` 两个一级节点,所有配置均支持按需扩展、修改。
|
|
132
203
|
|
|
133
|
-
|
|
204
|
+
### 1. `styles` 节点
|
|
205
|
+
用于定义页面所有 CSS 样式,**键为任意合法 CSS 选择器**,值为样式属性对象,样式属性支持**驼峰式命名**(会自动转换为 CSS 标准短横线命名)。
|
|
206
|
+
- 支持选择器:类、ID、标签、伪类、伪元素、后代选择器、媒体查询等所有 CSS 合法选择器
|
|
207
|
+
- 样式属性:所有 CSS 原生属性,驼峰式(`fontSize`)会自动转为短横线式(`font-size`)
|
|
134
208
|
|
|
135
|
-
|
|
209
|
+
### 2. `content` 节点
|
|
210
|
+
用于定义页面文本/HTML 内容,**键为 CSS 选择器**,值为内容配置对象,包含两个必选属性:
|
|
211
|
+
- `value`:字符串类型,要渲染的内容(纯文本/HTML 片段)
|
|
212
|
+
- `isHtml`:布尔类型,`true` 表示内容为 HTML 片段,`false` 表示内容为纯文本(默认)
|
|
136
213
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
214
|
+
### 配置文件规范
|
|
215
|
+
1. 配置文件必须命名为 `config.json`,与 HTML 页面同级目录(CDN 方式无需手动创建,自动加载官方配置)
|
|
216
|
+
2. 选择器必须匹配 HTML 中的实际 DOM 节点,否则会被自动过滤
|
|
217
|
+
3. 样式属性值需符合 CSS 规范(如单位、颜色值、尺寸值)
|
|
218
|
+
4. HTML 片段需保证语法合法,避免 XSS 风险(建议仅在可信环境下使用 HTML 内容)
|
|
219
|
+
|
|
220
|
+
## 🎨 配置示例
|
|
221
|
+
### 完整配置示例
|
|
222
|
+
```json
|
|
223
|
+
{
|
|
224
|
+
"styles": {
|
|
225
|
+
// 通配符选择器
|
|
226
|
+
"*": {
|
|
227
|
+
"margin": "0",
|
|
228
|
+
"padding": "0",
|
|
229
|
+
"boxSizing": "border-box"
|
|
230
|
+
},
|
|
231
|
+
// 标签选择器
|
|
232
|
+
"body": {
|
|
233
|
+
"fontFamily": "Microsoft YaHei, sans-serif",
|
|
234
|
+
"lineHeight": "1.8",
|
|
235
|
+
"color": "#333",
|
|
236
|
+
"backgroundColor": "#f5f5f5"
|
|
237
|
+
},
|
|
238
|
+
// ID选择器
|
|
239
|
+
"#app": {
|
|
240
|
+
"maxWidth": "1200px",
|
|
241
|
+
"margin": "0 auto",
|
|
242
|
+
"padding": "2rem"
|
|
243
|
+
},
|
|
244
|
+
// 类选择器
|
|
245
|
+
".btn": {
|
|
246
|
+
"padding": "0.8rem 1.5rem",
|
|
247
|
+
"border": "none",
|
|
248
|
+
"borderRadius": "4px",
|
|
249
|
+
"cursor": "pointer",
|
|
250
|
+
"fontSize": "1rem"
|
|
251
|
+
},
|
|
252
|
+
// 伪类选择器
|
|
253
|
+
".btn-primary": {
|
|
254
|
+
"backgroundColor": "#3498db",
|
|
255
|
+
"color": "white"
|
|
256
|
+
},
|
|
257
|
+
".btn-primary:hover": {
|
|
258
|
+
"backgroundColor": "#2980b9"
|
|
259
|
+
},
|
|
260
|
+
// 媒体查询
|
|
261
|
+
"@media (max-width: 768px)": {
|
|
262
|
+
"#app": {
|
|
263
|
+
"padding": "1rem"
|
|
264
|
+
},
|
|
265
|
+
".btn": {
|
|
266
|
+
"width": "100%",
|
|
267
|
+
"marginBottom": "1rem"
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
},
|
|
271
|
+
"content": {
|
|
272
|
+
// 纯文本内容
|
|
273
|
+
"#app h1": {
|
|
274
|
+
"value": "XiangJsonCraft 配置示例",
|
|
275
|
+
"isHtml": false
|
|
276
|
+
},
|
|
277
|
+
// HTML 片段内容
|
|
278
|
+
".desc": {
|
|
279
|
+
"value": "支持 <strong>HTML 片段</strong> 和 <em>纯文本</em> 两种渲染方式",
|
|
280
|
+
"isHtml": true
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
140
284
|
```
|
|
141
285
|
|
|
142
|
-
##
|
|
286
|
+
## 🥚 彩蛋:工具背后的小插曲
|
|
287
|
+
### “敢改包”的底气来源
|
|
143
288
|
|
|
144
|
-
```markdown
|
|
145
|
-
# 工具背后的小插曲:“敢改包”的底气来源
|
|
146
289
|
其实XiangJsonCraft的诞生,还藏着一段有趣的小场景——
|
|
147
290
|
|
|
148
291
|
某天,朋友在Vue项目里用这个包时,遇到了个不符合自己编程习惯的小细节,对着node_modules里的代码犯愁:“老师说这地方不能随便改,容易牵一发而动全身。”
|
|
@@ -157,26 +300,30 @@ renderJson();
|
|
|
157
300
|
|
|
158
301
|
所以如果你用的时候也有小想法,不用怕“改坏”——工具本身就为“灵活适配”留足了空间,而作为作者,我也始终在背后,为它的稳定和好用托底。
|
|
159
302
|
|
|
303
|
+
## 🌐 浏览器兼容性
|
|
304
|
+
支持所有现代浏览器,无需额外引入 polyfill:
|
|
305
|
+
- Chrome ≥ 61
|
|
306
|
+
- Firefox ≥ 60
|
|
307
|
+
- Edge ≥ 79
|
|
308
|
+
- Safari ≥ 12.1
|
|
309
|
+
- Opera ≥ 48
|
|
310
|
+
- 移动端所有现代浏览器(微信浏览器、QQ浏览器、Safari 移动端等)
|
|
160
311
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
312
|
+
## 🤝 贡献指南
|
|
313
|
+
XiangJsonCraft 欢迎所有开发者的贡献和建议,如果你有以下想法,欢迎随时交流:
|
|
314
|
+
- 新增功能需求
|
|
315
|
+
- 性能优化建议
|
|
316
|
+
- Bug 修复
|
|
317
|
+
- 文档完善
|
|
164
318
|
|
|
165
|
-
|
|
319
|
+
**贡献方式**:通过邮箱联系作者,提供你的想法、代码或问题描述,作者会第一时间回复。
|
|
166
320
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
1. 克隆仓库:`git clone https://github.com/dxiang-wiki/xiangjsoncraft.git`
|
|
170
|
-
2. 创建新分支:`git checkout -b feature/your-feature`
|
|
171
|
-
3. 提交代码:`git commit -m "Add your feature"`
|
|
172
|
-
4. 推送分支:`git push origin feature/your-feature`
|
|
173
|
-
5. 创建 Pull Request
|
|
174
|
-
|
|
175
|
-
## 许可证
|
|
321
|
+
## 📄 许可证
|
|
322
|
+
本项目基于 **MIT 开源许可证** 发布,你可以自由使用、修改、分发本项目,无需支付任何费用,只需保留版权声明。
|
|
176
323
|
|
|
324
|
+
```
|
|
177
325
|
MIT License
|
|
178
|
-
|
|
179
|
-
Copyright (c) 2025 xiang
|
|
326
|
+
Copyright (c) 2025 董翔
|
|
180
327
|
|
|
181
328
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
182
329
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -195,12 +342,14 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
195
342
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
196
343
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
197
344
|
SOFTWARE.
|
|
345
|
+
```
|
|
198
346
|
|
|
199
|
-
## 联系我们
|
|
200
|
-
|
|
201
|
-
|
|
347
|
+
## 📞 联系我们
|
|
348
|
+
如果你有任何问题、建议或合作想法,欢迎通过以下方式联系作者:
|
|
349
|
+
- **Email**:3631247406@qq.com
|
|
350
|
+
- **作者**:董翔
|
|
202
351
|
|
|
203
|
-
|
|
204
|
-
- Email: 3631247406@qq.com
|
|
352
|
+
---
|
|
205
353
|
|
|
206
|
-
|
|
354
|
+
**感谢使用 XiangJsonCraft!**
|
|
355
|
+
愿这个小工具能让你的前端开发更高效、更轻松 🚀
|
package/config.json
CHANGED
|
@@ -1,23 +1,218 @@
|
|
|
1
1
|
{
|
|
2
2
|
"styles": {
|
|
3
|
-
"
|
|
3
|
+
"*": {
|
|
4
4
|
"margin": "0",
|
|
5
5
|
"padding": "0",
|
|
6
|
-
"boxSizing": "border-box"
|
|
6
|
+
"boxSizing": "border-box",
|
|
7
|
+
"fontFamily": "'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif"
|
|
8
|
+
},
|
|
9
|
+
"body": {
|
|
10
|
+
"backgroundColor": "#f0f4f8",
|
|
11
|
+
"color": "#334e68",
|
|
12
|
+
"lineHeight": "1.6",
|
|
13
|
+
"transition": "backgroundColor 0.5s ease",
|
|
14
|
+
"minHeight": "100vh"
|
|
15
|
+
},
|
|
16
|
+
".welcome-container": {
|
|
17
|
+
"maxWidth": "1200px",
|
|
18
|
+
"margin": "0 auto",
|
|
19
|
+
"padding": "20px"
|
|
20
|
+
},
|
|
21
|
+
".welcome-header": {
|
|
22
|
+
"textAlign": "center",
|
|
23
|
+
"padding": "60px 20px",
|
|
24
|
+
"marginBottom": "40px",
|
|
25
|
+
"borderRadius": "12px",
|
|
26
|
+
"background": "linear-gradient(135deg, #4299e1, #63b3ed)",
|
|
27
|
+
"color": "white",
|
|
28
|
+
"boxShadow": "0 10px 25px -5px rgba(66, 153, 225, 0.3)",
|
|
29
|
+
"transition": "transform 0.5s ease, boxShadow 0.5s ease"
|
|
7
30
|
},
|
|
8
|
-
"header": {
|
|
31
|
+
".welcome-header:hover": {
|
|
32
|
+
"transform": "translateY(-5px)",
|
|
33
|
+
"boxShadow": "0 15px 30px -8px rgba(66, 153, 225, 0.4)"
|
|
34
|
+
},
|
|
35
|
+
".logo-container": {
|
|
36
|
+
"marginBottom": "30px"
|
|
37
|
+
},
|
|
38
|
+
".logo": {
|
|
39
|
+
"width": "120px",
|
|
40
|
+
"height": "120px",
|
|
41
|
+
"margin": "0 auto",
|
|
42
|
+
"backgroundColor": "white",
|
|
43
|
+
"borderRadius": "50%",
|
|
9
44
|
"display": "flex",
|
|
45
|
+
"alignItems": "center",
|
|
10
46
|
"justifyContent": "center",
|
|
47
|
+
"fontSize": "48px",
|
|
48
|
+
"color": "#4299e1",
|
|
49
|
+
"boxShadow": "0 4px 12px rgba(0, 0, 0, 0.1)"
|
|
50
|
+
},
|
|
51
|
+
".logo::after": {
|
|
52
|
+
"content": "'J'",
|
|
53
|
+
"fontWeight": "bold"
|
|
54
|
+
},
|
|
55
|
+
".main-title": {
|
|
56
|
+
"fontSize": "2.5rem",
|
|
57
|
+
"marginBottom": "15px",
|
|
58
|
+
"textShadow": "0 2px 4px rgba(0, 0, 0, 0.1)"
|
|
59
|
+
},
|
|
60
|
+
"@media (maxWidth: 768px)": {
|
|
61
|
+
".main-title": {
|
|
62
|
+
"fontSize": "2rem"
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
".subtitle": {
|
|
66
|
+
"fontSize": "1.1rem",
|
|
67
|
+
"opacity": "0.9",
|
|
68
|
+
"maxWidth": "600px",
|
|
69
|
+
"margin": "0 auto"
|
|
70
|
+
},
|
|
71
|
+
".features-section": {
|
|
72
|
+
"display": "grid",
|
|
73
|
+
"gridTemplateColumns": "repeat(auto-fit, minmax(300px, 1fr))",
|
|
74
|
+
"gap": "30px",
|
|
75
|
+
"marginBottom": "60px"
|
|
76
|
+
},
|
|
77
|
+
".feature-card": {
|
|
78
|
+
"backgroundColor": "white",
|
|
79
|
+
"borderRadius": "12px",
|
|
80
|
+
"padding": "30px",
|
|
81
|
+
"boxShadow": "0 4px 12px rgba(0, 0, 0, 0.05)",
|
|
82
|
+
"transition": "transform 0.3s ease, boxShadow 0.3s ease"
|
|
83
|
+
},
|
|
84
|
+
".feature-card:hover": {
|
|
85
|
+
"transform": "translateY(-8px)",
|
|
86
|
+
"boxShadow": "0 12px 20px rgba(0, 0, 0, 0.08)"
|
|
87
|
+
},
|
|
88
|
+
".feature-icon": {
|
|
89
|
+
"width": "60px",
|
|
90
|
+
"height": "60px",
|
|
91
|
+
"borderRadius": "12px",
|
|
92
|
+
"backgroundColor": "#ebf8ff",
|
|
93
|
+
"color": "#4299e1",
|
|
94
|
+
"display": "flex",
|
|
11
95
|
"alignItems": "center",
|
|
12
|
-
"
|
|
13
|
-
"
|
|
96
|
+
"justifyContent": "center",
|
|
97
|
+
"fontSize": "24px",
|
|
98
|
+
"marginBottom": "20px"
|
|
99
|
+
},
|
|
100
|
+
".feature-title": {
|
|
101
|
+
"fontSize": "1.3rem",
|
|
102
|
+
"marginBottom": "15px",
|
|
103
|
+
"color": "#2d3748"
|
|
14
104
|
},
|
|
15
|
-
"
|
|
16
|
-
"color": "
|
|
17
|
-
"
|
|
18
|
-
}
|
|
105
|
+
".feature-description": {
|
|
106
|
+
"color": "#718096",
|
|
107
|
+
"lineHeight": "1.7"
|
|
108
|
+
},
|
|
109
|
+
".action-section": {
|
|
110
|
+
"textAlign": "center",
|
|
111
|
+
"marginBottom": "80px"
|
|
112
|
+
},
|
|
113
|
+
".primary-button": {
|
|
114
|
+
"backgroundColor": "#4299e1",
|
|
115
|
+
"color": "white",
|
|
116
|
+
"border": "none",
|
|
117
|
+
"borderRadius": "8px",
|
|
118
|
+
"padding": "14px 32px",
|
|
119
|
+
"fontSize": "1rem",
|
|
120
|
+
"fontWeight": "600",
|
|
121
|
+
"cursor": "pointer",
|
|
122
|
+
"transition": "all 0.3s ease",
|
|
123
|
+
"boxShadow": "0 4px 6px rgba(66, 153, 225, 0.2)"
|
|
124
|
+
},
|
|
125
|
+
".primary-button:hover": {
|
|
126
|
+
"backgroundColor": "#3182ce",
|
|
127
|
+
"transform": "translateY(-2px)",
|
|
128
|
+
"boxShadow": "0 6px 10px rgba(66, 153, 225, 0.3)"
|
|
129
|
+
},
|
|
130
|
+
".additional-info": {
|
|
131
|
+
"marginTop": "15px",
|
|
132
|
+
"color": "#718096",
|
|
133
|
+
"fontSize": "0.95rem"
|
|
134
|
+
},
|
|
135
|
+
".page-footer": {
|
|
136
|
+
"textAlign": "center",
|
|
137
|
+
"paddingTop": "30px",
|
|
138
|
+
"borderTop": "1px solid #e2e8f0",
|
|
139
|
+
"color": "#718096"
|
|
140
|
+
},
|
|
141
|
+
".copyright": {
|
|
142
|
+
"marginBottom": "15px",
|
|
143
|
+
"fontSize": "0.9rem"
|
|
144
|
+
},
|
|
145
|
+
".social-links": {
|
|
146
|
+
"display": "flex",
|
|
147
|
+
"justifyContent": "center",
|
|
148
|
+
"gap": "15px"
|
|
149
|
+
},
|
|
150
|
+
".social-icon": {
|
|
151
|
+
"color": "#718096",
|
|
152
|
+
"fontSize": "1.2rem",
|
|
153
|
+
"transition": "color 0.3s ease"
|
|
154
|
+
},
|
|
155
|
+
".social-icon:hover": {
|
|
156
|
+
"color": "#4299e1"
|
|
157
|
+
},
|
|
158
|
+
|
|
159
|
+
"body:not(.loaded) .welcome-header": {
|
|
160
|
+
"opacity": "0",
|
|
161
|
+
"transform": "translateY(20px)"
|
|
162
|
+
},
|
|
163
|
+
"body.loaded .welcome-header": {
|
|
164
|
+
"opacity": "1",
|
|
165
|
+
"transform": "translateY(0)",
|
|
166
|
+
"transition": "opacity 0.8s ease, transform 0.8s ease"
|
|
167
|
+
},
|
|
168
|
+
"body:not(.loaded) .feature-card": {
|
|
169
|
+
"opacity": "0",
|
|
170
|
+
"transform": "scale(0.95)"
|
|
171
|
+
},
|
|
172
|
+
"body.loaded .feature-card": {
|
|
173
|
+
"opacity": "1",
|
|
174
|
+
"transform": "scale(1)",
|
|
175
|
+
"transition": "opacity 0.6s ease, transform 0.6s ease"
|
|
176
|
+
},
|
|
177
|
+
"body.loaded .feature-card:nth-child(1)": { "transitionDelay": "0.2s" },
|
|
178
|
+
"body.loaded .feature-card:nth-child(2)": { "transitionDelay": "0.4s" },
|
|
179
|
+
"body.loaded .feature-card:nth-child(3)": { "transitionDelay": "0.6s" }
|
|
19
180
|
},
|
|
20
181
|
"content": {
|
|
21
|
-
"
|
|
182
|
+
".main-title": "Welcome to xiangjsoncraft",
|
|
183
|
+
".subtitle": "Create beautiful web pages with simple JSON configuration",
|
|
184
|
+
".primary-button": "Get Started",
|
|
185
|
+
".additional-info": "Join thousands of developers using our JSON configuration system",
|
|
186
|
+
".copyright": "© 2025 Dong Xiang. All rights reserved."
|
|
187
|
+
},
|
|
188
|
+
"features": {
|
|
189
|
+
"selectorPrefix": "#feature",
|
|
190
|
+
"items": [
|
|
191
|
+
{
|
|
192
|
+
"iconClass": "fas fa-code",
|
|
193
|
+
"title": "Simple Configuration",
|
|
194
|
+
"description": "Define your entire page style and content with easy-to-understand JSON"
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
"iconClass": "fas fa-paint-brush",
|
|
198
|
+
"title": "Beautiful Designs",
|
|
199
|
+
"description": "Create stunning interfaces without writing complex CSS code"
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
"iconClass": "fas fa-mobile-alt",
|
|
203
|
+
"title": "Responsive by Default",
|
|
204
|
+
"description": "Your pages will look great on all devices with built-in responsiveness"
|
|
205
|
+
}
|
|
206
|
+
]
|
|
207
|
+
},
|
|
208
|
+
"icons": {
|
|
209
|
+
"selector": ".social-links",
|
|
210
|
+
"items": [
|
|
211
|
+
{ "class": "fab fa-github", "url": "#" },
|
|
212
|
+
{ "class": "fab fa-twitter", "url": "#" },
|
|
213
|
+
{ "class": "fab fa-linkedin", "url": "#" },
|
|
214
|
+
{ "class": "fab fa-instagram", "url": "#" }
|
|
215
|
+
]
|
|
22
216
|
}
|
|
23
217
|
}
|
|
218
|
+
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
4
|
+
// 定义 replaceCamelCase 方法,用于将驼峰式命名转换为连字符命名
|
|
5
|
+
String.prototype.replaceCamelCase = function (separator = '-') {
|
|
6
|
+
return this.replace(/[A-Z]/g, function (match) {
|
|
7
|
+
return separator + match.toLowerCase();
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
// 创建样式块并添加到文档头部
|
|
12
|
+
function createStyleBlock() {
|
|
13
|
+
const style = document.createElement('style');
|
|
14
|
+
style.id = 'dynamic-styles';
|
|
15
|
+
document.head.appendChild(style);
|
|
16
|
+
return style;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// 封装通用JSON样式渲染函数,支持任意CSS选择器、HTML内容、媒体查询(v1.1.0核心功能)
|
|
20
|
+
function renderJsonStyles() {
|
|
21
|
+
// 动态适配CDN/本地环境的config.json路径(发布后双环境可用)
|
|
22
|
+
const isCdn = (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('xiangjsoncraft.cjs.js', document.baseURI).href)).includes('cdn.jsdelivr.net') || (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('xiangjsoncraft.cjs.js', document.baseURI).href)).includes('unpkg.com');
|
|
23
|
+
const configUrl = isCdn
|
|
24
|
+
? 'https://cdn.jsdelivr.net/npm/xiangjsoncraft@1.1.1/config.json'
|
|
25
|
+
: './config.json';
|
|
26
|
+
|
|
27
|
+
// 使用fetch API获取JSON配置文件
|
|
28
|
+
fetch(configUrl)
|
|
29
|
+
.then(response => {
|
|
30
|
+
if (!response.ok) {
|
|
31
|
+
throw new Error(`网络响应失败: ${response.status} (无法加载配置文件)`);
|
|
32
|
+
}
|
|
33
|
+
return response.json();
|
|
34
|
+
})
|
|
35
|
+
.then(config => {
|
|
36
|
+
// 获取或创建样式块,避免重复创建
|
|
37
|
+
const styleBlock = document.getElementById('dynamic-styles') || createStyleBlock();
|
|
38
|
+
if (!styleBlock) return console.error('样式块创建失败,无法渲染样式');
|
|
39
|
+
|
|
40
|
+
// 生成CSS规则
|
|
41
|
+
let cssRules = '';
|
|
42
|
+
|
|
43
|
+
// 处理所有选择器样式(支持任意CSS选择器、媒体查询)
|
|
44
|
+
if (config.styles && typeof config.styles === 'object' && Object.keys(config.styles).length > 0) {
|
|
45
|
+
// 遍历所有选择器(类、ID、伪类、媒体查询等)
|
|
46
|
+
Object.entries(config.styles).forEach(([selector, styles]) => {
|
|
47
|
+
// 过滤空样式,避免无效CSS
|
|
48
|
+
if (!styles || typeof styles !== 'object') return;
|
|
49
|
+
// 生成该选择器的所有样式属性
|
|
50
|
+
const styleProperties = Object.entries(styles)
|
|
51
|
+
.map(([prop, value]) => {
|
|
52
|
+
// 过滤空属性,驼峰式属性名转换为CSS标准格式
|
|
53
|
+
if (!prop || value === undefined || value === null) return '';
|
|
54
|
+
const cssProp = prop.replaceCamelCase();
|
|
55
|
+
return `${cssProp}: ${value};`;
|
|
56
|
+
})
|
|
57
|
+
.filter(Boolean) // 移除空属性
|
|
58
|
+
.join('\n ');
|
|
59
|
+
|
|
60
|
+
// 仅当有样式属性时,添加到CSS规则
|
|
61
|
+
if (styleProperties) {
|
|
62
|
+
cssRules += `${selector} {\n ${styleProperties}\n}\n\n`;
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// 应用生成的CSS规则到样式块
|
|
68
|
+
if (cssRules) {
|
|
69
|
+
styleBlock.innerHTML = cssRules;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// 处理内容配置(支持纯文本/HTML内容,通过isHtml标识)
|
|
73
|
+
if (config.content && typeof config.content === 'object' && Object.keys(config.content).length > 0) {
|
|
74
|
+
Object.entries(config.content).forEach(([selector, content]) => {
|
|
75
|
+
// 过滤无效选择器和内容
|
|
76
|
+
if (!selector || !content || !content.hasOwnProperty('value')) return;
|
|
77
|
+
const elements = document.querySelectorAll(selector);
|
|
78
|
+
elements.forEach(el => {
|
|
79
|
+
if (!el) return;
|
|
80
|
+
// 支持HTML内容或纯文本,默认纯文本
|
|
81
|
+
if (content.isHtml) {
|
|
82
|
+
el.innerHTML = content.value;
|
|
83
|
+
} else {
|
|
84
|
+
el.textContent = content.value;
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
console.log('✅ XiangJsonCraft v1.1.0 渲染成功!');
|
|
91
|
+
})
|
|
92
|
+
.catch(error => {
|
|
93
|
+
console.error('❌ XiangJsonCraft 处理样式配置时出错:', error.message);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
exports.renderJsonStyles = renderJsonStyles;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// 定义 replaceCamelCase 方法,用于将驼峰式命名转换为连字符命名
|
|
2
|
+
String.prototype.replaceCamelCase = function (separator = '-') {
|
|
3
|
+
return this.replace(/[A-Z]/g, function (match) {
|
|
4
|
+
return separator + match.toLowerCase();
|
|
5
|
+
});
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
// 创建样式块并添加到文档头部
|
|
9
|
+
function createStyleBlock() {
|
|
10
|
+
const style = document.createElement('style');
|
|
11
|
+
style.id = 'dynamic-styles';
|
|
12
|
+
document.head.appendChild(style);
|
|
13
|
+
return style;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// 封装通用JSON样式渲染函数,支持任意CSS选择器、HTML内容、媒体查询(v1.1.0核心功能)
|
|
17
|
+
function renderJsonStyles() {
|
|
18
|
+
// 动态适配CDN/本地环境的config.json路径(发布后双环境可用)
|
|
19
|
+
const isCdn = import.meta.url.includes('cdn.jsdelivr.net') || import.meta.url.includes('unpkg.com');
|
|
20
|
+
const configUrl = isCdn
|
|
21
|
+
? 'https://cdn.jsdelivr.net/npm/xiangjsoncraft@1.1.1/config.json'
|
|
22
|
+
: './config.json';
|
|
23
|
+
|
|
24
|
+
// 使用fetch API获取JSON配置文件
|
|
25
|
+
fetch(configUrl)
|
|
26
|
+
.then(response => {
|
|
27
|
+
if (!response.ok) {
|
|
28
|
+
throw new Error(`网络响应失败: ${response.status} (无法加载配置文件)`);
|
|
29
|
+
}
|
|
30
|
+
return response.json();
|
|
31
|
+
})
|
|
32
|
+
.then(config => {
|
|
33
|
+
// 获取或创建样式块,避免重复创建
|
|
34
|
+
const styleBlock = document.getElementById('dynamic-styles') || createStyleBlock();
|
|
35
|
+
if (!styleBlock) return console.error('样式块创建失败,无法渲染样式');
|
|
36
|
+
|
|
37
|
+
// 生成CSS规则
|
|
38
|
+
let cssRules = '';
|
|
39
|
+
|
|
40
|
+
// 处理所有选择器样式(支持任意CSS选择器、媒体查询)
|
|
41
|
+
if (config.styles && typeof config.styles === 'object' && Object.keys(config.styles).length > 0) {
|
|
42
|
+
// 遍历所有选择器(类、ID、伪类、媒体查询等)
|
|
43
|
+
Object.entries(config.styles).forEach(([selector, styles]) => {
|
|
44
|
+
// 过滤空样式,避免无效CSS
|
|
45
|
+
if (!styles || typeof styles !== 'object') return;
|
|
46
|
+
// 生成该选择器的所有样式属性
|
|
47
|
+
const styleProperties = Object.entries(styles)
|
|
48
|
+
.map(([prop, value]) => {
|
|
49
|
+
// 过滤空属性,驼峰式属性名转换为CSS标准格式
|
|
50
|
+
if (!prop || value === undefined || value === null) return '';
|
|
51
|
+
const cssProp = prop.replaceCamelCase();
|
|
52
|
+
return `${cssProp}: ${value};`;
|
|
53
|
+
})
|
|
54
|
+
.filter(Boolean) // 移除空属性
|
|
55
|
+
.join('\n ');
|
|
56
|
+
|
|
57
|
+
// 仅当有样式属性时,添加到CSS规则
|
|
58
|
+
if (styleProperties) {
|
|
59
|
+
cssRules += `${selector} {\n ${styleProperties}\n}\n\n`;
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// 应用生成的CSS规则到样式块
|
|
65
|
+
if (cssRules) {
|
|
66
|
+
styleBlock.innerHTML = cssRules;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// 处理内容配置(支持纯文本/HTML内容,通过isHtml标识)
|
|
70
|
+
if (config.content && typeof config.content === 'object' && Object.keys(config.content).length > 0) {
|
|
71
|
+
Object.entries(config.content).forEach(([selector, content]) => {
|
|
72
|
+
// 过滤无效选择器和内容
|
|
73
|
+
if (!selector || !content || !content.hasOwnProperty('value')) return;
|
|
74
|
+
const elements = document.querySelectorAll(selector);
|
|
75
|
+
elements.forEach(el => {
|
|
76
|
+
if (!el) return;
|
|
77
|
+
// 支持HTML内容或纯文本,默认纯文本
|
|
78
|
+
if (content.isHtml) {
|
|
79
|
+
el.innerHTML = content.value;
|
|
80
|
+
} else {
|
|
81
|
+
el.textContent = content.value;
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
console.log('✅ XiangJsonCraft v1.1.0 渲染成功!');
|
|
88
|
+
})
|
|
89
|
+
.catch(error => {
|
|
90
|
+
console.error('❌ XiangJsonCraft 处理样式配置时出错:', error.message);
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export { renderJsonStyles };
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
(function(g,f){typeof exports==='object'&&typeof module!=='undefined'?f(exports):typeof define==='function'&&define.amd?define(['exports'],f):(g=typeof globalThis!=='undefined'?globalThis:g||self,f(g.XiangJsonCraft={}));})(this,(function(exports){'use strict';var _documentCurrentScript=typeof document!=='undefined'?document.currentScript:null;// 定义 replaceCamelCase 方法,用于将驼峰式命名转换为连字符命名
|
|
2
|
+
String.prototype.replaceCamelCase = function (separator = '-') {
|
|
3
|
+
return this.replace(/[A-Z]/g, function (match) {
|
|
4
|
+
return separator + match.toLowerCase();
|
|
5
|
+
});
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
// 创建样式块并添加到文档头部
|
|
9
|
+
function createStyleBlock() {
|
|
10
|
+
const style = document.createElement('style');
|
|
11
|
+
style.id = 'dynamic-styles';
|
|
12
|
+
document.head.appendChild(style);
|
|
13
|
+
return style;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// 封装通用JSON样式渲染函数,支持任意CSS选择器、HTML内容、媒体查询(v1.1.0核心功能)
|
|
17
|
+
function renderJsonStyles() {
|
|
18
|
+
// 动态适配CDN/本地环境的config.json路径(发布后双环境可用)
|
|
19
|
+
const isCdn = (typeof document === 'undefined' && typeof location === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : typeof document === 'undefined' ? location.href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('xiangjsoncraft.umd.js', document.baseURI).href)).includes('cdn.jsdelivr.net') || (typeof document === 'undefined' && typeof location === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : typeof document === 'undefined' ? location.href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('xiangjsoncraft.umd.js', document.baseURI).href)).includes('unpkg.com');
|
|
20
|
+
const configUrl = isCdn
|
|
21
|
+
? 'https://cdn.jsdelivr.net/npm/xiangjsoncraft@1.1.1/config.json'
|
|
22
|
+
: './config.json';
|
|
23
|
+
|
|
24
|
+
// 使用fetch API获取JSON配置文件
|
|
25
|
+
fetch(configUrl)
|
|
26
|
+
.then(response => {
|
|
27
|
+
if (!response.ok) {
|
|
28
|
+
throw new Error(`网络响应失败: ${response.status} (无法加载配置文件)`);
|
|
29
|
+
}
|
|
30
|
+
return response.json();
|
|
31
|
+
})
|
|
32
|
+
.then(config => {
|
|
33
|
+
// 获取或创建样式块,避免重复创建
|
|
34
|
+
const styleBlock = document.getElementById('dynamic-styles') || createStyleBlock();
|
|
35
|
+
if (!styleBlock) return console.error('样式块创建失败,无法渲染样式');
|
|
36
|
+
|
|
37
|
+
// 生成CSS规则
|
|
38
|
+
let cssRules = '';
|
|
39
|
+
|
|
40
|
+
// 处理所有选择器样式(支持任意CSS选择器、媒体查询)
|
|
41
|
+
if (config.styles && typeof config.styles === 'object' && Object.keys(config.styles).length > 0) {
|
|
42
|
+
// 遍历所有选择器(类、ID、伪类、媒体查询等)
|
|
43
|
+
Object.entries(config.styles).forEach(([selector, styles]) => {
|
|
44
|
+
// 过滤空样式,避免无效CSS
|
|
45
|
+
if (!styles || typeof styles !== 'object') return;
|
|
46
|
+
// 生成该选择器的所有样式属性
|
|
47
|
+
const styleProperties = Object.entries(styles)
|
|
48
|
+
.map(([prop, value]) => {
|
|
49
|
+
// 过滤空属性,驼峰式属性名转换为CSS标准格式
|
|
50
|
+
if (!prop || value === undefined || value === null) return '';
|
|
51
|
+
const cssProp = prop.replaceCamelCase();
|
|
52
|
+
return `${cssProp}: ${value};`;
|
|
53
|
+
})
|
|
54
|
+
.filter(Boolean) // 移除空属性
|
|
55
|
+
.join('\n ');
|
|
56
|
+
|
|
57
|
+
// 仅当有样式属性时,添加到CSS规则
|
|
58
|
+
if (styleProperties) {
|
|
59
|
+
cssRules += `${selector} {\n ${styleProperties}\n}\n\n`;
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// 应用生成的CSS规则到样式块
|
|
65
|
+
if (cssRules) {
|
|
66
|
+
styleBlock.innerHTML = cssRules;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// 处理内容配置(支持纯文本/HTML内容,通过isHtml标识)
|
|
70
|
+
if (config.content && typeof config.content === 'object' && Object.keys(config.content).length > 0) {
|
|
71
|
+
Object.entries(config.content).forEach(([selector, content]) => {
|
|
72
|
+
// 过滤无效选择器和内容
|
|
73
|
+
if (!selector || !content || !content.hasOwnProperty('value')) return;
|
|
74
|
+
const elements = document.querySelectorAll(selector);
|
|
75
|
+
elements.forEach(el => {
|
|
76
|
+
if (!el) return;
|
|
77
|
+
// 支持HTML内容或纯文本,默认纯文本
|
|
78
|
+
if (content.isHtml) {
|
|
79
|
+
el.innerHTML = content.value;
|
|
80
|
+
} else {
|
|
81
|
+
el.textContent = content.value;
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
console.log('✅ XiangJsonCraft v1.1.0 渲染成功!');
|
|
88
|
+
})
|
|
89
|
+
.catch(error => {
|
|
90
|
+
console.error('❌ XiangJsonCraft 处理样式配置时出错:', error.message);
|
|
91
|
+
});
|
|
92
|
+
}exports.renderJsonStyles=renderJsonStyles;}));
|
package/package.json
CHANGED
|
@@ -1,16 +1,33 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xiangjsoncraft",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "",
|
|
5
|
-
"main": "
|
|
3
|
+
"version": "1.1.1",
|
|
4
|
+
"description": "简单而强大的JSON配置与HTML页面渲染工具,支持任意CSS选择器、响应式设计、HTML内容动态注入,轻量无依赖",
|
|
5
|
+
"main": "dist/xiangjsoncraft.cjs.js",
|
|
6
|
+
"module": "dist/xiangjsoncraft.esm.js",
|
|
7
|
+
"browser": "dist/xiangjsoncraft.umd.js",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist",
|
|
10
|
+
"renderJson.js",
|
|
11
|
+
"config.json",
|
|
12
|
+
"README.md",
|
|
13
|
+
"LICENSE"
|
|
14
|
+
],
|
|
6
15
|
"scripts": {
|
|
7
|
-
"
|
|
16
|
+
"build": "rollup -c",
|
|
17
|
+
"dev": "npx serve ."
|
|
8
18
|
},
|
|
9
|
-
"
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
"
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"rollup": "^4.12.0"
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"json-render",
|
|
24
|
+
"dynamic-css",
|
|
25
|
+
"html-render",
|
|
26
|
+
"json-config",
|
|
27
|
+
"frontend-tool",
|
|
28
|
+
"xiangjsoncraft"
|
|
29
|
+
],
|
|
30
|
+
"author": "董翔 <3631247406@qq.com>",
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"homepage": "https://www.npmjs.com/package/xiangjsoncraft"
|
|
33
|
+
}
|
package/renderJson.js
CHANGED
|
@@ -1,38 +1,92 @@
|
|
|
1
|
-
// 定义 replaceCamelCase
|
|
1
|
+
// 定义 replaceCamelCase 方法,用于将驼峰式命名转换为连字符命名
|
|
2
2
|
String.prototype.replaceCamelCase = function (separator = '-') {
|
|
3
3
|
return this.replace(/[A-Z]/g, function (match) {
|
|
4
4
|
return separator + match.toLowerCase();
|
|
5
5
|
});
|
|
6
6
|
};
|
|
7
7
|
|
|
8
|
-
//
|
|
9
|
-
function
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
// 创建样式块并添加到文档头部
|
|
9
|
+
function createStyleBlock() {
|
|
10
|
+
const style = document.createElement('style');
|
|
11
|
+
style.id = 'dynamic-styles';
|
|
12
|
+
document.head.appendChild(style);
|
|
13
|
+
return style;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// 封装通用JSON样式渲染函数,支持任意CSS选择器、HTML内容、媒体查询(v1.1.0核心功能)
|
|
17
|
+
export function renderJsonStyles() {
|
|
18
|
+
// 动态适配CDN/本地环境的config.json路径(发布后双环境可用)
|
|
19
|
+
const isCdn = import.meta.url.includes('cdn.jsdelivr.net') || import.meta.url.includes('unpkg.com');
|
|
20
|
+
const configUrl = isCdn
|
|
21
|
+
? 'https://cdn.jsdelivr.net/npm/xiangjsoncraft@1.1.1/config.json'
|
|
22
|
+
: './config.json';
|
|
23
|
+
|
|
24
|
+
// 使用fetch API获取JSON配置文件
|
|
25
|
+
fetch(configUrl)
|
|
12
26
|
.then(response => {
|
|
13
|
-
// 检查响应是否成功
|
|
14
27
|
if (!response.ok) {
|
|
15
|
-
throw new Error(
|
|
28
|
+
throw new Error(`网络响应失败: ${response.status} (无法加载配置文件)`);
|
|
16
29
|
}
|
|
17
|
-
// 将响应转换为 JSON 格式
|
|
18
30
|
return response.json();
|
|
19
31
|
})
|
|
20
32
|
.then(config => {
|
|
21
|
-
//
|
|
22
|
-
const styleBlock = document.getElementById('
|
|
23
|
-
styleBlock
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
33
|
+
// 获取或创建样式块,避免重复创建
|
|
34
|
+
const styleBlock = document.getElementById('dynamic-styles') || createStyleBlock();
|
|
35
|
+
if (!styleBlock) return console.error('样式块创建失败,无法渲染样式');
|
|
36
|
+
|
|
37
|
+
// 生成CSS规则
|
|
38
|
+
let cssRules = '';
|
|
39
|
+
|
|
40
|
+
// 处理所有选择器样式(支持任意CSS选择器、媒体查询)
|
|
41
|
+
if (config.styles && typeof config.styles === 'object' && Object.keys(config.styles).length > 0) {
|
|
42
|
+
// 遍历所有选择器(类、ID、伪类、媒体查询等)
|
|
43
|
+
Object.entries(config.styles).forEach(([selector, styles]) => {
|
|
44
|
+
// 过滤空样式,避免无效CSS
|
|
45
|
+
if (!styles || typeof styles !== 'object') return;
|
|
46
|
+
// 生成该选择器的所有样式属性
|
|
47
|
+
const styleProperties = Object.entries(styles)
|
|
48
|
+
.map(([prop, value]) => {
|
|
49
|
+
// 过滤空属性,驼峰式属性名转换为CSS标准格式
|
|
50
|
+
if (!prop || value === undefined || value === null) return '';
|
|
51
|
+
const cssProp = prop.replaceCamelCase();
|
|
52
|
+
return `${cssProp}: ${value};`;
|
|
53
|
+
})
|
|
54
|
+
.filter(Boolean) // 移除空属性
|
|
55
|
+
.join('\n ');
|
|
56
|
+
|
|
57
|
+
// 仅当有样式属性时,添加到CSS规则
|
|
58
|
+
if (styleProperties) {
|
|
59
|
+
cssRules += `${selector} {\n ${styleProperties}\n}\n\n`;
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// 应用生成的CSS规则到样式块
|
|
65
|
+
if (cssRules) {
|
|
66
|
+
styleBlock.innerHTML = cssRules;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// 处理内容配置(支持纯文本/HTML内容,通过isHtml标识)
|
|
70
|
+
if (config.content && typeof config.content === 'object' && Object.keys(config.content).length > 0) {
|
|
71
|
+
Object.entries(config.content).forEach(([selector, content]) => {
|
|
72
|
+
// 过滤无效选择器和内容
|
|
73
|
+
if (!selector || !content || !content.hasOwnProperty('value')) return;
|
|
74
|
+
const elements = document.querySelectorAll(selector);
|
|
75
|
+
elements.forEach(el => {
|
|
76
|
+
if (!el) return;
|
|
77
|
+
// 支持HTML内容或纯文本,默认纯文本
|
|
78
|
+
if (content.isHtml) {
|
|
79
|
+
el.innerHTML = content.value;
|
|
80
|
+
} else {
|
|
81
|
+
el.textContent = content.value;
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
console.log('✅ XiangJsonCraft v1.1.0 渲染成功!');
|
|
31
88
|
})
|
|
32
89
|
.catch(error => {
|
|
33
|
-
console.error('
|
|
90
|
+
console.error('❌ XiangJsonCraft 处理样式配置时出错:', error.message);
|
|
34
91
|
});
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// 导出渲染函数
|
|
38
|
-
export { renderJson };
|
|
92
|
+
}
|
package/index.html
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8">
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
<title>Document</title>
|
|
7
|
-
<style id="style-block"></style>
|
|
8
|
-
</head>
|
|
9
|
-
<body>
|
|
10
|
-
<header>
|
|
11
|
-
<p id="header-text"></p>
|
|
12
|
-
</header>
|
|
13
|
-
<!-- 引入外部 JavaScript 文件 -->
|
|
14
|
-
<script type="module">
|
|
15
|
-
import { renderJson } from './renderJson.js';
|
|
16
|
-
renderJson();
|
|
17
|
-
</script>
|
|
18
|
-
</body>
|
|
19
|
-
</html>
|