@nowline/embed 0.4.2 → 0.5.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.
package/dist/share.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- /** Default share destination — the Nowline Free app's open route. */
2
1
  export declare const DEFAULT_SHARE_BASE = "https://free.nowline.io/open";
3
2
  /**
4
3
  * The `share` initialize option selects where share links point.
@@ -1 +1 @@
1
- {"version":3,"file":"share.d.ts","sourceRoot":"","sources":["../src/share.ts"],"names":[],"mappings":"AAeA,qEAAqE;AACrE,eAAO,MAAM,kBAAkB,iCAAiC,CAAC;AAEjE;;;;;;;;;;GAUG;AACH,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7F;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEjD;AAgBD,MAAM,WAAW,qBAAqB;IAClC,mEAAmE;IACnE,MAAM,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,iDAAiD;IACjD,KAAK,EAAE,WAAW,CAAC;CACtB;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,qBAAqB,GAAG,MAAM,GAAG,IAAI,CAwBjG"}
1
+ {"version":3,"file":"share.d.ts","sourceRoot":"","sources":["../src/share.ts"],"names":[],"mappings":"AAeA,eAAO,MAAM,kBAAkB,iCAAiC,CAAC;AAEjE;;;;;;;;;;GAUG;AACH,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7F;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEjD;AAgBD,MAAM,WAAW,qBAAqB;IAClC,mEAAmE;IACnE,MAAM,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,iDAAiD;IACjD,KAAK,EAAE,WAAW,CAAC;CACtB;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,qBAAqB,GAAG,MAAM,GAAG,IAAI,CAwBjG"}
package/dist/share.js CHANGED
@@ -11,7 +11,6 @@
11
11
  //
12
12
  // Sync, works on every browser, no feature-detect.
13
13
  import { zlibSync } from 'fflate';
14
- /** Default share destination — the Nowline Free app's open route. */
15
14
  export const DEFAULT_SHARE_BASE = 'https://free.nowline.io/open';
