rimecms 0.25.5 → 0.25.7

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.
@@ -130,8 +130,8 @@ export type PanelConfig = {
130
130
  };
131
131
  /** a relative path from the "static" directory or an external url
132
132
  * @example
133
- * // for static/panel/custom.css
134
- * css : '/panel/custom.css'
133
+ * // for static/assets/custom.css
134
+ * css : '/assets/custom.css'
135
135
  */
136
136
  css?: string;
137
137
  };
@@ -152,8 +152,8 @@ export const init = async ({ force, name: incomingName, skipInstall }) => {
152
152
  async function copyAssets() {
153
153
  try {
154
154
  const currentDir = path.dirname(fileURLToPath(import.meta.url));
155
- await mkdir(path.resolve(process.cwd(), 'static/panel/fonts'), { recursive: true });
156
- await cp(path.join(currentDir, '../../../../panel/fonts'), path.resolve(process.cwd(), 'static/panel/fonts'), {
155
+ await mkdir(path.resolve(process.cwd(), 'static/assets/panel/fonts'), { recursive: true });
156
+ await cp(path.join(currentDir, '../../../../panel/fonts'), path.resolve(process.cwd(), 'static/assets/panel/fonts'), {
157
157
  recursive: true
158
158
  });
159
159
  logger.info('[✓] Copied assets');
@@ -1,20 +1,20 @@
1
1
  @font-face {
2
2
  font-family: 'Lora';
3
- src: url('/panel/fonts/Lora-Italic-VariableFont_wght.ttf') format('truetype');
3
+ src: url('/assets/panel/fonts/Lora-Italic-VariableFont_wght.ttf') format('truetype');
4
4
  font-weight: 100 1000;
5
5
  font-style: Italic;
6
6
  }
7
7
 
8
8
  @font-face {
9
9
  font-family: 'Lora';
10
- src: url('/panel/fonts/Lora-VariableFont_wght.ttf') format('truetype');
10
+ src: url('/assets/panel/fonts/Lora-VariableFont_wght.ttf') format('truetype');
11
11
  font-weight: 100 1000;
12
12
  font-style: normal;
13
13
  }
14
14
 
15
15
  @font-face {
16
16
  font-family: 'Chivo';
17
- src: url('/panel/fonts/ChivoMono-Italic-VariableFont_wght.ttf') format('truetype');
17
+ src: url('/assets/panel/fonts/ChivoMono-Italic-VariableFont_wght.ttf') format('truetype');
18
18
  font-weight: 100 1000;
19
19
  font-style: Italic;
20
20
  }
@@ -23,8 +23,8 @@
23
23
  --rz-font-scale: 0.8;
24
24
 
25
25
  --rz-font-sans:
26
- -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji',
27
- 'Segoe UI Emoji', 'Segoe UI Symbol';
26
+ -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif,
27
+ 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
28
28
  --rz-font-mono: 'SFMono-Regular', Consolas, Liberation Mono, Menlo, Courier, monospace;
29
29
  --rz-font-serif: 'Lora';
30
30
 
@@ -174,6 +174,7 @@ export const sanitize = (value) => {
174
174
  return value || '';
175
175
  if (!parser)
176
176
  parser = Parser();
177
+ const WHITESPACE_MARKER = '\uE000';
177
178
  const decode = (value) => value
178
179
  .replace(/&/g, '&')
179
180
  .replace(/"/g, '"')
@@ -182,12 +183,20 @@ export const sanitize = (value) => {
182
183
  .replace(/'/g, "'")
183
184
  .replace(/'/g, "'")
184
185
  .replace(/&/g, '&');
186
+ const encodeTextSpace = (html) => html
187
+ .split(/(<[^>]*>)/g)
188
+ .map((segment) => segment.startsWith('<') && segment.endsWith('>')
189
+ ? segment
190
+ : segment.replace(/ /g, WHITESPACE_MARKER))
191
+ .join('');
192
+ const restoreWhitespace = (str) => str.replace(new RegExp(WHITESPACE_MARKER, 'g'), ' ');
185
193
  // Decode multiple levels of encoding on input
186
194
  let decodedValue = value;
187
195
  while (decodedValue.match(/&amp;|&quot;|&lt;|&gt;|&#x27;|&#39;|&#38;/)) {
188
196
  decodedValue = decode(decodedValue);
189
197
  }
190
- const { root } = parser.parseFromString(decodedValue);
198
+ const protectedInput = encodeTextSpace(decodedValue);
199
+ const { root } = parser.parseFromString(protectedInput);
191
200
  const allowedTags = new Set(['strong', 'b', 'em', 'i', 'u', 'br', 'a']);
192
201
  const dangerousTags = new Set(['script', 'style', 'iframe', 'object', 'embed', 'svg']);
193
202
  const eventHandlers = /^on[a-z]+$/i;
@@ -197,7 +206,7 @@ export const sanitize = (value) => {
197
206
  return '';
198
207
  // Handle text nodes
199
208
  if (node.nodeName === '#text') {
200
- return node.nodeValue || '';
209
+ return (node.nodeValue || '').replace(new RegExp(WHITESPACE_MARKER, 'g'), ' ');
201
210
  }
202
211
  // Handle comment nodes - remove them
203
212
  if (node.nodeName === '#comment') {
@@ -260,5 +269,5 @@ export const sanitize = (value) => {
260
269
  return '';
261
270
  };
262
271
  const sanitized = root.children ? root.children.map(processNode).join('') : '';
263
- return decode(sanitized);
272
+ return decode(restoreWhitespace(sanitized));
264
273
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rimecms",
3
- "version": "0.25.5",
3
+ "version": "0.25.7",
4
4
  "homepage": "https://github.com/bienbiendev/rime",
5
5
  "scripts": {
6
6
  "dev": "vite dev",