xiangjsoncraft 1.1.0 → 1.1.2
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 +226 -189
- package/dist/xiangjsoncraft.cjs.js +86 -0
- package/dist/xiangjsoncraft.esm.js +84 -0
- package/dist/xiangjsoncraft.umd.js +82 -0
- package/package.json +25 -13
- package/renderJson.js +61 -76
- package/index.html +0 -53
package/README.md
CHANGED
|
@@ -1,69 +1,54 @@
|
|
|
1
|
-
# XiangJsonCraft
|
|
2
|
-
|
|
1
|
+
# XiangJsonCraft
|
|
3
2
|

|
|
4
3
|
|
|
5
|
-
XiangJsonCraft 是一个简单而强大的 JSON 配置与 HTML 页面渲染工具,由大学生董翔开发,专为前端开发者设计。通过简洁的 API,它允许你使用 JSON 配置文件来定义样式和内容,并将其应用到 HTML
|
|
6
|
-
|
|
7
|
-
## 🚀 最新更新 (v1.1.
|
|
8
|
-
|
|
9
|
-
|
|
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 安装
|
|
27
|
+
```bash
|
|
28
|
+
# npm
|
|
29
|
+
npm install xiangjsoncraft --save
|
|
10
30
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
- **增强的渲染逻辑**:重构了渲染引擎,支持更复杂的样式结构和内容类型
|
|
14
|
-
- **响应式设计支持**:通过媒体查询配置,轻松实现不同屏幕尺寸的适配
|
|
15
|
-
- **HTML 内容支持**:不仅能设置文本内容,还可以配置 HTML 片段
|
|
31
|
+
# yarn
|
|
32
|
+
yarn add xiangjsoncraft
|
|
16
33
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
```json
|
|
20
|
-
{
|
|
21
|
-
"styles": {
|
|
22
|
-
"body": { ... },
|
|
23
|
-
"header": { ... }
|
|
24
|
-
}
|
|
25
|
-
}
|
|
34
|
+
# pnpm
|
|
35
|
+
pnpm add xiangjsoncraft
|
|
26
36
|
```
|
|
27
37
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
"content": {
|
|
38
|
-
".title": {
|
|
39
|
-
"value": "<strong>欢迎使用</strong>",
|
|
40
|
-
"isHtml": true
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
## 特性
|
|
47
|
-
|
|
48
|
-
- **简单易用**:只需几行代码即可完成页面渲染
|
|
49
|
-
- **灵活配置**:通过 JSON 文件定义样式和内容
|
|
50
|
-
- **轻量级**:无额外依赖,体积小巧
|
|
51
|
-
- **全面的选择器支持**:兼容所有 CSS 选择器语法
|
|
52
|
-
- **响应式设计**:轻松配置不同设备的显示效果
|
|
53
|
-
- **动态内容**:支持文本和 HTML 内容的动态注入
|
|
54
|
-
|
|
55
|
-
## 安装
|
|
56
|
-
|
|
57
|
-
```bash
|
|
58
|
-
npm install xiangjsoncraft
|
|
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>
|
|
59
47
|
```
|
|
60
48
|
|
|
61
|
-
## 快速开始
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
创建 `config.json` 配置文件,定义页面的样式和内容:
|
|
66
|
-
|
|
49
|
+
## ⚡ 快速开始
|
|
50
|
+
### 步骤1:创建 JSON 配置文件
|
|
51
|
+
在项目根目录/HTML 同级目录创建 `config.json`,定义页面的样式、文本及 HTML 内容,支持所有 CSS 选择器和媒体查询:
|
|
67
52
|
```json
|
|
68
53
|
{
|
|
69
54
|
"styles": {
|
|
@@ -75,197 +60,232 @@ npm install xiangjsoncraft
|
|
|
75
60
|
"body": {
|
|
76
61
|
"fontFamily": "Arial, sans-serif",
|
|
77
62
|
"lineHeight": "1.6",
|
|
78
|
-
"color": "#333"
|
|
63
|
+
"color": "#333",
|
|
64
|
+
"backgroundColor": "#f9f9f9",
|
|
65
|
+
"padding": "2rem"
|
|
79
66
|
},
|
|
80
67
|
".header": {
|
|
81
68
|
"backgroundColor": "#2c3e50",
|
|
82
69
|
"color": "white",
|
|
83
|
-
"padding": "
|
|
84
|
-
"textAlign": "center"
|
|
70
|
+
"padding": "1.5rem",
|
|
71
|
+
"textAlign": "center",
|
|
72
|
+
"borderRadius": "8px",
|
|
73
|
+
"marginBottom": "2rem"
|
|
85
74
|
},
|
|
86
75
|
"nav ul": {
|
|
87
76
|
"display": "flex",
|
|
88
77
|
"listStyle": "none",
|
|
89
78
|
"justifyContent": "center",
|
|
90
|
-
"gap": "
|
|
79
|
+
"gap": "1.5rem",
|
|
80
|
+
"marginBottom": "2rem"
|
|
81
|
+
},
|
|
82
|
+
"nav a": {
|
|
83
|
+
"color": "#2c3e50",
|
|
84
|
+
"textDecoration": "none",
|
|
85
|
+
"fontSize": "1.1rem"
|
|
91
86
|
},
|
|
92
87
|
"nav a:hover": {
|
|
93
88
|
"color": "#f39c12",
|
|
94
|
-
"textDecoration": "
|
|
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)"
|
|
95
96
|
},
|
|
96
97
|
"@media (max-width: 768px)": {
|
|
98
|
+
"body": {
|
|
99
|
+
"padding": "1rem"
|
|
100
|
+
},
|
|
97
101
|
"nav ul": {
|
|
98
102
|
"flexDirection": "column",
|
|
99
|
-
"alignItems": "center"
|
|
103
|
+
"alignItems": "center",
|
|
104
|
+
"gap": "1rem"
|
|
100
105
|
}
|
|
101
106
|
}
|
|
102
107
|
},
|
|
103
108
|
"content": {
|
|
104
109
|
".header h1": {
|
|
105
|
-
"value": "
|
|
110
|
+
"value": "XiangJsonCraft 演示页面",
|
|
106
111
|
"isHtml": false
|
|
107
112
|
},
|
|
108
|
-
"
|
|
109
|
-
"value": "<
|
|
113
|
+
".card h2": {
|
|
114
|
+
"value": "<span style='color:#2c3e50;'>JSON 配置渲染</span> 就是这么简单",
|
|
110
115
|
"isHtml": true
|
|
116
|
+
},
|
|
117
|
+
".card p": {
|
|
118
|
+
"value": "通过单个 JSON 文件定义所有样式和内容,一行代码完成页面渲染,实现代码与配置的解耦管理。",
|
|
119
|
+
"isHtml": false
|
|
111
120
|
}
|
|
112
121
|
}
|
|
113
122
|
}
|
|
114
123
|
```
|
|
115
124
|
|
|
116
|
-
### 2
|
|
117
|
-
|
|
118
|
-
创建 `index.html` 页面:
|
|
119
|
-
|
|
125
|
+
### 步骤2:创建 HTML 页面
|
|
126
|
+
创建 `index.html`,引入渲染容器并调用核心 API,无需手写任何 CSS 样式:
|
|
120
127
|
```html
|
|
121
128
|
<!DOCTYPE html>
|
|
122
129
|
<html lang="en">
|
|
123
130
|
<head>
|
|
124
131
|
<meta charset="UTF-8">
|
|
125
132
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
126
|
-
<title>XiangJsonCraft
|
|
133
|
+
<title>XiangJsonCraft 快速开始</title>
|
|
134
|
+
<!-- 动态样式块,渲染后的CSS会注入到这里 -->
|
|
127
135
|
<style id="dynamic-styles"></style>
|
|
128
136
|
</head>
|
|
129
137
|
<body>
|
|
138
|
+
<!-- 页面渲染容器,与config.json中的选择器匹配 -->
|
|
130
139
|
<header class="header">
|
|
131
140
|
<h1></h1>
|
|
132
141
|
</header>
|
|
133
142
|
<nav>
|
|
134
143
|
<ul>
|
|
135
144
|
<li><a href="#">首页</a></li>
|
|
136
|
-
<li><a href="#"
|
|
137
|
-
<li><a href="#"
|
|
145
|
+
<li><a href="#">文档</a></li>
|
|
146
|
+
<li><a href="#">示例</a></li>
|
|
138
147
|
</ul>
|
|
139
148
|
</nav>
|
|
140
|
-
<div
|
|
149
|
+
<div class="card">
|
|
150
|
+
<h2></h2>
|
|
151
|
+
<p></p>
|
|
152
|
+
</div>
|
|
141
153
|
|
|
154
|
+
<!-- 方式1:本地模块化引入(推荐,适合项目开发) -->
|
|
142
155
|
<script type="module">
|
|
143
156
|
import { renderJsonStyles } from './renderJson.js';
|
|
157
|
+
// 一行调用,完成所有样式和内容渲染
|
|
144
158
|
renderJsonStyles();
|
|
145
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> -->
|
|
146
166
|
</body>
|
|
147
167
|
</html>
|
|
148
168
|
```
|
|
149
169
|
|
|
150
|
-
### 3
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
```javascript
|
|
155
|
-
// 定义 replaceCamelCase 方法,用于将驼峰式命名转换为连字符命名
|
|
156
|
-
String.prototype.replaceCamelCase = function (separator = '-') {
|
|
157
|
-
return this.replace(/[A-Z]/g, function (match) {
|
|
158
|
-
return separator + match.toLowerCase();
|
|
159
|
-
});
|
|
160
|
-
};
|
|
161
|
-
|
|
162
|
-
// 封装通用JSON样式渲染函数,支持任意CSS选择器
|
|
163
|
-
function renderJsonStyles() {
|
|
164
|
-
// 使用fetch API获取JSON配置文件
|
|
165
|
-
fetch('./config.json')
|
|
166
|
-
.then(response => {
|
|
167
|
-
if (!response.ok) {
|
|
168
|
-
throw new Error(`网络响应失败: ${response.status}`);
|
|
169
|
-
}
|
|
170
|
-
return response.json();
|
|
171
|
-
})
|
|
172
|
-
.then(config => {
|
|
173
|
-
const styleBlock = document.getElementById('dynamic-styles') || createStyleBlock();
|
|
174
|
-
|
|
175
|
-
// 生成CSS规则
|
|
176
|
-
let cssRules = '';
|
|
177
|
-
|
|
178
|
-
// 处理所有选择器样式
|
|
179
|
-
if (config.styles && typeof config.styles === 'object') {
|
|
180
|
-
// 遍历所有选择器
|
|
181
|
-
Object.entries(config.styles).forEach(([selector, styles]) => {
|
|
182
|
-
// 生成该选择器的所有样式属性
|
|
183
|
-
const styleProperties = Object.entries(styles)
|
|
184
|
-
.map(([prop, value]) => {
|
|
185
|
-
// 将驼峰式属性名转换为CSS格式(如fontSize -> font-size)
|
|
186
|
-
const cssProp = prop.replaceCamelCase();
|
|
187
|
-
return `${cssProp}: ${value};`;
|
|
188
|
-
})
|
|
189
|
-
.join('\n ');
|
|
190
|
-
|
|
191
|
-
// 添加选择器及其样式到CSS规则
|
|
192
|
-
cssRules += `${selector} {\n ${styleProperties}\n}\n\n`;
|
|
193
|
-
});
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
// 处理内容配置
|
|
197
|
-
if (config.content && typeof config.content === 'object') {
|
|
198
|
-
Object.entries(config.content).forEach(([selector, content]) => {
|
|
199
|
-
const elements = document.querySelectorAll(selector);
|
|
200
|
-
elements.forEach(el => {
|
|
201
|
-
// 支持HTML内容或纯文本
|
|
202
|
-
if (content.isHtml) {
|
|
203
|
-
el.innerHTML = content.value;
|
|
204
|
-
} else {
|
|
205
|
-
el.textContent = content.value;
|
|
206
|
-
}
|
|
207
|
-
});
|
|
208
|
-
});
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
// 将生成的CSS应用到样式块
|
|
212
|
-
styleBlock.innerHTML = cssRules;
|
|
213
|
-
})
|
|
214
|
-
.catch(error => {
|
|
215
|
-
console.error('处理样式配置时出错:', error);
|
|
216
|
-
});
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
// 创建样式块并添加到文档头部
|
|
220
|
-
function createStyleBlock() {
|
|
221
|
-
const style = document.createElement('style');
|
|
222
|
-
style.id = 'dynamic-styles';
|
|
223
|
-
document.head.appendChild(style);
|
|
224
|
-
return style;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
// 导出渲染函数
|
|
228
|
-
export { renderJsonStyles };
|
|
229
|
-
```
|
|
170
|
+
### 步骤3:开发运行
|
|
171
|
+
```bash
|
|
172
|
+
# 安装开发依赖(首次使用)
|
|
173
|
+
npm install
|
|
230
174
|
|
|
231
|
-
|
|
175
|
+
# 打包生成多格式文件(UMD/ES/CJS)
|
|
176
|
+
npm run build
|
|
232
177
|
|
|
233
|
-
|
|
234
|
-
# 运行开发服务器
|
|
178
|
+
# 启动开发服务器,一键预览效果
|
|
235
179
|
npm run dev
|
|
236
180
|
```
|
|
181
|
+
在浏览器中访问 `http://localhost:3000`,即可看到由 JSON 配置渲染的完整页面。
|
|
237
182
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
## API 文档
|
|
241
|
-
|
|
183
|
+
## 📚 API 文档
|
|
242
184
|
### `renderJsonStyles()`
|
|
185
|
+
**核心渲染方法**,无入参,执行后自动完成以下操作:
|
|
186
|
+
1. 自动识别运行环境(本地/CDN),加载对应路径的 `config.json` 配置文件
|
|
187
|
+
2. 解析配置中的 `styles` 节点,生成标准 CSS 样式并注入到页面头部的 `#dynamic-styles` 样式块
|
|
188
|
+
3. 解析配置中的 `content` 节点,根据 `isHtml` 标识,向匹配的 DOM 节点注入纯文本/HTML 内容
|
|
189
|
+
4. 控制台输出渲染成功提示,若配置异常则输出友好的错误信息
|
|
243
190
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
#### 示例
|
|
247
|
-
|
|
191
|
+
#### 调用方式
|
|
248
192
|
```javascript
|
|
249
|
-
|
|
193
|
+
// 方式1:ES6模块化引入(本地开发/前端框架)
|
|
194
|
+
import { renderJsonStyles } from 'xiangjsoncraft';
|
|
250
195
|
renderJsonStyles();
|
|
196
|
+
|
|
197
|
+
// 方式2:CDN全局调用(静态页面/快速开发)
|
|
198
|
+
XiangJsonCraft.renderJsonStyles();
|
|
251
199
|
```
|
|
252
200
|
|
|
253
|
-
##
|
|
201
|
+
## ⚙️ 配置文件说明
|
|
202
|
+
配置文件为标准 JSON 格式,核心包含 `styles` 和 `content` 两个一级节点,所有配置均支持按需扩展、修改。
|
|
254
203
|
|
|
255
|
-
|
|
204
|
+
### 1. `styles` 节点
|
|
205
|
+
用于定义页面所有 CSS 样式,**键为任意合法 CSS 选择器**,值为样式属性对象,样式属性支持**驼峰式命名**(会自动转换为 CSS 标准短横线命名)。
|
|
206
|
+
- 支持选择器:类、ID、标签、伪类、伪元素、后代选择器、媒体查询等所有 CSS 合法选择器
|
|
207
|
+
- 样式属性:所有 CSS 原生属性,驼峰式(`fontSize`)会自动转为短横线式(`font-size`)
|
|
256
208
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
209
|
+
### 2. `content` 节点
|
|
210
|
+
用于定义页面文本/HTML 内容,**键为 CSS 选择器**,值为内容配置对象,包含两个必选属性:
|
|
211
|
+
- `value`:字符串类型,要渲染的内容(纯文本/HTML 片段)
|
|
212
|
+
- `isHtml`:布尔类型,`true` 表示内容为 HTML 片段,`false` 表示内容为纯文本(默认)
|
|
260
213
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
214
|
+
### 配置文件规范
|
|
215
|
+
1. 配置文件必须命名为 `config.json`,与 HTML 页面同级目录(CDN 方式无需手动创建,自动加载官方配置)
|
|
216
|
+
2. 选择器必须匹配 HTML 中的实际 DOM 节点,否则会被自动过滤
|
|
217
|
+
3. 样式属性值需符合 CSS 规范(如单位、颜色值、尺寸值)
|
|
218
|
+
4. HTML 片段需保证语法合法,避免 XSS 风险(建议仅在可信环境下使用 HTML 内容)
|
|
264
219
|
|
|
265
|
-
##
|
|
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
|
+
}
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
## 🥚 彩蛋:工具背后的小插曲
|
|
287
|
+
### “敢改包”的底气来源
|
|
266
288
|
|
|
267
|
-
```markdown
|
|
268
|
-
# 工具背后的小插曲:“敢改包”的底气来源
|
|
269
289
|
其实XiangJsonCraft的诞生,还藏着一段有趣的小场景——
|
|
270
290
|
|
|
271
291
|
某天,朋友在Vue项目里用这个包时,遇到了个不符合自己编程习惯的小细节,对着node_modules里的代码犯愁:“老师说这地方不能随便改,容易牵一发而动全身。”
|
|
@@ -279,17 +299,31 @@ renderJsonStyles();
|
|
|
279
299
|
对别人来说,改node_modules是“碰别人的代码”;但对我来说,改的是“自己写的工具”。知道怎么调整既不破坏核心功能,又能贴合朋友的习惯,这份底气,其实来自“开发者”这个身份最本质的掌控感。
|
|
280
300
|
|
|
281
301
|
所以如果你用的时候也有小想法,不用怕“改坏”——工具本身就为“灵活适配”留足了空间,而作为作者,我也始终在背后,为它的稳定和好用托底。
|
|
282
|
-
```
|
|
283
302
|
|
|
284
|
-
##
|
|
303
|
+
## 🌐 浏览器兼容性
|
|
304
|
+
支持所有现代浏览器,无需额外引入 polyfill:
|
|
305
|
+
- Chrome ≥ 61
|
|
306
|
+
- Firefox ≥ 60
|
|
307
|
+
- Edge ≥ 79
|
|
308
|
+
- Safari ≥ 12.1
|
|
309
|
+
- Opera ≥ 48
|
|
310
|
+
- 移动端所有现代浏览器(微信浏览器、QQ浏览器、Safari 移动端等)
|
|
285
311
|
|
|
286
|
-
|
|
312
|
+
## 🤝 贡献指南
|
|
313
|
+
XiangJsonCraft 欢迎所有开发者的贡献和建议,如果你有以下想法,欢迎随时交流:
|
|
314
|
+
- 新增功能需求
|
|
315
|
+
- 性能优化建议
|
|
316
|
+
- Bug 修复
|
|
317
|
+
- 文档完善
|
|
287
318
|
|
|
288
|
-
|
|
319
|
+
**贡献方式**:通过邮箱联系作者,提供你的想法、代码或问题描述,作者会第一时间回复。
|
|
289
320
|
|
|
290
|
-
|
|
321
|
+
## 📄 许可证
|
|
322
|
+
本项目基于 **MIT 开源许可证** 发布,你可以自由使用、修改、分发本项目,无需支付任何费用,只需保留版权声明。
|
|
291
323
|
|
|
292
|
-
|
|
324
|
+
```
|
|
325
|
+
MIT License
|
|
326
|
+
Copyright (c) 2025 董翔
|
|
293
327
|
|
|
294
328
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
295
329
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -308,11 +342,14 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
308
342
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
309
343
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
310
344
|
SOFTWARE.
|
|
345
|
+
```
|
|
311
346
|
|
|
312
|
-
## 联系我们
|
|
313
|
-
|
|
314
|
-
|
|
347
|
+
## 📞 联系我们
|
|
348
|
+
如果你有任何问题、建议或合作想法,欢迎通过以下方式联系作者:
|
|
349
|
+
- **Email**:3631247406@qq.com
|
|
350
|
+
- **作者**:董翔
|
|
315
351
|
|
|
316
|
-
|
|
352
|
+
---
|
|
317
353
|
|
|
318
|
-
|
|
354
|
+
**感谢使用 XiangJsonCraft!**
|
|
355
|
+
愿这个小工具能让你的前端开发更高效、更轻松 🚀
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// 封装通用JSON样式渲染函数,支持任意CSS选择器、HTML内容、媒体查询(v1.1.0核心功能)
|
|
4
|
+
function renderJsonStyles() {
|
|
5
|
+
// 核心原则:本地config.json永远最高优先级,加载失败再用CDN官方配置
|
|
6
|
+
const localConfigUrl = './config.json'; // 本地用户自定义配置
|
|
7
|
+
const cdnConfigUrl = 'https://cdn.jsdelivr.net/npm/xiangjsoncraft@1.1.1/config.json'; // CDN兜底配置
|
|
8
|
+
|
|
9
|
+
// 先尝试加载本地config.json
|
|
10
|
+
fetch(localConfigUrl)
|
|
11
|
+
.then(response => {
|
|
12
|
+
// 本地配置存在(状态码200),则使用本地配置
|
|
13
|
+
if (response.ok) {
|
|
14
|
+
console.log('🔧 检测到本地config.json,优先加载用户自定义配置');
|
|
15
|
+
return response.json();
|
|
16
|
+
}
|
|
17
|
+
// 本地配置不存在/加载失败,切换到CDN兜底配置
|
|
18
|
+
console.log('ℹ️ 本地未检测到config.json,加载CDN官方示例配置');
|
|
19
|
+
return fetch(cdnConfigUrl).then(res => {
|
|
20
|
+
if (!res.ok) throw new Error('CDN官方配置加载失败');
|
|
21
|
+
return res.json();
|
|
22
|
+
});
|
|
23
|
+
})
|
|
24
|
+
.then(config => {
|
|
25
|
+
// 获取或创建样式块,避免重复创建
|
|
26
|
+
const styleBlock = document.getElementById('dynamic-styles') || createStyleBlock();
|
|
27
|
+
if (!styleBlock) return console.error('❌ 样式块创建失败,无法渲染样式');
|
|
28
|
+
|
|
29
|
+
// 生成CSS规则
|
|
30
|
+
let cssRules = '';
|
|
31
|
+
|
|
32
|
+
// 处理所有选择器样式(支持任意CSS选择器、媒体查询)
|
|
33
|
+
if (config.styles && typeof config.styles === 'object' && Object.keys(config.styles).length > 0) {
|
|
34
|
+
// 遍历所有选择器(类、ID、伪类、媒体查询等)
|
|
35
|
+
Object.entries(config.styles).forEach(([selector, styles]) => {
|
|
36
|
+
// 过滤空样式,避免无效CSS
|
|
37
|
+
if (!styles || typeof styles !== 'object') return;
|
|
38
|
+
// 生成该选择器的所有样式属性
|
|
39
|
+
const styleProperties = Object.entries(styles)
|
|
40
|
+
.map(([prop, value]) => {
|
|
41
|
+
// 过滤空属性,驼峰式属性名转换为CSS标准格式
|
|
42
|
+
if (!prop || value === undefined || value === null) return '';
|
|
43
|
+
const cssProp = prop.replaceCamelCase();
|
|
44
|
+
return `${cssProp}: ${value};`;
|
|
45
|
+
})
|
|
46
|
+
.filter(Boolean) // 移除空属性
|
|
47
|
+
.join('\n ');
|
|
48
|
+
|
|
49
|
+
// 仅当有样式属性时,添加到CSS规则
|
|
50
|
+
if (styleProperties) {
|
|
51
|
+
cssRules += `${selector} {\n ${styleProperties}\n}\n\n`;
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// 应用生成的CSS规则到样式块
|
|
57
|
+
if (cssRules) {
|
|
58
|
+
styleBlock.innerHTML = cssRules;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// 处理内容配置(支持纯文本/HTML内容,通过isHtml标识)
|
|
62
|
+
if (config.content && typeof config.content === 'object' && Object.keys(config.content).length > 0) {
|
|
63
|
+
Object.entries(config.content).forEach(([selector, content]) => {
|
|
64
|
+
// 过滤无效选择器和内容
|
|
65
|
+
if (!selector || !content || !content.hasOwnProperty('value')) return;
|
|
66
|
+
const elements = document.querySelectorAll(selector);
|
|
67
|
+
elements.forEach(el => {
|
|
68
|
+
if (!el) return;
|
|
69
|
+
// 支持HTML内容或纯文本,默认纯文本
|
|
70
|
+
if (content.isHtml) {
|
|
71
|
+
el.innerHTML = content.value;
|
|
72
|
+
} else {
|
|
73
|
+
el.textContent = content.value;
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
console.log('✅ XiangJsonCraft v1.1.1 渲染成功!');
|
|
80
|
+
})
|
|
81
|
+
.catch(error => {
|
|
82
|
+
console.error('❌ XiangJsonCraft 处理配置时出错:', error.message);
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
exports.renderJsonStyles = renderJsonStyles;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// 封装通用JSON样式渲染函数,支持任意CSS选择器、HTML内容、媒体查询(v1.1.0核心功能)
|
|
2
|
+
function renderJsonStyles() {
|
|
3
|
+
// 核心原则:本地config.json永远最高优先级,加载失败再用CDN官方配置
|
|
4
|
+
const localConfigUrl = './config.json'; // 本地用户自定义配置
|
|
5
|
+
const cdnConfigUrl = 'https://cdn.jsdelivr.net/npm/xiangjsoncraft@1.1.1/config.json'; // CDN兜底配置
|
|
6
|
+
|
|
7
|
+
// 先尝试加载本地config.json
|
|
8
|
+
fetch(localConfigUrl)
|
|
9
|
+
.then(response => {
|
|
10
|
+
// 本地配置存在(状态码200),则使用本地配置
|
|
11
|
+
if (response.ok) {
|
|
12
|
+
console.log('🔧 检测到本地config.json,优先加载用户自定义配置');
|
|
13
|
+
return response.json();
|
|
14
|
+
}
|
|
15
|
+
// 本地配置不存在/加载失败,切换到CDN兜底配置
|
|
16
|
+
console.log('ℹ️ 本地未检测到config.json,加载CDN官方示例配置');
|
|
17
|
+
return fetch(cdnConfigUrl).then(res => {
|
|
18
|
+
if (!res.ok) throw new Error('CDN官方配置加载失败');
|
|
19
|
+
return res.json();
|
|
20
|
+
});
|
|
21
|
+
})
|
|
22
|
+
.then(config => {
|
|
23
|
+
// 获取或创建样式块,避免重复创建
|
|
24
|
+
const styleBlock = document.getElementById('dynamic-styles') || createStyleBlock();
|
|
25
|
+
if (!styleBlock) return console.error('❌ 样式块创建失败,无法渲染样式');
|
|
26
|
+
|
|
27
|
+
// 生成CSS规则
|
|
28
|
+
let cssRules = '';
|
|
29
|
+
|
|
30
|
+
// 处理所有选择器样式(支持任意CSS选择器、媒体查询)
|
|
31
|
+
if (config.styles && typeof config.styles === 'object' && Object.keys(config.styles).length > 0) {
|
|
32
|
+
// 遍历所有选择器(类、ID、伪类、媒体查询等)
|
|
33
|
+
Object.entries(config.styles).forEach(([selector, styles]) => {
|
|
34
|
+
// 过滤空样式,避免无效CSS
|
|
35
|
+
if (!styles || typeof styles !== 'object') return;
|
|
36
|
+
// 生成该选择器的所有样式属性
|
|
37
|
+
const styleProperties = Object.entries(styles)
|
|
38
|
+
.map(([prop, value]) => {
|
|
39
|
+
// 过滤空属性,驼峰式属性名转换为CSS标准格式
|
|
40
|
+
if (!prop || value === undefined || value === null) return '';
|
|
41
|
+
const cssProp = prop.replaceCamelCase();
|
|
42
|
+
return `${cssProp}: ${value};`;
|
|
43
|
+
})
|
|
44
|
+
.filter(Boolean) // 移除空属性
|
|
45
|
+
.join('\n ');
|
|
46
|
+
|
|
47
|
+
// 仅当有样式属性时,添加到CSS规则
|
|
48
|
+
if (styleProperties) {
|
|
49
|
+
cssRules += `${selector} {\n ${styleProperties}\n}\n\n`;
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// 应用生成的CSS规则到样式块
|
|
55
|
+
if (cssRules) {
|
|
56
|
+
styleBlock.innerHTML = cssRules;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// 处理内容配置(支持纯文本/HTML内容,通过isHtml标识)
|
|
60
|
+
if (config.content && typeof config.content === 'object' && Object.keys(config.content).length > 0) {
|
|
61
|
+
Object.entries(config.content).forEach(([selector, content]) => {
|
|
62
|
+
// 过滤无效选择器和内容
|
|
63
|
+
if (!selector || !content || !content.hasOwnProperty('value')) return;
|
|
64
|
+
const elements = document.querySelectorAll(selector);
|
|
65
|
+
elements.forEach(el => {
|
|
66
|
+
if (!el) return;
|
|
67
|
+
// 支持HTML内容或纯文本,默认纯文本
|
|
68
|
+
if (content.isHtml) {
|
|
69
|
+
el.innerHTML = content.value;
|
|
70
|
+
} else {
|
|
71
|
+
el.textContent = content.value;
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
console.log('✅ XiangJsonCraft v1.1.1 渲染成功!');
|
|
78
|
+
})
|
|
79
|
+
.catch(error => {
|
|
80
|
+
console.error('❌ XiangJsonCraft 处理配置时出错:', error.message);
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export { renderJsonStyles };
|
|
@@ -0,0 +1,82 @@
|
|
|
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';// 封装通用JSON样式渲染函数,支持任意CSS选择器、HTML内容、媒体查询(v1.1.0核心功能)
|
|
2
|
+
function renderJsonStyles() {
|
|
3
|
+
// 核心原则:本地config.json永远最高优先级,加载失败再用CDN官方配置
|
|
4
|
+
const localConfigUrl = './config.json'; // 本地用户自定义配置
|
|
5
|
+
const cdnConfigUrl = 'https://cdn.jsdelivr.net/npm/xiangjsoncraft@1.1.1/config.json'; // CDN兜底配置
|
|
6
|
+
|
|
7
|
+
// 先尝试加载本地config.json
|
|
8
|
+
fetch(localConfigUrl)
|
|
9
|
+
.then(response => {
|
|
10
|
+
// 本地配置存在(状态码200),则使用本地配置
|
|
11
|
+
if (response.ok) {
|
|
12
|
+
console.log('🔧 检测到本地config.json,优先加载用户自定义配置');
|
|
13
|
+
return response.json();
|
|
14
|
+
}
|
|
15
|
+
// 本地配置不存在/加载失败,切换到CDN兜底配置
|
|
16
|
+
console.log('ℹ️ 本地未检测到config.json,加载CDN官方示例配置');
|
|
17
|
+
return fetch(cdnConfigUrl).then(res => {
|
|
18
|
+
if (!res.ok) throw new Error('CDN官方配置加载失败');
|
|
19
|
+
return res.json();
|
|
20
|
+
});
|
|
21
|
+
})
|
|
22
|
+
.then(config => {
|
|
23
|
+
// 获取或创建样式块,避免重复创建
|
|
24
|
+
const styleBlock = document.getElementById('dynamic-styles') || createStyleBlock();
|
|
25
|
+
if (!styleBlock) return console.error('❌ 样式块创建失败,无法渲染样式');
|
|
26
|
+
|
|
27
|
+
// 生成CSS规则
|
|
28
|
+
let cssRules = '';
|
|
29
|
+
|
|
30
|
+
// 处理所有选择器样式(支持任意CSS选择器、媒体查询)
|
|
31
|
+
if (config.styles && typeof config.styles === 'object' && Object.keys(config.styles).length > 0) {
|
|
32
|
+
// 遍历所有选择器(类、ID、伪类、媒体查询等)
|
|
33
|
+
Object.entries(config.styles).forEach(([selector, styles]) => {
|
|
34
|
+
// 过滤空样式,避免无效CSS
|
|
35
|
+
if (!styles || typeof styles !== 'object') return;
|
|
36
|
+
// 生成该选择器的所有样式属性
|
|
37
|
+
const styleProperties = Object.entries(styles)
|
|
38
|
+
.map(([prop, value]) => {
|
|
39
|
+
// 过滤空属性,驼峰式属性名转换为CSS标准格式
|
|
40
|
+
if (!prop || value === undefined || value === null) return '';
|
|
41
|
+
const cssProp = prop.replaceCamelCase();
|
|
42
|
+
return `${cssProp}: ${value};`;
|
|
43
|
+
})
|
|
44
|
+
.filter(Boolean) // 移除空属性
|
|
45
|
+
.join('\n ');
|
|
46
|
+
|
|
47
|
+
// 仅当有样式属性时,添加到CSS规则
|
|
48
|
+
if (styleProperties) {
|
|
49
|
+
cssRules += `${selector} {\n ${styleProperties}\n}\n\n`;
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// 应用生成的CSS规则到样式块
|
|
55
|
+
if (cssRules) {
|
|
56
|
+
styleBlock.innerHTML = cssRules;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// 处理内容配置(支持纯文本/HTML内容,通过isHtml标识)
|
|
60
|
+
if (config.content && typeof config.content === 'object' && Object.keys(config.content).length > 0) {
|
|
61
|
+
Object.entries(config.content).forEach(([selector, content]) => {
|
|
62
|
+
// 过滤无效选择器和内容
|
|
63
|
+
if (!selector || !content || !content.hasOwnProperty('value')) return;
|
|
64
|
+
const elements = document.querySelectorAll(selector);
|
|
65
|
+
elements.forEach(el => {
|
|
66
|
+
if (!el) return;
|
|
67
|
+
// 支持HTML内容或纯文本,默认纯文本
|
|
68
|
+
if (content.isHtml) {
|
|
69
|
+
el.innerHTML = content.value;
|
|
70
|
+
} else {
|
|
71
|
+
el.textContent = content.value;
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
console.log('✅ XiangJsonCraft v1.1.1 渲染成功!');
|
|
78
|
+
})
|
|
79
|
+
.catch(error => {
|
|
80
|
+
console.error('❌ XiangJsonCraft 处理配置时出错:', error.message);
|
|
81
|
+
});
|
|
82
|
+
}exports.renderJsonStyles=renderJsonStyles;}));
|
package/package.json
CHANGED
|
@@ -1,21 +1,33 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xiangjsoncraft",
|
|
3
|
-
"version": "1.1.
|
|
4
|
-
"description": "
|
|
5
|
-
"main": "
|
|
3
|
+
"version": "1.1.2",
|
|
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
|
-
"
|
|
8
|
-
"dev": "npx
|
|
16
|
+
"build": "rollup -c",
|
|
17
|
+
"dev": "npx serve ."
|
|
18
|
+
},
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"rollup": "^4.12.0"
|
|
9
21
|
},
|
|
10
22
|
"keywords": [
|
|
11
|
-
"json",
|
|
12
|
-
"css",
|
|
13
|
-
"html",
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
23
|
+
"json-render",
|
|
24
|
+
"dynamic-css",
|
|
25
|
+
"html-render",
|
|
26
|
+
"json-config",
|
|
27
|
+
"frontend-tool",
|
|
28
|
+
"xiangjsoncraft"
|
|
17
29
|
],
|
|
18
|
-
"author": "",
|
|
30
|
+
"author": "董翔 <3631247406@qq.com>",
|
|
19
31
|
"license": "MIT",
|
|
20
|
-
"
|
|
32
|
+
"homepage": "https://www.npmjs.com/package/xiangjsoncraft"
|
|
21
33
|
}
|
package/renderJson.js
CHANGED
|
@@ -1,97 +1,82 @@
|
|
|
1
|
-
//
|
|
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
|
-
// 渲染图标函数
|
|
17
|
-
function renderIcons(selector, icons) {
|
|
18
|
-
const container = document.querySelector(selector);
|
|
19
|
-
if (!container) return;
|
|
20
|
-
|
|
21
|
-
container.innerHTML = icons.map(icon => `
|
|
22
|
-
<a href="${icon.url}" class="social-icon" target="_blank" rel="noopener">
|
|
23
|
-
<i class="${icon.class}"></i>
|
|
24
|
-
</a>
|
|
25
|
-
`).join('');
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// 渲染特性卡片函数
|
|
29
|
-
function renderFeatureCards(selectorPrefix, features) {
|
|
30
|
-
features.forEach((feature, index) => {
|
|
31
|
-
const card = document.querySelector(`${selectorPrefix}-${index + 1}`);
|
|
32
|
-
if (card) {
|
|
33
|
-
card.innerHTML = `
|
|
34
|
-
<div class="feature-icon"><i class="${feature.iconClass}"></i></div>
|
|
35
|
-
<h3 class="feature-title">${feature.title}</h3>
|
|
36
|
-
<p class="feature-description">${feature.description}</p>
|
|
37
|
-
`;
|
|
38
|
-
}
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// 主渲染函数
|
|
1
|
+
// 封装通用JSON样式渲染函数,支持任意CSS选择器、HTML内容、媒体查询(v1.1.0核心功能)
|
|
43
2
|
export function renderJsonStyles() {
|
|
44
|
-
|
|
3
|
+
// 核心原则:本地config.json永远最高优先级,加载失败再用CDN官方配置
|
|
4
|
+
const localConfigUrl = './config.json'; // 本地用户自定义配置
|
|
5
|
+
const cdnConfigUrl = 'https://cdn.jsdelivr.net/npm/xiangjsoncraft@1.1.1/config.json'; // CDN兜底配置
|
|
6
|
+
|
|
7
|
+
// 先尝试加载本地config.json
|
|
8
|
+
fetch(localConfigUrl)
|
|
45
9
|
.then(response => {
|
|
46
|
-
|
|
47
|
-
|
|
10
|
+
// 本地配置存在(状态码200),则使用本地配置
|
|
11
|
+
if (response.ok) {
|
|
12
|
+
console.log('🔧 检测到本地config.json,优先加载用户自定义配置');
|
|
13
|
+
return response.json();
|
|
48
14
|
}
|
|
49
|
-
|
|
15
|
+
// 本地配置不存在/加载失败,切换到CDN兜底配置
|
|
16
|
+
console.log('ℹ️ 本地未检测到config.json,加载CDN官方示例配置');
|
|
17
|
+
return fetch(cdnConfigUrl).then(res => {
|
|
18
|
+
if (!res.ok) throw new Error('CDN官方配置加载失败');
|
|
19
|
+
return res.json();
|
|
20
|
+
});
|
|
50
21
|
})
|
|
51
22
|
.then(config => {
|
|
23
|
+
// 获取或创建样式块,避免重复创建
|
|
52
24
|
const styleBlock = document.getElementById('dynamic-styles') || createStyleBlock();
|
|
25
|
+
if (!styleBlock) return console.error('❌ 样式块创建失败,无法渲染样式');
|
|
26
|
+
|
|
27
|
+
// 生成CSS规则
|
|
53
28
|
let cssRules = '';
|
|
54
|
-
|
|
55
|
-
//
|
|
56
|
-
if (config.styles && typeof config.styles === 'object') {
|
|
29
|
+
|
|
30
|
+
// 处理所有选择器样式(支持任意CSS选择器、媒体查询)
|
|
31
|
+
if (config.styles && typeof config.styles === 'object' && Object.keys(config.styles).length > 0) {
|
|
32
|
+
// 遍历所有选择器(类、ID、伪类、媒体查询等)
|
|
57
33
|
Object.entries(config.styles).forEach(([selector, styles]) => {
|
|
34
|
+
// 过滤空样式,避免无效CSS
|
|
35
|
+
if (!styles || typeof styles !== 'object') return;
|
|
36
|
+
// 生成该选择器的所有样式属性
|
|
58
37
|
const styleProperties = Object.entries(styles)
|
|
59
|
-
.map(([prop, value]) =>
|
|
38
|
+
.map(([prop, value]) => {
|
|
39
|
+
// 过滤空属性,驼峰式属性名转换为CSS标准格式
|
|
40
|
+
if (!prop || value === undefined || value === null) return '';
|
|
41
|
+
const cssProp = prop.replaceCamelCase();
|
|
42
|
+
return `${cssProp}: ${value};`;
|
|
43
|
+
})
|
|
44
|
+
.filter(Boolean) // 移除空属性
|
|
60
45
|
.join('\n ');
|
|
61
|
-
|
|
62
|
-
|
|
46
|
+
|
|
47
|
+
// 仅当有样式属性时,添加到CSS规则
|
|
48
|
+
if (styleProperties) {
|
|
49
|
+
cssRules += `${selector} {\n ${styleProperties}\n}\n\n`;
|
|
50
|
+
}
|
|
63
51
|
});
|
|
64
52
|
}
|
|
65
|
-
|
|
66
|
-
//
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
53
|
+
|
|
54
|
+
// 应用生成的CSS规则到样式块
|
|
55
|
+
if (cssRules) {
|
|
56
|
+
styleBlock.innerHTML = cssRules;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// 处理内容配置(支持纯文本/HTML内容,通过isHtml标识)
|
|
60
|
+
if (config.content && typeof config.content === 'object' && Object.keys(config.content).length > 0) {
|
|
71
61
|
Object.entries(config.content).forEach(([selector, content]) => {
|
|
62
|
+
// 过滤无效选择器和内容
|
|
63
|
+
if (!selector || !content || !content.hasOwnProperty('value')) return;
|
|
72
64
|
const elements = document.querySelectorAll(selector);
|
|
73
65
|
elements.forEach(el => {
|
|
74
|
-
el
|
|
66
|
+
if (!el) return;
|
|
67
|
+
// 支持HTML内容或纯文本,默认纯文本
|
|
68
|
+
if (content.isHtml) {
|
|
69
|
+
el.innerHTML = content.value;
|
|
70
|
+
} else {
|
|
71
|
+
el.textContent = content.value;
|
|
72
|
+
}
|
|
75
73
|
});
|
|
76
74
|
});
|
|
77
75
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
if (config.icons) {
|
|
81
|
-
renderIcons(config.icons.selector, config.icons.items);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// 渲染特性卡片
|
|
85
|
-
if (config.features) {
|
|
86
|
-
renderFeatureCards(config.features.selectorPrefix, config.features.items);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// 添加页面载入动画类
|
|
90
|
-
document.body.classList.add('loaded');
|
|
91
|
-
|
|
76
|
+
|
|
77
|
+
console.log('✅ XiangJsonCraft v1.1.1 渲染成功!');
|
|
92
78
|
})
|
|
93
79
|
.catch(error => {
|
|
94
|
-
console.error('处理配置时出错:', error);
|
|
80
|
+
console.error('❌ XiangJsonCraft 处理配置时出错:', error.message);
|
|
95
81
|
});
|
|
96
|
-
}
|
|
97
|
-
|
|
82
|
+
}
|
package/index.html
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
|
|
4
|
-
<head>
|
|
5
|
-
<meta charset="UTF-8">
|
|
6
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
|
-
<title>Welcome Page</title>
|
|
8
|
-
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
|
9
|
-
<style id="dynamic-styles"></style>
|
|
10
|
-
</head>
|
|
11
|
-
|
|
12
|
-
<body>
|
|
13
|
-
<div class="welcome-container">
|
|
14
|
-
<header class="welcome-header">
|
|
15
|
-
<div class="logo-container">
|
|
16
|
-
<div class="logo"></div>
|
|
17
|
-
</div>
|
|
18
|
-
<h1 class="main-title"></h1>
|
|
19
|
-
<p class="subtitle"></p>
|
|
20
|
-
</header>
|
|
21
|
-
|
|
22
|
-
<main class="features-section">
|
|
23
|
-
<div class="feature-card" id="feature-1"></div>
|
|
24
|
-
<div class="feature-card" id="feature-2"></div>
|
|
25
|
-
<div class="feature-card" id="feature-3"></div>
|
|
26
|
-
</main>
|
|
27
|
-
|
|
28
|
-
<section class="action-section">
|
|
29
|
-
<a href="https://www.npmjs.com/package/xiangjsoncraft">
|
|
30
|
-
<button class="primary-button"></button>
|
|
31
|
-
</a>
|
|
32
|
-
<p class="additional-info"></p>
|
|
33
|
-
</section>
|
|
34
|
-
|
|
35
|
-
<footer class="page-footer">
|
|
36
|
-
<p class="copyright"></p>
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
<div class="social-links">
|
|
40
|
-
</div>
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
</footer>
|
|
44
|
-
</div>
|
|
45
|
-
|
|
46
|
-
<script type="module">
|
|
47
|
-
import { renderJsonStyles } from './renderJson.js';
|
|
48
|
-
// 页面加载完成后渲染
|
|
49
|
-
window.addEventListener('DOMContentLoaded', renderJsonStyles);
|
|
50
|
-
</script>
|
|
51
|
-
</body>
|
|
52
|
-
|
|
53
|
-
</html>
|