react-native-webview-stream-chunks 0.2.0 → 0.3.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-webview-stream-chunks",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Reusable preload script and event types for streaming large HTML/chunks into WebView",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -15,10 +15,11 @@
15
15
  "dist"
16
16
  ],
17
17
  "scripts": {
18
+ "clean": "rimraf dist",
18
19
  "lint": "eslint ./src --ext ts",
19
20
  "lint:fix": "eslint ./src --ext ts --fix",
20
21
  "build:inject": "node scripts/injectReceiver.mjs",
21
- "build": "tsc -p tsconfig.json && npm run build:inject",
22
+ "build": "npm run clean && tsc -p tsconfig.json && npm run build:inject",
22
23
  "check": "tsc --noEmit -p tsconfig.json",
23
24
  "prepublishOnly": "npm run build"
24
25
  },
@@ -32,6 +33,7 @@
32
33
  "devDependencies": {
33
34
  "eslint": "^9.39.0",
34
35
  "eslint-config-tidgi": "^2.2.0",
36
+ "rimraf": "^6.1.2",
35
37
  "typescript": "^5.9.3"
36
38
  }
37
39
  }
@@ -1,2 +0,0 @@
1
- export declare const webViewStreamReceiverIIFESource = "function webViewStreamReceiverIIFE(options, eventTypes) {\n let payloadChunks = [];\n let contentMutationObserved = false;\n const injectedPayloadScriptClasses = new Set();\n function resetState() {\n payloadChunks = [];\n contentMutationObserved = false;\n }\n const targetWindow = window;\n // -- receiver-ready callback resolver -------------------------------------\n function runReceiverReadyCallback() {\n if (!options.receiverReadyCallbackPath.trim())\n return;\n const segments = options.receiverReadyCallbackPath.split('.').filter(Boolean);\n let current = targetWindow;\n for (const segment of segments) {\n if (current === null || current === undefined || typeof current !== 'object') {\n current = undefined;\n break;\n }\n current = current[segment];\n }\n if (typeof current === 'function') {\n current();\n }\n }\n // -- event dispatcher -----------------------------------------------------\n targetWindow.onStreamChunksToWebView = function (event) {\n var _a;\n switch (event.type) {\n case eventTypes.SET_CONTENT: {\n resetState();\n replaceBodyContent((_a = event.data) !== null && _a !== void 0 ? _a : '');\n break;\n }\n case eventTypes.APPEND_CHUNK: {\n if (event.data)\n payloadChunks.push(event.data);\n break;\n }\n case eventTypes.FINALIZE_PAYLOAD: {\n const waitAndInject = () => {\n if (contentMutationObserved) {\n injectPayloadScript(event.data);\n }\n else {\n setTimeout(waitAndInject, 100);\n }\n };\n waitAndInject();\n break;\n }\n case eventTypes.REEXECUTE_SCRIPTS: {\n const waitAndExec = () => {\n if (contentMutationObserved) {\n reexecuteScripts(event.data);\n }\n else {\n setTimeout(waitAndExec, 100);\n }\n };\n waitAndExec();\n break;\n }\n case eventTypes.CHECK_RECEIVER_READY: {\n runReceiverReadyCallback();\n break;\n }\n }\n };\n // -- DOM helpers ----------------------------------------------------------\n function replaceBodyContent(newInnerHTML) {\n const observer = new MutationObserver((mutationsList, currentObserver) => {\n for (const mutation of mutationsList) {\n if (mutation.type === 'childList') {\n currentObserver.disconnect();\n contentMutationObserved = true;\n return;\n }\n }\n });\n observer.observe(document.body, { childList: true });\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n document.body.innerHTML = newInnerHTML;\n }\n const defaultInjectionOptions = {\n scriptType: 'application/json',\n scriptClassName: 'webview-stream-payload',\n scriptTagName: 'default-payload',\n anchorSelector: '#styleArea',\n };\n function resolveInjectionOptions(rawData) {\n var _a, _b, _c, _d;\n if (!rawData) {\n return defaultInjectionOptions;\n }\n try {\n const parsed = JSON.parse(rawData);\n return {\n scriptType: (_a = parsed.scriptType) !== null && _a !== void 0 ? _a : defaultInjectionOptions.scriptType,\n scriptClassName: (_b = parsed.scriptClassName) !== null && _b !== void 0 ? _b : defaultInjectionOptions.scriptClassName,\n scriptTagName: (_c = parsed.scriptTagName) !== null && _c !== void 0 ? _c : defaultInjectionOptions.scriptTagName,\n anchorSelector: (_d = parsed.anchorSelector) !== null && _d !== void 0 ? _d : defaultInjectionOptions.anchorSelector,\n };\n }\n catch (_e) {\n return defaultInjectionOptions;\n }\n }\n function injectPayloadScript(rawData) {\n try {\n const injectionOptions = resolveInjectionOptions(rawData);\n const fullPayload = payloadChunks.join('');\n const scriptElement = document.createElement('script');\n scriptElement.type = injectionOptions.scriptType;\n scriptElement.classList.add(injectionOptions.scriptClassName, injectionOptions.scriptTagName);\n scriptElement.textContent = fullPayload;\n const anchor = document.querySelector(injectionOptions.anchorSelector);\n anchor === null || anchor === void 0 ? void 0 : anchor.insertAdjacentElement('afterend', scriptElement);\n injectedPayloadScriptClasses.add(injectionOptions.scriptClassName);\n }\n catch (error) {\n console.error('[webview-stream] injectPayloadScript error', error);\n }\n payloadChunks = [];\n }\n function reexecuteScripts(selector) {\n try {\n const query = (selector === null || selector === void 0 ? void 0 : selector.trim()) || 'script';\n const elements = Array.from(document.querySelectorAll(query));\n for (const element of elements) {\n if (!(element instanceof HTMLScriptElement))\n continue;\n let isInjectedPayloadScript = false;\n for (const payloadClassName of injectedPayloadScriptClasses) {\n if (element.classList.contains(payloadClassName)) {\n isInjectedPayloadScript = true;\n break;\n }\n }\n if (isInjectedPayloadScript)\n continue;\n const replacement = document.createElement('script');\n for (const { name, value } of Array.from(element.attributes)) {\n replacement.setAttribute(name, value);\n }\n if (element.src) {\n replacement.src = element.src;\n }\n else {\n replacement.textContent = element.textContent;\n }\n if (element.parentNode !== null) {\n try {\n element.parentNode.replaceChild(replacement, element);\n }\n catch (error) {\n console.error('[webview-stream] Failed to re-execute script tag', replacement, element, error);\n }\n }\n }\n }\n catch (error) {\n console.error('[webview-stream] reexecuteScripts error', error);\n }\n }\n}";
2
- //# sourceMappingURL=webviewReceiverString.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"webviewReceiverString.d.ts","sourceRoot":"","sources":["../src/webviewReceiverString.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,+BAA+B,87NAsK1C,CAAC"}
@@ -1,169 +0,0 @@
1
- // This file is auto-generated by scripts/buildReceiver.mjs
2
- // Do not edit this file directly.
3
- export const webViewStreamReceiverIIFESource = `function webViewStreamReceiverIIFE(options, eventTypes) {
4
- let payloadChunks = [];
5
- let contentMutationObserved = false;
6
- const injectedPayloadScriptClasses = new Set();
7
- function resetState() {
8
- payloadChunks = [];
9
- contentMutationObserved = false;
10
- }
11
- const targetWindow = window;
12
- // -- receiver-ready callback resolver -------------------------------------
13
- function runReceiverReadyCallback() {
14
- if (!options.receiverReadyCallbackPath.trim())
15
- return;
16
- const segments = options.receiverReadyCallbackPath.split('.').filter(Boolean);
17
- let current = targetWindow;
18
- for (const segment of segments) {
19
- if (current === null || current === undefined || typeof current !== 'object') {
20
- current = undefined;
21
- break;
22
- }
23
- current = current[segment];
24
- }
25
- if (typeof current === 'function') {
26
- current();
27
- }
28
- }
29
- // -- event dispatcher -----------------------------------------------------
30
- targetWindow.onStreamChunksToWebView = function (event) {
31
- var _a;
32
- switch (event.type) {
33
- case eventTypes.SET_CONTENT: {
34
- resetState();
35
- replaceBodyContent((_a = event.data) !== null && _a !== void 0 ? _a : '');
36
- break;
37
- }
38
- case eventTypes.APPEND_CHUNK: {
39
- if (event.data)
40
- payloadChunks.push(event.data);
41
- break;
42
- }
43
- case eventTypes.FINALIZE_PAYLOAD: {
44
- const waitAndInject = () => {
45
- if (contentMutationObserved) {
46
- injectPayloadScript(event.data);
47
- }
48
- else {
49
- setTimeout(waitAndInject, 100);
50
- }
51
- };
52
- waitAndInject();
53
- break;
54
- }
55
- case eventTypes.REEXECUTE_SCRIPTS: {
56
- const waitAndExec = () => {
57
- if (contentMutationObserved) {
58
- reexecuteScripts(event.data);
59
- }
60
- else {
61
- setTimeout(waitAndExec, 100);
62
- }
63
- };
64
- waitAndExec();
65
- break;
66
- }
67
- case eventTypes.CHECK_RECEIVER_READY: {
68
- runReceiverReadyCallback();
69
- break;
70
- }
71
- }
72
- };
73
- // -- DOM helpers ----------------------------------------------------------
74
- function replaceBodyContent(newInnerHTML) {
75
- const observer = new MutationObserver((mutationsList, currentObserver) => {
76
- for (const mutation of mutationsList) {
77
- if (mutation.type === 'childList') {
78
- currentObserver.disconnect();
79
- contentMutationObserved = true;
80
- return;
81
- }
82
- }
83
- });
84
- observer.observe(document.body, { childList: true });
85
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
86
- document.body.innerHTML = newInnerHTML;
87
- }
88
- const defaultInjectionOptions = {
89
- scriptType: 'application/json',
90
- scriptClassName: 'webview-stream-payload',
91
- scriptTagName: 'default-payload',
92
- anchorSelector: '#styleArea',
93
- };
94
- function resolveInjectionOptions(rawData) {
95
- var _a, _b, _c, _d;
96
- if (!rawData) {
97
- return defaultInjectionOptions;
98
- }
99
- try {
100
- const parsed = JSON.parse(rawData);
101
- return {
102
- scriptType: (_a = parsed.scriptType) !== null && _a !== void 0 ? _a : defaultInjectionOptions.scriptType,
103
- scriptClassName: (_b = parsed.scriptClassName) !== null && _b !== void 0 ? _b : defaultInjectionOptions.scriptClassName,
104
- scriptTagName: (_c = parsed.scriptTagName) !== null && _c !== void 0 ? _c : defaultInjectionOptions.scriptTagName,
105
- anchorSelector: (_d = parsed.anchorSelector) !== null && _d !== void 0 ? _d : defaultInjectionOptions.anchorSelector,
106
- };
107
- }
108
- catch (_e) {
109
- return defaultInjectionOptions;
110
- }
111
- }
112
- function injectPayloadScript(rawData) {
113
- try {
114
- const injectionOptions = resolveInjectionOptions(rawData);
115
- const fullPayload = payloadChunks.join('');
116
- const scriptElement = document.createElement('script');
117
- scriptElement.type = injectionOptions.scriptType;
118
- scriptElement.classList.add(injectionOptions.scriptClassName, injectionOptions.scriptTagName);
119
- scriptElement.textContent = fullPayload;
120
- const anchor = document.querySelector(injectionOptions.anchorSelector);
121
- anchor === null || anchor === void 0 ? void 0 : anchor.insertAdjacentElement('afterend', scriptElement);
122
- injectedPayloadScriptClasses.add(injectionOptions.scriptClassName);
123
- }
124
- catch (error) {
125
- console.error('[webview-stream] injectPayloadScript error', error);
126
- }
127
- payloadChunks = [];
128
- }
129
- function reexecuteScripts(selector) {
130
- try {
131
- const query = (selector === null || selector === void 0 ? void 0 : selector.trim()) || 'script';
132
- const elements = Array.from(document.querySelectorAll(query));
133
- for (const element of elements) {
134
- if (!(element instanceof HTMLScriptElement))
135
- continue;
136
- let isInjectedPayloadScript = false;
137
- for (const payloadClassName of injectedPayloadScriptClasses) {
138
- if (element.classList.contains(payloadClassName)) {
139
- isInjectedPayloadScript = true;
140
- break;
141
- }
142
- }
143
- if (isInjectedPayloadScript)
144
- continue;
145
- const replacement = document.createElement('script');
146
- for (const { name, value } of Array.from(element.attributes)) {
147
- replacement.setAttribute(name, value);
148
- }
149
- if (element.src) {
150
- replacement.src = element.src;
151
- }
152
- else {
153
- replacement.textContent = element.textContent;
154
- }
155
- if (element.parentNode !== null) {
156
- try {
157
- element.parentNode.replaceChild(replacement, element);
158
- }
159
- catch (error) {
160
- console.error('[webview-stream] Failed to re-execute script tag', replacement, element, error);
161
- }
162
- }
163
- }
164
- }
165
- catch (error) {
166
- console.error('[webview-stream] reexecuteScripts error', error);
167
- }
168
- }
169
- }`;