@scalar/client-side-rendering 0.4.4 → 0.4.6

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/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # @scalar/client-side-rendering
2
2
 
3
+ ## 0.4.6
4
+
5
+ ## 0.4.5
6
+
7
+ ### Patch Changes
8
+
9
+ - [#10344](https://github.com/scalar/scalar/pull/10344): Share JSON and property-name escaping for inline scripts between client-side and server-side rendering.
10
+ - [#10344](https://github.com/scalar/scalar/pull/10344): Escape configuration data embedded in inline scripts to prevent HTML script injection.
11
+
3
12
  ## 0.4.4
4
13
 
5
14
  ## 0.4.3
@@ -61,6 +61,9 @@ export declare function renderApiReference(options: {
61
61
  * That is what lets callbacks survive being written into an inline `<script>` tag, or across any other
62
62
  * boundary that would otherwise JSON-serialize the configuration and silently drop functions.
63
63
  *
64
+ * Function values are trusted executable code, not untrusted configuration data. Their source
65
+ * must be safe to embed in an inline script.
66
+ *
64
67
  * Note: functions must be arrow functions or `function` expressions. Object method shorthand
65
68
  * (`onBeforeRequest(request) {}`) does not serialize to a valid standalone expression.
66
69
  */
@@ -1 +1 @@
1
- {"version":3,"file":"html-rendering.d.ts","sourceRoot":"","sources":["../src/html-rendering.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,4BAA4B,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAA;AAE3G,YAAY,EAAE,4BAA4B,EAAE,0BAA0B,EAAE,CAAA;AAExE;;;;;GAKG;AACH,eAAO,MAAM,WAAW,uDAAuD,CAAA;AAE/E;;;;;GAKG;AACH,eAAO,MAAM,eAAe,8DAA8D,CAAA;AAoE1F;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE;IACP,uCAAuC;IACvC,MAAM,EAAE,4BAA4B,CAAA;IACpC,sDAAsD;IACtD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,+DAA+D;IAC/D,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ;;;;;;;;;;OAUG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;;;;;;;OASG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CAC1B,EACD,WAAW,SAAK,GACf,MAAM,CAiCR;AASD;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CA+BlF;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,aAAa,CAC3B,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACtC,GAAG,CAAC,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,GACxB,MAAM,CA8BR;AAED;;GAEG;AACH,eAAO,MAAM,gBAAgB,GAC3B,oBAAoB,OAAO,CAAC,0BAA0B,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAChF,MAAM,CAAC,MAAM,EAAE,OAAO,CAcxB,CAAA"}
1
+ {"version":3,"file":"html-rendering.d.ts","sourceRoot":"","sources":["../src/html-rendering.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,4BAA4B,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAA;AAE3G,YAAY,EAAE,4BAA4B,EAAE,0BAA0B,EAAE,CAAA;AAExE;;;;;GAKG;AACH,eAAO,MAAM,WAAW,uDAAuD,CAAA;AAE/E;;;;;GAKG;AACH,eAAO,MAAM,eAAe,8DAA8D,CAAA;AAoE1F;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE;IACP,uCAAuC;IACvC,MAAM,EAAE,4BAA4B,CAAA;IACpC,sDAAsD;IACtD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,+DAA+D;IAC/D,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ;;;;;;;;;;OAUG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;;;;;;;OASG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CAC1B,EACD,WAAW,SAAK,GACf,MAAM,CAiCR;AASD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CAAC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CA+BlF;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,aAAa,CAC3B,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACtC,GAAG,CAAC,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,GACxB,MAAM,CA8BR;AAED;;GAEG;AACH,eAAO,MAAM,gBAAgB,GAC3B,oBAAoB,OAAO,CAAC,0BAA0B,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAChF,MAAM,CAAC,MAAM,EAAE,OAAO,CAcxB,CAAA"}
@@ -1,3 +1,5 @@
1
+ import { escapeJsonForInlineScript } from '@scalar/helpers/json/escape-json-for-inline-script';
2
+ import { serializePropertyKey } from '@scalar/helpers/json/serialize-property-key';
1
3
  /**
2
4
  * Default CDN URL for the @scalar/api-reference UMD standalone bundle.
3
5
  *
@@ -111,7 +113,7 @@ export function renderApiReference(options, customTheme = '') {
111
113
  * Helper function to serialize arrays that may contain functions
112
114
  */
113
115
  const serializeArrayWithFunctions = (arr) => {
114
- return `[${arr.map((item) => (typeof item === 'function' ? item.toString() : JSON.stringify(item))).join(', ')}]`;
116
+ return `[${arr.map((item) => (typeof item === 'function' ? item.toString() : escapeJsonForInlineScript(JSON.stringify(item) ?? 'undefined'))).join(', ')}]`;
115
117
  };
116
118
  /**
117
119
  * Serialize a configuration object to a JavaScript object literal string.
@@ -121,6 +123,9 @@ const serializeArrayWithFunctions = (arr) => {
121
123
  * That is what lets callbacks survive being written into an inline `<script>` tag, or across any other
122
124
  * boundary that would otherwise JSON-serialize the configuration and silently drop functions.
123
125
  *
126
+ * Function values are trusted executable code, not untrusted configuration data. Their source
127
+ * must be safe to embed in an inline script.
128
+ *
124
129
  * Note: functions must be arrow functions or `function` expressions. Object method shorthand
125
130
  * (`onBeforeRequest(request) {}`) does not serialize to a valid standalone expression.
126
131
  */
@@ -129,15 +134,15 @@ export function serializeConfigToJs(configuration) {
129
134
  const functionProps = [];
130
135
  for (const [key, value] of Object.entries(configuration)) {
131
136
  if (typeof value === 'function') {
132
- functionProps.push(`"${key}": ${value.toString()}`);
137
+ functionProps.push(`${serializePropertyKey(key)}: ${value.toString()}`);
133
138
  delete restConfig[key];
134
139
  }
135
140
  else if (Array.isArray(value) && value.some((item) => typeof item === 'function')) {
136
- functionProps.push(`"${key}": ${serializeArrayWithFunctions(value)}`);
141
+ functionProps.push(`${serializePropertyKey(key)}: ${serializeArrayWithFunctions(value)}`);
137
142
  delete restConfig[key];
138
143
  }
139
144
  }
140
- const jsonString = JSON.stringify(restConfig, null, 2);
145
+ const jsonString = escapeJsonForInlineScript(JSON.stringify(restConfig, null, 2));
141
146
  const indentedJsonString = jsonString
142
147
  .split('\n')
143
148
  .map((line, index) => (index === 0 ? line : ` ${line}`))
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "directory": "packages/client-side-rendering"
12
12
  },
13
13
  "keywords": [],
14
- "version": "0.4.4",
14
+ "version": "0.4.6",
15
15
  "engines": {
16
16
  "node": ">=22"
17
17
  },
@@ -29,8 +29,9 @@
29
29
  "CHANGELOG.md"
30
30
  ],
31
31
  "dependencies": {
32
- "@scalar/schemas": "0.12.0",
33
- "@scalar/types": "0.22.0",
32
+ "@scalar/helpers": "0.16.0",
33
+ "@scalar/schemas": "0.12.2",
34
+ "@scalar/types": "0.22.2",
34
35
  "@scalar/validation": "0.6.5"
35
36
  },
36
37
  "devDependencies": {