16
15
  /**
17
16
  * Encode source text → `#text=<base64url(zlib(utf8(source)))>`.
package/dist/share.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"share.js","sourceRoot":"","sources":["../src/share.ts"],"names":[],"mappings":"AAAA,mEAAmE;AACnE,kDAAkD;AAClD,EAAE;AACF,4DAA4D;AAC5D,wCAAwC;AACxC,qBAAqB;AACrB,EAAE;AACF,mEAAmE;AACnE,mEAAmE;AACnE,WAAW;AACX,EAAE;AACF,mDAAmD;AAEnD,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAElC,qEAAqE;AACrE,MAAM,CAAC,MAAM,kBAAkB,GAAG,8BAA8B,CAAC;AAejE;;;;;;;GAOG;AACH,MAAM,UAAU,UAAU,CAAC,MAAc;IACrC,OAAO,SAAS,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC;AAC7C,CAAC;AAED,iEAAiE;AACjE,SAAS,cAAc,CAAC,MAAc;IAClC,MAAM,KAAK,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC/C,MAAM,UAAU,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACnC,iEAAiE;IACjE,uCAAuC;IACvC,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,4CAA4C;IAClE,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC;QAChD,GAAG,IAAI,MAAM,CAAC,YAAY,CAAC,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;IACrE,CAAC;IACD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AAChF,CAAC;AAeD;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAyB;IAC9E,IAAI,KAAK,KAAK,KAAK,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;QACtC,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC5B,wCAAwC;QACxC,IAAI,SAAS,KAAK,SAAS,IAAI,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;YACjD,OAAO,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,kBAAkB,CAAC,SAAS,CAAC,CAAC,CAAC;QAC3E,CAAC;QACD,OAAO,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC;IACnE,CAAC;IAED,2EAA2E;IAC3E,MAAM,IAAI,GAAG,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,KAAK,CAAC;IACzD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC;IAE1B,IAAI,SAAS,KAAK,SAAS,IAAI,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QACjD,GAAG,CAAC,IAAI,GAAG,OAAO,kBAAkB,CAAC,SAAS,CAAC,EAAE,CAAC;IACtD,CAAC;SAAM,CAAC;QACJ,GAAG,CAAC,IAAI,GAAG,QAAQ,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC;IAChD,CAAC;IAED,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;AAC1B,CAAC;AAED,SAAS,QAAQ,CAAC,GAAW;IACzB,IAAI,CAAC;QACD,OAAO,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC;IAC9C,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,KAAK,CAAC;IACjB,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"share.js","sourceRoot":"","sources":["../src/share.ts"],"names":[],"mappings":"AAAA,mEAAmE;AACnE,kDAAkD;AAClD,EAAE;AACF,4DAA4D;AAC5D,wCAAwC;AACxC,qBAAqB;AACrB,EAAE;AACF,mEAAmE;AACnE,mEAAmE;AACnE,WAAW;AACX,EAAE;AACF,mDAAmD;AAEnD,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAElC,MAAM,CAAC,MAAM,kBAAkB,GAAG,8BAA8B,CAAC;AAejE;;;;;;;GAOG;AACH,MAAM,UAAU,UAAU,CAAC,MAAc;IACrC,OAAO,SAAS,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC;AAC7C,CAAC;AAED,iEAAiE;AACjE,SAAS,cAAc,CAAC,MAAc;IAClC,MAAM,KAAK,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC/C,MAAM,UAAU,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACnC,iEAAiE;IACjE,uCAAuC;IACvC,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,4CAA4C;IAClE,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC;QAChD,GAAG,IAAI,MAAM,CAAC,YAAY,CAAC,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;IACrE,CAAC;IACD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AAChF,CAAC;AAeD;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAyB;IAC9E,IAAI,KAAK,KAAK,KAAK,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;QACtC,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC5B,wCAAwC;QACxC,IAAI,SAAS,KAAK,SAAS,IAAI,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;YACjD,OAAO,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,kBAAkB,CAAC,SAAS,CAAC,CAAC,CAAC;QAC3E,CAAC;QACD,OAAO,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC;IACnE,CAAC;IAED,2EAA2E;IAC3E,MAAM,IAAI,GAAG,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,KAAK,CAAC;IACzD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC;IAE1B,IAAI,SAAS,KAAK,SAAS,IAAI,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QACjD,GAAG,CAAC,IAAI,GAAG,OAAO,kBAAkB,CAAC,SAAS,CAAC,EAAE,CAAC;IACtD,CAAC;SAAM,CAAC;QACJ,GAAG,CAAC,IAAI,GAAG,QAAQ,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC;IAChD,CAAC;IAED,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;AAC1B,CAAC;AAED,SAAS,QAAQ,CAAC,GAAW;IACzB,IAAI,CAAC;QACD,OAAO,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC;IAC9C,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,KAAK,CAAC;IACjB,CAAC;AACL,CAAC"}
package/dist/theme.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import type { ThemeName } from '@nowline/layout';
2
- export type EmbedTheme = ThemeName | 'auto';
3
- export declare function resolveSystemTheme(): ThemeName;
1
+ import { type ThemeName } from '@nowline/layout';
2
+ export type EmbedTheme = ThemeName | 'greyscale' | 'auto';
3
+ export declare function resolveSystemTheme(): 'light' | 'dark';
4
4
  export declare function effectiveTheme(theme: EmbedTheme | undefined, systemTheme: ThemeName): ThemeName;
5
5
  //# sourceMappingURL=theme.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../src/theme.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,MAAM,CAAC;AAE5C,wBAAgB,kBAAkB,IAAI,SAAS,CAS9C;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,UAAU,GAAG,SAAS,EAAE,WAAW,EAAE,SAAS,GAAG,SAAS,CAG/F"}
1
+ {"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../src/theme.ts"],"names":[],"mappings":"AAeA,OAAO,EAAsB,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAGrE,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,WAAW,GAAG,MAAM,CAAC;AAE1D,wBAAgB,kBAAkB,IAAI,OAAO,GAAG,MAAM,CASrD;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,UAAU,GAAG,SAAS,EAAE,WAAW,EAAE,SAAS,GAAG,SAAS,CAG/F"}
package/dist/theme.js CHANGED
@@ -1,7 +1,8 @@
1
1
  // Theme resolution for the embed.
2
2
  //
3
3
  // Precedence (highest to lowest):
4
- // 1. `initialize({ theme })` flag (light / dark / auto).
4
+ // 1. `initialize({ theme })` flag (light / dark / grayscale / auto;
5
+ // `greyscale` is accepted and canonicalized to `grayscale`).
5
6
  // 2. The file's own `nowline v1 theme:` directive — handled inside
6
7
  // layout, so we just don't override it when the embed config says
7
8
  // `'auto'` and we have no system preference reading.
@@ -11,6 +12,7 @@
11
12
  // flipping the OS theme mid-session does not cause every embedded
12
13
  // roadmap on the page to repaint. This matches Mermaid's posture and
13
14
  // keeps the embed deterministic for screenshot tools.
15
+ import { normalizeThemeName } from '@nowline/layout';
14
16
  export function resolveSystemTheme() {
15
17
  if (typeof globalThis === 'undefined')
16
18
  return 'light';
@@ -25,8 +27,8 @@ export function resolveSystemTheme() {
25
27
  }
26
28
  }
27
29
  export function effectiveTheme(theme, systemTheme) {
28
- if (theme === 'light' || theme === 'dark')
29
- return theme;
30
+ if (theme && theme !== 'auto')
31
+ return normalizeThemeName(theme) ?? systemTheme;
30
32
  return systemTheme;
31
33
  }
32
34
  //# sourceMappingURL=theme.js.map
package/dist/theme.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"theme.js","sourceRoot":"","sources":["../src/theme.ts"],"names":[],"mappings":"AAAA,kCAAkC;AAClC,EAAE;AACF,kCAAkC;AAClC,2DAA2D;AAC3D,qEAAqE;AACrE,uEAAuE;AACvE,0DAA0D;AAC1D,yDAAyD;AACzD,EAAE;AACF,sEAAsE;AACtE,kEAAkE;AAClE,qEAAqE;AACrE,sDAAsD;AAMtD,MAAM,UAAU,kBAAkB;IAC9B,IAAI,OAAO,UAAU,KAAK,WAAW;QAAE,OAAO,OAAO,CAAC;IACtD,MAAM,GAAG,GAAI,UAAmE,CAAC,UAAU,CAAC;IAC5F,IAAI,OAAO,GAAG,KAAK,UAAU;QAAE,OAAO,OAAO,CAAC;IAC9C,IAAI,CAAC;QACD,OAAO,GAAG,CAAC,8BAA8B,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;IAC1E,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,OAAO,CAAC;IACnB,CAAC;AACL,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAA6B,EAAE,WAAsB;IAChF,IAAI,KAAK,KAAK,OAAO,IAAI,KAAK,KAAK,MAAM;QAAE,OAAO,KAAK,CAAC;IACxD,OAAO,WAAW,CAAC;AACvB,CAAC"}
1
+ {"version":3,"file":"theme.js","sourceRoot":"","sources":["../src/theme.ts"],"names":[],"mappings":"AAAA,kCAAkC;AAClC,EAAE;AACF,kCAAkC;AAClC,sEAAsE;AACtE,kEAAkE;AAClE,qEAAqE;AACrE,uEAAuE;AACvE,0DAA0D;AAC1D,yDAAyD;AACzD,EAAE;AACF,sEAAsE;AACtE,kEAAkE;AAClE,qEAAqE;AACrE,sDAAsD;AAEtD,OAAO,EAAE,kBAAkB,EAAkB,MAAM,iBAAiB,CAAC;AAKrE,MAAM,UAAU,kBAAkB;IAC9B,IAAI,OAAO,UAAU,KAAK,WAAW;QAAE,OAAO,OAAO,CAAC;IACtD,MAAM,GAAG,GAAI,UAAmE,CAAC,UAAU,CAAC;IAC5F,IAAI,OAAO,GAAG,KAAK,UAAU;QAAE,OAAO,OAAO,CAAC;IAC9C,IAAI,CAAC;QACD,OAAO,GAAG,CAAC,8BAA8B,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;IAC1E,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,OAAO,CAAC;IACnB,CAAC;AACL,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAA6B,EAAE,WAAsB;IAChF,IAAI,KAAK,IAAI,KAAK,KAAK,MAAM;QAAE,OAAO,kBAAkB,CAAC,KAAK,CAAC,IAAI,WAAW,CAAC;IAC/E,OAAO,WAAW,CAAC;AACvB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nowline/embed",
3
- "version": "0.4.2",
3
+ "version": "0.5.0",
4
4
  "description": "Browser embed bundle for Nowline. Drop a <script> tag and ```nowline``` blocks render in place.",
5
5
  "license": "Apache-2.0",
6
6
  "engines": {
@@ -41,15 +41,14 @@
41
41
  "dependencies": {
42
42
  "fflate": "^0.8.3",
43
43
  "langium": "~4.2.4",
44
- "@nowline/core": "0.4.2",
45
- "@nowline/layout": "0.4.2",
46
- "@nowline/renderer": "0.4.2",
47
- "@nowline/browser": "0.4.2"
44
+ "@nowline/browser": "0.5.0",
45
+ "@nowline/core": "0.5.0",
46
+ "@nowline/layout": "0.5.0",
47
+ "@nowline/renderer": "0.5.0"
48
48
  },
49
49
  "devDependencies": {
50
50
  "@types/node": "^25.9.1",
51
51
  "esbuild": "^0.28.0",
52
- "firebase": "^12.13.0",
53
52
  "happy-dom": "^20.9.0",
54
53
  "typescript": "^6.0.3",
55
54
  "vitest": "^4.1.7"
@@ -59,7 +58,6 @@
59
58
  "watch": "tsc -b tsconfig.json --watch",
60
59
  "typecheck": "tsc --noEmit -p tsconfig.json",
61
60
  "bundle": "node scripts/bundle.mjs",
62
- "bundle:dev": "node scripts/bundle.mjs --dev",
63
61
  "check-size": "node scripts/check-size.mjs",
64
62
  "test": "vitest run",
65
63
  "test:watch": "vitest"
package/src/index.ts CHANGED
@@ -5,17 +5,12 @@
5
5
  // The IIFE bundle exposes everything below as `window.nowline.*`. ESM
6
6
  // consumers import named exports from the package root.
7
7
 
8
- import { EMBED_SHA, EMBED_VERSION } from './auth/env.js';
9
-
10
- // Build-time constant substituted by esbuild's `define` (see
11
- // `scripts/bundle.mjs`). Reading it directly at the call site (rather
12
- // than via an `IS_DEV` re-export from env.ts) means esbuild can fold
13
- // the `if` below to a literal `true`/`false` at minify time and
14
- // dead-code-eliminate the dynamic-import branch in the prod bundle,
15
- // stripping `firebase/app` + `firebase/auth` from `dist/nowline.min.js`.
16
- // The `typeof` guard keeps the file safe to import under vitest, where
17
- // esbuild's define never runs and the identifier is undeclared.
18
- declare const __NOWLINE_EMBED_ENV__: string;
8
+ // Build-time constants substituted by esbuild's `define` (see
9
+ // `scripts/bundle.mjs`). The `typeof` guards keep this file safe to
10
+ // import under vitest, where esbuild's define never runs and the
11
+ // identifiers are undeclared.
12
+ declare const __NOWLINE_EMBED_VERSION__: string;
13
+ declare const __NOWLINE_EMBED_SHA__: string;
19
14
 
20
15
  import {
21
16
  __resetAutoScanForTests,
@@ -51,8 +46,10 @@ export {
51
46
  * pages and bug reports can identify the exact build without scraping
52
47
  * the comment banner.
53
48
  */
