@mdfriday/foundry 26.3.7 → 26.3.9
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/dist/cli.js +431 -122
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/internal/application/container.d.ts +9 -0
- package/dist/internal/application/index.d.ts +4 -0
- package/dist/internal/application/publish.d.ts +8 -9
- package/dist/internal/application/workspace.d.ts +11 -0
- package/dist/internal/domain/workspace/entity/project.d.ts +19 -0
- package/dist/internal/domain/workspace/factory/workspace-factory.d.ts +12 -0
- package/dist/internal/domain/workspace/repository/file-system.d.ts +1 -0
- package/dist/internal/domain/workspace/value-object/project-metadata.d.ts +10 -0
- package/dist/internal/interfaces/cli/commands/publish.d.ts +1 -11
- package/dist/internal/interfaces/cli/container.d.ts +1 -7
- package/dist/internal/interfaces/cli/types.d.ts +1 -2
- package/dist/internal/interfaces/obsidian/auth.d.ts +5 -5
- package/dist/internal/interfaces/obsidian/container.d.ts +4 -4
- package/dist/internal/interfaces/obsidian/domain.d.ts +5 -5
- package/dist/internal/interfaces/obsidian/index.d.ts +3 -1
- package/dist/internal/interfaces/obsidian/license.d.ts +5 -7
- package/dist/internal/interfaces/obsidian/publish.d.ts +3 -2
- package/dist/internal/interfaces/obsidian/serve.d.ts +6 -4
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -118,6 +118,7 @@ var init_project_metadata = __esm({
|
|
|
118
118
|
contentLinks;
|
|
119
119
|
staticLink;
|
|
120
120
|
fileLink;
|
|
121
|
+
baseURLStructure;
|
|
121
122
|
constructor(data) {
|
|
122
123
|
this.id = data.id;
|
|
123
124
|
this.name = data.name;
|
|
@@ -129,6 +130,7 @@ var init_project_metadata = __esm({
|
|
|
129
130
|
this.contentLinks = data.contentLinks || [];
|
|
130
131
|
this.staticLink = data.staticLink || null;
|
|
131
132
|
this.fileLink = data.fileLink || null;
|
|
133
|
+
this.baseURLStructure = data.baseURLStructure || null;
|
|
132
134
|
}
|
|
133
135
|
static create(data) {
|
|
134
136
|
if (!data.id || !data.name) {
|
|
@@ -168,6 +170,9 @@ var init_project_metadata = __esm({
|
|
|
168
170
|
if (this.fileLink) {
|
|
169
171
|
result.fileLink = this.fileLink;
|
|
170
172
|
}
|
|
173
|
+
if (this.baseURLStructure) {
|
|
174
|
+
result.baseURLStructure = this.baseURLStructure;
|
|
175
|
+
}
|
|
171
176
|
return result;
|
|
172
177
|
}
|
|
173
178
|
};
|
|
@@ -1337,6 +1342,80 @@ var init_project = __esm({
|
|
|
1337
1342
|
}
|
|
1338
1343
|
return linkDirs;
|
|
1339
1344
|
}
|
|
1345
|
+
// ============================================================================
|
|
1346
|
+
// baseURL Structure Management
|
|
1347
|
+
// ============================================================================
|
|
1348
|
+
/**
|
|
1349
|
+
* 获取 baseURL(从 Hugo config.json)
|
|
1350
|
+
*/
|
|
1351
|
+
async getBaseURL() {
|
|
1352
|
+
const config = await this.loadConfig();
|
|
1353
|
+
return config.baseURL || "/";
|
|
1354
|
+
}
|
|
1355
|
+
/**
|
|
1356
|
+
* 设置 baseURL(更新 Hugo config.json)
|
|
1357
|
+
*/
|
|
1358
|
+
async setBaseURL(baseURL) {
|
|
1359
|
+
const config = await this.loadConfig();
|
|
1360
|
+
config.baseURL = baseURL;
|
|
1361
|
+
const configPath = import_path2.default.join(this.projectPath, "config.json");
|
|
1362
|
+
await import_fs.promises.writeFile(configPath, JSON.stringify(config, null, 2), "utf-8");
|
|
1363
|
+
this.config = config;
|
|
1364
|
+
}
|
|
1365
|
+
/**
|
|
1366
|
+
* 解析 baseURL 路径信息
|
|
1367
|
+
*/
|
|
1368
|
+
parseBaseURLPath(baseURL) {
|
|
1369
|
+
let normalized = baseURL.trim();
|
|
1370
|
+
if (normalized.startsWith("/")) {
|
|
1371
|
+
normalized = normalized.slice(1);
|
|
1372
|
+
}
|
|
1373
|
+
if (normalized.endsWith("/")) {
|
|
1374
|
+
normalized = normalized.slice(0, -1);
|
|
1375
|
+
}
|
|
1376
|
+
if (normalized === "") {
|
|
1377
|
+
return {
|
|
1378
|
+
isRoot: true,
|
|
1379
|
+
pathParts: [],
|
|
1380
|
+
parentParts: [],
|
|
1381
|
+
finalDirName: "",
|
|
1382
|
+
relativeToPublic: "."
|
|
1383
|
+
};
|
|
1384
|
+
}
|
|
1385
|
+
const parts = normalized.split("/").filter((p2) => p2 !== "");
|
|
1386
|
+
if (parts.length === 0) {
|
|
1387
|
+
return {
|
|
1388
|
+
isRoot: true,
|
|
1389
|
+
pathParts: [],
|
|
1390
|
+
parentParts: [],
|
|
1391
|
+
finalDirName: "",
|
|
1392
|
+
relativeToPublic: "."
|
|
1393
|
+
};
|
|
1394
|
+
}
|
|
1395
|
+
const depth = parts.length;
|
|
1396
|
+
const relativeToPublic = depth === 1 ? "." : "../".repeat(depth - 1).slice(0, -1);
|
|
1397
|
+
return {
|
|
1398
|
+
isRoot: false,
|
|
1399
|
+
pathParts: parts,
|
|
1400
|
+
parentParts: parts.slice(0, -1),
|
|
1401
|
+
finalDirName: parts[parts.length - 1],
|
|
1402
|
+
relativeToPublic
|
|
1403
|
+
};
|
|
1404
|
+
}
|
|
1405
|
+
/**
|
|
1406
|
+
* 获取当前 baseURL 结构信息
|
|
1407
|
+
*/
|
|
1408
|
+
getBaseURLStructure() {
|
|
1409
|
+
return this.metadata.baseURLStructure || null;
|
|
1410
|
+
}
|
|
1411
|
+
/**
|
|
1412
|
+
* 更新 baseURL 结构记录
|
|
1413
|
+
*/
|
|
1414
|
+
updateBaseURLStructure(info) {
|
|
1415
|
+
this.metadata = this.metadata.update({
|
|
1416
|
+
baseURLStructure: info
|
|
1417
|
+
});
|
|
1418
|
+
}
|
|
1340
1419
|
};
|
|
1341
1420
|
}
|
|
1342
1421
|
});
|
|
@@ -3303,7 +3382,8 @@ var init_workspace_factory = __esm({
|
|
|
3303
3382
|
});
|
|
3304
3383
|
const defaultTheme = options.theme || "https://gohugo.net/quartz-theme.zip?version=1.2";
|
|
3305
3384
|
const config = {
|
|
3306
|
-
baseURL: "/",
|
|
3385
|
+
baseURL: options.baseURL || "/",
|
|
3386
|
+
// 新增:使用传入的 baseURL
|
|
3307
3387
|
title: name,
|
|
3308
3388
|
contentDir,
|
|
3309
3389
|
publishDir,
|
|
@@ -3792,6 +3872,154 @@ var init_workspace_factory = __esm({
|
|
|
3792
3872
|
// ============================================================================
|
|
3793
3873
|
// Private Helpers
|
|
3794
3874
|
// ============================================================================
|
|
3875
|
+
// ============================================================================
|
|
3876
|
+
// baseURL Structure Management
|
|
3877
|
+
// ============================================================================
|
|
3878
|
+
/**
|
|
3879
|
+
* 在 public/ 目录下创建 baseURL 访问路径结构
|
|
3880
|
+
*
|
|
3881
|
+
* 例如:baseURL = "/blog/" 时,在 public/ 下创建 blog/ -> . (symlink)
|
|
3882
|
+
*/
|
|
3883
|
+
async setupBaseURLStructure(project) {
|
|
3884
|
+
if (!this.fileSystemRepo) {
|
|
3885
|
+
throw new Error("FileSystemRepository is required for baseURL structure");
|
|
3886
|
+
}
|
|
3887
|
+
const baseURL = await project.getBaseURL();
|
|
3888
|
+
const pathInfo = project.parseBaseURLPath(baseURL);
|
|
3889
|
+
const projectRoot = project.getPath();
|
|
3890
|
+
const publicDir = import_path3.default.join(projectRoot, "public");
|
|
3891
|
+
if (pathInfo.isRoot) {
|
|
3892
|
+
log5.debug("baseURL is root, no structure needed");
|
|
3893
|
+
return {
|
|
3894
|
+
serverRoot: publicDir,
|
|
3895
|
+
baseURL: "/",
|
|
3896
|
+
symlinkCreated: false
|
|
3897
|
+
};
|
|
3898
|
+
}
|
|
3899
|
+
log5.info("Creating baseURL structure in public/", {
|
|
3900
|
+
baseURL,
|
|
3901
|
+
pathParts: pathInfo.pathParts
|
|
3902
|
+
});
|
|
3903
|
+
let currentDir = publicDir;
|
|
3904
|
+
for (const dirName of pathInfo.parentParts) {
|
|
3905
|
+
currentDir = import_path3.default.join(currentDir, dirName);
|
|
3906
|
+
if (!await this.fileSystemRepo.exists(currentDir)) {
|
|
3907
|
+
await this.fileSystemRepo.createDirectory(currentDir, false);
|
|
3908
|
+
log5.debug(`Created parent directory: ${dirName}`);
|
|
3909
|
+
}
|
|
3910
|
+
}
|
|
3911
|
+
const symlinkPath = import_path3.default.join(currentDir, pathInfo.finalDirName);
|
|
3912
|
+
if (await this.fileSystemRepo.exists(symlinkPath)) {
|
|
3913
|
+
await this.fileSystemRepo.remove(symlinkPath, true);
|
|
3914
|
+
log5.debug(`Removed existing symlink: ${symlinkPath}`);
|
|
3915
|
+
}
|
|
3916
|
+
const symlinkResult = await this.fileSystemRepo.createSymlink(
|
|
3917
|
+
pathInfo.relativeToPublic,
|
|
3918
|
+
symlinkPath
|
|
3919
|
+
);
|
|
3920
|
+
if (!symlinkResult.success) {
|
|
3921
|
+
log5.error("Failed to create baseURL symlink", {
|
|
3922
|
+
target: pathInfo.relativeToPublic,
|
|
3923
|
+
link: symlinkPath,
|
|
3924
|
+
error: symlinkResult.error
|
|
3925
|
+
});
|
|
3926
|
+
throw new Error(`Failed to create baseURL structure: ${symlinkResult.error}`);
|
|
3927
|
+
}
|
|
3928
|
+
log5.info("baseURL structure created successfully", {
|
|
3929
|
+
symlinkPath: pathInfo.pathParts.join("/"),
|
|
3930
|
+
target: pathInfo.relativeToPublic
|
|
3931
|
+
});
|
|
3932
|
+
project.updateBaseURLStructure({
|
|
3933
|
+
baseURL,
|
|
3934
|
+
createdAt: Date.now(),
|
|
3935
|
+
pathParts: pathInfo.pathParts
|
|
3936
|
+
});
|
|
3937
|
+
await this.projectRepo.saveProjectMetadata(
|
|
3938
|
+
project.getPath(),
|
|
3939
|
+
project.getMetadata().toJSON()
|
|
3940
|
+
);
|
|
3941
|
+
return {
|
|
3942
|
+
serverRoot: publicDir,
|
|
3943
|
+
baseURL,
|
|
3944
|
+
symlinkCreated: true
|
|
3945
|
+
};
|
|
3946
|
+
}
|
|
3947
|
+
/**
|
|
3948
|
+
* 清理 public/ 下的 baseURL 路径结构
|
|
3949
|
+
*/
|
|
3950
|
+
async cleanBaseURLStructure(project) {
|
|
3951
|
+
if (!this.fileSystemRepo) {
|
|
3952
|
+
return;
|
|
3953
|
+
}
|
|
3954
|
+
const structureInfo = project.getBaseURLStructure();
|
|
3955
|
+
if (!structureInfo || structureInfo.pathParts.length === 0) {
|
|
3956
|
+
return;
|
|
3957
|
+
}
|
|
3958
|
+
const projectRoot = project.getPath();
|
|
3959
|
+
const publicDir = import_path3.default.join(projectRoot, "public");
|
|
3960
|
+
log5.info("Cleaning baseURL structure in public/", {
|
|
3961
|
+
pathParts: structureInfo.pathParts
|
|
3962
|
+
});
|
|
3963
|
+
for (let i = structureInfo.pathParts.length; i > 0; i--) {
|
|
3964
|
+
const targetPath = import_path3.default.join(
|
|
3965
|
+
publicDir,
|
|
3966
|
+
...structureInfo.pathParts.slice(0, i)
|
|
3967
|
+
);
|
|
3968
|
+
if (await this.fileSystemRepo.exists(targetPath)) {
|
|
3969
|
+
await this.fileSystemRepo.remove(targetPath, true);
|
|
3970
|
+
log5.debug(`Removed: ${structureInfo.pathParts.slice(0, i).join("/")}`);
|
|
3971
|
+
}
|
|
3972
|
+
if (i > 1) {
|
|
3973
|
+
const parentPath = import_path3.default.join(
|
|
3974
|
+
publicDir,
|
|
3975
|
+
...structureInfo.pathParts.slice(0, i - 1)
|
|
3976
|
+
);
|
|
3977
|
+
if (await this.fileSystemRepo.exists(parentPath)) {
|
|
3978
|
+
const children = await this.fileSystemRepo.readDirectory(parentPath);
|
|
3979
|
+
if (children.length > 0) {
|
|
3980
|
+
break;
|
|
3981
|
+
}
|
|
3982
|
+
}
|
|
3983
|
+
}
|
|
3984
|
+
}
|
|
3985
|
+
project.updateBaseURLStructure(null);
|
|
3986
|
+
await this.projectRepo.saveProjectMetadata(
|
|
3987
|
+
project.getPath(),
|
|
3988
|
+
project.getMetadata().toJSON()
|
|
3989
|
+
);
|
|
3990
|
+
log5.info("baseURL structure cleaned");
|
|
3991
|
+
}
|
|
3992
|
+
/**
|
|
3993
|
+
* 确保 baseURL 结构正确
|
|
3994
|
+
* 检查 baseURL 是否变化,如需要则重新创建
|
|
3995
|
+
*/
|
|
3996
|
+
async ensureBaseURLStructure(project) {
|
|
3997
|
+
const currentBaseURL = await project.getBaseURL();
|
|
3998
|
+
const structureInfo = project.getBaseURLStructure();
|
|
3999
|
+
const needRecreate = !structureInfo || structureInfo.baseURL !== currentBaseURL;
|
|
4000
|
+
if (needRecreate) {
|
|
4001
|
+
if (structureInfo) {
|
|
4002
|
+
log5.info("baseURL changed, recreating structure", {
|
|
4003
|
+
old: structureInfo.baseURL,
|
|
4004
|
+
new: currentBaseURL
|
|
4005
|
+
});
|
|
4006
|
+
await this.cleanBaseURLStructure(project);
|
|
4007
|
+
}
|
|
4008
|
+
const result = await this.setupBaseURLStructure(project);
|
|
4009
|
+
return {
|
|
4010
|
+
...result,
|
|
4011
|
+
recreated: true
|
|
4012
|
+
};
|
|
4013
|
+
}
|
|
4014
|
+
return {
|
|
4015
|
+
serverRoot: import_path3.default.join(project.getPath(), "public"),
|
|
4016
|
+
baseURL: currentBaseURL,
|
|
4017
|
+
recreated: false
|
|
4018
|
+
};
|
|
4019
|
+
}
|
|
4020
|
+
// ============================================================================
|
|
4021
|
+
// Private Helpers
|
|
4022
|
+
// ============================================================================
|
|
3795
4023
|
createSampleContent() {
|
|
3796
4024
|
return `---
|
|
3797
4025
|
title: Welcome to MDFriday
|
|
@@ -4059,6 +4287,29 @@ Please specify a project name with --project <name>`);
|
|
|
4059
4287
|
createIdentityStorage(workspace) {
|
|
4060
4288
|
return this.workspaceFactory.createIdentityStorage(workspace);
|
|
4061
4289
|
}
|
|
4290
|
+
// ============================================================================
|
|
4291
|
+
// baseURL Structure Management
|
|
4292
|
+
// ============================================================================
|
|
4293
|
+
/**
|
|
4294
|
+
* 设置项目的 baseURL 路径结构
|
|
4295
|
+
* 在 public/ 目录下创建对应的 symlink 结构
|
|
4296
|
+
*/
|
|
4297
|
+
async setupProjectBaseURLStructure(project) {
|
|
4298
|
+
return this.workspaceFactory.setupBaseURLStructure(project);
|
|
4299
|
+
}
|
|
4300
|
+
/**
|
|
4301
|
+
* 清理项目的 baseURL 路径结构
|
|
4302
|
+
*/
|
|
4303
|
+
async cleanProjectBaseURLStructure(project) {
|
|
4304
|
+
return this.workspaceFactory.cleanBaseURLStructure(project);
|
|
4305
|
+
}
|
|
4306
|
+
/**
|
|
4307
|
+
* 确保项目的 baseURL 路径结构正确
|
|
4308
|
+
* 检查 baseURL 是否变化,如需要则重新创建
|
|
4309
|
+
*/
|
|
4310
|
+
async ensureProjectBaseURLStructure(project) {
|
|
4311
|
+
return this.workspaceFactory.ensureBaseURLStructure(project);
|
|
4312
|
+
}
|
|
4062
4313
|
};
|
|
4063
4314
|
}
|
|
4064
4315
|
});
|
|
@@ -8922,20 +9173,15 @@ var init_publish2 = __esm({
|
|
|
8922
9173
|
}
|
|
8923
9174
|
/**
|
|
8924
9175
|
* Publish project to specified platform
|
|
9176
|
+
*
|
|
9177
|
+
* @param project - 项目实例
|
|
9178
|
+
* @param config - 已合并的发布配置(由调用方准备)
|
|
9179
|
+
* @param options - 发布选项
|
|
9180
|
+
* @param onProgress - 进度回调
|
|
8925
9181
|
*/
|
|
8926
|
-
async publish(project,
|
|
8927
|
-
log17.info(`Publishing project: ${project.getName()} to ${
|
|
9182
|
+
async publish(project, config, options, onProgress) {
|
|
9183
|
+
log17.info(`Publishing project: ${project.getName()} to ${config.type}`);
|
|
8928
9184
|
try {
|
|
8929
|
-
const workspace = await this.workspaceService.loadWorkspace();
|
|
8930
|
-
const globalConfig = await workspace.getAllConfig();
|
|
8931
|
-
const publishConfig = WorkspacePublishConfig.fromGlobalConfig(globalConfig);
|
|
8932
|
-
let config;
|
|
8933
|
-
if (options?.config) {
|
|
8934
|
-
const mergedConfig = publishConfig.merge(options.config, method);
|
|
8935
|
-
config = await this.getMethodConfig(mergedConfig, method);
|
|
8936
|
-
} else {
|
|
8937
|
-
config = await this.getMethodConfig(publishConfig, method);
|
|
8938
|
-
}
|
|
8939
9185
|
const publicDir = await project.getPublishDir();
|
|
8940
9186
|
const publisher = this.publisherFactory.create(
|
|
8941
9187
|
project.getId(),
|
|
@@ -8954,27 +9200,59 @@ var init_publish2 = __esm({
|
|
|
8954
9200
|
const result = await publisher.publish(publicDir, publishOptions);
|
|
8955
9201
|
return result;
|
|
8956
9202
|
} catch (error) {
|
|
8957
|
-
log17.error(`Publish failed: ${
|
|
9203
|
+
log17.error(`Publish failed: ${config.type}`, error);
|
|
8958
9204
|
throw error;
|
|
8959
9205
|
}
|
|
8960
9206
|
}
|
|
8961
9207
|
/**
|
|
8962
9208
|
* Test connection
|
|
9209
|
+
*
|
|
9210
|
+
* @param project - 项目实例
|
|
9211
|
+
* @param config - 已合并的发布配置(由调用方准备)
|
|
8963
9212
|
*/
|
|
8964
|
-
async testConnection(project,
|
|
8965
|
-
|
|
9213
|
+
async testConnection(project, config) {
|
|
9214
|
+
log17.info(`Testing ${config.type} connection for project: ${project.getName()}`);
|
|
9215
|
+
try {
|
|
9216
|
+
const publisher = this.publisherFactory.create(
|
|
9217
|
+
project.getId(),
|
|
9218
|
+
project.getPath(),
|
|
9219
|
+
config
|
|
9220
|
+
);
|
|
9221
|
+
if (publisher.testConnection) {
|
|
9222
|
+
return await publisher.testConnection();
|
|
9223
|
+
}
|
|
9224
|
+
return { success: true };
|
|
9225
|
+
} catch (error) {
|
|
9226
|
+
log17.error(`Test connection failed: ${config.type}`, error);
|
|
9227
|
+
return {
|
|
9228
|
+
success: false,
|
|
9229
|
+
error: error.message
|
|
9230
|
+
};
|
|
9231
|
+
}
|
|
9232
|
+
}
|
|
9233
|
+
/**
|
|
9234
|
+
* 准备最终的发布配置
|
|
9235
|
+
*
|
|
9236
|
+
* 配置查找优先级(两级):
|
|
9237
|
+
* 1. 项目配置 (project.config.publish)
|
|
9238
|
+
* 2. 全局配置 (workspace global config)
|
|
9239
|
+
*
|
|
9240
|
+
* @param workspace - Workspace 实例
|
|
9241
|
+
* @param project - Project 实例
|
|
9242
|
+
* @param method - 发布方法
|
|
9243
|
+
* @returns 最终的发布配置
|
|
9244
|
+
*/
|
|
9245
|
+
async prepareFinalConfig(workspace, project, method) {
|
|
8966
9246
|
const globalConfig = await workspace.getAllConfig();
|
|
8967
|
-
|
|
8968
|
-
|
|
8969
|
-
const
|
|
8970
|
-
|
|
8971
|
-
|
|
8972
|
-
|
|
8973
|
-
|
|
8974
|
-
if (publisher.testConnection) {
|
|
8975
|
-
return await publisher.testConnection();
|
|
9247
|
+
let publishConfig = WorkspacePublishConfig.fromGlobalConfig(globalConfig);
|
|
9248
|
+
await project.loadConfig();
|
|
9249
|
+
const projectConfig = project.getConfig();
|
|
9250
|
+
if (projectConfig?.publish) {
|
|
9251
|
+
log17.debug("Merging project publish config");
|
|
9252
|
+
const projectPublishData = projectConfig.publish;
|
|
9253
|
+
publishConfig = publishConfig.merge(projectPublishData, method);
|
|
8976
9254
|
}
|
|
8977
|
-
return
|
|
9255
|
+
return this.getMethodConfig(publishConfig, method, workspace);
|
|
8978
9256
|
}
|
|
8979
9257
|
// ============================================================================
|
|
8980
9258
|
// Private Methods
|
|
@@ -8982,7 +9260,7 @@ var init_publish2 = __esm({
|
|
|
8982
9260
|
/**
|
|
8983
9261
|
* Get method-specific config from WorkspacePublishConfig
|
|
8984
9262
|
*/
|
|
8985
|
-
async getMethodConfig(publishConfig, method) {
|
|
9263
|
+
async getMethodConfig(publishConfig, method, workspace) {
|
|
8986
9264
|
switch (method) {
|
|
8987
9265
|
case "ftp":
|
|
8988
9266
|
const ftpConfig = publishConfig.getFTPConfig();
|
|
@@ -9016,15 +9294,14 @@ var init_publish2 = __esm({
|
|
|
9016
9294
|
const licenseKey = mdConfig.licenseKey || "";
|
|
9017
9295
|
if (!licenseKey) {
|
|
9018
9296
|
throw new Error(
|
|
9019
|
-
"\u274C MDFriday license key is required for publishing.\n\nDifferent licenses deploy to different servers.\nYou must explicitly configure
|
|
9297
|
+
"\u274C MDFriday license key is required for publishing.\n\nDifferent licenses deploy to different servers.\nYou must explicitly configure a license key:\n\nConfigure license globally (recommended):\n mdf config:set publish.mdfriday.licenseKey MDF-XXXX-XXXX-XXXX --global\n\nOr configure for project only:\n mdf config:set publish.mdfriday.licenseKey MDF-XXXX-XXXX-XXXX\n\n\u{1F4A1} Note: License login (mdf license:login) only gets TOKEN.\n Publishing requires explicitly setting a license key."
|
|
9020
9298
|
);
|
|
9021
9299
|
}
|
|
9022
|
-
const workspace = await this.workspaceService.loadWorkspace();
|
|
9023
9300
|
const { createIdentityService: createIdentityService2 } = await Promise.resolve().then(() => (init_container(), container_exports));
|
|
9024
9301
|
let accessToken = null;
|
|
9025
9302
|
let apiUrl = "https://app.mdfriday.com";
|
|
9026
9303
|
try {
|
|
9027
|
-
const identityService = await createIdentityService2();
|
|
9304
|
+
const identityService = await createIdentityService2(workspace.getInfo().path);
|
|
9028
9305
|
await identityService.initialize();
|
|
9029
9306
|
accessToken = identityService.getToken();
|
|
9030
9307
|
const serverConfig = identityService.getServerConfig();
|
|
@@ -9037,33 +9314,30 @@ var init_publish2 = __esm({
|
|
|
9037
9314
|
}
|
|
9038
9315
|
if (!accessToken) {
|
|
9039
9316
|
throw new Error(
|
|
9040
|
-
"\u274C
|
|
9317
|
+
"\u274C Not authenticated.\n\nPlease login first:\n mdf auth:login\n\nOr use license login:\n mdf license:login --key YOUR-LICENSE-KEY"
|
|
9041
9318
|
);
|
|
9042
9319
|
}
|
|
9043
9320
|
return {
|
|
9044
9321
|
type: "mdfriday",
|
|
9045
|
-
deploymentType: mdConfig.type || "share",
|
|
9046
|
-
// Already merged with CLI override
|
|
9047
9322
|
licenseKey,
|
|
9048
|
-
// Required, from merged config
|
|
9049
|
-
enabled: mdConfig.enabled,
|
|
9050
9323
|
accessToken,
|
|
9051
|
-
|
|
9052
|
-
|
|
9053
|
-
|
|
9324
|
+
apiUrl,
|
|
9325
|
+
deploymentType: mdConfig.type || "share",
|
|
9326
|
+
enabled: true
|
|
9054
9327
|
};
|
|
9055
9328
|
default:
|
|
9056
|
-
throw new Error(`
|
|
9329
|
+
throw new Error(`Unsupported publish method: ${method}`);
|
|
9057
9330
|
}
|
|
9058
9331
|
}
|
|
9059
9332
|
};
|
|
9060
9333
|
}
|
|
9061
9334
|
});
|
|
9062
9335
|
|
|
9063
|
-
// internal/
|
|
9336
|
+
// internal/application/container.ts
|
|
9064
9337
|
var container_exports = {};
|
|
9065
9338
|
__export(container_exports, {
|
|
9066
9339
|
createIdentityService: () => createIdentityService,
|
|
9340
|
+
createIdentityServiceForObsidian: () => createIdentityServiceForObsidian,
|
|
9067
9341
|
createPublishAppService: () => createPublishAppService,
|
|
9068
9342
|
createWorkspaceAppService: () => createWorkspaceAppService,
|
|
9069
9343
|
createWorkspaceFactory: () => createWorkspaceFactory
|
|
@@ -9083,19 +9357,30 @@ function createWorkspaceAppService() {
|
|
|
9083
9357
|
workspaceFactory
|
|
9084
9358
|
});
|
|
9085
9359
|
}
|
|
9086
|
-
async function createIdentityService(
|
|
9360
|
+
async function createIdentityService(workspacePath) {
|
|
9087
9361
|
const httpClient = new NodeHttpClient();
|
|
9088
9362
|
const workspaceAppService = createWorkspaceAppService();
|
|
9089
|
-
const workspace = await workspaceAppService.loadWorkspace(
|
|
9363
|
+
const workspace = await workspaceAppService.loadWorkspace(workspacePath);
|
|
9090
9364
|
const storageProvider = workspaceAppService.createIdentityStorage(workspace);
|
|
9091
9365
|
const userFactory = new UserFactory({
|
|
9092
9366
|
httpClient,
|
|
9093
9367
|
storageProvider
|
|
9094
9368
|
});
|
|
9095
|
-
|
|
9369
|
+
return new IdentityAppService({
|
|
9370
|
+
userFactory
|
|
9371
|
+
});
|
|
9372
|
+
}
|
|
9373
|
+
async function createIdentityServiceForObsidian(workspacePath, httpClient) {
|
|
9374
|
+
const workspaceAppService = createWorkspaceAppService();
|
|
9375
|
+
const workspace = await workspaceAppService.loadWorkspace(workspacePath);
|
|
9376
|
+
const storageProvider = workspaceAppService.createIdentityStorage(workspace);
|
|
9377
|
+
const userFactory = new UserFactory({
|
|
9378
|
+
httpClient,
|
|
9379
|
+
storageProvider
|
|
9380
|
+
});
|
|
9381
|
+
return new IdentityAppService({
|
|
9096
9382
|
userFactory
|
|
9097
9383
|
});
|
|
9098
|
-
return identityAppService;
|
|
9099
9384
|
}
|
|
9100
9385
|
function createPublishAppService() {
|
|
9101
9386
|
const { PublishAppService: PublishAppService2 } = (init_publish2(), __toCommonJS(publish_exports2));
|
|
@@ -9111,7 +9396,7 @@ function createPublishAppService() {
|
|
|
9111
9396
|
);
|
|
9112
9397
|
}
|
|
9113
9398
|
var init_container = __esm({
|
|
9114
|
-
"internal/
|
|
9399
|
+
"internal/application/container.ts"() {
|
|
9115
9400
|
"use strict";
|
|
9116
9401
|
init_workspace2();
|
|
9117
9402
|
init_workspace3();
|
|
@@ -9121,6 +9406,22 @@ var init_container = __esm({
|
|
|
9121
9406
|
}
|
|
9122
9407
|
});
|
|
9123
9408
|
|
|
9409
|
+
// internal/interfaces/cli/container.ts
|
|
9410
|
+
var container_exports2 = {};
|
|
9411
|
+
__export(container_exports2, {
|
|
9412
|
+
createIdentityService: () => createIdentityService,
|
|
9413
|
+
createIdentityServiceForObsidian: () => createIdentityServiceForObsidian,
|
|
9414
|
+
createPublishAppService: () => createPublishAppService,
|
|
9415
|
+
createWorkspaceAppService: () => createWorkspaceAppService,
|
|
9416
|
+
createWorkspaceFactory: () => createWorkspaceFactory
|
|
9417
|
+
});
|
|
9418
|
+
var init_container2 = __esm({
|
|
9419
|
+
"internal/interfaces/cli/container.ts"() {
|
|
9420
|
+
"use strict";
|
|
9421
|
+
init_container();
|
|
9422
|
+
}
|
|
9423
|
+
});
|
|
9424
|
+
|
|
9124
9425
|
// internal/domain/config/type.ts
|
|
9125
9426
|
var ConfigError, ErrConfigNotFound, ErrInvalidConfig, ErrWorkspaceNotFound, ErrConfigFileNotFound, ErrInvalidConfigFormat;
|
|
9126
9427
|
var init_type4 = __esm({
|
|
@@ -50307,7 +50608,7 @@ __export(cli_exports, {
|
|
|
50307
50608
|
module.exports = __toCommonJS(cli_exports);
|
|
50308
50609
|
|
|
50309
50610
|
// internal/interfaces/cli/router.ts
|
|
50310
|
-
|
|
50611
|
+
init_container2();
|
|
50311
50612
|
|
|
50312
50613
|
// internal/interfaces/cli/commands/workspace.ts
|
|
50313
50614
|
init_log();
|
|
@@ -50508,16 +50809,20 @@ var ProjectNewCommand = class {
|
|
|
50508
50809
|
createOptions.theme = options.theme;
|
|
50509
50810
|
if (options.path)
|
|
50510
50811
|
createOptions.projectPath = options.path;
|
|
50812
|
+
if (options.baseUrl)
|
|
50813
|
+
createOptions.baseURL = options.baseUrl;
|
|
50511
50814
|
const project = await this.workspaceAppService.createProject(workspace, name, createOptions);
|
|
50512
50815
|
const info = project.getInfo();
|
|
50513
50816
|
const displayTheme = options.theme || "quartz (default)";
|
|
50817
|
+
const baseURL = options.baseUrl || "/";
|
|
50514
50818
|
log19.info(`Created project: ${name}`);
|
|
50515
50819
|
return {
|
|
50516
50820
|
success: true,
|
|
50517
50821
|
message: `\u2713 Project created: ${name}
|
|
50518
50822
|
Path: ${info.path}
|
|
50519
50823
|
Theme: ${displayTheme}
|
|
50520
|
-
Language: ${options.language || defaultLanguage2}
|
|
50824
|
+
Language: ${options.language || defaultLanguage2}
|
|
50825
|
+
` + (baseURL !== "/" ? ` Base URL: ${baseURL}` : ""),
|
|
50521
50826
|
data: info
|
|
50522
50827
|
};
|
|
50523
50828
|
} catch (error) {
|
|
@@ -51410,11 +51715,19 @@ var BuildCommand = class {
|
|
|
51410
51715
|
project.addBuildHistory(historyEntry);
|
|
51411
51716
|
await this.workspaceAppService.saveProject(project);
|
|
51412
51717
|
log82.info(`Build completed in ${duration}ms`);
|
|
51718
|
+
const structureInfo = await this.workspaceAppService.setupProjectBaseURLStructure(project);
|
|
51719
|
+
log82.debug("baseURL structure setup complete", structureInfo);
|
|
51413
51720
|
let message = `\u2713 Built site in ${(duration / 1e3).toFixed(1)}s
|
|
51414
51721
|
`;
|
|
51415
51722
|
message += `\u2713 Project: ${project.getName()}
|
|
51416
51723
|
`;
|
|
51417
51724
|
message += `\u2713 Output: ${outputDir}`;
|
|
51725
|
+
if (structureInfo.symlinkCreated) {
|
|
51726
|
+
message += `
|
|
51727
|
+
\u2713 Base URL structure created: ${structureInfo.baseURL}`;
|
|
51728
|
+
message += `
|
|
51729
|
+
Run 'mdf serve' to preview at http://localhost:8080${structureInfo.baseURL}`;
|
|
51730
|
+
}
|
|
51418
51731
|
if (options.parallel) {
|
|
51419
51732
|
message += "\n\u2713 Used parallel processing";
|
|
51420
51733
|
}
|
|
@@ -51437,7 +51750,8 @@ var BuildCommand = class {
|
|
|
51437
51750
|
duration,
|
|
51438
51751
|
outputDir,
|
|
51439
51752
|
contentDirs,
|
|
51440
|
-
snapshot: snapshotInfo
|
|
51753
|
+
snapshot: snapshotInfo,
|
|
51754
|
+
baseURL: structureInfo.baseURL
|
|
51441
51755
|
}
|
|
51442
51756
|
};
|
|
51443
51757
|
} catch (error) {
|
|
@@ -52582,6 +52896,10 @@ var ServeCommand = class {
|
|
|
52582
52896
|
const host = options.host || "localhost";
|
|
52583
52897
|
const livereloadPort = options.livereloadPort || 35729;
|
|
52584
52898
|
const enableLivereload = options.livereload !== false;
|
|
52899
|
+
const structureInfo = await this.workspaceAppService.ensureProjectBaseURLStructure(project);
|
|
52900
|
+
if (structureInfo.recreated) {
|
|
52901
|
+
log88.info("baseURL structure created/updated");
|
|
52902
|
+
}
|
|
52585
52903
|
const projContentDirs = await project.getContentDirs();
|
|
52586
52904
|
const contentDirs = project.getLinkDirs();
|
|
52587
52905
|
const modulesDir = workspace.getModulesDir();
|
|
@@ -52602,17 +52920,7 @@ var ServeCommand = class {
|
|
|
52602
52920
|
},
|
|
52603
52921
|
onSuccess: async () => {
|
|
52604
52922
|
if (options.publish && this.publishAppService) {
|
|
52605
|
-
|
|
52606
|
-
if (options.type)
|
|
52607
|
-
publishOptions.type = options.type;
|
|
52608
|
-
if (options.licenseKey)
|
|
52609
|
-
publishOptions.licenseKey = options.licenseKey;
|
|
52610
|
-
await this.autoPublish(
|
|
52611
|
-
project,
|
|
52612
|
-
options.publish,
|
|
52613
|
-
options.publishDelay,
|
|
52614
|
-
publishOptions
|
|
52615
|
-
);
|
|
52923
|
+
await this.autoPublish(workspace, project, options.publish, options.publishDelay);
|
|
52616
52924
|
}
|
|
52617
52925
|
}
|
|
52618
52926
|
};
|
|
@@ -52629,11 +52937,10 @@ var ServeCommand = class {
|
|
|
52629
52937
|
if (!this.coordinator.isInitialized()) {
|
|
52630
52938
|
throw new Error("Failed to initialize build coordinator");
|
|
52631
52939
|
}
|
|
52632
|
-
const
|
|
52633
|
-
|
|
52634
|
-
log88.info(`Server running at ${url}`);
|
|
52940
|
+
const serverUrl = `http://${host}:${port}${structureInfo.baseURL}`;
|
|
52941
|
+
log88.info(`Server running at ${serverUrl}`);
|
|
52635
52942
|
if (options.open) {
|
|
52636
|
-
await this.openBrowser(
|
|
52943
|
+
await this.openBrowser(serverUrl);
|
|
52637
52944
|
}
|
|
52638
52945
|
let isShuttingDown = false;
|
|
52639
52946
|
const cleanup = async () => {
|
|
@@ -52662,14 +52969,14 @@ var ServeCommand = class {
|
|
|
52662
52969
|
process.on("SIGHUP", cleanup);
|
|
52663
52970
|
return {
|
|
52664
52971
|
success: true,
|
|
52665
|
-
message: `\u2713 Server running at ${
|
|
52972
|
+
message: `\u2713 Server running at ${serverUrl}
|
|
52666
52973
|
` + (enableLivereload ? `\u2713 LiveReload enabled on port ${livereloadPort}
|
|
52667
52974
|
` : "") + (options.publish ? `\u2713 Auto-publish enabled (${options.publish})
|
|
52668
52975
|
` : "") + `\u2713 Watching for changes...
|
|
52669
52976
|
|
|
52670
52977
|
Press Ctrl+C to stop`,
|
|
52671
52978
|
data: {
|
|
52672
|
-
url,
|
|
52979
|
+
url: serverUrl,
|
|
52673
52980
|
port,
|
|
52674
52981
|
host,
|
|
52675
52982
|
livereloadPort: enableLivereload ? livereloadPort : void 0,
|
|
@@ -52713,7 +53020,7 @@ Press Ctrl+C to stop`,
|
|
|
52713
53020
|
/**
|
|
52714
53021
|
* 自动发布(带防抖)
|
|
52715
53022
|
*/
|
|
52716
|
-
async autoPublish(project, method, delayMs
|
|
53023
|
+
async autoPublish(workspace, project, method, delayMs) {
|
|
52717
53024
|
if (this.publishTimer) {
|
|
52718
53025
|
clearTimeout(this.publishTimer);
|
|
52719
53026
|
}
|
|
@@ -52728,17 +53035,11 @@ Press Ctrl+C to stop`,
|
|
|
52728
53035
|
clearOnComplete: true
|
|
52729
53036
|
});
|
|
52730
53037
|
const startTime = Date.now();
|
|
52731
|
-
const
|
|
52732
|
-
if (options && (options.type || options.licenseKey)) {
|
|
52733
|
-
publishOptions.config = {
|
|
52734
|
-
type: options.type,
|
|
52735
|
-
licenseKey: options.licenseKey
|
|
52736
|
-
};
|
|
52737
|
-
}
|
|
53038
|
+
const config = await this.publishAppService.prepareFinalConfig(workspace, project, method);
|
|
52738
53039
|
const result = await this.publishAppService.publish(
|
|
52739
53040
|
project,
|
|
52740
|
-
|
|
52741
|
-
|
|
53041
|
+
config,
|
|
53042
|
+
{ incremental: true },
|
|
52742
53043
|
(progress) => {
|
|
52743
53044
|
progressBar.update(progress.percentage, progress.message);
|
|
52744
53045
|
}
|
|
@@ -52919,7 +53220,7 @@ var SnapshotDeleteCommand = class {
|
|
|
52919
53220
|
};
|
|
52920
53221
|
|
|
52921
53222
|
// internal/interfaces/cli/commands/auth.ts
|
|
52922
|
-
|
|
53223
|
+
init_container2();
|
|
52923
53224
|
init_log();
|
|
52924
53225
|
var log90 = getDomainLogger("auth-command", { component: "cli" });
|
|
52925
53226
|
async function getIdentityService() {
|
|
@@ -54068,18 +54369,22 @@ var PublishCommand = class {
|
|
|
54068
54369
|
description = "Publish project to hosting platform";
|
|
54069
54370
|
async execute(args, options) {
|
|
54070
54371
|
try {
|
|
54071
|
-
const
|
|
54372
|
+
const subcommand = args[0];
|
|
54373
|
+
if (subcommand === "test") {
|
|
54374
|
+
return await this.executeTest(args.slice(1), options);
|
|
54375
|
+
}
|
|
54376
|
+
const method = subcommand;
|
|
54072
54377
|
if (!method || !["ftp", "netlify", "mdfriday"].includes(method)) {
|
|
54073
54378
|
return {
|
|
54074
54379
|
success: false,
|
|
54075
|
-
message: "Please specify publish method: ftp, netlify, or mdfriday\n\nUsage:\n mdf publish ftp [options]\n mdf publish netlify [options]\n mdf publish mdfriday [options]\n\nOptions:\n --project <name> Project to publish\n --force Force full publish (ignore incremental)\n --verbose Show detailed progress\n\
|
|
54380
|
+
message: "Please specify publish method: ftp, netlify, or mdfriday\n\nUsage:\n mdf publish ftp [options]\n mdf publish netlify [options]\n mdf publish mdfriday [options]\n mdf publish test <method>\n\nOptions:\n --project <name> Project to publish\n --force Force full publish (ignore incremental)\n --verbose Show detailed progress\n\nConfiguration:\n All publish settings are configured via config command:\n mdf config:set publish.<method>.<key> <value> --global\n mdf config:set publish.<method>.<key> <value> (project-level)\n\nExamples:\n mdf publish ftp\n mdf publish ftp --project my-blog --force\n mdf publish test ftp"
|
|
54076
54381
|
};
|
|
54077
54382
|
}
|
|
54078
54383
|
const { workspace, project } = await this.workspaceAppService.loadWorkspaceAndProject(
|
|
54079
54384
|
options.project
|
|
54080
54385
|
);
|
|
54081
54386
|
log92.info(`Publishing project: ${project.getName()} to ${method}`);
|
|
54082
|
-
const
|
|
54387
|
+
const config = await this.publishService.prepareFinalConfig(workspace, project, method);
|
|
54083
54388
|
const progressBar = new ProgressBar({
|
|
54084
54389
|
width: 30,
|
|
54085
54390
|
showPercentage: true,
|
|
@@ -54087,17 +54392,10 @@ var PublishCommand = class {
|
|
|
54087
54392
|
clearOnComplete: true
|
|
54088
54393
|
});
|
|
54089
54394
|
const startTime = Date.now();
|
|
54090
|
-
const appPublishOptions = {};
|
|
54091
|
-
if (options.force) {
|
|
54092
|
-
appPublishOptions.force = true;
|
|
54093
|
-
}
|
|
54094
|
-
if (configOverride) {
|
|
54095
|
-
appPublishOptions.config = configOverride;
|
|
54096
|
-
}
|
|
54097
54395
|
const result = await this.publishService.publish(
|
|
54098
54396
|
project,
|
|
54099
|
-
|
|
54100
|
-
|
|
54397
|
+
config,
|
|
54398
|
+
options.force ? { force: true } : {},
|
|
54101
54399
|
(progress) => {
|
|
54102
54400
|
if (options.verbose) {
|
|
54103
54401
|
console.log(
|
|
@@ -54157,40 +54455,48 @@ var PublishCommand = class {
|
|
|
54157
54455
|
}
|
|
54158
54456
|
}
|
|
54159
54457
|
/**
|
|
54160
|
-
*
|
|
54458
|
+
* Execute test connection command
|
|
54161
54459
|
*/
|
|
54162
|
-
|
|
54163
|
-
|
|
54164
|
-
|
|
54165
|
-
|
|
54166
|
-
|
|
54167
|
-
|
|
54168
|
-
|
|
54169
|
-
|
|
54170
|
-
|
|
54171
|
-
|
|
54172
|
-
|
|
54173
|
-
|
|
54174
|
-
|
|
54175
|
-
|
|
54176
|
-
|
|
54177
|
-
|
|
54178
|
-
|
|
54179
|
-
|
|
54180
|
-
|
|
54181
|
-
|
|
54182
|
-
|
|
54183
|
-
|
|
54184
|
-
|
|
54185
|
-
|
|
54186
|
-
|
|
54187
|
-
|
|
54188
|
-
|
|
54189
|
-
|
|
54190
|
-
|
|
54191
|
-
|
|
54460
|
+
async executeTest(args, options) {
|
|
54461
|
+
try {
|
|
54462
|
+
const method = args[0];
|
|
54463
|
+
if (!method || !["ftp", "netlify", "mdfriday"].includes(method)) {
|
|
54464
|
+
return {
|
|
54465
|
+
success: false,
|
|
54466
|
+
message: "Please specify publish method to test: ftp, netlify, or mdfriday\n\nUsage:\n mdf publish test ftp\n mdf publish test netlify\n mdf publish test mdfriday\n\nOptions:\n --project <name> Project to test (optional)\n\nConfiguration:\n All publish settings are configured via config command:\n mdf config:set publish.<method>.<key> <value> --global\n mdf config:set publish.<method>.<key> <value> (project-level)\n\nExamples:\n mdf publish test ftp\n mdf publish test netlify"
|
|
54467
|
+
};
|
|
54468
|
+
}
|
|
54469
|
+
const { workspace, project } = await this.workspaceAppService.loadWorkspaceAndProject(
|
|
54470
|
+
options.project
|
|
54471
|
+
);
|
|
54472
|
+
log92.info(`Testing ${method} connection for project: ${project.getName()}`);
|
|
54473
|
+
const config = await this.publishService.prepareFinalConfig(workspace, project, method);
|
|
54474
|
+
console.log(`
|
|
54475
|
+
Testing ${method.toUpperCase()} connection...`);
|
|
54476
|
+
console.log("Configuration priority: Project config > Global config\n");
|
|
54477
|
+
const result = await this.publishService.testConnection(project, config);
|
|
54478
|
+
if (result.success) {
|
|
54479
|
+
return {
|
|
54480
|
+
success: true,
|
|
54481
|
+
message: `
|
|
54482
|
+
\u2713 ${method.toUpperCase()} connection test passed!`
|
|
54483
|
+
};
|
|
54484
|
+
} else {
|
|
54485
|
+
return {
|
|
54486
|
+
success: false,
|
|
54487
|
+
message: `
|
|
54488
|
+
\u2717 ${method.toUpperCase()} connection test failed: ${result.error}`,
|
|
54489
|
+
error: new Error(result.error)
|
|
54490
|
+
};
|
|
54491
|
+
}
|
|
54492
|
+
} catch (error) {
|
|
54493
|
+
log92.error("Test connection command failed", error);
|
|
54494
|
+
return {
|
|
54495
|
+
success: false,
|
|
54496
|
+
message: `Test connection failed: ${error.message}`,
|
|
54497
|
+
error
|
|
54498
|
+
};
|
|
54192
54499
|
}
|
|
54193
|
-
return void 0;
|
|
54194
54500
|
}
|
|
54195
54501
|
};
|
|
54196
54502
|
|
|
@@ -54213,7 +54519,7 @@ var CommandRegistry = class {
|
|
|
54213
54519
|
this.register(new ProjectShowCommand(workspaceAppService));
|
|
54214
54520
|
this.register(new ProjectDeleteCommand(workspaceAppService));
|
|
54215
54521
|
this.register(new BuildCommand(workspaceAppService));
|
|
54216
|
-
const { createPublishAppService: createPublishAppService2 } = (
|
|
54522
|
+
const { createPublishAppService: createPublishAppService2 } = (init_container2(), __toCommonJS(container_exports2));
|
|
54217
54523
|
const publishAppService = createPublishAppService2();
|
|
54218
54524
|
this.register(new PublishCommand(publishAppService, workspaceAppService));
|
|
54219
54525
|
this.register(new ServeCommand(workspaceAppService, publishAppService));
|
|
@@ -54380,6 +54686,7 @@ Commands:
|
|
|
54380
54686
|
--source-file <path> Create from single file (uses note theme by default)
|
|
54381
54687
|
--theme <url> Theme URL (default: quartz)
|
|
54382
54688
|
--language <lang> Default language (default: en)
|
|
54689
|
+
--base-url <url> Base URL for the site (e.g., /blog/)
|
|
54383
54690
|
project list List all projects
|
|
54384
54691
|
project show [name] Show project details
|
|
54385
54692
|
project delete <name> Delete a project
|
|
@@ -54488,6 +54795,8 @@ Examples:
|
|
|
54488
54795
|
|
|
54489
54796
|
# Project
|
|
54490
54797
|
mdf project new my-blog Create a new project
|
|
54798
|
+
mdf project new my-blog --base-url /blog/
|
|
54799
|
+
Create project with custom base URL
|
|
54491
54800
|
mdf project new my-blog --source ~/Documents/my-blog
|
|
54492
54801
|
Create project from existing folder (auto-detect content/static)
|
|
54493
54802
|
mdf project new my-note --source-file ~/Documents/my-note.md
|
|
@@ -54562,7 +54871,7 @@ For more information, visit: https://help.mdfriday.com
|
|
|
54562
54871
|
* Show version
|
|
54563
54872
|
*/
|
|
54564
54873
|
showVersion() {
|
|
54565
|
-
const version = "26.3.
|
|
54874
|
+
const version = "26.3.9";
|
|
54566
54875
|
return {
|
|
54567
54876
|
success: true,
|
|
54568
54877
|
message: `MDFriday CLI v${version}`
|