@heroiclands/content-language-server 0.2.1 → 0.2.2

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.
@@ -39,7 +39,7 @@ An explicitly configured foreign project can be searched even when it is not a d
39
39
 
40
40
  Completion inside a `[[...` link searches the selected projects' saved indexes, including when an editor inserts the closing `]]` after the cursor. The query matches anywhere in a note's full name, aliases, shortcode, short Address, or canonical Address. The existing `nameAscii` and `aliasesAscii` fields supply typeable forms of names with non-ASCII characters. The server builds lowercase search keys in memory when it loads an index and transliterates the query with the same rule. The JSONL format carries no separate search field.
41
41
 
42
- Each result identifies its owning package and canonical Address. Readable `note` content, systemless `none` targets, and game system documents stay selectable even when they share a Markdown file. An ordinary `[[link|text]]` defaults to `note`, while an embedded `![[link|text]]` defaults to `none` and uses `image` as the type of a bare shortcode. Stating a system selects that exact target: `[[macro-autoattack|Text]]` reaches the readable note, and `[[none-macro-autoattack|Text]]` reaches the Macro. An embed offers asset targets and can reach an icon with `![[icon-anvil|Anvil]]`.
42
+ Each result identifies its owning package and canonical Address. Address completion items also carry `data.address` with that canonical Address, `data.display` with the authored name or exactly matched alias, and `data.exact` to distinguish a full name or alias match from a substring match. Editors can use these fields when completing a link's display text without merging targets that share a file or name. Readable `note` content, systemless `none` targets, and game system documents stay selectable even when they share a Markdown file. An ordinary `[[link|text]]` defaults to `note`, while an embedded `![[link|text]]` defaults to `none` and uses `image` as the type of a bare shortcode. Stating a system selects that exact target: `[[macro-autoattack|Text]]` reaches the readable note, and `[[none-macro-autoattack|Text]]` reaches the Macro. An embed offers asset targets and can reach an icon with `![[icon-anvil|Anvil]]`.
43
43
 
44
44
  The text edit inserts the shortest Address that parses to the selected target at the cursor. A local game system document can require `sohl-being-bctrncml`, while a target in another package requires a fully qualified Address. A `[[...#` query completes anchors from the selected note. Completion in a declared frontmatter Address field uses that field's type and system defaults: image, icon, and folder fields use `none`; other fields use their game system block or `note` outside one. Explicit system segments keep their stated meaning. Input `doc<type>` aliases select readable note records; generated records and completion candidates use the authored type.
45
45
 
@@ -82,6 +82,15 @@ function searchKey(value) {
82
82
  return typeof value === "string" ? (asciiName(value) ?? "").toLowerCase() : "";
83
83
  }
84
84
 
85
+ /** Preserve the authored spelling when a query exactly names a note or alias. */
86
+ function completionDisplay(record, query) {
87
+ const full = noteName(record);
88
+ const needle = searchKey(query);
89
+ const names = [full, ...(record.name?.aliases ?? [])];
90
+ const exact = needle ? names.find((name) => searchKey(name) === needle) : null;
91
+ return { display: exact ?? full, exact: Boolean(exact) };
92
+ }
93
+
85
94
  /** Parse editor symbol filters without looking outside configured projects. */
86
95
  function symbolQuery(query) {
87
96
  let text = String(query ?? "").trim();
@@ -108,12 +117,13 @@ function symbolQuery(query) {
108
117
  }
109
118
 
110
119
  /** A completion item changes the Address text while its label remains readable. */
111
- function completionItem(label, detail, inserted, text, from, to, filterText) {
120
+ function completionItem(label, detail, inserted, text, from, to, filterText, data) {
112
121
  return {
113
122
  label,
114
123
  kind: 18,
115
124
  detail,
116
125
  filterText,
126
+ ...(data ? { data } : {}),
117
127
  textEdit: {
118
128
  range: { start: positionAt(text, from), end: positionAt(text, to) },
119
129
  newText: inserted,
@@ -646,6 +656,10 @@ export class ContentWorkspace {
646
656
  context.from,
647
657
  context.to,
648
658
  context.query,
659
+ {
660
+ address: canonical,
661
+ ...completionDisplay(record, context.query),
662
+ },
649
663
  ),
650
664
  );
651
665
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@heroiclands/content-language-server",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "Language server for HeroicLands content projects",
5
5
  "license": "GPL-3.0-or-later",
6
6
  "type": "module",