@tnotesjs/core 0.2.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -1
- package/config/defaultConfig.ts +33 -4
- package/config/index.ts +6 -0
- package/core/NoteIndexCache.ts +7 -1
- package/core/NoteManager.ts +18 -30
- package/dist/{chunk-5Y5IYS6C.js → chunk-UJG3UU5X.js} +21 -5
- package/dist/{chunk-5QN44ES5.js → chunk-XCWFZLER.js} +48 -368
- package/dist/cli/index.js +26 -78
- package/dist/index.js +1 -1
- package/dist/vitepress/config/index.js +2 -2
- package/package.json +1 -1
- package/services/index.ts +0 -1
- package/services/init-sub-repo/initSubRepoLogic.ts +0 -1
- package/services/note/service.ts +0 -1
- package/types/config.ts +0 -3
- package/types/note.ts +0 -2
- package/vitepress/assets/icons/icon__cursor.svg +4 -0
- package/vitepress/assets/icons/index.ts +1 -0
- package/vitepress/components/Layout/AboutPanel.vue +0 -24
- package/vitepress/components/Layout/DocBeforeControls.vue +6 -14
- package/vitepress/components/Layout/DocFooter.vue +3 -3
- package/vitepress/components/Layout/Layout.vue +0 -30
- package/vitepress/components/Layout/composables/useVSCodeIntegration.ts +20 -11
- package/vitepress/components/Layout/homeReadme.data.ts +0 -48
- package/vitepress/components/MarkMap/MarkMap.vue +6 -13
- package/vitepress/components/Settings/Settings.vue +76 -73
- package/vitepress/components/SidebarCard/FolderTreeItems.vue +16 -6
- package/vitepress/components/SidebarCard/SidebarCard.vue +21 -27
- package/vitepress/components/composables/useLocalIde.ts +83 -0
- package/vitepress/components/constants.ts +5 -6
- package/vitepress/components/utils/vscodePaths.test.ts +22 -0
- package/vitepress/components/utils/vscodePaths.ts +24 -2
- package/vitepress/theme/styles/doc-layout.scss +4 -4
- package/services/timestamp/index.ts +0 -7
- package/services/timestamp/service.ts +0 -465
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
ConfigManager,
|
|
3
3
|
getConfigManager,
|
|
4
4
|
getDefaultConfig
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-UJG3UU5X.js";
|
|
6
6
|
|
|
7
7
|
// utils/errorHandler.ts
|
|
8
8
|
var TNotesError = class _TNotesError extends Error {
|
|
@@ -1320,9 +1320,7 @@ var NoteManager = class _NoteManager {
|
|
|
1320
1320
|
"category",
|
|
1321
1321
|
"enableDiscussions",
|
|
1322
1322
|
"description",
|
|
1323
|
-
"id"
|
|
1324
|
-
"created_at",
|
|
1325
|
-
"updated_at"
|
|
1323
|
+
"id"
|
|
1326
1324
|
];
|
|
1327
1325
|
}
|
|
1328
1326
|
static {
|
|
@@ -1336,6 +1334,13 @@ var NoteManager = class _NoteManager {
|
|
|
1336
1334
|
description: ""
|
|
1337
1335
|
};
|
|
1338
1336
|
}
|
|
1337
|
+
static {
|
|
1338
|
+
/** 已废弃、写回时需剥离的笔记配置字段 */
|
|
1339
|
+
this.DEPRECATED_CONFIG_FIELDS = [
|
|
1340
|
+
"created_at",
|
|
1341
|
+
"updated_at"
|
|
1342
|
+
];
|
|
1343
|
+
}
|
|
1339
1344
|
static {
|
|
1340
1345
|
/** 必需字段(不能缺失) */
|
|
1341
1346
|
this.REQUIRED_FIELDS = ["id"];
|
|
@@ -1355,6 +1360,7 @@ var NoteManager = class _NoteManager {
|
|
|
1355
1360
|
return null;
|
|
1356
1361
|
}
|
|
1357
1362
|
let needsUpdate = false;
|
|
1363
|
+
const configRecord = config2;
|
|
1358
1364
|
for (const field of _NoteManager.REQUIRED_FIELDS) {
|
|
1359
1365
|
if (!config2[field]) {
|
|
1360
1366
|
return null;
|
|
@@ -1364,26 +1370,17 @@ var NoteManager = class _NoteManager {
|
|
|
1364
1370
|
_NoteManager.DEFAULT_CONFIG_FIELDS
|
|
1365
1371
|
)) {
|
|
1366
1372
|
if (!(key in config2)) {
|
|
1367
|
-
;
|
|
1368
|
-
config2[key] = defaultValue;
|
|
1373
|
+
configRecord[key] = defaultValue;
|
|
1369
1374
|
needsUpdate = true;
|
|
1370
1375
|
logger.info(`\u8865\u5145\u7F3A\u5931\u5B57\u6BB5 "${key}": ${configPath}`);
|
|
1371
1376
|
}
|
|
1372
1377
|
}
|
|
1373
|
-
const
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
);
|
|
1380
|
-
}
|
|
1381
|
-
if (!config2.updated_at) {
|
|
1382
|
-
config2.updated_at = now;
|
|
1383
|
-
needsUpdate = true;
|
|
1384
|
-
logger.info(
|
|
1385
|
-
`\u68C0\u6D4B\u5230 ${configPath} \u7F3A\u5931 updated_at \u5B57\u6BB5\uFF0C\u8BF7\u6267\u884C tn:fix-timestamps \u6821\u51C6\u4E3A\u7B14\u8BB0\u6700\u540E\u4E00\u6B21 git commit \u7684\u65F6\u95F4\uFF09`
|
|
1386
|
-
);
|
|
1378
|
+
for (const key of _NoteManager.DEPRECATED_CONFIG_FIELDS) {
|
|
1379
|
+
if (key in configRecord) {
|
|
1380
|
+
delete configRecord[key];
|
|
1381
|
+
needsUpdate = true;
|
|
1382
|
+
logger.info(`\u79FB\u9664\u5E9F\u5F03\u5B57\u6BB5 "${key}": ${configPath}`);
|
|
1383
|
+
}
|
|
1387
1384
|
}
|
|
1388
1385
|
const sortedConfig = this.sortConfigKeys(config2);
|
|
1389
1386
|
if (needsUpdate) {
|
|
@@ -1393,18 +1390,13 @@ var NoteManager = class _NoteManager {
|
|
|
1393
1390
|
return sortedConfig;
|
|
1394
1391
|
}
|
|
1395
1392
|
/**
|
|
1396
|
-
*
|
|
1393
|
+
* 按指定顺序排序配置对象的键(仅保留已知字段,丢弃废弃/未知字段)
|
|
1397
1394
|
*/
|
|
1398
1395
|
sortConfigKeys(config2) {
|
|
1399
1396
|
const configRecord = config2;
|
|
1400
1397
|
const sorted = {};
|
|
1401
1398
|
for (const key of _NoteManager.FIELD_ORDER) {
|
|
1402
|
-
if (key in
|
|
1403
|
-
sorted[key] = configRecord[key];
|
|
1404
|
-
}
|
|
1405
|
-
}
|
|
1406
|
-
for (const key of Object.keys(config2)) {
|
|
1407
|
-
if (!(key in sorted)) {
|
|
1399
|
+
if (key in configRecord) {
|
|
1408
1400
|
sorted[key] = configRecord[key];
|
|
1409
1401
|
}
|
|
1410
1402
|
}
|
|
@@ -1467,7 +1459,6 @@ var NoteManager = class _NoteManager {
|
|
|
1467
1459
|
if (!this.validateConfig(config2)) {
|
|
1468
1460
|
throw new Error(`Invalid config for note: ${noteInfo.dirName}`);
|
|
1469
1461
|
}
|
|
1470
|
-
config2.updated_at = Date.now();
|
|
1471
1462
|
this.writeNoteConfig(noteInfo.configPath, config2);
|
|
1472
1463
|
logger.info(`Updated config for note: ${noteInfo.dirName}`);
|
|
1473
1464
|
}
|
|
@@ -1649,7 +1640,6 @@ var COMMAND_NAMES = {
|
|
|
1649
1640
|
BUILD: "build",
|
|
1650
1641
|
CREATE_NOTES: "create-notes",
|
|
1651
1642
|
DEV: "dev",
|
|
1652
|
-
FIX_TIMESTAMPS: "fix-timestamps",
|
|
1653
1643
|
HELP: "help",
|
|
1654
1644
|
PREVIEW: "preview",
|
|
1655
1645
|
PULL: "pull",
|
|
@@ -1672,7 +1662,6 @@ var COMMAND_DESCRIPTIONS = {
|
|
|
1672
1662
|
[COMMAND_NAMES.CREATE_NOTES]: "\u65B0\u5EFA\u7B14\u8BB0\uFF08\u652F\u6301\u6279\u91CF\u521B\u5EFA\uFF09",
|
|
1673
1663
|
[COMMAND_NAMES.PUSH]: "\u5C06\u77E5\u8BC6\u5E93\u63A8\u9001\u5230 GitHub",
|
|
1674
1664
|
[COMMAND_NAMES.PULL]: "\u5C06 GitHub \u7684\u77E5\u8BC6\u5E93\u62C9\u4E0B\u6765",
|
|
1675
|
-
[COMMAND_NAMES.FIX_TIMESTAMPS]: "\u4FEE\u590D\u6240\u6709\u7B14\u8BB0\u7684\u65F6\u95F4\u6233\uFF08\u57FA\u4E8E git \u5386\u53F2\uFF09",
|
|
1676
1665
|
[COMMAND_NAMES.UPDATE_NOTE_CONFIG]: "\u66F4\u65B0\u7B14\u8BB0\u914D\u7F6E\u6587\u4EF6",
|
|
1677
1666
|
[COMMAND_NAMES.RENAME_NOTE]: "\u91CD\u547D\u540D\u7B14\u8BB0",
|
|
1678
1667
|
[COMMAND_NAMES.HELP]: "\u663E\u793A\u5E2E\u52A9\u4FE1\u606F"
|
|
@@ -1779,7 +1768,9 @@ var NoteIndexCache = class _NoteIndexCache {
|
|
|
1779
1768
|
return;
|
|
1780
1769
|
}
|
|
1781
1770
|
Object.assign(item.noteConfig, configUpdates);
|
|
1782
|
-
|
|
1771
|
+
const noteConfigRecord = item.noteConfig;
|
|
1772
|
+
delete noteConfigRecord.created_at;
|
|
1773
|
+
delete noteConfigRecord.updated_at;
|
|
1783
1774
|
logger.debug(`\u66F4\u65B0\u7B14\u8BB0\u914D\u7F6E: ${noteIndex}`, configUpdates);
|
|
1784
1775
|
}
|
|
1785
1776
|
/**
|
|
@@ -1947,7 +1938,6 @@ var NoteService = class _NoteService {
|
|
|
1947
1938
|
done: false,
|
|
1948
1939
|
category,
|
|
1949
1940
|
enableDiscussions
|
|
1950
|
-
// created_at / updated_at 由 tn:push 时 fix-timestamps 自动写入
|
|
1951
1941
|
};
|
|
1952
1942
|
this.noteManager.writeNoteConfig(configPath, config2);
|
|
1953
1943
|
const noteInfo = {
|
|
@@ -4987,314 +4977,6 @@ var GitService = class {
|
|
|
4987
4977
|
}
|
|
4988
4978
|
};
|
|
4989
4979
|
|
|
4990
|
-
// services/timestamp/service.ts
|
|
4991
|
-
import { execSync as execSync3 } from "child_process";
|
|
4992
|
-
import {
|
|
4993
|
-
existsSync as existsSync8,
|
|
4994
|
-
readFileSync as readFileSync7,
|
|
4995
|
-
writeFileSync as writeFileSync6,
|
|
4996
|
-
readdirSync as readdirSync3,
|
|
4997
|
-
statSync as statSync2
|
|
4998
|
-
} from "fs";
|
|
4999
|
-
import { join as join8 } from "path";
|
|
5000
|
-
var BIRTH_DATE = (/* @__PURE__ */ new Date("1999-06-29T00:00:00+08:00")).getTime();
|
|
5001
|
-
var TimestampService = class {
|
|
5002
|
-
constructor() {
|
|
5003
|
-
this.noteManager = NoteManager.getInstance();
|
|
5004
|
-
}
|
|
5005
|
-
/**
|
|
5006
|
-
* 批量获取所有笔记 README.md 的 git 时间戳
|
|
5007
|
-
* 只执行 2 次 git log,构建 filePath → {created_at, updated_at} 的映射
|
|
5008
|
-
*
|
|
5009
|
-
* - 第 1 次:git log --name-only --format=... --diff-filter=A
|
|
5010
|
-
* 获取每个文件的首次提交时间(created_at)
|
|
5011
|
-
* - 第 2 次:git log --name-only --format=...
|
|
5012
|
-
* 获取每个文件的最后修改时间(updated_at)
|
|
5013
|
-
*/
|
|
5014
|
-
buildGitTimestampMap() {
|
|
5015
|
-
const createdMap = /* @__PURE__ */ new Map();
|
|
5016
|
-
const updatedMap = /* @__PURE__ */ new Map();
|
|
5017
|
-
try {
|
|
5018
|
-
const createdRaw = execSync3(
|
|
5019
|
-
`git log --name-only --format="---COMMIT---%ct" --diff-filter=A -- "notes/*/README.md"`,
|
|
5020
|
-
{
|
|
5021
|
-
cwd: ROOT_DIR_PATH,
|
|
5022
|
-
encoding: "utf-8",
|
|
5023
|
-
maxBuffer: 100 * 1024 * 1024,
|
|
5024
|
-
stdio: ["pipe", "pipe", "ignore"]
|
|
5025
|
-
}
|
|
5026
|
-
);
|
|
5027
|
-
let currentTimestamp = 0;
|
|
5028
|
-
for (const line of createdRaw.split(/\r?\n/)) {
|
|
5029
|
-
if (line.startsWith("---COMMIT---")) {
|
|
5030
|
-
currentTimestamp = parseInt(line.slice(12)) * 1e3;
|
|
5031
|
-
} else if (line.trim() && currentTimestamp) {
|
|
5032
|
-
createdMap.set(line.trim(), currentTimestamp);
|
|
5033
|
-
}
|
|
5034
|
-
}
|
|
5035
|
-
const updatedRaw = execSync3(
|
|
5036
|
-
`git log --name-only --format="---COMMIT---%ct" -- "notes/*/README.md"`,
|
|
5037
|
-
{
|
|
5038
|
-
cwd: ROOT_DIR_PATH,
|
|
5039
|
-
encoding: "utf-8",
|
|
5040
|
-
maxBuffer: 100 * 1024 * 1024,
|
|
5041
|
-
stdio: ["pipe", "pipe", "ignore"]
|
|
5042
|
-
}
|
|
5043
|
-
);
|
|
5044
|
-
currentTimestamp = 0;
|
|
5045
|
-
for (const line of updatedRaw.split(/\r?\n/)) {
|
|
5046
|
-
if (line.startsWith("---COMMIT---")) {
|
|
5047
|
-
currentTimestamp = parseInt(line.slice(12)) * 1e3;
|
|
5048
|
-
} else if (line.trim() && currentTimestamp) {
|
|
5049
|
-
if (!updatedMap.has(line.trim())) {
|
|
5050
|
-
updatedMap.set(line.trim(), currentTimestamp);
|
|
5051
|
-
}
|
|
5052
|
-
}
|
|
5053
|
-
}
|
|
5054
|
-
} catch (error) {
|
|
5055
|
-
logger.error("\u6279\u91CF\u83B7\u53D6 git \u65F6\u95F4\u6233\u5931\u8D25", error);
|
|
5056
|
-
}
|
|
5057
|
-
const result = /* @__PURE__ */ new Map();
|
|
5058
|
-
for (const [file, created_at] of createdMap) {
|
|
5059
|
-
const updated_at = updatedMap.get(file) ?? created_at;
|
|
5060
|
-
result.set(file, { created_at, updated_at });
|
|
5061
|
-
}
|
|
5062
|
-
for (const [file, updated_at] of updatedMap) {
|
|
5063
|
-
if (!result.has(file)) {
|
|
5064
|
-
result.set(file, { created_at: updated_at, updated_at });
|
|
5065
|
-
}
|
|
5066
|
-
}
|
|
5067
|
-
return result;
|
|
5068
|
-
}
|
|
5069
|
-
/**
|
|
5070
|
-
* 从 git 获取文件的创建时间和最后修改时间
|
|
5071
|
-
* @param noteDirPath - 笔记目录路径
|
|
5072
|
-
* @returns 时间戳对象,包含 created_at 和 updated_at
|
|
5073
|
-
*/
|
|
5074
|
-
getGitTimestamps(noteDirPath) {
|
|
5075
|
-
try {
|
|
5076
|
-
const readmePath = join8(noteDirPath, "README.md");
|
|
5077
|
-
const createdAtOutput = execSync3(
|
|
5078
|
-
`git log --diff-filter=A --follow --format=%ct -- "${readmePath}"`,
|
|
5079
|
-
{
|
|
5080
|
-
cwd: ROOT_DIR_PATH,
|
|
5081
|
-
encoding: "utf-8",
|
|
5082
|
-
stdio: ["pipe", "pipe", "ignore"]
|
|
5083
|
-
}
|
|
5084
|
-
).split(/\r?\n/).filter(Boolean).pop();
|
|
5085
|
-
const updatedAtOutput = execSync3(
|
|
5086
|
-
`git log -1 --format=%ct -- "${readmePath}"`,
|
|
5087
|
-
{
|
|
5088
|
-
cwd: ROOT_DIR_PATH,
|
|
5089
|
-
encoding: "utf-8",
|
|
5090
|
-
stdio: ["pipe", "pipe", "ignore"]
|
|
5091
|
-
}
|
|
5092
|
-
).trim();
|
|
5093
|
-
if (!createdAtOutput || !updatedAtOutput) {
|
|
5094
|
-
return null;
|
|
5095
|
-
}
|
|
5096
|
-
return {
|
|
5097
|
-
created_at: parseInt(createdAtOutput) * 1e3,
|
|
5098
|
-
// 转换为毫秒
|
|
5099
|
-
updated_at: parseInt(updatedAtOutput) * 1e3
|
|
5100
|
-
};
|
|
5101
|
-
} catch (error) {
|
|
5102
|
-
logger.debug?.(`getGitTimestamps failed: ${noteDirPath}`, error);
|
|
5103
|
-
return null;
|
|
5104
|
-
}
|
|
5105
|
-
}
|
|
5106
|
-
/**
|
|
5107
|
-
* 修复单个笔记的时间戳
|
|
5108
|
-
* @param noteDir - 笔记目录名
|
|
5109
|
-
* @param forceUpdate - 是否强制更新(忽略现有值)
|
|
5110
|
-
* @param timestampMap - 预构建的时间戳映射(批量模式传入,避免逐个 git log)
|
|
5111
|
-
* @returns 是否进行了修复
|
|
5112
|
-
*/
|
|
5113
|
-
fixNoteTimestamps(noteDir, forceUpdate = false, timestampMap) {
|
|
5114
|
-
const configPath = join8(NOTES_DIR_PATH, noteDir, ".tnotes.json");
|
|
5115
|
-
if (!existsSync8(configPath)) {
|
|
5116
|
-
return false;
|
|
5117
|
-
}
|
|
5118
|
-
try {
|
|
5119
|
-
const configContent = readFileSync7(configPath, "utf-8");
|
|
5120
|
-
const config2 = JSON.parse(configContent);
|
|
5121
|
-
const readmeRelPath = `notes/${noteDir}/README.md`;
|
|
5122
|
-
const timestamps = timestampMap ? timestampMap.get(readmeRelPath) ?? null : this.getGitTimestamps(join8(NOTES_DIR_PATH, noteDir));
|
|
5123
|
-
if (!timestamps) {
|
|
5124
|
-
return false;
|
|
5125
|
-
}
|
|
5126
|
-
let modified = false;
|
|
5127
|
-
if (forceUpdate || !config2.created_at || config2.created_at !== timestamps.created_at) {
|
|
5128
|
-
config2.created_at = timestamps.created_at;
|
|
5129
|
-
modified = true;
|
|
5130
|
-
}
|
|
5131
|
-
if (forceUpdate) {
|
|
5132
|
-
if (config2.updated_at !== timestamps.updated_at) {
|
|
5133
|
-
config2.updated_at = timestamps.updated_at;
|
|
5134
|
-
modified = true;
|
|
5135
|
-
}
|
|
5136
|
-
} else {
|
|
5137
|
-
if (!config2.updated_at) {
|
|
5138
|
-
config2.updated_at = timestamps.updated_at;
|
|
5139
|
-
modified = true;
|
|
5140
|
-
} else if (timestamps.updated_at > config2.updated_at) {
|
|
5141
|
-
config2.updated_at = timestamps.updated_at;
|
|
5142
|
-
modified = true;
|
|
5143
|
-
}
|
|
5144
|
-
}
|
|
5145
|
-
if (modified) {
|
|
5146
|
-
this.noteManager.writeNoteConfig(configPath, config2);
|
|
5147
|
-
return true;
|
|
5148
|
-
}
|
|
5149
|
-
return false;
|
|
5150
|
-
} catch (error) {
|
|
5151
|
-
logger.error(`\u4FEE\u590D\u65F6\u95F4\u6233\u5931\u8D25: ${noteDir}`, error);
|
|
5152
|
-
return false;
|
|
5153
|
-
}
|
|
5154
|
-
}
|
|
5155
|
-
/**
|
|
5156
|
-
* 修复根配置文件的时间戳
|
|
5157
|
-
* @param forceUpdate - 是否强制更新
|
|
5158
|
-
* @returns 是否进行了修复
|
|
5159
|
-
*/
|
|
5160
|
-
fixRootConfigTimestamps(forceUpdate = false) {
|
|
5161
|
-
try {
|
|
5162
|
-
const configContent = readFileSync7(ROOT_CONFIG_PATH, "utf-8");
|
|
5163
|
-
const config2 = JSON.parse(configContent);
|
|
5164
|
-
const createdAtOutput = execSync3("git log --reverse --format=%ct", {
|
|
5165
|
-
cwd: ROOT_DIR_PATH,
|
|
5166
|
-
encoding: "utf-8",
|
|
5167
|
-
stdio: ["pipe", "pipe", "ignore"]
|
|
5168
|
-
}).trim();
|
|
5169
|
-
const updatedAtOutput = execSync3("git log -1 --format=%ct", {
|
|
5170
|
-
cwd: ROOT_DIR_PATH,
|
|
5171
|
-
encoding: "utf-8",
|
|
5172
|
-
stdio: ["pipe", "pipe", "ignore"]
|
|
5173
|
-
}).trim();
|
|
5174
|
-
if (!createdAtOutput || !updatedAtOutput) {
|
|
5175
|
-
return false;
|
|
5176
|
-
}
|
|
5177
|
-
const firstTimestamp = createdAtOutput.split("\n")[0];
|
|
5178
|
-
const createdAt = parseInt(firstTimestamp) * 1e3;
|
|
5179
|
-
const updatedAt = parseInt(updatedAtOutput) * 1e3;
|
|
5180
|
-
let modified = false;
|
|
5181
|
-
if (forceUpdate || !config2.root_item.created_at || config2.root_item.created_at !== createdAt) {
|
|
5182
|
-
config2.root_item.created_at = createdAt;
|
|
5183
|
-
modified = true;
|
|
5184
|
-
}
|
|
5185
|
-
if (forceUpdate || !config2.root_item.updated_at || config2.root_item.updated_at !== updatedAt) {
|
|
5186
|
-
config2.root_item.updated_at = updatedAt;
|
|
5187
|
-
modified = true;
|
|
5188
|
-
}
|
|
5189
|
-
if (modified) {
|
|
5190
|
-
const daysSinceBirth = Math.floor((updatedAt - BIRTH_DATE) / (1e3 * 60 * 60 * 24)) + 1;
|
|
5191
|
-
config2.root_item.days_since_birth = daysSinceBirth;
|
|
5192
|
-
writeFileSync6(
|
|
5193
|
-
ROOT_CONFIG_PATH,
|
|
5194
|
-
JSON.stringify(config2, null, 2) + "\n",
|
|
5195
|
-
"utf-8"
|
|
5196
|
-
);
|
|
5197
|
-
return true;
|
|
5198
|
-
}
|
|
5199
|
-
return false;
|
|
5200
|
-
} catch (error) {
|
|
5201
|
-
logger.error("\u4FEE\u590D\u6839\u914D\u7F6E\u6587\u4EF6\u65F6\u95F4\u6233\u5931\u8D25", error);
|
|
5202
|
-
return false;
|
|
5203
|
-
}
|
|
5204
|
-
}
|
|
5205
|
-
/**
|
|
5206
|
-
* 修复所有笔记的时间戳
|
|
5207
|
-
* @param forceUpdate - 是否强制更新(忽略现有值,用于修复历史错误数据)
|
|
5208
|
-
* @returns 修复统计信息
|
|
5209
|
-
*/
|
|
5210
|
-
async fixAllTimestamps(forceUpdate = false) {
|
|
5211
|
-
if (forceUpdate) {
|
|
5212
|
-
logger.info("\u6B63\u5728\u5F3A\u5236\u4FEE\u590D\u7B14\u8BB0\u65F6\u95F4\u6233\uFF08\u4F7F\u7528 git \u771F\u5B9E\u65F6\u95F4\uFF09...");
|
|
5213
|
-
} else {
|
|
5214
|
-
logger.info("\u6B63\u5728\u4FEE\u590D\u7B14\u8BB0\u65F6\u95F4\u6233...");
|
|
5215
|
-
}
|
|
5216
|
-
const rootConfigFixed = this.fixRootConfigTimestamps(forceUpdate);
|
|
5217
|
-
if (rootConfigFixed) {
|
|
5218
|
-
logger.success("\u2705 \u6839\u914D\u7F6E\u6587\u4EF6\u65F6\u95F4\u6233\u5DF2\u4FEE\u590D");
|
|
5219
|
-
}
|
|
5220
|
-
const timestampMap = this.buildGitTimestampMap();
|
|
5221
|
-
logger.info(`\u5DF2\u4ECE git \u5386\u53F2\u4E2D\u63D0\u53D6 ${timestampMap.size} \u4E2A\u6587\u4EF6\u7684\u65F6\u95F4\u6233\u4FE1\u606F`);
|
|
5222
|
-
if (!existsSync8(NOTES_DIR_PATH)) {
|
|
5223
|
-
logger.error("notes \u76EE\u5F55\u4E0D\u5B58\u5728");
|
|
5224
|
-
return { fixed: 0, skipped: 0, total: 0, rootConfigFixed };
|
|
5225
|
-
}
|
|
5226
|
-
const noteDirs = readdirSync3(NOTES_DIR_PATH).filter((name) => {
|
|
5227
|
-
const fullPath = join8(NOTES_DIR_PATH, name);
|
|
5228
|
-
return statSync2(fullPath).isDirectory() && /^\d{4}\./.test(name);
|
|
5229
|
-
}).sort();
|
|
5230
|
-
let fixedCount = 0;
|
|
5231
|
-
let skippedCount = 0;
|
|
5232
|
-
for (const noteDir of noteDirs) {
|
|
5233
|
-
const fixed = this.fixNoteTimestamps(noteDir, forceUpdate, timestampMap);
|
|
5234
|
-
if (fixed) {
|
|
5235
|
-
fixedCount++;
|
|
5236
|
-
} else {
|
|
5237
|
-
skippedCount++;
|
|
5238
|
-
}
|
|
5239
|
-
}
|
|
5240
|
-
if (fixedCount > 0) {
|
|
5241
|
-
logger.success(`\u65F6\u95F4\u6233\u4FEE\u590D\u5B8C\u6210: ${fixedCount} \u4E2A\u7B14\u8BB0\u5DF2\u66F4\u65B0`);
|
|
5242
|
-
} else {
|
|
5243
|
-
logger.info("\u6240\u6709\u7B14\u8BB0\u65F6\u95F4\u6233\u5747\u5DF2\u6B63\u786E");
|
|
5244
|
-
}
|
|
5245
|
-
return {
|
|
5246
|
-
fixed: fixedCount,
|
|
5247
|
-
skipped: skippedCount,
|
|
5248
|
-
total: noteDirs.length,
|
|
5249
|
-
rootConfigFixed
|
|
5250
|
-
};
|
|
5251
|
-
}
|
|
5252
|
-
/**
|
|
5253
|
-
* 更新指定笔记的时间戳为当前时间
|
|
5254
|
-
* @param noteDirNames - 笔记目录名数组
|
|
5255
|
-
* @returns 更新的笔记数量
|
|
5256
|
-
*/
|
|
5257
|
-
async updateNotesTimestamp(noteDirNames) {
|
|
5258
|
-
if (noteDirNames.length === 0) {
|
|
5259
|
-
return 0;
|
|
5260
|
-
}
|
|
5261
|
-
const now = Date.now();
|
|
5262
|
-
let updatedCount = 0;
|
|
5263
|
-
for (const noteDir of noteDirNames) {
|
|
5264
|
-
const configPath = join8(NOTES_DIR_PATH, noteDir, ".tnotes.json");
|
|
5265
|
-
if (!existsSync8(configPath)) {
|
|
5266
|
-
continue;
|
|
5267
|
-
}
|
|
5268
|
-
try {
|
|
5269
|
-
const configContent = readFileSync7(configPath, "utf-8");
|
|
5270
|
-
const config2 = JSON.parse(configContent);
|
|
5271
|
-
config2.updated_at = now;
|
|
5272
|
-
this.noteManager.writeNoteConfig(configPath, config2);
|
|
5273
|
-
updatedCount++;
|
|
5274
|
-
} catch (error) {
|
|
5275
|
-
logger.error(`\u66F4\u65B0\u65F6\u95F4\u6233\u5931\u8D25: ${noteDir}`, error);
|
|
5276
|
-
}
|
|
5277
|
-
}
|
|
5278
|
-
return updatedCount;
|
|
5279
|
-
}
|
|
5280
|
-
/**
|
|
5281
|
-
* 获取本次变更中包含 README.md 的笔记列表
|
|
5282
|
-
* @param changedFiles - git status 返回的变更文件列表
|
|
5283
|
-
* @returns 变更的笔记目录名数组
|
|
5284
|
-
*/
|
|
5285
|
-
getChangedNotes(changedFiles) {
|
|
5286
|
-
const changedNotes = /* @__PURE__ */ new Set();
|
|
5287
|
-
for (let file of changedFiles) {
|
|
5288
|
-
file = file.replace(/^"(.*)"$/, "$1").replace(/"$/, "");
|
|
5289
|
-
const match = file.match(/^notes\/([^/]+)\/README\.md$/);
|
|
5290
|
-
if (match) {
|
|
5291
|
-
changedNotes.add(match[1]);
|
|
5292
|
-
}
|
|
5293
|
-
}
|
|
5294
|
-
return Array.from(changedNotes);
|
|
5295
|
-
}
|
|
5296
|
-
};
|
|
5297
|
-
|
|
5298
4980
|
// services/vitepress/service.ts
|
|
5299
4981
|
import { spawn as spawn2 } from "child_process";
|
|
5300
4982
|
var VitepressService = class _VitepressService {
|
|
@@ -5524,13 +5206,13 @@ var VitepressService = class _VitepressService {
|
|
|
5524
5206
|
};
|
|
5525
5207
|
|
|
5526
5208
|
// services/init-sub-repo/service.ts
|
|
5527
|
-
import { copyFileSync, existsSync as
|
|
5528
|
-
import { dirname as dirname2, join as
|
|
5209
|
+
import { copyFileSync, existsSync as existsSync9, mkdirSync, readFileSync as readFileSync8, writeFileSync as writeFileSync6 } from "fs";
|
|
5210
|
+
import { dirname as dirname2, join as join9, resolve as resolve3 } from "path";
|
|
5529
5211
|
import { fileURLToPath } from "url";
|
|
5530
5212
|
|
|
5531
5213
|
// services/init-sub-repo/initSubRepoLogic.ts
|
|
5532
|
-
import { existsSync as
|
|
5533
|
-
import { join as
|
|
5214
|
+
import { existsSync as existsSync8, readFileSync as readFileSync7 } from "fs";
|
|
5215
|
+
import { join as join8, resolve as resolve2 } from "path";
|
|
5534
5216
|
var TOPIC_PATTERN = /^[a-z][a-z0-9-]*$/;
|
|
5535
5217
|
var DEFAULT_PORT = 8e3;
|
|
5536
5218
|
var DEFAULT_DESCRIPTION = "\u8FD9\u662F\u4E00\u4E2A\u57FA\u4E8E tnotesjs/core \u642D\u5EFA\u7684 TNotes \u77E5\u8BC6\u5E93\u3002";
|
|
@@ -5659,7 +5341,6 @@ function buildPackageJsonTemplate(coreVersion) {
|
|
|
5659
5341
|
"tn:build": "tnotes --build",
|
|
5660
5342
|
"tn:create-notes": "tnotes --create-notes",
|
|
5661
5343
|
"tn:dev": "tnotes --dev",
|
|
5662
|
-
"tn:fix-timestamps": "tnotes --fix-timestamps",
|
|
5663
5344
|
"tn:help": "tnotes --help",
|
|
5664
5345
|
"tn:init-sub-repo": "tnotes --init-sub-repo",
|
|
5665
5346
|
"tn:preview": "tnotes --preview",
|
|
@@ -5712,31 +5393,31 @@ function buildDynamicFiles(ctx) {
|
|
|
5712
5393
|
content: renderRootReadme(ctx)
|
|
5713
5394
|
},
|
|
5714
5395
|
{
|
|
5715
|
-
relativePath:
|
|
5396
|
+
relativePath: join8("notes", ctx.noteDirName, "README.md"),
|
|
5716
5397
|
content: renderFirstNoteReadme(ctx)
|
|
5717
5398
|
},
|
|
5718
5399
|
{
|
|
5719
|
-
relativePath:
|
|
5400
|
+
relativePath: join8("notes", ctx.noteDirName, ".tnotes.json"),
|
|
5720
5401
|
content: `${JSON.stringify(buildNoteConfig(ctx.noteUuid), null, 2)}
|
|
5721
5402
|
`
|
|
5722
5403
|
}
|
|
5723
5404
|
];
|
|
5724
5405
|
}
|
|
5725
5406
|
function isAlreadyInitialized(rootPath2) {
|
|
5726
|
-
return
|
|
5407
|
+
return existsSync8(resolve2(rootPath2, ".tnotes.json"));
|
|
5727
5408
|
}
|
|
5728
5409
|
function getInitializedConfigPath(rootPath2) {
|
|
5729
5410
|
return resolve2(rootPath2, ".tnotes.json");
|
|
5730
5411
|
}
|
|
5731
5412
|
function resolvePackageJsonMerge(targetPath, template) {
|
|
5732
|
-
if (!
|
|
5413
|
+
if (!existsSync8(targetPath)) {
|
|
5733
5414
|
return {
|
|
5734
5415
|
content: `${JSON.stringify(template, null, 2)}
|
|
5735
5416
|
`,
|
|
5736
5417
|
action: "created"
|
|
5737
5418
|
};
|
|
5738
5419
|
}
|
|
5739
|
-
const existing = JSON.parse(
|
|
5420
|
+
const existing = JSON.parse(readFileSync7(targetPath, "utf-8"));
|
|
5740
5421
|
const merged = mergePackageJson(existing, template);
|
|
5741
5422
|
return {
|
|
5742
5423
|
content: `${JSON.stringify(merged, null, 2)}
|
|
@@ -5761,9 +5442,9 @@ function buildManualSteps(ctx) {
|
|
|
5761
5442
|
function getCorePackageRoot(fromModuleUrl) {
|
|
5762
5443
|
let dir = dirname2(fileURLToPath(fromModuleUrl));
|
|
5763
5444
|
while (dir !== dirname2(dir)) {
|
|
5764
|
-
const pkgPath =
|
|
5765
|
-
if (
|
|
5766
|
-
const pkg = JSON.parse(
|
|
5445
|
+
const pkgPath = join9(dir, "package.json");
|
|
5446
|
+
if (existsSync9(pkgPath)) {
|
|
5447
|
+
const pkg = JSON.parse(readFileSync8(pkgPath, "utf-8"));
|
|
5767
5448
|
if (pkg.name === "@tnotesjs/core") return dir;
|
|
5768
5449
|
}
|
|
5769
5450
|
dir = dirname2(dir);
|
|
@@ -5771,7 +5452,7 @@ function getCorePackageRoot(fromModuleUrl) {
|
|
|
5771
5452
|
throw new Error("\u65E0\u6CD5\u5B9A\u4F4D @tnotesjs/core \u5305\u6839\u76EE\u5F55");
|
|
5772
5453
|
}
|
|
5773
5454
|
function getTemplateRoot(fromModuleUrl) {
|
|
5774
|
-
return
|
|
5455
|
+
return join9(getCorePackageRoot(fromModuleUrl), "templates", "sub-repo");
|
|
5775
5456
|
}
|
|
5776
5457
|
var InitSubRepoService = class _InitSubRepoService {
|
|
5777
5458
|
constructor(rootPath2, templateRoot) {
|
|
@@ -5788,11 +5469,11 @@ var InitSubRepoService = class _InitSubRepoService {
|
|
|
5788
5469
|
const updated = [];
|
|
5789
5470
|
for (const relativePath of STATIC_TEMPLATE_FILES) {
|
|
5790
5471
|
const targetPath = resolve3(this.rootPath, relativePath);
|
|
5791
|
-
if (
|
|
5472
|
+
if (existsSync9(targetPath)) {
|
|
5792
5473
|
skipped.push(relativePath);
|
|
5793
5474
|
continue;
|
|
5794
5475
|
}
|
|
5795
|
-
const sourcePath =
|
|
5476
|
+
const sourcePath = join9(this.templateRoot, relativePath);
|
|
5796
5477
|
mkdirSync(dirname2(targetPath), { recursive: true });
|
|
5797
5478
|
copyFileSync(sourcePath, targetPath);
|
|
5798
5479
|
created.push(relativePath);
|
|
@@ -5806,17 +5487,17 @@ var InitSubRepoService = class _InitSubRepoService {
|
|
|
5806
5487
|
packageTemplate
|
|
5807
5488
|
);
|
|
5808
5489
|
mkdirSync(dirname2(targetPath), { recursive: true });
|
|
5809
|
-
|
|
5490
|
+
writeFileSync6(targetPath, content, "utf-8");
|
|
5810
5491
|
if (action === "created") created.push(file.relativePath);
|
|
5811
5492
|
else updated.push(file.relativePath);
|
|
5812
5493
|
continue;
|
|
5813
5494
|
}
|
|
5814
|
-
if (
|
|
5495
|
+
if (existsSync9(targetPath)) {
|
|
5815
5496
|
skipped.push(file.relativePath);
|
|
5816
5497
|
continue;
|
|
5817
5498
|
}
|
|
5818
5499
|
mkdirSync(dirname2(targetPath), { recursive: true });
|
|
5819
|
-
|
|
5500
|
+
writeFileSync6(targetPath, file.content, "utf-8");
|
|
5820
5501
|
created.push(file.relativePath);
|
|
5821
5502
|
}
|
|
5822
5503
|
return { created, skipped, updated };
|
|
@@ -5907,8 +5588,8 @@ var UpdateNoteConfigCommand = class extends BaseCommand {
|
|
|
5907
5588
|
};
|
|
5908
5589
|
|
|
5909
5590
|
// commands/note/RenameNoteCommand.ts
|
|
5910
|
-
import { existsSync as
|
|
5911
|
-
import { join as
|
|
5591
|
+
import { existsSync as existsSync10, renameSync, readFileSync as readFileSync9, writeFileSync as writeFileSync7 } from "fs";
|
|
5592
|
+
import { join as join10 } from "path";
|
|
5912
5593
|
var RenameNoteCommand = class extends BaseCommand {
|
|
5913
5594
|
constructor() {
|
|
5914
5595
|
super("rename-note");
|
|
@@ -5943,8 +5624,8 @@ var RenameNoteCommand = class extends BaseCommand {
|
|
|
5943
5624
|
throw new Error(validation.error || "\u6807\u9898\u683C\u5F0F\u65E0\u6548");
|
|
5944
5625
|
}
|
|
5945
5626
|
const newDirName = `${noteIndex}. ${newTitle.trim()}`;
|
|
5946
|
-
const newPath =
|
|
5947
|
-
if (
|
|
5627
|
+
const newPath = join10(NOTES_PATH, newDirName);
|
|
5628
|
+
if (existsSync10(newPath)) {
|
|
5948
5629
|
throw new Error(`\u76EE\u6807\u6587\u4EF6\u5939\u5DF2\u5B58\u5728: ${newDirName}`);
|
|
5949
5630
|
}
|
|
5950
5631
|
const watcher = FileWatcherService.getInstance();
|
|
@@ -5963,9 +5644,9 @@ var RenameNoteCommand = class extends BaseCommand {
|
|
|
5963
5644
|
}
|
|
5964
5645
|
try {
|
|
5965
5646
|
this.logger.info("\u6B63\u5728\u66F4\u65B0\u7B14\u8BB0\u5185\u90E8\u6807\u9898...");
|
|
5966
|
-
const readmePath =
|
|
5967
|
-
if (
|
|
5968
|
-
const content =
|
|
5647
|
+
const readmePath = join10(newPath, "README.md");
|
|
5648
|
+
if (existsSync10(readmePath)) {
|
|
5649
|
+
const content = readFileSync9(readmePath, "utf-8");
|
|
5969
5650
|
const lines = content.split("\n");
|
|
5970
5651
|
let h1Index = -1;
|
|
5971
5652
|
for (let i = 0; i < lines.length; i++) {
|
|
@@ -5981,7 +5662,7 @@ var RenameNoteCommand = class extends BaseCommand {
|
|
|
5981
5662
|
REPO_NOTES_URL
|
|
5982
5663
|
);
|
|
5983
5664
|
lines[h1Index] = newH1;
|
|
5984
|
-
|
|
5665
|
+
writeFileSync7(readmePath, lines.join("\n"), "utf-8");
|
|
5985
5666
|
this.logger.success("\u2705 \u7B14\u8BB0\u6807\u9898\u5DF2\u66F4\u65B0");
|
|
5986
5667
|
} else {
|
|
5987
5668
|
this.logger.warn(
|
|
@@ -6029,7 +5710,6 @@ export {
|
|
|
6029
5710
|
FileWatcherService,
|
|
6030
5711
|
GitManager,
|
|
6031
5712
|
GitService,
|
|
6032
|
-
TimestampService,
|
|
6033
5713
|
VitepressService,
|
|
6034
5714
|
DEFAULT_PORT,
|
|
6035
5715
|
DEFAULT_DESCRIPTION,
|