stikfix 1.3.2 → 1.6.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.
@@ -23,6 +23,7 @@ __export(native_host_exports, {
23
23
  handlePickFolder: () => handlePickFolder,
24
24
  handleStartHost: () => handleStartHost,
25
25
  main: () => main,
26
+ runNativeHost: () => runNativeHost,
26
27
  validateChosenFolder: () => validateChosenFolder
27
28
  });
28
29
  module.exports = __toCommonJS(native_host_exports);
@@ -212,8 +213,11 @@ function handleStartHost(cfg, root, spawnFn = import_node_child_process2.spawn,
212
213
  }
213
214
  const nodePath = typeof cfg.nodePath === "string" && cfg.nodePath.length > 0 ? cfg.nodePath : process.execPath;
214
215
  const hostEntry = resolveHostEntry(cfg);
216
+ const hostExe = typeof cfg.hostExe === "string" && cfg.hostExe.length > 0 ? cfg.hostExe : void 0;
217
+ const spawnCmd = hostExe ?? nodePath;
218
+ const spawnArgs = hostExe ? ["serve", "--root", resolvedRoot] : [hostEntry, "--root", resolvedRoot];
215
219
  try {
216
- const child = spawnFn(nodePath, [hostEntry, "--root", resolvedRoot], {
220
+ const child = spawnFn(spawnCmd, spawnArgs, {
217
221
  detached: true,
218
222
  stdio: "ignore",
219
223
  windowsHide: true
@@ -315,7 +319,17 @@ function main() {
315
319
  process.exit(0);
316
320
  });
317
321
  }
318
- if (typeof require !== "undefined" && typeof module !== "undefined" && require.main === module) {
322
+ async function runNativeHost() {
323
+ main();
324
+ }
325
+ function bundledInExe() {
326
+ try {
327
+ return typeof __STIKFIX_BUNDLED__ !== "undefined" && __STIKFIX_BUNDLED__ === true;
328
+ } catch {
329
+ return false;
330
+ }
331
+ }
332
+ if (!bundledInExe() && typeof require !== "undefined" && typeof module !== "undefined" && require.main === module) {
319
333
  main();
320
334
  }
321
335
  // Annotate the CommonJS export names for ESM import in node:
@@ -323,5 +337,6 @@ if (typeof require !== "undefined" && typeof module !== "undefined" && require.m
323
337
  handlePickFolder,
324
338
  handleStartHost,
325
339
  main,
340
+ runNativeHost,
326
341
  validateChosenFolder
327
342
  });
@@ -0,0 +1,69 @@
1
+ /**
2
+ * URL-path matching and pin position computation for stikfix persistent pins.
3
+ *
4
+ * matchesUrlPath + computePinPosition — pure, node:test-safe (no DOM/chrome at module level).
5
+ * Scroll offsets and anchor rects are PASSED AS PARAMETERS by the caller (pin.ts in Plan 04),
6
+ * which supplies window.scrollX/scrollY and el.getBoundingClientRect() at render time.
7
+ *
8
+ * INVARIANT: No top-level browser API access — no window/document/chrome references.
9
+ * This module imports cleanly under node:test.
10
+ */
11
+ /**
12
+ * Compare two URLs by pathname only, ignoring query string and fragment (D-02).
13
+ * Returns false (not throws) on any malformed URL input.
14
+ *
15
+ * @param noteUrl The URL stored in the note's YAML frontmatter
16
+ * @param pageUrl The current page URL from chrome.tabs.get
17
+ */
18
+ export function matchesUrlPath(noteUrl, pageUrl) {
19
+ try {
20
+ const notePath = new URL(noteUrl).pathname;
21
+ const pagePath = new URL(pageUrl).pathname;
22
+ return notePath === pagePath;
23
+ }
24
+ catch {
25
+ return false;
26
+ }
27
+ }
28
+ /**
29
+ * Compute the CSS viewport position for an on-page pin — pure, DOM-free.
30
+ *
31
+ * Branch logic:
32
+ * - orphaned || anchorRect === null: orphaned-fallback at last-known page-absolute
33
+ * rect minus scroll offsets → { left: storedRect.x - scrollX, top: storedRect.y - scrollY, orphaned: true }
34
+ * - !orphaned && anchorRect !== null: use anchorRect x/y directly (already in
35
+ * fixed/viewport coords from getBoundingClientRect or stored viewport coords
36
+ * for free notes) → { left: anchorRect.x, top: anchorRect.y, orphaned: false }
37
+ *
38
+ * The caller (pin.ts) passes:
39
+ * - anchorRect: el.getBoundingClientRect() for element pins, stored viewport
40
+ * coords {x,y,width:0,height:0} for free pins, or null when selector misses.
41
+ * - storedRect: page-absolute rect from frontmatter (for orphaned-fallback).
42
+ * - scrollX/scrollY: window.scrollX / window.scrollY at call time.
43
+ * - orphaned: true when the selector re-query returned null.
44
+ *
45
+ * NEVER reads window.scrollX or window.scrollY internally — caller supplies them.
46
+ *
47
+ * @param anchorRect Live fixed-coord rect from getBoundingClientRect, or null
48
+ * @param storedRect Page-absolute rect from frontmatter (orphaned fallback), or null
49
+ * @param scrollX window.scrollX at call time (passed by caller)
50
+ * @param scrollY window.scrollY at call time (passed by caller)
51
+ * @param orphaned true when selector matched nothing on the current page
52
+ */
53
+ export function computePinPosition(anchorRect, storedRect, scrollX, scrollY, orphaned) {
54
+ if (orphaned || anchorRect === null) {
55
+ // Orphaned fallback: last-known page-absolute rect → convert to viewport via scroll
56
+ return {
57
+ left: (storedRect?.x ?? 0) - scrollX,
58
+ top: (storedRect?.y ?? 0) - scrollY,
59
+ orphaned: true,
60
+ };
61
+ }
62
+ // Element-anchored (live getBoundingClientRect in fixed/viewport coords)
63
+ // OR free-floating (stored viewport coords already in anchorRect x/y)
64
+ return {
65
+ left: anchorRect.x,
66
+ top: anchorRect.y,
67
+ orphaned: false,
68
+ };
69
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stikfix",
3
- "version": "1.3.2",
3
+ "version": "1.6.0",
4
4
  "description": "Pin sticky notes on any page — your AI reads them.",
5
5
  "license": "MIT",
6
6
  "author": "Omer Nesher <omernesher@gmail.com>",
@@ -32,6 +32,7 @@
32
32
  },
33
33
  "files": [
34
34
  "dist/host/src",
35
+ "dist/lib/pin-position.js",
35
36
  "dist/host/stikfix-init.cjs",
36
37
  "dist/host/stikfix-native.cjs",
37
38
  "public/icon",
@@ -50,13 +51,19 @@
50
51
  "test:lib": "tsc -p tsconfig.lib.json && node --test \"dist/lib/lib/test/**/*.test.js\"",
51
52
  "test": "tsc -p tsconfig.host.json && node --test \"dist/host/test/**/*.test.js\"",
52
53
  "check": "tsc --noEmit && tsc --noEmit -p tsconfig.host.json && node scripts/clean-room-check.mjs && node scripts/host-smoke-test.mjs && npm run test:lib && npm test",
54
+ "pack:crx": "node scripts/pack-crx.mjs",
55
+ "gen:update-xml": "node scripts/gen-update-xml.mjs",
56
+ "build:sea": "node scripts/build-sea.mjs",
57
+ "build:installer": "node scripts/build-installer.mjs",
53
58
  "postinstall": "node -e \"try{require.resolve('wxt');require('node:child_process').execSync('wxt prepare',{stdio:'inherit'})}catch(e){}\""
54
59
  },
55
60
  "devDependencies": {
56
61
  "@medv/finder": "4.0.2",
57
62
  "@types/chrome": "0.1.42",
58
63
  "@types/node": "25.9.1",
64
+ "crx3": "2.0.0",
59
65
  "interactjs": "1.10.27",
66
+ "postject": "1.0.0-alpha.6",
60
67
  "typescript": "6.0.3",
61
68
  "wxt": "0.20.26"
62
69
  },