@velvetmonkey/vault-core 2.0.135 → 2.0.136
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/wikilinks.js +41 -0
- package/package.json +1 -1
package/dist/wikilinks.js
CHANGED
|
@@ -571,11 +571,18 @@ export function resolveAliasWikilinks(content, entities, options = {}) {
|
|
|
571
571
|
// Key: alias (lowercase if caseInsensitive)
|
|
572
572
|
// Value: { entityName: canonical name, aliasText: original alias casing }
|
|
573
573
|
const aliasMap = new Map();
|
|
574
|
+
// Track ambiguous aliases (shared by multiple entities) — skip these to avoid wrong resolution
|
|
575
|
+
const ambiguousAliases = new Set();
|
|
574
576
|
for (const entity of entities) {
|
|
575
577
|
if (typeof entity === 'string')
|
|
576
578
|
continue;
|
|
577
579
|
for (const alias of entity.aliases) {
|
|
578
580
|
const key = caseInsensitive ? alias.toLowerCase() : alias;
|
|
581
|
+
const existing = aliasMap.get(key);
|
|
582
|
+
if (existing && existing.entityName !== entity.name) {
|
|
583
|
+
// Two different entities claim this alias — mark as ambiguous
|
|
584
|
+
ambiguousAliases.add(key);
|
|
585
|
+
}
|
|
579
586
|
aliasMap.set(key, { entityName: entity.name, aliasText: alias });
|
|
580
587
|
}
|
|
581
588
|
// Also map the entity name itself so we can detect if target already points to entity
|
|
@@ -611,6 +618,10 @@ export function resolveAliasWikilinks(content, entities, options = {}) {
|
|
|
611
618
|
// Target doesn't match any alias or entity name - leave unchanged
|
|
612
619
|
continue;
|
|
613
620
|
}
|
|
621
|
+
// Skip ambiguous aliases — multiple entities claim this alias, resolution would be arbitrary
|
|
622
|
+
if (ambiguousAliases.has(targetKey)) {
|
|
623
|
+
continue;
|
|
624
|
+
}
|
|
614
625
|
// Check if already pointing to the entity name (no resolution needed)
|
|
615
626
|
const entityNameKey = caseInsensitive ? aliasInfo.entityName.toLowerCase() : aliasInfo.entityName;
|
|
616
627
|
if (targetKey === entityNameKey) {
|
|
@@ -1116,6 +1127,36 @@ export function detectImplicitEntities(content, config = {}) {
|
|
|
1116
1127
|
}
|
|
1117
1128
|
}
|
|
1118
1129
|
}
|
|
1130
|
+
// Guard: max 4 words — longer phrases are almost always prose, not entity names
|
|
1131
|
+
const wordCount = text.split(/\s+/).length;
|
|
1132
|
+
if (wordCount > 4)
|
|
1133
|
+
continue;
|
|
1134
|
+
// Guard: max 40 chars
|
|
1135
|
+
if (text.length > 40)
|
|
1136
|
+
continue;
|
|
1137
|
+
// Guard: strip trailing punctuation from match text
|
|
1138
|
+
const stripped = text.replace(/[,.:;!?]+$/, '');
|
|
1139
|
+
if (stripped.length < minEntityLength)
|
|
1140
|
+
continue;
|
|
1141
|
+
if (stripped !== text) {
|
|
1142
|
+
end = start + stripped.length;
|
|
1143
|
+
text = stripped;
|
|
1144
|
+
}
|
|
1145
|
+
// Guard: sentence-start capitalization — if match begins at start of line
|
|
1146
|
+
// (after list marker or newline), first word cap is positional, not semantic.
|
|
1147
|
+
// Require at least 2 capitalized words remaining after the first.
|
|
1148
|
+
if (start > 0) {
|
|
1149
|
+
const lineStart = content.lastIndexOf('\n', start - 1) + 1;
|
|
1150
|
+
const before = content.substring(lineStart, start).trim();
|
|
1151
|
+
// After list marker (- * >) or empty (line start), first cap is positional
|
|
1152
|
+
if (before === '' || /^[-*>]+$/.test(before) || /^\d+\.$/.test(before)) {
|
|
1153
|
+
// Already trimmed sentence starters above; this catches the remaining
|
|
1154
|
+
// cases where the first word is capitalized only because of its position
|
|
1155
|
+
const wordsArr = text.split(/\s+/);
|
|
1156
|
+
if (wordsArr.length <= 2)
|
|
1157
|
+
continue; // Too few words to trust positional cap
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1119
1160
|
if (!shouldExclude(text) && !isProtected(start, end)) {
|
|
1120
1161
|
detected.push({ text, start, end, pattern: 'proper-nouns' });
|
|
1121
1162
|
seenTexts.add(text.toLowerCase());
|
package/package.json
CHANGED