@megabudino/stack-utils 1.2.1 → 1.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/README.md +3 -1
- package/dist/proxy/dom-actions.d.ts +9 -0
- package/dist/proxy/dom-actions.js +47 -0
- package/dist/proxy/handle.js +3 -0
- package/dist/proxy/index.d.ts +1 -1
- package/dist/proxy/types.d.ts +27 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -53,13 +53,15 @@ Proxy config:
|
|
|
53
53
|
| `sitemapCacheSeconds` | `number` | `3600` | Cache max-age for sitemap responses |
|
|
54
54
|
| `proxyAssets` | `boolean` | `false` | Rewrite origin asset URLs to relative paths |
|
|
55
55
|
| `additionalOrigins` | `string[]` | `[]` | Additional absolute origins to rewrite like `originUrl` |
|
|
56
|
+
| `domActions` | `DomAction[]` | `[]` | Declarative DOM transformations for proxied HTML |
|
|
57
|
+
| `textReplacements` | `Record<string, string>` | `{}` | Final string replacements applied after DOM actions |
|
|
56
58
|
|
|
57
59
|
What it does:
|
|
58
60
|
|
|
59
61
|
- lets SvelteKit routes resolve normally when a route exists
|
|
60
62
|
- proxies unmatched requests to the configured origin
|
|
61
63
|
- rewrites redirects back to the public domain
|
|
62
|
-
- rewrites HTML and injects extra sitemap entries when configured
|
|
64
|
+
- rewrites HTML, applies optional DOM actions, and injects extra sitemap entries when configured
|
|
63
65
|
|
|
64
66
|
### `images`
|
|
65
67
|
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { DomAction } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Apply declarative DOM actions in array order.
|
|
4
|
+
*
|
|
5
|
+
* Actions run after the proxy's standard HTML rewrites so selectors see the
|
|
6
|
+
* final proxied markup shape, and before `textReplacements` so the legacy
|
|
7
|
+
* string-based pass remains the last low-level override.
|
|
8
|
+
*/
|
|
9
|
+
export declare function applyDomActions(html: string, actions: DomAction[]): string;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { load } from 'cheerio';
|
|
2
|
+
/**
|
|
3
|
+
* Apply declarative DOM actions in array order.
|
|
4
|
+
*
|
|
5
|
+
* Actions run after the proxy's standard HTML rewrites so selectors see the
|
|
6
|
+
* final proxied markup shape, and before `textReplacements` so the legacy
|
|
7
|
+
* string-based pass remains the last low-level override.
|
|
8
|
+
*/
|
|
9
|
+
export function applyDomActions(html, actions) {
|
|
10
|
+
if (actions.length === 0) {
|
|
11
|
+
return html;
|
|
12
|
+
}
|
|
13
|
+
const $ = load(html);
|
|
14
|
+
for (const action of actions) {
|
|
15
|
+
const elements = $(action.selector);
|
|
16
|
+
if (elements.length === 0) {
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
if (action.remove) {
|
|
20
|
+
elements.remove();
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
if (action.setAttributes) {
|
|
24
|
+
for (const [name, value] of Object.entries(action.setAttributes)) {
|
|
25
|
+
elements.attr(name, value);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
if (action.removeAttributes) {
|
|
29
|
+
for (const name of action.removeAttributes) {
|
|
30
|
+
elements.removeAttr(name);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (action.addClass && action.addClass.length > 0) {
|
|
34
|
+
elements.addClass(action.addClass.join(' '));
|
|
35
|
+
}
|
|
36
|
+
if (action.removeClass && action.removeClass.length > 0) {
|
|
37
|
+
elements.removeClass(action.removeClass.join(' '));
|
|
38
|
+
}
|
|
39
|
+
if (action.setText !== undefined) {
|
|
40
|
+
elements.text(action.setText);
|
|
41
|
+
}
|
|
42
|
+
if (action.setHtml !== undefined) {
|
|
43
|
+
elements.html(action.setHtml);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return $.html();
|
|
47
|
+
}
|
package/dist/proxy/handle.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { applyDomActions } from './dom-actions.js';
|
|
1
2
|
import { injectIntoSitemapIndex, rewriteHtml } from './rewrite.js';
|
|
2
3
|
/**
|
|
3
4
|
* Create a SvelteKit `Handle` hook that reverse-proxies requests to an origin.
|
|
@@ -12,6 +13,7 @@ export function createProxyHandle(config) {
|
|
|
12
13
|
const proxyAssets = config.proxyAssets ?? false;
|
|
13
14
|
const additionalOrigins = config.additionalOrigins ?? [];
|
|
14
15
|
const maxRedirects = config.maxInternalRedirects ?? 5;
|
|
16
|
+
const domActions = config.domActions ?? [];
|
|
15
17
|
const textReplacements = config.textReplacements ?? {};
|
|
16
18
|
const siteHost = new URL(siteUrl).hostname;
|
|
17
19
|
const originHosts = new Set([
|
|
@@ -83,6 +85,7 @@ export function createProxyHandle(config) {
|
|
|
83
85
|
if (contentType.includes('text/html')) {
|
|
84
86
|
const html = await upstreamResponse.text();
|
|
85
87
|
let result = rewriteHtml(html, originUrl, siteUrl, proxyAssets, additionalOrigins);
|
|
88
|
+
result = applyDomActions(result, domActions);
|
|
86
89
|
for (const [search, replace] of Object.entries(textReplacements)) {
|
|
87
90
|
result = result.replaceAll(search, replace);
|
|
88
91
|
}
|
package/dist/proxy/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { createProxyHandle } from './handle.js';
|
|
2
|
-
export type { ProxyConfig } from './types.js';
|
|
2
|
+
export type { DomAction, ProxyConfig } from './types.js';
|
package/dist/proxy/types.d.ts
CHANGED
|
@@ -1,3 +1,25 @@
|
|
|
1
|
+
/** Declarative DOM transformations applied to proxied HTML documents. */
|
|
2
|
+
export interface DomAction {
|
|
3
|
+
/** CSS selector used to match elements in the proxied HTML document. */
|
|
4
|
+
selector: string;
|
|
5
|
+
/** Set or replace attributes on every matched element. */
|
|
6
|
+
setAttributes?: Record<string, string>;
|
|
7
|
+
/** Remove attributes from every matched element. */
|
|
8
|
+
removeAttributes?: string[];
|
|
9
|
+
/** Add CSS classes to every matched element. */
|
|
10
|
+
addClass?: string[];
|
|
11
|
+
/** Remove CSS classes from every matched element. */
|
|
12
|
+
removeClass?: string[];
|
|
13
|
+
/** Replace the text content of every matched element. */
|
|
14
|
+
setText?: string;
|
|
15
|
+
/** Replace the inner HTML of every matched element. */
|
|
16
|
+
setHtml?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Remove every matched element.
|
|
19
|
+
* When true, removal takes precedence over all other fields in the same action.
|
|
20
|
+
*/
|
|
21
|
+
remove?: boolean;
|
|
22
|
+
}
|
|
1
23
|
/** Configuration for the reverse proxy. */
|
|
2
24
|
export interface ProxyConfig {
|
|
3
25
|
/** The origin URL (not publicly exposed). */
|
|
@@ -37,4 +59,9 @@ export interface ProxyConfig {
|
|
|
37
59
|
* using `String.prototype.replaceAll`.
|
|
38
60
|
*/
|
|
39
61
|
textReplacements?: Record<string, string>;
|
|
62
|
+
/**
|
|
63
|
+
* Declarative DOM transformations applied to HTML responses after the
|
|
64
|
+
* standard proxy rewrites and before `textReplacements`.
|
|
65
|
+
*/
|
|
66
|
+
domActions?: DomAction[];
|
|
40
67
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@megabudino/stack-utils",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Reusable utilities for a SvelteKit stack, including a reverse proxy and static image pipeline",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
"typecheck": "tsc --noEmit"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
+
"cheerio": "^1.2.0",
|
|
35
36
|
"sharp": "^0.34.5"
|
|
36
37
|
},
|
|
37
38
|
"peerDependencies": {
|