bsign-customization-full 0.0.2 → 0.0.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bsign-customization-full",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "dev": "vite",
Binary file
Binary file
package/src/index.css CHANGED
@@ -4,7 +4,7 @@
4
4
  @font-face {
5
5
  font-family: 'Bebasneue';
6
6
  src:
7
- url('https://cdn.jsdelivr.net/npm/bsign-customization@latest/src/fonts/BEBASNEUE-REGULAR.TTF') format('truetype');
7
+ url('/fonts/BEBASNEUE-REGULAR.TTF') format('truetype');
8
8
  font-weight: 400;
9
9
  font-style: normal;
10
10
  font-display: swap;
@@ -13,7 +13,7 @@
13
13
  @font-face {
14
14
  font-family: 'GOTHICB';
15
15
  src:
16
- url('./fonts/GOTHICB.TTF') format('truetype');
16
+ url('/fonts/GOTHICB.TTF') format('truetype');
17
17
  font-weight: 400;
18
18
  font-style: normal;
19
19
  font-display: swap;
@@ -22,11 +22,11 @@
22
22
  @font-face {
23
23
  font-family: 'Braille';
24
24
  src:
25
- url('https://cdn.jsdelivr.net/npm/bsign-customization@latest/src/fonts/Braille-Regular.ttf') format('truetype');
26
- font-weight: 400;
27
- font-style: normal;
28
- font-display: swap;
29
- }
25
+ url('/fonts/Braille-Regular.ttf') format('truetype');
26
+ font-weight: 400;
27
+ font-style: normal;
28
+ font-display: swap;
29
+ }
30
30
 
31
31
  @custom-variant dark (&:is(.dark *));
32
32
 
package/src/index.tsx CHANGED
@@ -3,6 +3,7 @@ import SignCustomizer, { type SignCustomizerProps } from "./AppDemo2"
3
3
  import resizableStyles from "react-resizable/css/styles.css?inline"
4
4
  import widgetStyles from "./index.css?inline"
5
5
  import { WidgetPortalContainerContext } from "./lib/widget-context"
6
+ import { resolveAssetUrl } from "./lib/asset-url"
6
7
 
7
8
  export type WidgetTarget = string | HTMLElement
8
9
 
@@ -10,7 +11,24 @@ export interface MountConstructorWidgetProps extends SignCustomizerProps {
10
11
  widgetCss?: string | string[]
11
12
  }
12
13
 
13
- const BASE_WIDGET_CSS = `${resizableStyles}\n${widgetStyles}`
14
+ const FONT_ASSET_PATHS = [
15
+ "/fonts/BEBASNEUE-REGULAR.TTF",
16
+ "/fonts/GOTHICB.TTF",
17
+ "/fonts/Braille-Regular.ttf",
18
+ ] as const
19
+
20
+ function resolveFontUrlsInCss(styles: string): string {
21
+ return FONT_ASSET_PATHS.reduce((nextStyles, fontPath) => {
22
+ const resolvedFontPath = resolveAssetUrl(fontPath)
23
+
24
+ return nextStyles
25
+ .replaceAll(`url('${fontPath}')`, `url('${resolvedFontPath}')`)
26
+ .replaceAll(`url("${fontPath}")`, `url("${resolvedFontPath}")`)
27
+ .replaceAll(`url(${fontPath})`, `url(${resolvedFontPath})`)
28
+ }, styles)
29
+ }
30
+
31
+ const BASE_WIDGET_CSS = `${resizableStyles}\n${resolveFontUrlsInCss(widgetStyles)}`
14
32
  const rootsByHost = new WeakMap<HTMLElement, Root>()
15
33
 
16
34
  function resolveTarget(target: WidgetTarget): HTMLElement {
@@ -1,6 +1,18 @@
1
1
  const ABSOLUTE_URL_PATTERN = /^(?:[a-z][a-z\d+\-.]*:)?\/\//i
2
2
  const SPECIAL_PROTOCOL_PATTERN = /^(?:data|blob):/i
3
3
 
4
+ /**
5
+ * Default CDN source for static widget assets (templates/colors/fonts/logo/etc).
6
+ * Can be overridden globally before widget init:
7
+ * window.BSIGN_WIDGET_ASSET_BASE_URL = "https://your-cdn/path/to/dist/"
8
+ */
9
+ const DEFAULT_CDN_ASSET_BASE_URL =
10
+ "https://cdn.jsdelivr.net/npm/bsign-customization-full@latest/dist/"
11
+
12
+ type WindowWithWidgetAssetBase = Window & {
13
+ BSIGN_WIDGET_ASSET_BASE_URL?: string
14
+ }
15
+
4
16
  function toBaseUrl(url: string): string | undefined {
5
17
  try {
6
18
  return new URL(".", url).toString()
@@ -9,36 +21,100 @@ function toBaseUrl(url: string): string | undefined {
9
21
  }
10
22
  }
11
23
 
12
- function resolveDefaultAssetBaseUrl(): string {
13
- const importMetaBase = toBaseUrl(import.meta.url)
14
- if (importMetaBase) {
15
- return importMetaBase
24
+ function isLocalhostHost(hostname: string): boolean {
25
+ const normalizedHost = hostname.toLowerCase()
26
+ return (
27
+ normalizedHost === "localhost" ||
28
+ normalizedHost === "127.0.0.1" ||
29
+ normalizedHost === "[::1]" ||
30
+ normalizedHost.endsWith(".localhost")
31
+ )
32
+ }
33
+
34
+ function shouldUseRelativeUrls(): boolean {
35
+ if (typeof window === "undefined") {
36
+ return false
16
37
  }
17
38
 
18
- if (typeof document !== "undefined") {
19
- const currentScript = document.currentScript
20
- if (currentScript instanceof HTMLScriptElement && currentScript.src) {
21
- const scriptBase = toBaseUrl(currentScript.src)
22
- if (scriptBase) {
23
- return scriptBase
24
- }
25
- }
39
+ return isLocalhostHost(window.location.hostname)
40
+ }
26
41
 
27
- const scripts = document.getElementsByTagName("script")
28
- const lastScript = scripts.item(scripts.length - 1)
29
- if (lastScript instanceof HTMLScriptElement && lastScript.src) {
30
- const scriptBase = toBaseUrl(lastScript.src)
31
- if (scriptBase) {
32
- return scriptBase
42
+ function resolveGlobalAssetBaseUrl(): string | undefined {
43
+ if (typeof window === "undefined") {
44
+ return undefined
45
+ }
46
+
47
+ const candidate = (window as WindowWithWidgetAssetBase).BSIGN_WIDGET_ASSET_BASE_URL
48
+ if (typeof candidate !== "string") {
49
+ return undefined
50
+ }
51
+
52
+ const trimmed = candidate.trim()
53
+ if (!trimmed) {
54
+ return undefined
55
+ }
56
+
57
+ return toBaseUrl(trimmed) ?? trimmed
58
+ }
59
+
60
+ function resolveScriptTagAssetBaseUrl(): string | undefined {
61
+ if (typeof document === "undefined") {
62
+ return undefined
63
+ }
64
+
65
+ const currentScript = document.currentScript
66
+ if (
67
+ currentScript instanceof HTMLScriptElement &&
68
+ typeof currentScript.src === "string" &&
69
+ currentScript.src.includes("sign-constructor")
70
+ ) {
71
+ return toBaseUrl(currentScript.src)
72
+ }
73
+
74
+ const scripts = document.getElementsByTagName("script")
75
+ for (let index = scripts.length - 1; index >= 0; index -= 1) {
76
+ const script = scripts.item(index)
77
+ if (
78
+ script instanceof HTMLScriptElement &&
79
+ typeof script.src === "string" &&
80
+ script.src.includes("sign-constructor")
81
+ ) {
82
+ const base = toBaseUrl(script.src)
83
+ if (base) {
84
+ return base
33
85
  }
34
86
  }
35
87
  }
36
88
 
37
- if (typeof window !== "undefined") {
38
- return toBaseUrl(window.location.href) ?? "/"
89
+ return undefined
90
+ }
91
+
92
+ function resolveImportMetaAssetBaseUrl(): string | undefined {
93
+ const moduleUrl = import.meta.url
94
+ if (!moduleUrl || !moduleUrl.includes("sign-constructor")) {
95
+ return undefined
96
+ }
97
+
98
+ return toBaseUrl(moduleUrl)
99
+ }
100
+
101
+ function resolveDefaultAssetBaseUrl(): string {
102
+ const globalBase = resolveGlobalAssetBaseUrl()
103
+ if (globalBase) {
104
+ return globalBase
105
+ }
106
+
107
+ const scriptBase = resolveScriptTagAssetBaseUrl()
108
+ if (scriptBase) {
109
+ return scriptBase
39
110
  }
40
111
 
41
- return "/"
112
+ const importMetaBase = resolveImportMetaAssetBaseUrl()
113
+ if (importMetaBase) {
114
+ return importMetaBase
115
+ }
116
+
117
+ return DEFAULT_CDN_ASSET_BASE_URL
42
118
  }
43
119
 
44
120
  let assetBaseUrl = resolveDefaultAssetBaseUrl()
@@ -65,6 +141,15 @@ export function resolveAssetUrl(path: string): string {
65
141
  return path
66
142
  }
67
143
 
144
+ if (shouldUseRelativeUrls()) {
145
+ if (path.startsWith("./") || path.startsWith("../")) {
146
+ return path
147
+ }
148
+
149
+ const normalizedPath = path.replace(/^\/+/, "")
150
+ return `./${normalizedPath}`
151
+ }
152
+
68
153
  const normalizedPath = path.startsWith("/") ? path.slice(1) : path
69
154
  return new URL(normalizedPath, getAssetBaseUrl()).toString()
70
155
  }