obsidian-dev-utils 98.0.0 → 100.0.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/CHANGELOG.md +13 -0
- package/dist/integration-test-plugin/main.js +132 -17
- package/dist/lib/cjs/__merged.cjs +11 -1
- package/dist/lib/cjs/__merged.d.cts +3 -3
- package/dist/lib/cjs/generated-during-build.cjs +1 -1
- package/dist/lib/cjs/obsidian/attachment-path.cjs +6 -1
- package/dist/lib/cjs/obsidian/attachment-path.d.cts +29 -0
- package/dist/lib/cjs/obsidian/attachment-unit-folder.cjs +7 -2
- package/dist/lib/cjs/obsidian/attachment-unit-folder.d.cts +32 -2
- package/dist/lib/cjs/obsidian/components/plugin-settings-component.cjs +36 -1
- package/dist/lib/cjs/obsidian/components/plugin-settings-component.d.cts +21 -0
- package/dist/lib/cjs/obsidian/components/plugin-suggestion-component.cjs +20 -6
- package/dist/lib/cjs/obsidian/components/plugin-suggestion-component.d.cts +26 -4
- package/dist/lib/cjs/obsidian/file-change.cjs +6 -6
- package/dist/lib/cjs/obsidian/link.cjs +33 -6
- package/dist/lib/cjs/obsidian/link.d.cts +35 -0
- package/dist/lib/cjs/obsidian/reference.cjs +9 -1
- package/dist/lib/cjs/obsidian/reference.d.cts +33 -0
- package/dist/lib/cjs/obsidian/validation.cjs +22 -3
- package/dist/lib/cjs/obsidian/validation.d.cts +37 -0
- package/dist/lib/cjs/obsidian/vault.cjs +4 -1
- package/dist/lib/cjs/obsidian/vault.d.cts +8 -1
- package/dist/lib/cjs/script-utils/nano-staged-config.cjs +7 -5
- package/dist/lib/cjs/script-utils/nano-staged-config.d.cts +5 -2
- package/dist/lib/cjs/script-utils/package-manager.cjs +113 -30
- package/dist/lib/cjs/script-utils/package-manager.d.cts +20 -4
- package/dist/lib/esm/__merged.d.mts +3 -3
- package/dist/lib/esm/__merged.mjs +11 -1
- package/dist/lib/esm/generated-during-build.mjs +1 -1
- package/dist/lib/esm/obsidian/attachment-path.d.mts +29 -0
- package/dist/lib/esm/obsidian/attachment-path.mjs +5 -1
- package/dist/lib/esm/obsidian/attachment-unit-folder.d.mts +32 -2
- package/dist/lib/esm/obsidian/attachment-unit-folder.mjs +7 -2
- package/dist/lib/esm/obsidian/components/plugin-settings-component.d.mts +21 -0
- package/dist/lib/esm/obsidian/components/plugin-settings-component.mjs +36 -1
- package/dist/lib/esm/obsidian/components/plugin-suggestion-component.d.mts +26 -4
- package/dist/lib/esm/obsidian/components/plugin-suggestion-component.mjs +20 -6
- package/dist/lib/esm/obsidian/file-change.mjs +6 -6
- package/dist/lib/esm/obsidian/link.d.mts +35 -0
- package/dist/lib/esm/obsidian/link.mjs +38 -7
- package/dist/lib/esm/obsidian/reference.d.mts +33 -0
- package/dist/lib/esm/obsidian/reference.mjs +8 -1
- package/dist/lib/esm/obsidian/validation.d.mts +37 -0
- package/dist/lib/esm/obsidian/validation.mjs +21 -2
- package/dist/lib/esm/obsidian/vault.d.mts +8 -1
- package/dist/lib/esm/obsidian/vault.mjs +4 -1
- package/dist/lib/esm/script-utils/nano-staged-config.d.mts +5 -2
- package/dist/lib/esm/script-utils/nano-staged-config.mjs +7 -5
- package/dist/lib/esm/script-utils/package-manager.d.mts +20 -4
- package/dist/lib/esm/script-utils/package-manager.mjs +113 -30
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
+
## 100.0.0
|
|
4
|
+
|
|
5
|
+
- feat(attachment-unit-folder)!: own the designation, not just the walker
|
|
6
|
+
|
|
7
|
+
## 99.0.0
|
|
8
|
+
|
|
9
|
+
- fix(plugin-suggestion)!: decide the notice after the host settings load
|
|
10
|
+
- fix(vault): complete the operation when there is nothing to write
|
|
11
|
+
- feat(validation): own the Windows reserved-name and trailing-character rules
|
|
12
|
+
- feat(link): scope link editing to an offset range
|
|
13
|
+
- fix(package-manager): collect every signal before picking the manager
|
|
14
|
+
- fix(script-utils): route the remaining npm run hops through the detected package manager
|
|
15
|
+
|
|
3
16
|
## 98.0.0
|
|
4
17
|
|
|
5
18
|
- feat(deps)!: require obsidian-integration-testing ^12 as a peer, so OIT 11 no longer resolves
|
|
@@ -10574,6 +10574,7 @@ __export(merged_exports, {
|
|
|
10574
10574
|
getCacheSafe: () => getCacheSafe,
|
|
10575
10575
|
getCanvasReferences: () => getCanvasReferences,
|
|
10576
10576
|
getCaseInsensitiveFileIndex: () => getCaseInsensitiveFileIndex,
|
|
10577
|
+
getCheckIsAttachmentUnitFolderFunction: () => getCheckIsAttachmentUnitFolderFunction,
|
|
10577
10578
|
getCodeBlockMarkdownInfo: () => getCodeBlockMarkdownInfo,
|
|
10578
10579
|
getCommunityPluginRepo: () => getCommunityPluginRepo,
|
|
10579
10580
|
getDebugController: () => getDebugController,
|
|
@@ -10639,6 +10640,7 @@ __export(merged_exports, {
|
|
|
10639
10640
|
hasPatchToken: () => hasPatchToken,
|
|
10640
10641
|
hasSingleOccurrence: () => hasSingleOccurrence,
|
|
10641
10642
|
hasWikilinkSyntax: () => hasWikilinkSyntax,
|
|
10643
|
+
hasWindowsTrailingChars: () => hasWindowsTrailingChars,
|
|
10642
10644
|
hoverElement: () => hoverElement3,
|
|
10643
10645
|
ignoreError: () => ignoreError,
|
|
10644
10646
|
indent: () => indent,
|
|
@@ -10693,6 +10695,7 @@ __export(merged_exports, {
|
|
|
10693
10695
|
isNote: () => isNote,
|
|
10694
10696
|
isParseLinkFrontmatterReference: () => isParseLinkFrontmatterReference,
|
|
10695
10697
|
isParseLinkReference: () => isParseLinkReference,
|
|
10698
|
+
isReferenceInOffsetRange: () => isReferenceInOffsetRange,
|
|
10696
10699
|
isResourceLockedForPath: () => isResourceLockedForPath,
|
|
10697
10700
|
isResourceLockedForPathByAncestor: () => isResourceLockedForPathByAncestor,
|
|
10698
10701
|
isSpellcheckEnabled: () => isSpellcheckEnabled,
|
|
@@ -10700,6 +10703,7 @@ __export(merged_exports, {
|
|
|
10700
10703
|
isUrl: () => isUrl,
|
|
10701
10704
|
isValidRegExp: () => isValidRegExp,
|
|
10702
10705
|
isValidationMessageHolder: () => isValidationMessageHolder,
|
|
10706
|
+
isWindowsReservedName: () => isWindowsReservedName,
|
|
10703
10707
|
join: () => join,
|
|
10704
10708
|
listSafe: () => listSafe,
|
|
10705
10709
|
lockResourceForPath: () => lockResourceForPath,
|
|
@@ -10844,6 +10848,7 @@ __export(merged_exports, {
|
|
|
10844
10848
|
trimEnd: () => trimEnd,
|
|
10845
10849
|
trimMarkdownExtension: () => trimMarkdownExtension,
|
|
10846
10850
|
trimStart: () => trimStart,
|
|
10851
|
+
trimWindowsTrailingChars: () => trimWindowsTrailingChars,
|
|
10847
10852
|
typeIntoEditor: () => typeIntoEditor3,
|
|
10848
10853
|
unescape: () => unescape,
|
|
10849
10854
|
unescapeAlias: () => unescapeAlias,
|
|
@@ -11560,6 +11565,7 @@ __export(attachment_path_exports, {
|
|
|
11560
11565
|
getAttachmentFolderPath: () => getAttachmentFolderPath,
|
|
11561
11566
|
getAttachmentFolderPathSyncOrNull: () => getAttachmentFolderPathSyncOrNull,
|
|
11562
11567
|
getAvailablePathForAttachments: () => getAvailablePathForAttachments,
|
|
11568
|
+
getCheckIsAttachmentUnitFolderFunction: () => getCheckIsAttachmentUnitFolderFunction,
|
|
11563
11569
|
hasOwnAttachmentFolder: () => hasOwnAttachmentFolder,
|
|
11564
11570
|
isAtProperAttachmentPath: () => isAtProperAttachmentPath
|
|
11565
11571
|
});
|
|
@@ -12572,6 +12578,9 @@ async function getAvailablePathForAttachments(params) {
|
|
|
12572
12578
|
}
|
|
12573
12579
|
return getAvailablePathForAttachmentsSync(params);
|
|
12574
12580
|
}
|
|
12581
|
+
function getCheckIsAttachmentUnitFolderFunction(app) {
|
|
12582
|
+
return app.vault.getAvailablePathForAttachments.checkIsAttachmentUnitFolder;
|
|
12583
|
+
}
|
|
12575
12584
|
async function hasOwnAttachmentFolder(params) {
|
|
12576
12585
|
const {
|
|
12577
12586
|
app,
|
|
@@ -12719,10 +12728,14 @@ function findAttachmentUnitFolderPath(params) {
|
|
|
12719
12728
|
if (!parentFolderPath2 || parentFolderPath2 === "." || parentFolderPath2 === "/") {
|
|
12720
12729
|
return null;
|
|
12721
12730
|
}
|
|
12731
|
+
const checkIsAttachmentUnitFolder = "checkIsAttachmentUnitFolder" in params ? params.checkIsAttachmentUnitFolder : getCheckIsAttachmentUnitFolderFunction(params.app);
|
|
12732
|
+
if (!checkIsAttachmentUnitFolder) {
|
|
12733
|
+
return null;
|
|
12734
|
+
}
|
|
12722
12735
|
const segments = parentFolderPath2.split("/").filter(Boolean);
|
|
12723
12736
|
for (let count = 1; count <= segments.length; count++) {
|
|
12724
12737
|
const candidate = segments.slice(0, count).join("/");
|
|
12725
|
-
if (
|
|
12738
|
+
if (checkIsAttachmentUnitFolder(candidate)) {
|
|
12726
12739
|
return candidate;
|
|
12727
12740
|
}
|
|
12728
12741
|
}
|
|
@@ -13286,6 +13299,7 @@ __export(link_exports, {
|
|
|
13286
13299
|
});
|
|
13287
13300
|
var import_obsidian102 = require("obsidian");
|
|
13288
13301
|
init_abort_controller();
|
|
13302
|
+
init_debug();
|
|
13289
13303
|
init_object_utils();
|
|
13290
13304
|
init_obsidian_dev_utils_state();
|
|
13291
13305
|
init_path();
|
|
@@ -13497,6 +13511,7 @@ __export(reference_exports, {
|
|
|
13497
13511
|
isCanvasFileNodeReference: () => isCanvasFileNodeReference,
|
|
13498
13512
|
isCanvasReference: () => isCanvasReference,
|
|
13499
13513
|
isCanvasTextNodeReference: () => isCanvasTextNodeReference,
|
|
13514
|
+
isReferenceInOffsetRange: () => isReferenceInOffsetRange,
|
|
13500
13515
|
referenceToFileChange: () => referenceToFileChange,
|
|
13501
13516
|
sortReferences: () => sortReferences
|
|
13502
13517
|
});
|
|
@@ -13509,6 +13524,12 @@ function isCanvasReference(reference) {
|
|
|
13509
13524
|
function isCanvasTextNodeReference(reference) {
|
|
13510
13525
|
return isCanvasReference(reference) && reference.type === "text";
|
|
13511
13526
|
}
|
|
13527
|
+
function isReferenceInOffsetRange(reference, offsetRange) {
|
|
13528
|
+
if (!isReferenceCache(reference)) {
|
|
13529
|
+
return false;
|
|
13530
|
+
}
|
|
13531
|
+
return offsetRange.startOffset <= reference.position.start.offset && reference.position.end.offset <= offsetRange.endOffset;
|
|
13532
|
+
}
|
|
13512
13533
|
function referenceToFileChange(reference, newContent) {
|
|
13513
13534
|
if (isFrontmatterLinkCacheWithOffsets(reference)) {
|
|
13514
13535
|
return {
|
|
@@ -13887,6 +13908,9 @@ async function process2(params) {
|
|
|
13887
13908
|
if (newContent === null) {
|
|
13888
13909
|
return false;
|
|
13889
13910
|
}
|
|
13911
|
+
if (newContent === oldContent) {
|
|
13912
|
+
return true;
|
|
13913
|
+
}
|
|
13890
13914
|
let isSuccess = true;
|
|
13891
13915
|
const result = await invokeFileActionSafe({
|
|
13892
13916
|
app,
|
|
@@ -14123,7 +14147,7 @@ async function applyCanvasChanges(params) {
|
|
|
14123
14147
|
const canvasData = parseJsonSafe(content3);
|
|
14124
14148
|
if (!Array.isArray(canvasData.nodes) || !Array.isArray(canvasData.edges)) {
|
|
14125
14149
|
getLibDebugger("FileChange:applyCanvasChanges")("Not a valid canvas; skipping rewrite", { path });
|
|
14126
|
-
return
|
|
14150
|
+
return content3;
|
|
14127
14151
|
}
|
|
14128
14152
|
const canvasTextChanges = /* @__PURE__ */ new Map();
|
|
14129
14153
|
for (const change of changes) {
|
|
@@ -14142,7 +14166,7 @@ async function applyCanvasChanges(params) {
|
|
|
14142
14166
|
nodeIndex: change.reference.nodeIndex,
|
|
14143
14167
|
path
|
|
14144
14168
|
});
|
|
14145
|
-
return
|
|
14169
|
+
return content3;
|
|
14146
14170
|
}
|
|
14147
14171
|
if (isCanvasFileNodeChange(change)) {
|
|
14148
14172
|
if (node2.file !== change.oldContent) {
|
|
@@ -14153,7 +14177,7 @@ async function applyCanvasChanges(params) {
|
|
|
14153
14177
|
path,
|
|
14154
14178
|
type: "file"
|
|
14155
14179
|
});
|
|
14156
|
-
return
|
|
14180
|
+
return content3;
|
|
14157
14181
|
}
|
|
14158
14182
|
node2.file = change.newContent;
|
|
14159
14183
|
} else if (isCanvasTextNodeChange(change)) {
|
|
@@ -14173,7 +14197,7 @@ async function applyCanvasChanges(params) {
|
|
|
14173
14197
|
nodeIndex,
|
|
14174
14198
|
path
|
|
14175
14199
|
});
|
|
14176
|
-
return
|
|
14200
|
+
return content3;
|
|
14177
14201
|
}
|
|
14178
14202
|
if (typeof node2.text !== "string") {
|
|
14179
14203
|
const message = "Node text is not a string";
|
|
@@ -14181,7 +14205,7 @@ async function applyCanvasChanges(params) {
|
|
|
14181
14205
|
nodeIndex,
|
|
14182
14206
|
path
|
|
14183
14207
|
});
|
|
14184
|
-
return
|
|
14208
|
+
return content3;
|
|
14185
14209
|
}
|
|
14186
14210
|
const contentChanges = canvasTextChangesForNode.map((change) => {
|
|
14187
14211
|
const newContent = change.reference.originalReference.original.includes(ESCAPED_WIKILINK_DIVIDER) ? change.newContent.replaceAll(UNESCAPED_WIKILINK_DIVIDER_REGEXP, () => ESCAPED_WIKILINK_DIVIDER) : change.newContent;
|
|
@@ -25309,12 +25333,16 @@ async function editLinks(params) {
|
|
|
25309
25333
|
const {
|
|
25310
25334
|
app,
|
|
25311
25335
|
linkConverter,
|
|
25336
|
+
offsetRange,
|
|
25312
25337
|
pathOrFile,
|
|
25313
25338
|
shouldEditExternalLinks = false,
|
|
25314
25339
|
shouldEditFrontmatterExternalLinks = false,
|
|
25315
25340
|
shouldEditMultiValueFrontmatterExternalLinks = false,
|
|
25316
25341
|
...options
|
|
25317
25342
|
} = params;
|
|
25343
|
+
if (offsetRange !== void 0) {
|
|
25344
|
+
validateOffsetRange(offsetRange);
|
|
25345
|
+
}
|
|
25318
25346
|
await applyFileChanges({
|
|
25319
25347
|
app,
|
|
25320
25348
|
changesProvider: async ({ abortSignal, content: content3 }) => {
|
|
@@ -25330,25 +25358,29 @@ async function editLinks(params) {
|
|
|
25330
25358
|
if (content3 !== cachedContent) {
|
|
25331
25359
|
return null;
|
|
25332
25360
|
}
|
|
25333
|
-
return await getFileChanges({
|
|
25361
|
+
return await getFileChanges(normalizeOptionalProperties({
|
|
25334
25362
|
abortSignal,
|
|
25335
25363
|
cache,
|
|
25336
25364
|
isCanvasFileCache: isCanvasFile(pathOrFile),
|
|
25337
25365
|
linkConverter,
|
|
25366
|
+
offsetRange,
|
|
25338
25367
|
shouldIncludeExternalLinks: shouldEditExternalLinks,
|
|
25339
25368
|
shouldIncludeFrontmatterExternalLinks: shouldEditFrontmatterExternalLinks,
|
|
25340
25369
|
shouldIncludeMultiValueFrontmatterExternalLinks: shouldEditMultiValueFrontmatterExternalLinks
|
|
25341
|
-
});
|
|
25370
|
+
}));
|
|
25342
25371
|
},
|
|
25343
25372
|
pathOrFile,
|
|
25344
25373
|
...options
|
|
25345
25374
|
});
|
|
25346
25375
|
}
|
|
25347
25376
|
async function editLinksInContent(params) {
|
|
25348
|
-
const { app, content: content3, linkConverter, shouldEditExternalLinks = false, shouldEditFrontmatterExternalLinks = false, shouldEditMultiValueFrontmatterExternalLinks = false } = params;
|
|
25377
|
+
const { app, content: content3, linkConverter, offsetRange, shouldEditExternalLinks = false, shouldEditFrontmatterExternalLinks = false, shouldEditMultiValueFrontmatterExternalLinks = false } = params;
|
|
25349
25378
|
let { abortSignal } = params;
|
|
25350
25379
|
abortSignal ??= abortSignalNever();
|
|
25351
25380
|
abortSignal.throwIfAborted();
|
|
25381
|
+
if (offsetRange !== void 0) {
|
|
25382
|
+
validateOffsetRange(offsetRange);
|
|
25383
|
+
}
|
|
25352
25384
|
const newContent = await applyContentChanges({
|
|
25353
25385
|
abortSignal,
|
|
25354
25386
|
changesProvider: async () => {
|
|
@@ -25358,15 +25390,16 @@ async function editLinksInContent(params) {
|
|
|
25358
25390
|
shouldParseMultiValueFrontmatterExternalLinks: shouldEditMultiValueFrontmatterExternalLinks
|
|
25359
25391
|
});
|
|
25360
25392
|
abortSignal.throwIfAborted();
|
|
25361
|
-
const changes = await getFileChanges({
|
|
25393
|
+
const changes = await getFileChanges(normalizeOptionalProperties({
|
|
25362
25394
|
abortSignal,
|
|
25363
25395
|
cache,
|
|
25364
25396
|
isCanvasFileCache: false,
|
|
25365
25397
|
linkConverter,
|
|
25398
|
+
offsetRange,
|
|
25366
25399
|
shouldIncludeExternalLinks: shouldEditExternalLinks,
|
|
25367
25400
|
shouldIncludeFrontmatterExternalLinks: shouldEditFrontmatterExternalLinks,
|
|
25368
25401
|
shouldIncludeMultiValueFrontmatterExternalLinks: shouldEditMultiValueFrontmatterExternalLinks
|
|
25369
|
-
});
|
|
25402
|
+
}));
|
|
25370
25403
|
abortSignal.throwIfAborted();
|
|
25371
25404
|
return changes;
|
|
25372
25405
|
},
|
|
@@ -25811,6 +25844,7 @@ async function getFileChanges(params) {
|
|
|
25811
25844
|
cache,
|
|
25812
25845
|
isCanvasFileCache,
|
|
25813
25846
|
linkConverter,
|
|
25847
|
+
offsetRange,
|
|
25814
25848
|
shouldIncludeExternalLinks = false,
|
|
25815
25849
|
shouldIncludeFrontmatterExternalLinks = false,
|
|
25816
25850
|
shouldIncludeMultiValueFrontmatterExternalLinks = false
|
|
@@ -25826,8 +25860,16 @@ async function getFileChanges(params) {
|
|
|
25826
25860
|
end: section.position.end.offset,
|
|
25827
25861
|
start: section.position.start.offset
|
|
25828
25862
|
}));
|
|
25863
|
+
const getFileChangesDebugger = getLibDebugger("Link:getFileChanges");
|
|
25829
25864
|
for (const link2 of getLinks({ cache, shouldIncludeExternalLinks, shouldIncludeFrontmatterExternalLinks, shouldIncludeMultiValueFrontmatterExternalLinks })) {
|
|
25830
25865
|
abortSignal.throwIfAborted();
|
|
25866
|
+
if (offsetRange !== void 0 && !isReferenceInOffsetRange(link2, offsetRange)) {
|
|
25867
|
+
getFileChangesDebugger(
|
|
25868
|
+
isReferenceCache(link2) ? "Skipping a link that is not fully contained in the offset range" : "Skipping a link that carries no position within the content, so it can never be in the offset range",
|
|
25869
|
+
{ link: link2.original, offsetRange }
|
|
25870
|
+
);
|
|
25871
|
+
continue;
|
|
25872
|
+
}
|
|
25831
25873
|
const newContent = await linkConverter(link2, abortSignal);
|
|
25832
25874
|
abortSignal.throwIfAborted();
|
|
25833
25875
|
if (newContent === void 0) {
|
|
@@ -25954,6 +25996,14 @@ function shouldUseWikilinkStyle(params) {
|
|
|
25954
25996
|
}
|
|
25955
25997
|
}
|
|
25956
25998
|
}
|
|
25999
|
+
function validateOffsetRange(offsetRange) {
|
|
26000
|
+
if (offsetRange.startOffset < 0) {
|
|
26001
|
+
throw new Error(`Invalid offset range: the start offset ${String(offsetRange.startOffset)} must not be negative.`);
|
|
26002
|
+
}
|
|
26003
|
+
if (offsetRange.endOffset < offsetRange.startOffset) {
|
|
26004
|
+
throw new Error(`Invalid offset range: the end offset ${String(offsetRange.endOffset)} must not be less than the start offset ${String(offsetRange.startOffset)}.`);
|
|
26005
|
+
}
|
|
26006
|
+
}
|
|
25957
26007
|
|
|
25958
26008
|
// src/obsidian/backlink.ts
|
|
25959
26009
|
async function renderBacklinksTable(dv, pathOrFiles) {
|
|
@@ -28818,8 +28868,10 @@ var PluginSettingsComponentBase = class extends ComponentEx {
|
|
|
28818
28868
|
pluginSettingsClass;
|
|
28819
28869
|
asyncEvents = new AsyncEvents();
|
|
28820
28870
|
currentState;
|
|
28871
|
+
isLoadedFromFile = false;
|
|
28821
28872
|
lastSavedState;
|
|
28822
28873
|
legacySettingsConverters = [];
|
|
28874
|
+
loadedFromFileResolvers = [];
|
|
28823
28875
|
propertyNames;
|
|
28824
28876
|
validators = /* @__PURE__ */ new Map();
|
|
28825
28877
|
/**
|
|
@@ -28917,6 +28969,7 @@ var PluginSettingsComponentBase = class extends ComponentEx {
|
|
|
28917
28969
|
await this.saveToFileImpl();
|
|
28918
28970
|
}
|
|
28919
28971
|
} finally {
|
|
28972
|
+
this.markLoadedFromFile();
|
|
28920
28973
|
await this.asyncEvents.triggerAsync("loadSettings", this.currentState, isInitialLoad);
|
|
28921
28974
|
}
|
|
28922
28975
|
}
|
|
@@ -29086,6 +29139,31 @@ var PluginSettingsComponentBase = class extends ComponentEx {
|
|
|
29086
29139
|
}
|
|
29087
29140
|
return result;
|
|
29088
29141
|
}
|
|
29142
|
+
/**
|
|
29143
|
+
* Waits until the settings have been read from `data.json` at least once.
|
|
29144
|
+
*
|
|
29145
|
+
* Anything that reads a setting from outside this component has to wait for this, because until the first
|
|
29146
|
+
* {@link loadFromFile} completes {@link settings} still holds the DEFAULTS — reading it earlier answers
|
|
29147
|
+
* with a default rather than with what the user actually stored. That window is easy to miss, since it is
|
|
29148
|
+
* empty on a cold start (the workspace layout is not ready yet, so nothing has run) but wide open on a
|
|
29149
|
+
* runtime enable from the Community Plugins tab or a re-enable after an update, where a layout-ready
|
|
29150
|
+
* handler fires immediately while this component's own async load is still in flight.
|
|
29151
|
+
*
|
|
29152
|
+
* Resolves immediately once the settings have loaded, so a caller that arrives late is not stranded
|
|
29153
|
+
* waiting for an event that has already been raised. Later reloads (an external `data.json` change) do
|
|
29154
|
+
* not reset it — the question it answers is whether the settings have EVER been read, not whether the
|
|
29155
|
+
* most recent read has finished.
|
|
29156
|
+
*
|
|
29157
|
+
* @returns A {@link Promise} that resolves once the settings have been loaded from the file.
|
|
29158
|
+
*/
|
|
29159
|
+
whenLoadedFromFile() {
|
|
29160
|
+
if (this.isLoadedFromFile) {
|
|
29161
|
+
return noopAsync();
|
|
29162
|
+
}
|
|
29163
|
+
return new Promise((resolve2) => {
|
|
29164
|
+
this.loadedFromFileResolvers.push(resolve2);
|
|
29165
|
+
});
|
|
29166
|
+
}
|
|
29089
29167
|
/**
|
|
29090
29168
|
* Gets the transformer.
|
|
29091
29169
|
*
|
|
@@ -29188,6 +29266,13 @@ var PluginSettingsComponentBase = class extends ComponentEx {
|
|
|
29188
29266
|
}
|
|
29189
29267
|
return this.propertyNames.includes(property);
|
|
29190
29268
|
}
|
|
29269
|
+
markLoadedFromFile() {
|
|
29270
|
+
this.isLoadedFromFile = true;
|
|
29271
|
+
const resolvers = this.loadedFromFileResolvers.splice(0);
|
|
29272
|
+
for (const resolve2 of resolvers) {
|
|
29273
|
+
resolve2();
|
|
29274
|
+
}
|
|
29275
|
+
}
|
|
29191
29276
|
async rawRecordToSettings(rawRecord) {
|
|
29192
29277
|
rawRecord = this.getTransformer().transformObjectRecursively(rawRecord);
|
|
29193
29278
|
await this.onLoadRecord(rawRecord);
|
|
@@ -29292,6 +29377,7 @@ var PluginSuggestionComponent = class extends ComponentEx {
|
|
|
29292
29377
|
app;
|
|
29293
29378
|
isSuggestionDeclined;
|
|
29294
29379
|
pluginNoticeComponent;
|
|
29380
|
+
pluginSettingsComponent;
|
|
29295
29381
|
reason;
|
|
29296
29382
|
setSuggestionDeclined;
|
|
29297
29383
|
suggestedPluginId;
|
|
@@ -29305,6 +29391,7 @@ var PluginSuggestionComponent = class extends ComponentEx {
|
|
|
29305
29391
|
super();
|
|
29306
29392
|
this.app = params.app;
|
|
29307
29393
|
this.pluginNoticeComponent = params.pluginNoticeComponent;
|
|
29394
|
+
this.pluginSettingsComponent = params.pluginSettingsComponent;
|
|
29308
29395
|
this.reason = params.reason;
|
|
29309
29396
|
this.suggestedPluginId = params.suggestedPluginId;
|
|
29310
29397
|
this.suggestedPluginName = params.suggestedPluginName;
|
|
@@ -29357,15 +29444,27 @@ var PluginSuggestionComponent = class extends ComponentEx {
|
|
|
29357
29444
|
}));
|
|
29358
29445
|
}
|
|
29359
29446
|
/**
|
|
29360
|
-
* Loads the component, showing the suggestion notice once the layout is ready
|
|
29447
|
+
* Loads the component, showing the suggestion notice once the layout is ready AND the host's settings
|
|
29448
|
+
* have been read from disk.
|
|
29449
|
+
*
|
|
29450
|
+
* Both waits matter, and neither implies the other:
|
|
29361
29451
|
*
|
|
29362
|
-
*
|
|
29363
|
-
* a moment after this one. Checking
|
|
29364
|
-
*
|
|
29452
|
+
* - Layout-ready, because plugins load in an unspecified order, so the suggested plugin may well be
|
|
29453
|
+
* enabled a moment after this one. Checking earlier would suggest installing something the user
|
|
29454
|
+
* already has.
|
|
29455
|
+
* - Settings-loaded, because {@link PluginSuggestionComponentConstructorParams.isSuggestionDeclined}
|
|
29456
|
+
* reads a setting of the host, and the host's settings component is a SIBLING whose own async load is
|
|
29457
|
+
* still in flight here. On a layout that is already ready — a runtime enable from the Community
|
|
29458
|
+
* Plugins tab, or a re-enable after an update — the layout-ready callback fires immediately, so the
|
|
29459
|
+
* read would see the default `false` and ask again a user who has already declined.
|
|
29365
29460
|
*/
|
|
29366
29461
|
onload() {
|
|
29367
29462
|
this.addChild(
|
|
29368
|
-
new CallbackLayoutReadyComponent(this.app, () => {
|
|
29463
|
+
new CallbackLayoutReadyComponent(this.app, async () => {
|
|
29464
|
+
await this.pluginSettingsComponent.whenLoadedFromFile();
|
|
29465
|
+
if (this.isUnloaded()) {
|
|
29466
|
+
return;
|
|
29467
|
+
}
|
|
29369
29468
|
this.showSuggestionNotice();
|
|
29370
29469
|
})
|
|
29371
29470
|
);
|
|
@@ -37106,9 +37205,13 @@ __export(validation_exports, {
|
|
|
37106
37205
|
WINDOWS_UNSAFE_PATH_CHARS: () => WINDOWS_UNSAFE_PATH_CHARS,
|
|
37107
37206
|
getOsAndObsidianUnsafePathCharsRegExp: () => getOsAndObsidianUnsafePathCharsRegExp,
|
|
37108
37207
|
getOsUnsafePathCharsRegExp: () => getOsUnsafePathCharsRegExp,
|
|
37109
|
-
|
|
37208
|
+
hasWindowsTrailingChars: () => hasWindowsTrailingChars,
|
|
37209
|
+
isValidationMessageHolder: () => isValidationMessageHolder,
|
|
37210
|
+
isWindowsReservedName: () => isWindowsReservedName,
|
|
37211
|
+
trimWindowsTrailingChars: () => trimWindowsTrailingChars
|
|
37110
37212
|
});
|
|
37111
37213
|
var import_obsidian154 = require("obsidian");
|
|
37214
|
+
init_path();
|
|
37112
37215
|
init_reg_exp();
|
|
37113
37216
|
function isValidationMessageHolder(value) {
|
|
37114
37217
|
return value.validationMessage !== void 0;
|
|
@@ -37116,6 +37219,8 @@ function isValidationMessageHolder(value) {
|
|
|
37116
37219
|
var OBSIDIAN_UNSAFE_FILENAME_CHARS = /[#^[\]|]/g;
|
|
37117
37220
|
var WINDOWS_UNSAFE_PATH_CHARS = /[*\\/<>:|?"]/g;
|
|
37118
37221
|
var UNIX_UNSAFE_PATH_CHARS = /[\0/]/g;
|
|
37222
|
+
var WINDOWS_RESERVED_NAME_REG_EXP = /^(?:AUX|COM[1-9]|CON|LPT[1-9]|NUL|PRN)$/i;
|
|
37223
|
+
var WINDOWS_TRAILING_CHARS_REG_EXP = /[ .]+$/;
|
|
37119
37224
|
function getOsAndObsidianUnsafePathCharsRegExp(isWindows) {
|
|
37120
37225
|
return oneOf([
|
|
37121
37226
|
getOsUnsafePathCharsRegExp(isWindows),
|
|
@@ -37126,6 +37231,16 @@ function getOsUnsafePathCharsRegExp(isWindows) {
|
|
|
37126
37231
|
isWindows ??= import_obsidian154.Platform.isWin;
|
|
37127
37232
|
return isWindows ? WINDOWS_UNSAFE_PATH_CHARS : UNIX_UNSAFE_PATH_CHARS;
|
|
37128
37233
|
}
|
|
37234
|
+
function hasWindowsTrailingChars(name) {
|
|
37235
|
+
return WINDOWS_TRAILING_CHARS_REG_EXP.test(name);
|
|
37236
|
+
}
|
|
37237
|
+
function isWindowsReservedName(name) {
|
|
37238
|
+
const trimmedName = trimWindowsTrailingChars(name);
|
|
37239
|
+
return WINDOWS_RESERVED_NAME_REG_EXP.test(basename(trimmedName, extname(trimmedName)));
|
|
37240
|
+
}
|
|
37241
|
+
function trimWindowsTrailingChars(name) {
|
|
37242
|
+
return name.replace(WINDOWS_TRAILING_CHARS_REG_EXP, "");
|
|
37243
|
+
}
|
|
37129
37244
|
|
|
37130
37245
|
// src/obsidian/plugin/plugin-settings-tab.ts
|
|
37131
37246
|
init_plugin_context();
|