@morlay/dsh-client-ui-primitives 0.0.2-alpha.4 → 0.0.2-alpha.5

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/src/reference.ts CHANGED
@@ -10,6 +10,7 @@ import {
10
10
  asciiAlpha,
11
11
  asciiAlphanumeric,
12
12
  asciiDigit,
13
+ markdownLineEnding,
13
14
  markdownLineEndingOrSpace,
14
15
  unicodePunctuation,
15
16
  unicodeWhitespace,
@@ -62,6 +63,8 @@ const SCHEME = /^([A-Za-z][A-Za-z0-9+.-]*):/u;
62
63
 
63
64
  const BARE_PATH = /^([^:]+):(\d+)(?::(\d+))?$/u;
64
65
 
66
+ const MENTION_WHITESPACE = /\s/u;
67
+
65
68
  const URI_UNSAFE = /[%#()\s<>"`]/gu;
66
69
 
67
70
  const PATH_PUNCTUATION: readonly Code[] = [
@@ -127,6 +130,13 @@ export function isLocalReference(reference: Reference): boolean {
127
130
  return !EXTERNAL_PROTOCOLS.includes(reference.protocol);
128
131
  }
129
132
 
133
+ // 引用在提示文本里的 mention 形态:`@` 接路径,路径含空白时用引号包住。
134
+ // 谁产出的都走这一个函数归一——消息里是这一形态与「产生方是谁」无关。
135
+ export function formatReferenceMention(reference: Reference): string {
136
+ const path = reference.path ?? "";
137
+ return MENTION_WHITESPACE.test(path) ? `@"${path}"` : `@${path}`;
138
+ }
139
+
130
140
  export function findReferences(text: string): readonly ReferenceSpan[] {
131
141
  const spans: ReferenceSpan[] = [];
132
142
  if (text === "" || !TRIGGERS.some((trigger) => text.includes(trigger))) return spans;
@@ -210,9 +220,34 @@ const tokenizeReference: Tokenizer = function (effects, ok, nok) {
210
220
  }
211
221
 
212
222
  function afterAt(code: Code): State | undefined {
223
+ if (code === codes.quotationMark) {
224
+ effects.consume(code);
225
+ return quotedPath;
226
+ }
213
227
  return asciiAlpha(code) ? headStart(code) : pathStart(code);
214
228
  }
215
229
 
230
+ // `@"path with spaces"`:引号内的空格是路径的一部分,换行与未闭合都让整个形态退回普通文本。
231
+ function quotedPath(code: Code): State | undefined {
232
+ if (code === null || markdownLineEnding(code)) return nok(code);
233
+ effects.consume(code);
234
+ return code === codes.quotationMark ? afterQuotedPath : quotedPath;
235
+ }
236
+
237
+ function afterQuotedPath(code: Code): State | undefined {
238
+ if (code !== codes.numberSign) return finish(code);
239
+ effects.consume(code);
240
+ return fragmentInside;
241
+ }
242
+
243
+ function fragmentInside(code: Code): State | undefined {
244
+ if (isPathCode(code) || code === codes.numberSign) {
245
+ effects.consume(code);
246
+ return fragmentInside;
247
+ }
248
+ return finish(code);
249
+ }
250
+
216
251
  function headStart(code: Code): State | undefined {
217
252
  if (!asciiAlpha(code)) return nok(code);
218
253
  head = "";
@@ -469,6 +504,7 @@ function textOf(node: MarkdownNode): string {
469
504
  function parseBareReference(raw: string): Reference | undefined {
470
505
  const body = raw.startsWith("@") ? raw.slice(1) : raw;
471
506
  if (body === "") return undefined;
507
+ if (body.startsWith(QUOTED_PATH)) return parseQuotedReference(body);
472
508
  const scheme = SCHEME.exec(body);
473
509
  if (scheme !== null && isKnownScheme(scheme[1] as string)) return parseReference(body);
474
510
  const matched = BARE_PATH.exec(body);
@@ -486,6 +522,20 @@ function parseBareReference(raw: string): Reference | undefined {
486
522
  };
487
523
  }
488
524
 
525
+ /** 引号 mention 的起手字符:`@"path with spaces"`。 */
526
+ const QUOTED_PATH = '"';
527
+
528
+ function parseQuotedReference(body: string): Reference | undefined {
529
+ const end = body.indexOf(QUOTED_PATH, 1);
530
+ if (end === -1) return undefined;
531
+ const path = body.slice(1, end);
532
+ if (path === "") return undefined;
533
+ // 闭合引号之后只允许行号 fragment(`@"a b.ts"#L12-L40`);其它尾巴说明这不是一个引号引用。
534
+ const fragment = splitLineFragment(body.slice(end + 1));
535
+ if (fragment.head !== "") return undefined;
536
+ return { protocol: DEFAULT_PROTOCOL, path, ...fragment.lines };
537
+ }
538
+
489
539
  export function referenceFromMarkdown(): MdastExtension {
490
540
  return {
491
541
  enter: { reference: enterReference },