@hardlydifficult/text 1.0.6 → 1.0.8

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 CHANGED
@@ -149,3 +149,45 @@ formatWithLineNumbers("line 1\nline 2\n...\nline 100", 98);
149
149
  ```
150
150
 
151
151
  This is useful for displaying code snippets, file contents, or log output with line numbers for reference.
152
+
153
+ ### `createLinker(rules?)`
154
+
155
+ Create a reusable linker that turns matched text patterns into platform-specific links.
156
+
157
+ Supports:
158
+
159
+ - plain strings
160
+ - idempotent re-runs (won't double-link existing linked text)
161
+ - skipping code spans/backticks and existing links by default
162
+ - deterministic conflict handling (priority, then longest match, then rule order)
163
+
164
+ ```typescript
165
+ import { createLinker } from "@hardlydifficult/text";
166
+
167
+ const linker = createLinker()
168
+ .linear("fairmint")
169
+ .githubPr("Fairmint/api")
170
+ .custom(/\bINC-\d+\b/g, ({ match }) => `https://incident.io/${match}`);
171
+
172
+ const slack = linker.linkText("Fix ENG-533 and PR#42", { format: "slack" });
173
+ // "Fix <https://linear.app/fairmint/issue/ENG-533|ENG-533> and <https://github.com/Fairmint/api/pull/42|PR#42>"
174
+ ```
175
+
176
+ You can also pass rules up front:
177
+
178
+ ```typescript
179
+ const linker = createLinker([
180
+ {
181
+ pattern: /\b([A-Z]{2,6}-\d+)\b/g,
182
+ href: "https://linear.app/fairmint/issue/$1",
183
+ },
184
+ ]);
185
+ ```
186
+
187
+ Formats:
188
+
189
+ - `slack` → `<url|text>`
190
+ - `markdown` / `discord` → `[text](url)`
191
+ - `plaintext` → raw `url`
192
+
193
+ `linker.apply(text, options)` is an alias of `linker.linkText(text, options)`.
@@ -2,6 +2,8 @@ export interface BuildTreeOptions {
2
2
  maxLevel2?: number;
3
3
  maxLevel3?: number;
4
4
  annotations?: ReadonlyMap<string, string>;
5
+ /** Directory names to collapse. Matched dirs show a content summary instead of expanding children. */
6
+ collapseDirs?: readonly string[];
5
7
  }
6
8
  /** Default truncation limits for file tree rendering. */
7
9
  export declare const FILE_TREE_DEFAULTS: Required<Pick<BuildTreeOptions, "maxLevel2" | "maxLevel3">>;
@@ -1 +1 @@
1
- {"version":3,"file":"buildFileTree.d.ts","sourceRoot":"","sources":["../src/buildFileTree.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC3C;AAED,yDAAyD;AACzD,eAAO,MAAM,kBAAkB,EAAE,QAAQ,CACvC,IAAI,CAAC,gBAAgB,EAAE,WAAW,GAAG,WAAW,CAAC,CAIlD,CAAC;AAEF;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,SAAS,EAAE,SAAS,MAAM,EAAE,EAC5B,OAAO,GAAE,gBAAqB,GAC7B,MAAM,CAkFR"}
1
+ {"version":3,"file":"buildFileTree.d.ts","sourceRoot":"","sources":["../src/buildFileTree.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,sGAAsG;IACtG,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAClC;AAED,yDAAyD;AACzD,eAAO,MAAM,kBAAkB,EAAE,QAAQ,CACvC,IAAI,CAAC,gBAAgB,EAAE,WAAW,GAAG,WAAW,CAAC,CAIlD,CAAC;AAiCF;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,SAAS,EAAE,SAAS,MAAM,EAAE,EAC5B,OAAO,GAAE,gBAAqB,GAC7B,MAAM,CAyFR"}
@@ -7,12 +7,43 @@ exports.FILE_TREE_DEFAULTS = {
7
7
  maxLevel2: 10,
8
8
  maxLevel3: 3,
9
9
  };
10
+ /**
11
+ * Count all descendant files and directories within a node.
12
+ */
13
+ function countDescendants(node) {
14
+ let files = 0;
15
+ let dirs = 0;
16
+ for (const child of node.children ?? []) {
17
+ if (child.isDir) {
18
+ dirs++;
19
+ const sub = countDescendants(child);
20
+ files += sub.files;
21
+ dirs += sub.dirs;
22
+ }
23
+ else {
24
+ files++;
25
+ }
26
+ }
27
+ return { files, dirs };
28
+ }
29
+ /**
30
+ * Format a collapsed directory summary, e.g. "(42 files across 3 dirs)".
31
+ */
32
+ function formatCollapsedSummary(files, dirs) {
33
+ const filePart = `${String(files)} ${files === 1 ? "file" : "files"}`;
34
+ if (dirs === 0) {
35
+ return `(${filePart})`;
36
+ }
37
+ const dirPart = `${String(dirs)} ${dirs === 1 ? "dir" : "dirs"}`;
38
+ return `(${filePart} across ${dirPart})`;
39
+ }
10
40
  /**
11
41
  * Builds a hierarchical file tree from flat paths with depth-based truncation.
12
42
  * Optionally annotates entries with short descriptions from the annotations map.
13
43
  */
14
44
  function buildFileTree(filePaths, options = {}) {
15
- const { maxLevel2 = exports.FILE_TREE_DEFAULTS.maxLevel2, maxLevel3 = exports.FILE_TREE_DEFAULTS.maxLevel3, annotations, } = options;
45
+ const { maxLevel2 = exports.FILE_TREE_DEFAULTS.maxLevel2, maxLevel3 = exports.FILE_TREE_DEFAULTS.maxLevel3, annotations, collapseDirs, } = options;
46
+ const collapseSet = collapseDirs ? new Set(collapseDirs) : undefined;
16
47
  // Build tree structure
17
48
  const root = { name: "", isDir: true, children: [], fullPath: "" };
18
49
  for (const filePath of filePaths) {
@@ -67,7 +98,13 @@ function buildFileTree(filePaths, options = {}) {
67
98
  const annotation = annotations?.get(child.fullPath) ?? "";
68
99
  const suffix = annotation !== "" ? ` — ${annotation}` : "";
69
100
  lines.push(`${prefix}${child.name}${marker}${suffix}`);
70
- if (child.children && child.children.length > 0) {
101
+ if (child.isDir && collapseSet?.has(child.name) === true) {
102
+ const { files, dirs } = countDescendants(child);
103
+ if (files > 0 || dirs > 0) {
104
+ lines.push(`${prefix} ${formatCollapsedSummary(files, dirs)}`);
105
+ }
106
+ }
107
+ else if (child.children && child.children.length > 0) {
71
108
  renderNode(child, depth + 1, `${prefix} `);
72
109
  }
73
110
  }
@@ -1 +1 @@
1
- {"version":3,"file":"buildFileTree.js","sourceRoot":"","sources":["../src/buildFileTree.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"buildFileTree.js","sourceRoot":"","sources":["../src/buildFileTree.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -8,4 +8,5 @@ export type { BuildTreeOptions } from "./buildFileTree.js";
8
8
  export { convertFormat } from "./convertFormat.js";
9
9
  export type { TextFormat } from "./convertFormat.js";
10
10
  export { formatWithLineNumbers } from "./formatWithLineNumbers.js";
11
+ export { Linker, createLinker, type LinkRule, type LinkHrefBuilder, type LinkMatchContext, type LinkerApplyOptions, type LinkerPlatform, } from "./linker.js";
11
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAC9E,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACrE,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACvE,YAAY,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAC9E,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACrE,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACvE,YAAY,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EACL,MAAM,EACN,YAAY,EACZ,KAAK,QAAQ,EACb,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,cAAc,GACpB,MAAM,aAAa,CAAC"}
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.formatWithLineNumbers = exports.convertFormat = exports.FILE_TREE_DEFAULTS = exports.buildFileTree = exports.formatDuration = exports.slugify = exports.chunkText = exports.extractPlaceholders = exports.replaceTemplate = exports.formatErrorForLog = exports.formatError = exports.getErrorMessage = void 0;
3
+ exports.createLinker = exports.Linker = exports.formatWithLineNumbers = exports.convertFormat = exports.FILE_TREE_DEFAULTS = exports.buildFileTree = exports.formatDuration = exports.slugify = exports.chunkText = exports.extractPlaceholders = exports.replaceTemplate = exports.formatErrorForLog = exports.formatError = exports.getErrorMessage = void 0;
4
4
  var errors_js_1 = require("./errors.js");
5
5
  Object.defineProperty(exports, "getErrorMessage", { enumerable: true, get: function () { return errors_js_1.getErrorMessage; } });
6
6
  Object.defineProperty(exports, "formatError", { enumerable: true, get: function () { return errors_js_1.formatError; } });
@@ -21,4 +21,7 @@ var convertFormat_js_1 = require("./convertFormat.js");
21
21
  Object.defineProperty(exports, "convertFormat", { enumerable: true, get: function () { return convertFormat_js_1.convertFormat; } });
22
22
  var formatWithLineNumbers_js_1 = require("./formatWithLineNumbers.js");
23
23
  Object.defineProperty(exports, "formatWithLineNumbers", { enumerable: true, get: function () { return formatWithLineNumbers_js_1.formatWithLineNumbers; } });
24
+ var linker_js_1 = require("./linker.js");
25
+ Object.defineProperty(exports, "Linker", { enumerable: true, get: function () { return linker_js_1.Linker; } });
26
+ Object.defineProperty(exports, "createLinker", { enumerable: true, get: function () { return linker_js_1.createLinker; } });
24
27
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,yCAA8E;AAArE,4GAAA,eAAe,OAAA;AAAE,wGAAA,WAAW,OAAA;AAAE,8GAAA,iBAAiB,OAAA;AACxD,6CAAqE;AAA5D,8GAAA,eAAe,OAAA;AAAE,kHAAA,mBAAmB,OAAA;AAC7C,+CAA2C;AAAlC,yGAAA,SAAS,OAAA;AAClB,2CAAuC;AAA9B,qGAAA,OAAO,OAAA;AAChB,yDAAqD;AAA5C,mHAAA,cAAc,OAAA;AACvB,uDAAuE;AAA9D,iHAAA,aAAa,OAAA;AAAE,sHAAA,kBAAkB,OAAA;AAE1C,uDAAmD;AAA1C,iHAAA,aAAa,OAAA;AAEtB,uEAAmE;AAA1D,iIAAA,qBAAqB,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,yCAA8E;AAArE,4GAAA,eAAe,OAAA;AAAE,wGAAA,WAAW,OAAA;AAAE,8GAAA,iBAAiB,OAAA;AACxD,6CAAqE;AAA5D,8GAAA,eAAe,OAAA;AAAE,kHAAA,mBAAmB,OAAA;AAC7C,+CAA2C;AAAlC,yGAAA,SAAS,OAAA;AAClB,2CAAuC;AAA9B,qGAAA,OAAO,OAAA;AAChB,yDAAqD;AAA5C,mHAAA,cAAc,OAAA;AACvB,uDAAuE;AAA9D,iHAAA,aAAa,OAAA;AAAE,sHAAA,kBAAkB,OAAA;AAE1C,uDAAmD;AAA1C,iHAAA,aAAa,OAAA;AAEtB,uEAAmE;AAA1D,iIAAA,qBAAqB,OAAA;AAC9B,yCAQqB;AAPnB,mGAAA,MAAM,OAAA;AACN,yGAAA,YAAY,OAAA"}
@@ -0,0 +1,90 @@
1
+ export type LinkerPlatform = "slack" | "discord" | "markdown" | "plaintext";
2
+ export interface LinkerApplyOptions {
3
+ /**
4
+ * Target output format.
5
+ * Alias: `platform`.
6
+ * Default: "markdown"
7
+ */
8
+ format?: LinkerPlatform;
9
+ platform?: LinkerPlatform;
10
+ /**
11
+ * When true (default), skips linkification inside inline/fenced code spans.
12
+ */
13
+ skipCode?: boolean;
14
+ /**
15
+ * When true (default), skips linkification inside existing links.
16
+ */
17
+ skipExistingLinks?: boolean;
18
+ }
19
+ export interface LinkMatchContext {
20
+ /** Full regex match text. */
21
+ match: string;
22
+ /** Positional capture groups. */
23
+ groups: string[];
24
+ /** Rule name assigned at registration time. */
25
+ ruleName: string;
26
+ /** Match start index in the original input. */
27
+ index: number;
28
+ /** Original input string. */
29
+ input: string;
30
+ }
31
+ export type LinkHrefBuilder = (context: LinkMatchContext) => string;
32
+ export interface LinkRule {
33
+ /** Optional stable name for diagnostics and conflict visibility. */
34
+ name?: string;
35
+ /** Match pattern. Global matching is enforced automatically. */
36
+ pattern: RegExp;
37
+ /**
38
+ * URL template string (supports $0/$& for full match, $1..$N for groups).
39
+ * Convenience alias for `toHref`.
40
+ */
41
+ href?: string;
42
+ /**
43
+ * Either a URL template string or a callback that builds an href from match context.
44
+ * If both `href` and `toHref` are provided, `toHref` wins.
45
+ */
46
+ toHref?: string | LinkHrefBuilder;
47
+ /**
48
+ * Higher priority wins for overlapping matches that start at the same index.
49
+ * Default: 0
50
+ */
51
+ priority?: number;
52
+ }
53
+ /**
54
+ * Stateful linker utility that applies configured rules to text.
55
+ *
56
+ * Behavior highlights:
57
+ * - idempotent by default (skips existing links)
58
+ * - skips code spans by default
59
+ * - deterministic overlap resolution (priority, length, then declaration order)
60
+ */
61
+ export declare class Linker {
62
+ private readonly rules;
63
+ constructor(initialRules?: LinkRule[]);
64
+ private addRule;
65
+ rule(rule: LinkRule): this;
66
+ rule(name: string, rule: Omit<LinkRule, "name">): this;
67
+ custom(pattern: RegExp, toHref: string | LinkHrefBuilder, options?: {
68
+ name?: string;
69
+ priority?: number;
70
+ }): this;
71
+ linear(workspace: string, options?: {
72
+ name?: string;
73
+ priority?: number;
74
+ }): this;
75
+ githubPr(repository: string, options?: {
76
+ name?: string;
77
+ priority?: number;
78
+ }): this;
79
+ apply(input: string, options?: LinkerApplyOptions): string;
80
+ linkText(input: string, options?: LinkerApplyOptions): string;
81
+ }
82
+ /**
83
+ * Create a linker with optional initial rules.
84
+ *
85
+ * - `href` accepts template substitutions (`$0`/`$&`, `$1..$N`)
86
+ * - `toHref` callback, when provided, takes precedence over `href`
87
+ * - omitted `priority` defaults to `0`
88
+ */
89
+ export declare function createLinker(initialRules?: LinkRule[]): Linker;
90
+ //# sourceMappingURL=linker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"linker.d.ts","sourceRoot":"","sources":["../src/linker.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,SAAS,GAAG,UAAU,GAAG,WAAW,CAAC;AAE5E,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,gBAAgB;IAC/B,6BAA6B;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,iCAAiC;IACjC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,+CAA+C;IAC/C,QAAQ,EAAE,MAAM,CAAC;IACjB,+CAA+C;IAC/C,KAAK,EAAE,MAAM,CAAC;IACd,6BAA6B;IAC7B,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,EAAE,gBAAgB,KAAK,MAAM,CAAC;AAEpE,MAAM,WAAW,QAAQ;IACvB,oEAAoE;IACpE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gEAAgE;IAChE,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,eAAe,CAAC;IAClC;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AA2JD;;;;;;;GAOG;AACH,qBAAa,MAAM;IACjB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAsB;gBAEhC,YAAY,GAAE,QAAQ,EAAO;IAMzC,OAAO,CAAC,OAAO;IAKf,IAAI,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI;IAC1B,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG,IAAI;IActD,MAAM,CACJ,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,GAAG,eAAe,EAChC,OAAO,GAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAO,GACjD,IAAI;IASP,MAAM,CACJ,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAO,GACjD,IAAI;IAQP,QAAQ,CACN,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAO,GACjD,IAAI;IASP,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,kBAAuB,GAAG,MAAM;IAI9D,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,kBAAuB,GAAG,MAAM;CAqFlE;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,YAAY,GAAE,QAAQ,EAAO,GAAG,MAAM,CAElE"}
package/dist/linker.js ADDED
@@ -0,0 +1,251 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Linker = void 0;
4
+ exports.createLinker = createLinker;
5
+ function ensureGlobal(pattern) {
6
+ if (pattern.flags.includes("g")) {
7
+ return new RegExp(pattern.source, pattern.flags);
8
+ }
9
+ return new RegExp(pattern.source, `${pattern.flags}g`);
10
+ }
11
+ function templateToHref(template) {
12
+ return ({ match, groups }) => template.replace(/\$\$|\$(\d+|&|0)/g, (token, capture) => {
13
+ if (token === "$$") {
14
+ return "$";
15
+ }
16
+ if (capture === "&" || capture === "0") {
17
+ return match;
18
+ }
19
+ const index = Number(capture);
20
+ if (!Number.isInteger(index) || index < 0) {
21
+ return "";
22
+ }
23
+ return groups[index - 1] ?? "";
24
+ });
25
+ }
26
+ function compileRule(rule, index) {
27
+ const source = rule.toHref ?? rule.href;
28
+ if (source === undefined) {
29
+ throw new Error(`Invalid linker rule "${rule.name ?? `rule-${String(index + 1)}`}": missing href/toHref`);
30
+ }
31
+ const toHref = typeof source === "string" ? templateToHref(source) : source;
32
+ return {
33
+ name: rule.name ?? `rule-${String(index + 1)}`,
34
+ pattern: ensureGlobal(rule.pattern),
35
+ priority: rule.priority ?? 0,
36
+ toHref,
37
+ };
38
+ }
39
+ function pushSpans(source, pattern, spans) {
40
+ const matcher = ensureGlobal(pattern);
41
+ let match = matcher.exec(source);
42
+ while (match !== null) {
43
+ if (match[0].length === 0) {
44
+ matcher.lastIndex += 1;
45
+ match = matcher.exec(source);
46
+ continue;
47
+ }
48
+ spans.push({
49
+ start: match.index,
50
+ end: match.index + match[0].length,
51
+ });
52
+ match = matcher.exec(source);
53
+ }
54
+ }
55
+ function normalizeSpans(spans) {
56
+ if (spans.length <= 1) {
57
+ return spans;
58
+ }
59
+ spans.sort((a, b) => a.start - b.start || a.end - b.end);
60
+ const merged = [spans[0]];
61
+ for (let i = 1; i < spans.length; i++) {
62
+ const current = spans[i];
63
+ const previous = merged[merged.length - 1];
64
+ if (current.start <= previous.end) {
65
+ previous.end = Math.max(previous.end, current.end);
66
+ continue;
67
+ }
68
+ merged.push(current);
69
+ }
70
+ return merged;
71
+ }
72
+ function getProtectedSpans(input, options) {
73
+ const spans = [];
74
+ if (options.skipCode) {
75
+ // Fenced code blocks first, then inline spans.
76
+ pushSpans(input, /```[\s\S]*?```/g, spans);
77
+ pushSpans(input, /`[^`\n]+`/g, spans);
78
+ }
79
+ if (options.skipExistingLinks) {
80
+ // Slack and angle-bracket links/mentions.
81
+ pushSpans(input, /<[^>\n]+>/g, spans);
82
+ // Markdown links.
83
+ pushSpans(input, /\[[^\]]+\]\([^)]+\)/g, spans);
84
+ // Plain URLs.
85
+ pushSpans(input, /https?:\/\/[^\s<>()]+/g, spans);
86
+ }
87
+ return normalizeSpans(spans);
88
+ }
89
+ function overlapsProtected(spans, start, end) {
90
+ for (const span of spans) {
91
+ if (span.end <= start) {
92
+ continue;
93
+ }
94
+ if (span.start >= end) {
95
+ return false;
96
+ }
97
+ return true;
98
+ }
99
+ return false;
100
+ }
101
+ function formatLink(href, text, platform) {
102
+ switch (platform) {
103
+ case "slack":
104
+ return `<${href}|${text}>`;
105
+ case "discord":
106
+ case "markdown":
107
+ return `[${text}](${href})`;
108
+ case "plaintext":
109
+ return href;
110
+ default:
111
+ return text;
112
+ }
113
+ }
114
+ function resolvePlatform(options) {
115
+ return options.format ?? options.platform ?? "markdown";
116
+ }
117
+ /**
118
+ * Stateful linker utility that applies configured rules to text.
119
+ *
120
+ * Behavior highlights:
121
+ * - idempotent by default (skips existing links)
122
+ * - skips code spans by default
123
+ * - deterministic overlap resolution (priority, length, then declaration order)
124
+ */
125
+ class Linker {
126
+ rules = [];
127
+ constructor(initialRules = []) {
128
+ for (const rule of initialRules) {
129
+ this.addRule(rule);
130
+ }
131
+ }
132
+ addRule(rule) {
133
+ this.rules.push(compileRule(rule, this.rules.length));
134
+ return this;
135
+ }
136
+ rule(ruleOrName, maybeRule) {
137
+ if (typeof ruleOrName === "string") {
138
+ if (maybeRule === undefined) {
139
+ throw new Error(`Missing rule config for "${ruleOrName}"`);
140
+ }
141
+ return this.addRule({ ...maybeRule, name: ruleOrName });
142
+ }
143
+ return this.addRule(ruleOrName);
144
+ }
145
+ custom(pattern, toHref, options = {}) {
146
+ return this.addRule({
147
+ name: options.name,
148
+ pattern,
149
+ toHref,
150
+ priority: options.priority,
151
+ });
152
+ }
153
+ linear(workspace, options = {}) {
154
+ return this.custom(/\b([A-Z]{2,6}-\d+)\b/g, ({ match }) => `https://linear.app/${workspace}/issue/${match}`, { name: options.name ?? "linear", priority: options.priority });
155
+ }
156
+ githubPr(repository, options = {}) {
157
+ return this.custom(/\bPR#(\d+)\b/g, ({ groups }) => `https://github.com/${repository}/pull/${groups[0] ?? ""}`, { name: options.name ?? "github-pr", priority: options.priority });
158
+ }
159
+ apply(input, options = {}) {
160
+ return this.linkText(input, options);
161
+ }
162
+ linkText(input, options = {}) {
163
+ if (this.rules.length === 0 || input === "") {
164
+ return input;
165
+ }
166
+ const platform = resolvePlatform(options);
167
+ const protectedSpans = getProtectedSpans(input, {
168
+ skipCode: options.skipCode ?? true,
169
+ skipExistingLinks: options.skipExistingLinks ?? true,
170
+ });
171
+ const candidates = [];
172
+ for (let ruleOrder = 0; ruleOrder < this.rules.length; ruleOrder++) {
173
+ const rule = this.rules[ruleOrder];
174
+ const matcher = rule.pattern;
175
+ matcher.lastIndex = 0;
176
+ let match = matcher.exec(input);
177
+ while (match !== null) {
178
+ const matchedText = match[0];
179
+ if (matchedText.length === 0) {
180
+ matcher.lastIndex += 1;
181
+ match = matcher.exec(input);
182
+ continue;
183
+ }
184
+ const start = match.index;
185
+ const end = start + matchedText.length;
186
+ if (!overlapsProtected(protectedSpans, start, end)) {
187
+ candidates.push({
188
+ start,
189
+ end,
190
+ text: matchedText,
191
+ groups: match.slice(1),
192
+ ruleOrder,
193
+ ruleName: rule.name,
194
+ priority: rule.priority,
195
+ });
196
+ }
197
+ match = matcher.exec(input);
198
+ }
199
+ }
200
+ if (candidates.length === 0) {
201
+ return input;
202
+ }
203
+ candidates.sort((a, b) => a.start - b.start ||
204
+ b.priority - a.priority ||
205
+ b.end - b.start - (a.end - a.start) ||
206
+ b.ruleOrder - a.ruleOrder);
207
+ const selected = [];
208
+ let cursorEnd = -1;
209
+ for (const candidate of candidates) {
210
+ if (candidate.start < cursorEnd) {
211
+ continue;
212
+ }
213
+ selected.push(candidate);
214
+ cursorEnd = candidate.end;
215
+ }
216
+ let output = "";
217
+ let inputCursor = 0;
218
+ for (const candidate of selected) {
219
+ output += input.slice(inputCursor, candidate.start);
220
+ const rule = this.rules[candidate.ruleOrder];
221
+ const href = rule.toHref({
222
+ match: candidate.text,
223
+ groups: candidate.groups,
224
+ ruleName: candidate.ruleName,
225
+ index: candidate.start,
226
+ input,
227
+ });
228
+ if (href === "") {
229
+ output += candidate.text;
230
+ }
231
+ else {
232
+ output += formatLink(href, candidate.text, platform);
233
+ }
234
+ inputCursor = candidate.end;
235
+ }
236
+ output += input.slice(inputCursor);
237
+ return output;
238
+ }
239
+ }
240
+ exports.Linker = Linker;
241
+ /**
242
+ * Create a linker with optional initial rules.
243
+ *
244
+ * - `href` accepts template substitutions (`$0`/`$&`, `$1..$N`)
245
+ * - `toHref` callback, when provided, takes precedence over `href`
246
+ * - omitted `priority` defaults to `0`
247
+ */
248
+ function createLinker(initialRules = []) {
249
+ return new Linker(initialRules);
250
+ }
251
+ //# sourceMappingURL=linker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"linker.js","sourceRoot":"","sources":["../src/linker.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hardlydifficult/text",
3
- "version": "1.0.6",
3
+ "version": "1.0.8",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "files": [