@flun/html-template 4.2.2 → 4.3.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/compile.js +197 -190
- package/customize/hotReloadInjector.js +22 -22
- package/dev-server.js +95 -143
- package/dev.js +12 -1
- package/f-CHANGELOG.md +15 -2
- package/f-README.md +66 -7
- package/index.d.ts +24 -7
- package/package.json +4 -4
- package/services/middleware.js +31 -0
- package/services/templateService.js +147 -3
- package/static/auth.js +1 -1
|
@@ -105,8 +105,152 @@ const writtenFilesToIgnore = [], userFeatures = {}, includedFiles = new Set(),
|
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
return String(value);
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* 解析并验证端口值
|
|
112
|
+
* @param {string|number} portValue - 端口值
|
|
113
|
+
* @param {string} source - 来源描述(用于错误消息)
|
|
114
|
+
* @returns {number} 有效的端口号或默认值
|
|
115
|
+
*/
|
|
116
|
+
_parseAndValidatePort = (portValue, source) => {
|
|
117
|
+
const portNum = parseInt(portValue);
|
|
118
|
+
if (!isNaN(portNum) && portNum > 0 && portNum < 65536) return portNum;
|
|
119
|
+
console.warn(`警告: ${source} "${portValue}" 无效,已启用默认端口:${defaultPort}`);
|
|
120
|
+
return defaultPort;
|
|
108
121
|
};
|
|
109
122
|
|
|
123
|
+
/**
|
|
124
|
+
* 统一服务器配置解析函数(与 dev-server.js 完全一致)
|
|
125
|
+
*
|
|
126
|
+
* 配置解析优先级:
|
|
127
|
+
* 端口:
|
|
128
|
+
* 1. 命令行参数 (--port 或 -p)
|
|
129
|
+
* 2. 函数参数 (options.port)
|
|
130
|
+
* 3. 环境变量 (process.env.PORT)
|
|
131
|
+
* 4. 默认值 (常量 defaultPort)
|
|
132
|
+
*
|
|
133
|
+
* 主机名:
|
|
134
|
+
* 1. 命令行参数 (--host 或 -H)
|
|
135
|
+
* 2. 函数参数 (options.host)
|
|
136
|
+
* 3. 环境变量 (process.env.HOST)
|
|
137
|
+
* 4. 默认值 ("localhost")
|
|
138
|
+
*
|
|
139
|
+
* 热重载:
|
|
140
|
+
* 1. 命令行参数 (--hot-reload/--no-hot-reload)
|
|
141
|
+
* 2. 函数参数 (options.hotReload)
|
|
142
|
+
* 3. 环境变量 (process.env.HOTRELOAD)
|
|
143
|
+
* 4. 默认值 (true)
|
|
144
|
+
*
|
|
145
|
+
* 登录模式:
|
|
146
|
+
* 1. 命令行参数 (--account/--no-account)
|
|
147
|
+
* 2. 函数参数 (options.account)
|
|
148
|
+
* 3. 环境变量 (process.env.ACCOUNT)
|
|
149
|
+
* 4. 默认值 (false)
|
|
150
|
+
*
|
|
151
|
+
* HTTPS:
|
|
152
|
+
* 1. 命令行参数 (--https/--no-https)
|
|
153
|
+
* 2. 函数参数 (options.https)
|
|
154
|
+
* 3. 环境变量 (process.env.HTTPS === 'true')
|
|
155
|
+
* 4. 默认值 (false)
|
|
156
|
+
*
|
|
157
|
+
* HTTPS证书路径(仅在启用HTTPS时必须提供):
|
|
158
|
+
* 1. 命令行参数 (--https-key, --https-cert)
|
|
159
|
+
* 2. 函数参数 (options.httpsKey, options.httpsCert)
|
|
160
|
+
* 3. 环境变量 (process.env.HTTPS_KEY, process.env.HTTPS_CERT)
|
|
161
|
+
* 4. 若仍未提供,启动时抛出错误
|
|
162
|
+
*/
|
|
163
|
+
const parseServerConfig = (options = {}, defaults = {}) => {
|
|
164
|
+
let port, host, hotReload, account, httpsEnabled, httpsKeyPath, httpsCertPath;
|
|
165
|
+
|
|
166
|
+
const args = process.argv.slice(2),
|
|
167
|
+
portArgIndex = args.findIndex(arg => arg === '--port' || arg === '-p'),
|
|
168
|
+
portArgValue = portArgIndex !== -1 ? args[portArgIndex + 1] : null,
|
|
169
|
+
hostArgIndex = args.findIndex(arg => arg === '--host' || arg === '-H'),
|
|
170
|
+
hostArgValue = hostArgIndex !== -1 ? args[hostArgIndex + 1] : null,
|
|
171
|
+
{ port: P, host: H, hotReload: Hot, account: Acc, https: Https, httpsKey: Key, httpsCert: Cert } = options;
|
|
172
|
+
|
|
173
|
+
// 解析端口
|
|
174
|
+
if (portArgValue) port = _parseAndValidatePort(portArgValue, '命令行参数');
|
|
175
|
+
else if (P !== undefined) port = _parseAndValidatePort(P, '函数参数');
|
|
176
|
+
else if (process.env.PORT) port = _parseAndValidatePort(process.env.PORT, '环境变量 PORT');
|
|
177
|
+
else if (defaults.port !== undefined) port = _parseAndValidatePort(defaults.port, '持久化配置');
|
|
178
|
+
else port = defaultPort;
|
|
179
|
+
|
|
180
|
+
// 解析主机名
|
|
181
|
+
if (hostArgValue) host = hostArgValue;
|
|
182
|
+
else if (H !== undefined) host = H;
|
|
183
|
+
else if (process.env.HOST) host = process.env.HOST;
|
|
184
|
+
else if (defaults.host !== undefined) host = defaults.host;
|
|
185
|
+
else host = 'localhost';
|
|
186
|
+
|
|
187
|
+
// 解析热重载
|
|
188
|
+
if (args.includes('--hot-reload')) hotReload = true;
|
|
189
|
+
else if (args.includes('--no-hot-reload')) hotReload = false;
|
|
190
|
+
else if (Hot !== undefined) hotReload = Hot;
|
|
191
|
+
else if (process.env.HOTRELOAD) hotReload = process.env.HOTRELOAD === 'true';
|
|
192
|
+
else if (defaults.hotReload !== undefined) hotReload = defaults.hotReload;
|
|
193
|
+
else hotReload = true;
|
|
194
|
+
|
|
195
|
+
// 解析登录模式
|
|
196
|
+
if (args.includes('--account')) account = true;
|
|
197
|
+
else if (args.includes('--no-account')) account = false;
|
|
198
|
+
else if (Acc !== undefined) account = Acc;
|
|
199
|
+
else if (process.env.ACCOUNT) account = process.env.ACCOUNT === 'true';
|
|
200
|
+
else if (defaults.account !== undefined) account = defaults.account;
|
|
201
|
+
else account = false;
|
|
202
|
+
|
|
203
|
+
// 解析HTTPS
|
|
204
|
+
if (args.includes('--https')) httpsEnabled = true;
|
|
205
|
+
else if (args.includes('--no-https')) httpsEnabled = false;
|
|
206
|
+
else if (Https !== undefined) httpsEnabled = Https;
|
|
207
|
+
else if (process.env.HTTPS) httpsEnabled = process.env.HTTPS === 'true';
|
|
208
|
+
else if (defaults.https !== undefined) httpsEnabled = defaults.https;
|
|
209
|
+
else httpsEnabled = false;
|
|
210
|
+
|
|
211
|
+
// 解析HTTPS证书路径(只有在 httpsEnabled 为 true 时才需要)
|
|
212
|
+
if (httpsEnabled) {
|
|
213
|
+
const keyArgIndex = args.findIndex(arg => arg === '--https-key');
|
|
214
|
+
if (keyArgIndex !== -1 && args[keyArgIndex + 1]) httpsKeyPath = args[keyArgIndex + 1];
|
|
215
|
+
else if (Key) httpsKeyPath = Key;
|
|
216
|
+
else if (process.env.HTTPS_KEY) httpsKeyPath = process.env.HTTPS_KEY;
|
|
217
|
+
else if (defaults.httpsKey) httpsKeyPath = defaults.httpsKey;
|
|
218
|
+
|
|
219
|
+
const certArgIndex = args.findIndex(arg => arg === '--https-cert');
|
|
220
|
+
if (certArgIndex !== -1 && args[certArgIndex + 1]) httpsCertPath = args[certArgIndex + 1];
|
|
221
|
+
else if (Cert) httpsCertPath = Cert;
|
|
222
|
+
else if (process.env.HTTPS_CERT) httpsCertPath = process.env.HTTPS_CERT;
|
|
223
|
+
else if (defaults.httpsCert) httpsCertPath = defaults.httpsCert;
|
|
224
|
+
|
|
225
|
+
if (!httpsKeyPath || !httpsCertPath) {
|
|
226
|
+
console.error('❌ 启用HTTPS时必须同时提供证书私钥路径和证书文件路径!');
|
|
227
|
+
console.error(' 请通过以下方式之一指定:');
|
|
228
|
+
console.error(' 1. 命令行: --https-key <path> --https-cert <path>');
|
|
229
|
+
console.error(' 2. 环境变量: HTTPS_KEY=<path> HTTPS_CERT=<path>');
|
|
230
|
+
console.error(' 3. 函数参数: { httpsKey: "...", httpsCert: "..." }');
|
|
231
|
+
console.error(' 4. 持久化配置文件 (.last-dev-config.json)');
|
|
232
|
+
process.exit(1);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
return { port, host, hotReload, account, httpsEnabled, httpsKeyPath, httpsCertPath };
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* 生成页面URL(支持HTTP/HTTPS和自定义主机名)
|
|
241
|
+
* @param {string} page - 页面文件名
|
|
242
|
+
* @param {number} port - 端口号
|
|
243
|
+
* @param {boolean} useHttps - 是否使用HTTPS
|
|
244
|
+
* @param {string} host - 主机名
|
|
245
|
+
* @returns {object} { url, encodedUrl, needsEncoding }
|
|
246
|
+
*/
|
|
247
|
+
const generateUrls = (page, port, useHttps, host) => {
|
|
248
|
+
const protocol = useHttps ? 'https' : 'http', baseUrl = `${protocol}://${host}:${port}`,
|
|
249
|
+
url = `${baseUrl}/${page}`, needsEncoding = !/^[a-zA-Z0-9\-_.~/]+$/.test(page);
|
|
250
|
+
|
|
251
|
+
return { url, encodedUrl: `${baseUrl}/${encodeURI(page)}`, needsEncoding };
|
|
252
|
+
};
|
|
253
|
+
|
|
110
254
|
/**
|
|
111
255
|
* 动态识别入口文件(优先级策略)
|
|
112
256
|
* 1. 查找包含\<!-- \@entry -->标记的文件
|
|
@@ -974,7 +1118,7 @@ const renderTemplate = async templateFile => {
|
|
|
974
1118
|
|
|
975
1119
|
// ==================== 9. 模块功能导出 ====================
|
|
976
1120
|
export {
|
|
977
|
-
path, fsPromises, CWD, templatesDir, templatesAbsDir, staticDir, customizeDir, accountDir,
|
|
978
|
-
getAvailableTemplates,
|
|
979
|
-
getIncludedFiles, processVariables, loadUserFeatures, monitorFileWrites
|
|
1121
|
+
path, fsPromises, CWD, templatesDir, templatesAbsDir, staticDir, customizeDir, accountDir, writtenFilesToIgnore,
|
|
1122
|
+
getAvailableTemplates, parseServerConfig, generateUrls, findEntryFile, validateTemplateFile, renderTemplate,
|
|
1123
|
+
processIncludes, setCompilationMode, getIncludedFiles, processVariables, loadUserFeatures, monitorFileWrites
|
|
980
1124
|
};
|
package/static/auth.js
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
if (data?.username) {
|
|
14
14
|
userCenter.style.display = 'flex';
|
|
15
15
|
const link = userCenter.querySelector('a');
|
|
16
|
-
if (link) link.innerHTML =
|
|
16
|
+
if (link) link.innerHTML = `👽 ${data.username}`;
|
|
17
17
|
document.dispatchEvent(new CustomEvent('userCenterReady')); // 创建并派发自定义事件,通知用户中心已准备好
|
|
18
18
|
}
|
|
19
19
|
else userCenter.style.display = 'none';
|