54
- export const version: string = EMBED_VERSION;
55
- export const sha: string = EMBED_SHA;
49
+ export const version: string =
50
+ typeof __NOWLINE_EMBED_VERSION__ !== 'undefined' ? __NOWLINE_EMBED_VERSION__ : '0.0.0';
51
+ export const sha: string =
52
+ typeof __NOWLINE_EMBED_SHA__ !== 'undefined' ? __NOWLINE_EMBED_SHA__ : 'unknown';
56
53
 
57
54
  const DEFAULT_SELECTOR = 'pre code.language-nowline, code.language-nowline';
58
55
 
@@ -80,7 +77,8 @@ export interface InitializeOptions {
80
77
  today?: Date;
81
78
  /**
82
79
  * Controls the "Share on Nowline" anchor appended after each rendered SVG.
83
- * - `true` (default) — link to `https://free.nowline.io/open#text=…`.
80
+ * - `true` (default) — link to the Free app open route
81
+ * (`https://free.nowline.io/open`).
84
82
  * - string — a custom base URL (may include a path); the fragment is appended.
85
83
  * - `false` / `'none'` — no anchor rendered.
86
84
  * - `{ textUrl, remoteUrl }` — template with `{text}` / `{url}` substitution.
@@ -205,23 +203,6 @@ export const run = init;
205
203
  if (typeof document !== 'undefined' && !autoStartScheduled) {
206
204
  autoStartScheduled = true;
207
205
 
208
- // Dev-only Firebase Auth gate (embed.nowline.dev). The condition
209
- // reads `__NOWLINE_EMBED_ENV__` directly so esbuild's `define`
210
- // substitutes a literal string at minify time — the prod bundle
211
- // sees `if ("prod" === "dev")` → `if (false)` and DCEs the dynamic
212
- // import that pulls in `firebase/app` + `firebase/auth`.
213
- // `check-size.mjs` asserts no `firebase` literal survives in the
214
- // prod IIFE as a belt-and-suspenders check.
215
- if (typeof __NOWLINE_EMBED_ENV__ !== 'undefined' && __NOWLINE_EMBED_ENV__ === 'dev') {
216
- void import('./auth/firebase-auth.client.js')
217
- .then(({ startDevAuthGate }) => {
218
- startDevAuthGate();
219
- })
220
- .catch((err) => {
221
- console.error('[nowline] dev auth gate failed to load:', err);
222
- });
223
- }
224
-
225
206
  const start = (): void => {
226
207
  if (!config.startOnLoad) return;
227
208
  // Fire-and-forget; render errors are surfaced via `console.error`
package/src/share.ts CHANGED
@@ -13,7 +13,6 @@
13
13
 
14
14
  import { zlibSync } from 'fflate';
15
15
 
16
- /** Default share destination — the Nowline Free app's open route. */
17
16
  export const DEFAULT_SHARE_BASE = 'https://free.nowline.io/open';
18
17
 
19
18
  /**
package/src/theme.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  // Theme resolution for the embed.
2
2
  //
3
3
  // Precedence (highest to lowest):
4
- // 1. `initialize({ theme })` flag (light / dark / auto).
4
+ // 1. `initialize({ theme })` flag (light / dark / grayscale / auto;
5
+ // `greyscale` is accepted and canonicalized to `grayscale`).
5
6
  // 2. The file's own `nowline v1 theme:` directive — handled inside
6
7
  // layout, so we just don't override it when the embed config says
7
8
  // `'auto'` and we have no system preference reading.
@@ -12,11 +13,12 @@
12
13
  // roadmap on the page to repaint. This matches Mermaid's posture and
13
14
  // keeps the embed deterministic for screenshot tools.
14
15
 
15
- import type { ThemeName } from '@nowline/layout';
16
+ import { normalizeThemeName, type ThemeName } from '@nowline/layout';
16
17
 
17
- export type EmbedTheme = ThemeName | 'auto';
18
+ // `'greyscale'` (UK) is an accepted alias for the canonical `'grayscale'`.
19
+ export type EmbedTheme = ThemeName | 'greyscale' | 'auto';
18
20
 
19
- export function resolveSystemTheme(): ThemeName {
21
+ export function resolveSystemTheme(): 'light' | 'dark' {
20
22
  if (typeof globalThis === 'undefined') return 'light';
21
23
  const win = (globalThis as { matchMedia?: (q: string) => { matches: boolean } }).matchMedia;
22
24
  if (typeof win !== 'function') return 'light';
@@ -28,6 +30,6 @@ export function resolveSystemTheme(): ThemeName {
28
30
  }
29
31
 
30
32
  export function effectiveTheme(theme: EmbedTheme | undefined, systemTheme: ThemeName): ThemeName {
31
- if (theme === 'light' || theme === 'dark') return theme;
33
+ if (theme && theme !== 'auto') return normalizeThemeName(theme) ?? systemTheme;
32
34
  return systemTheme;
33
35
  }
@@ -1,20 +0,0 @@
1
- /**
2
- * Allowlist for the dev embed bundle's Firebase Auth gate.
3
- *
4
- * An email is allowlisted if either:
5
- * 1. Its domain is in ALLOWED_DOMAINS (e.g. anything @nowline.io), OR
6
- * 2. The exact lowercase email is in ALLOWED_EMAILS.
7
- *
8
- * Mirrors the commercial site's `auth-allowlist.ts` so both Lolay
9
- * dev surfaces (the marketing site and the embed CDN dev tier) share
10
- * one allowlist policy. Keep this short; when it grows past ~5 entries,
11
- * migrate to Firebase custom claims (Admin SDK) or a Firestore
12
- * `allowlist` collection.
13
- *
14
- * See specs/embed.md § Bootstrap status (dev auth gate) and
15
- * the infrastructure deploy runbook § 4 for the deploy-side wiring.
16
- */
17
- export declare const ALLOWED_DOMAINS: readonly string[];
18
- export declare const ALLOWED_EMAILS: readonly string[];
19
- export declare function isAllowlisted(email: string | null | undefined): boolean;
20
- //# sourceMappingURL=allowlist.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"allowlist.d.ts","sourceRoot":"","sources":["../../src/auth/allowlist.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,eAAO,MAAM,eAAe,EAAE,SAAS,MAAM,EAAmB,CAAC;AAEjE,eAAO,MAAM,cAAc,EAAE,SAAS,MAAM,EAE3C,CAAC;AAEF,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAQvE"}
@@ -1,33 +0,0 @@
1
- /**
2
- * Allowlist for the dev embed bundle's Firebase Auth gate.
3
- *
4
- * An email is allowlisted if either:
5
- * 1. Its domain is in ALLOWED_DOMAINS (e.g. anything @nowline.io), OR
6
- * 2. The exact lowercase email is in ALLOWED_EMAILS.
7
- *
8
- * Mirrors the commercial site's `auth-allowlist.ts` so both Lolay
9
- * dev surfaces (the marketing site and the embed CDN dev tier) share
10
- * one allowlist policy. Keep this short; when it grows past ~5 entries,
11
- * migrate to Firebase custom claims (Admin SDK) or a Firestore
12
- * `allowlist` collection.
13
- *
14
- * See specs/embed.md § Bootstrap status (dev auth gate) and
15
- * the infrastructure deploy runbook § 4 for the deploy-side wiring.
16
- */
17
- export const ALLOWED_DOMAINS = ['nowline.io'];
18
- export const ALLOWED_EMAILS = [
19
- // Add additional allowlisted Google account emails here, one per line.
20
- ];
21
- export function isAllowlisted(email) {
22
- if (!email)
23
- return false;
24
- const normalized = email.trim().toLowerCase();
25
- if (ALLOWED_EMAILS.includes(normalized))
26
- return true;
27
- const at = normalized.lastIndexOf('@');
28
- if (at === -1)
29
- return false;
30
- const domain = normalized.slice(at + 1);
31
- return ALLOWED_DOMAINS.includes(domain);
32
- }
33
- //# sourceMappingURL=allowlist.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"allowlist.js","sourceRoot":"","sources":["../../src/auth/allowlist.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,CAAC,MAAM,eAAe,GAAsB,CAAC,YAAY,CAAC,CAAC;AAEjE,MAAM,CAAC,MAAM,cAAc,GAAsB;AAC7C,uEAAuE;CAC1E,CAAC;AAEF,MAAM,UAAU,aAAa,CAAC,KAAgC;IAC1D,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC9C,IAAI,cAAc,CAAC,QAAQ,CAAC,UAAU,CAAC;QAAE,OAAO,IAAI,CAAC;IACrD,MAAM,EAAE,GAAG,UAAU,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACvC,IAAI,EAAE,KAAK,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IAC5B,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;IACxC,OAAO,eAAe,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AAC5C,CAAC"}
@@ -1,23 +0,0 @@
1
- /**
2
- * Build-time environment helpers for `@nowline/embed`.
3
- *
4
- * `__NOWLINE_EMBED_ENV__` is substituted at bundle time by esbuild's
5
- * `define` (see `packages/embed/scripts/bundle.mjs`). The substitution
6
- * lets the prod minified bundle dead-code-eliminate the dev auth gate
7
- * and its Firebase imports — when the constant folds to the literal
8
- * string `"prod"`, every `IS_DEV` branch becomes `false` and esbuild's
9
- * minifier strips the dynamic-import site that pulls in `firebase/app`
10
- * + `firebase/auth`.
11
- *
12
- * The `typeof` guards keep this module safe to import under vitest,
13
- * where esbuild's define never runs and the identifier is undeclared.
14
- */
15
- export type EmbedEnv = 'dev' | 'prod';
16
- export declare const EMBED_ENV: EmbedEnv;
17
- export declare const IS_DEV: boolean;
18
- export declare const IS_PROD: boolean;
19
- export declare const EMBED_VERSION: string;
20
- export declare const EMBED_SHA: string;
21
- export declare const PROD_ORIGIN = "https://embed.nowline.io";
22
- export declare const DEV_ORIGIN = "https://embed.nowline.dev";
23
- //# sourceMappingURL=env.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/auth/env.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAMH,MAAM,MAAM,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;AAEtC,eAAO,MAAM,SAAS,EAAE,QAGR,CAAC;AAEjB,eAAO,MAAM,MAAM,EAAE,OAA6B,CAAC;AACnD,eAAO,MAAM,OAAO,EAAE,OAA8B,CAAC;AAErD,eAAO,MAAM,aAAa,EAAE,MAC8D,CAAC;AAE3F,eAAO,MAAM,SAAS,EAAE,MAC4D,CAAC;AAErF,eAAO,MAAM,WAAW,6BAA6B,CAAC;AACtD,eAAO,MAAM,UAAU,8BAA8B,CAAC"}
package/dist/auth/env.js DELETED
@@ -1,24 +0,0 @@
1
- /**
2
- * Build-time environment helpers for `@nowline/embed`.
3
- *
4
- * `__NOWLINE_EMBED_ENV__` is substituted at bundle time by esbuild's
5
- * `define` (see `packages/embed/scripts/bundle.mjs`). The substitution
6
- * lets the prod minified bundle dead-code-eliminate the dev auth gate
7
- * and its Firebase imports — when the constant folds to the literal
8
- * string `"prod"`, every `IS_DEV` branch becomes `false` and esbuild's
9
- * minifier strips the dynamic-import site that pulls in `firebase/app`
10
- * + `firebase/auth`.
11
- *
12
- * The `typeof` guards keep this module safe to import under vitest,
13
- * where esbuild's define never runs and the identifier is undeclared.
14
- */
15
- export const EMBED_ENV = typeof __NOWLINE_EMBED_ENV__ !== 'undefined' && __NOWLINE_EMBED_ENV__ === 'dev'
16
- ? 'dev'
17
- : 'prod';
18
- export const IS_DEV = EMBED_ENV === 'dev';
19
- export const IS_PROD = EMBED_ENV === 'prod';
20
- export const EMBED_VERSION = typeof __NOWLINE_EMBED_VERSION__ !== 'undefined' ? __NOWLINE_EMBED_VERSION__ : '0.0.0';
21
- export const EMBED_SHA = typeof __NOWLINE_EMBED_SHA__ !== 'undefined' ? __NOWLINE_EMBED_SHA__ : 'unknown';
22
- export const PROD_ORIGIN = 'https://embed.nowline.io';
23
- export const DEV_ORIGIN = 'https://embed.nowline.dev';
24
- //# sourceMappingURL=env.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/auth/env.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAQH,MAAM,CAAC,MAAM,SAAS,GAClB,OAAO,qBAAqB,KAAK,WAAW,IAAI,qBAAqB,KAAK,KAAK;IAC3E,CAAC,CAAC,KAAK;IACP,CAAC,CAAC,MAAM,CAAC;AAEjB,MAAM,CAAC,MAAM,MAAM,GAAY,SAAS,KAAK,KAAK,CAAC;AACnD,MAAM,CAAC,MAAM,OAAO,GAAY,SAAS,KAAK,MAAM,CAAC;AAErD,MAAM,CAAC,MAAM,aAAa,GACtB,OAAO,yBAAyB,KAAK,WAAW,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC,OAAO,CAAC;AAE3F,MAAM,CAAC,MAAM,SAAS,GAClB,OAAO,qBAAqB,KAAK,WAAW,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,SAAS,CAAC;AAErF,MAAM,CAAC,MAAM,WAAW,GAAG,0BAA0B,CAAC;AACtD,MAAM,CAAC,MAAM,UAAU,GAAG,2BAA2B,CAAC"}
@@ -1,21 +0,0 @@
1
- /**
2
- * Client-side Firebase Auth gate for the dev embed bundle.
3
- *
4
- * Mirrors the commercial site's `firebase-auth.client.ts` so the
5
- * two Lolay dev surfaces share one allowlist UX. Loaded only on the
6
- * dev build (when `__NOWLINE_EMBED_ENV__ === 'dev'`); the prod build
7
- * tree-shakes the dynamic import in `src/index.ts` and never pulls
8
- * `firebase/app` or `firebase/auth` into the IIFE.
9
- *
10
- * Renders a full-viewport overlay with z-index 2147483647 so it sits
11
- * above any host-page content. Until the visitor signs in with an
12
- * allowlisted Google account, the overlay stays put; once allowlisted,
13
- * it removes itself and the embed's auto-scan reaches the rendered
14
- * SVG underneath. The host page is told nothing — the gate is purely
15
- * client-side, opaque to the embedder.
16
- *
17
- * See specs/embed.md § Bootstrap status (dev auth gate) and
18
- * the infrastructure deploy runbook § 4 for the deploy-side wiring.
19
- */
20
- export declare function startDevAuthGate(): void;
21
- //# sourceMappingURL=firebase-auth.client.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"firebase-auth.client.d.ts","sourceRoot":"","sources":["../../src/auth/firebase-auth.client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAyGH,wBAAgB,gBAAgB,IAAI,IAAI,CAsDvC"}
@@ -1,146 +0,0 @@
1
- /**
2
- * Client-side Firebase Auth gate for the dev embed bundle.
3
- *
4
- * Mirrors the commercial site's `firebase-auth.client.ts` so the
5
- * two Lolay dev surfaces share one allowlist UX. Loaded only on the
6
- * dev build (when `__NOWLINE_EMBED_ENV__ === 'dev'`); the prod build
7
- * tree-shakes the dynamic import in `src/index.ts` and never pulls
8
- * `firebase/app` or `firebase/auth` into the IIFE.
9
- *
10
- * Renders a full-viewport overlay with z-index 2147483647 so it sits
11
- * above any host-page content. Until the visitor signs in with an
12
- * allowlisted Google account, the overlay stays put; once allowlisted,
13
- * it removes itself and the embed's auto-scan reaches the rendered
14
- * SVG underneath. The host page is told nothing — the gate is purely
15
- * client-side, opaque to the embedder.
16
- *
17
- * See specs/embed.md § Bootstrap status (dev auth gate) and
18
- * the infrastructure deploy runbook § 4 for the deploy-side wiring.
19
- */
20
- import { initializeApp } from 'firebase/app';
21
- import { GoogleAuthProvider, getAuth, onAuthStateChanged, signInWithPopup, signOut, } from 'firebase/auth';
22
- import { isAllowlisted } from './allowlist.js';
23
- const config = {
24
- apiKey: typeof __NOWLINE_FIREBASE_API_KEY__ !== 'undefined' ? __NOWLINE_FIREBASE_API_KEY__ : '',
25
- authDomain: typeof __NOWLINE_FIREBASE_AUTH_DOMAIN__ !== 'undefined'
26
- ? __NOWLINE_FIREBASE_AUTH_DOMAIN__
27
- : '',
28
- projectId: typeof __NOWLINE_FIREBASE_PROJECT_ID__ !== 'undefined'
29
- ? __NOWLINE_FIREBASE_PROJECT_ID__
30
- : '',
31
- appId: typeof __NOWLINE_FIREBASE_APP_ID__ !== 'undefined' ? __NOWLINE_FIREBASE_APP_ID__ : '',
32
- };
33
- const OVERLAY_ID = 'nowline-embed-dev-auth-overlay';
34
- let app = null;
35
- let auth = null;
36
- function getOrCreateOverlay() {
37
- let overlay = document.getElementById(OVERLAY_ID);
38
- if (overlay)
39
- return overlay;
40
- overlay = document.createElement('div');
41
- overlay.id = OVERLAY_ID;
42
- overlay.setAttribute('role', 'dialog');
43
- overlay.setAttribute('aria-modal', 'true');
44
- overlay.setAttribute('aria-label', 'Internal preview sign-in');
45
- overlay.style.cssText = [
46
- 'position: fixed',
47
- 'inset: 0',
48
- 'z-index: 2147483647',
49
- 'background-color: #ffffff',
50
- 'color: #1a1a2e',
51
- 'display: flex',
52
- 'align-items: center',
53
- 'justify-content: center',
54
- 'padding: 1.5rem',
55
- 'font-family: system-ui, -apple-system, "Segoe UI", sans-serif',
56
- ].join(';');
57
- document.body.appendChild(overlay);
58
- return overlay;
59
- }
60
- function removeOverlay() {
61
- const overlay = document.getElementById(OVERLAY_ID);
62
- overlay?.remove();
63
- }
64
- function renderSignIn(overlay, onClick) {
65
- overlay.innerHTML = `
66
- <div style="max-width: 28rem; text-align: center;">
67
- <div style="font-size: 0.75rem; letter-spacing: 0.08em; text-transform: uppercase; color: #5a5a6a; margin-bottom: 0.75rem;">embed.nowline.dev &mdash; internal preview</div>
68
- <h1 style="font-size: 1.875rem; font-weight: 700; margin: 0 0 0.75rem;">Sign in to continue</h1>
69
- <p style="margin: 0 0 1.5rem; color: #5a5a6a;">Access is limited to allowlisted Lolay accounts. Production embed is at <a href="https://embed.nowline.io" style="color: #1a4ed8;">embed.nowline.io</a>.</p>
70
- <button type="button" id="nowline-embed-dev-signin-btn" style="display: inline-block; padding: 0.75rem 1.5rem; border-radius: 8px; background-color: #e53e3e; color: #ffffff; font-weight: 700; border: 1px solid transparent; cursor: pointer; font-size: 1rem;">Sign in with Google</button>
71
- </div>
72
- `;
73
- const btn = overlay.querySelector('#nowline-embed-dev-signin-btn');
74
- btn?.addEventListener('click', onClick);
75
- }
76
- function renderDenied(overlay, email, onSignOut) {
77
- overlay.innerHTML = `
78
- <div style="max-width: 28rem; text-align: center;">
79
- <div style="font-size: 0.75rem; letter-spacing: 0.08em; text-transform: uppercase; color: #5a5a6a; margin-bottom: 0.75rem;">embed.nowline.dev &mdash; internal preview</div>
80
- <h1 style="font-size: 1.875rem; font-weight: 700; margin: 0 0 0.75rem;">Access denied</h1>
81
- <p style="margin: 0 0 1.5rem; color: #5a5a6a;">${escapeHtml(email)} is not on the allowlist for this preview environment. Production embed is publicly available at <a href="https://embed.nowline.io" style="color: #1a4ed8;">embed.nowline.io</a>.</p>
82
- <button type="button" id="nowline-embed-dev-signout-btn" style="display: inline-block; padding: 0.75rem 1.5rem; border-radius: 8px; background-color: transparent; color: #1a1a2e; font-weight: 700; border: 1px solid #c0c0c0; cursor: pointer; font-size: 1rem;">Sign out</button>
83
- </div>
84
- `;
85
- const btn = overlay.querySelector('#nowline-embed-dev-signout-btn');
86
- btn?.addEventListener('click', onSignOut);
87
- }
88
- function escapeHtml(value) {
89
- return value
90
- .replace(/&/g, '&amp;')
91
- .replace(/</g, '&lt;')
92
- .replace(/>/g, '&gt;')
93
- .replace(/"/g, '&quot;')
94
- .replace(/'/g, '&#39;');
95
- }
96
- export function startDevAuthGate() {
97
- if (typeof window === 'undefined' || typeof document === 'undefined')
98
- return;
99
- if (!config.apiKey || !config.authDomain || !config.projectId || !config.appId) {
100
- // No firebase config baked in. Likely a local `pnpm bundle` without
101
- // PUBLIC_FIREBASE_* exported (CI deploys always set them). Skip the
102
- // overlay rather than render an unrecoverable dialog so devs aren't
103
- // locked out of their own local builds.
104
- console.warn('[nowline-embed-dev-auth-gate] Missing PUBLIC_FIREBASE_* env vars at build time; gate is disabled. Configure them in .github/workflows/embed-cdn.yml or your local environment to enable.');
105
- return;
106
- }
107
- // Create the overlay up front so it covers content while Firebase
108
- // initialises; subsequent renders call getOrCreateOverlay() again
109
- // to find the same element.
110
- getOrCreateOverlay();
111
- app ??= initializeApp(config);
112
- auth ??= getAuth(app);
113
- const provider = new GoogleAuthProvider();
114
- const handleSignIn = () => {
115
- void (async () => {
116
- try {
117
- await signInWithPopup(auth, provider);
118
- }
119
- catch (err) {
120
- console.error('[nowline-embed-dev-auth-gate] Sign-in failed:', err);
121
- }
122
- })();
123
- };
124
- const handleSignOut = () => {
125
- void (async () => {
126
- try {
127
- await signOut(auth);
128
- }
129
- catch (err) {
130
- console.error('[nowline-embed-dev-auth-gate] Sign-out failed:', err);
131
- }
132
- })();
133
- };
134
- onAuthStateChanged(auth, (user) => {
135
- if (!user) {
136
- renderSignIn(getOrCreateOverlay(), handleSignIn);
137
- return;
138
- }
139
- if (!isAllowlisted(user.email)) {
140
- renderDenied(getOrCreateOverlay(), user.email ?? 'unknown', handleSignOut);
141
- return;
142
- }
143
- removeOverlay();
144
- });
145
- }
146
- //# sourceMappingURL=firebase-auth.client.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"firebase-auth.client.js","sourceRoot":"","sources":["../../src/auth/firebase-auth.client.ts"],"names":[],"mappings":"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"}
@@ -1,32 +0,0 @@
1
- /**
2
- * Allowlist for the dev embed bundle's Firebase Auth gate.
3
- *
4
- * An email is allowlisted if either:
5
- * 1. Its domain is in ALLOWED_DOMAINS (e.g. anything @nowline.io), OR
6
- * 2. The exact lowercase email is in ALLOWED_EMAILS.
7
- *
8
- * Mirrors the commercial site's `auth-allowlist.ts` so both Lolay
9
- * dev surfaces (the marketing site and the embed CDN dev tier) share
10
- * one allowlist policy. Keep this short; when it grows past ~5 entries,
11
- * migrate to Firebase custom claims (Admin SDK) or a Firestore
12
- * `allowlist` collection.
13
- *
14
- * See specs/embed.md § Bootstrap status (dev auth gate) and
15
- * the infrastructure deploy runbook § 4 for the deploy-side wiring.
16
- */
17
-
18
- export const ALLOWED_DOMAINS: readonly string[] = ['nowline.io'];
19
-
20
- export const ALLOWED_EMAILS: readonly string[] = [
21
- // Add additional allowlisted Google account emails here, one per line.
22
- ];
23
-
24
- export function isAllowlisted(email: string | null | undefined): boolean {
25
- if (!email) return false;
26
- const normalized = email.trim().toLowerCase();
27
- if (ALLOWED_EMAILS.includes(normalized)) return true;
28
- const at = normalized.lastIndexOf('@');
29
- if (at === -1) return false;
30
- const domain = normalized.slice(at + 1);
31
- return ALLOWED_DOMAINS.includes(domain);
32
- }
package/src/auth/env.ts DELETED
@@ -1,37 +0,0 @@
1
- /**
2
- * Build-time environment helpers for `@nowline/embed`.
3
- *
4
- * `__NOWLINE_EMBED_ENV__` is substituted at bundle time by esbuild's
5
- * `define` (see `packages/embed/scripts/bundle.mjs`). The substitution
6
- * lets the prod minified bundle dead-code-eliminate the dev auth gate
7
- * and its Firebase imports — when the constant folds to the literal
8
- * string `"prod"`, every `IS_DEV` branch becomes `false` and esbuild's
9
- * minifier strips the dynamic-import site that pulls in `firebase/app`
10
- * + `firebase/auth`.
11
- *
12
- * The `typeof` guards keep this module safe to import under vitest,
13
- * where esbuild's define never runs and the identifier is undeclared.
14
- */
15
-
16
- declare const __NOWLINE_EMBED_ENV__: string;
17
- declare const __NOWLINE_EMBED_VERSION__: string;
18
- declare const __NOWLINE_EMBED_SHA__: string;
19
-
20
- export type EmbedEnv = 'dev' | 'prod';
21
-
22
- export const EMBED_ENV: EmbedEnv =
23
- typeof __NOWLINE_EMBED_ENV__ !== 'undefined' && __NOWLINE_EMBED_ENV__ === 'dev'
24
- ? 'dev'
25
- : 'prod';
26
-
27
- export const IS_DEV: boolean = EMBED_ENV === 'dev';
28
- export const IS_PROD: boolean = EMBED_ENV === 'prod';
29
-
30
- export const EMBED_VERSION: string =
31
- typeof __NOWLINE_EMBED_VERSION__ !== 'undefined' ? __NOWLINE_EMBED_VERSION__ : '0.0.0';
32
-
33
- export const EMBED_SHA: string =
34
- typeof __NOWLINE_EMBED_SHA__ !== 'undefined' ? __NOWLINE_EMBED_SHA__ : 'unknown';
35
-
36
- export const PROD_ORIGIN = 'https://embed.nowline.io';
37
- export const DEV_ORIGIN = 'https://embed.nowline.dev';