@lowdefy/blocks-basic 0.0.0-experimental-20260904141432 → 0.0.0-experimental-20260905100314

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.
@@ -17,13 +17,20 @@ import DOMPurify from 'dompurify';
17
17
  import { withBlockDefaults } from '@lowdefy/block-utils';
18
18
  import { type } from '@lowdefy/helpers';
19
19
  let DangerousHtml = class DangerousHtml extends React.Component {
20
- componentDidMount() {
21
- const htmlString = type.isNone(this.props.properties.html) ? '' : this.props.properties.html.toString();
20
+ sanitize() {
21
+ const { html, DOMPurifyOptions } = this.props.properties;
22
+ if (!this.warnedOptionsChange && JSON.stringify(DOMPurifyOptions) !== JSON.stringify(this.DOMPurifyOptions)) {
23
+ this.warnedOptionsChange = true;
24
+ console.warn(`DangerousHtml block "${this.props.blockId}": DOMPurifyOptions changed after mount and the change is ignored. The sanitizer options are fixed at the first render; write them as a literal, not from state.`);
25
+ }
26
+ const htmlString = type.isNone(html) ? '' : html.toString();
22
27
  this.div.innerHTML = DOMPurify.sanitize(htmlString, this.DOMPurifyOptions);
23
28
  }
29
+ componentDidMount() {
30
+ this.sanitize();
31
+ }
24
32
  componentDidUpdate() {
25
- const htmlString = type.isNone(this.props.properties.html) ? '' : this.props.properties.html.toString();
26
- this.div.innerHTML = DOMPurify.sanitize(htmlString, this.DOMPurifyOptions);
33
+ this.sanitize();
27
34
  }
28
35
  render() {
29
36
  const { blockId, classNames, styles } = this.props;
@@ -44,8 +51,11 @@ let DangerousHtml = class DangerousHtml extends React.Component {
44
51
  this.div = {
45
52
  innerHTML: ''
46
53
  };
47
- // we do not revaluate DOMPurifyOptions improve options safety by not making options dynamic.
54
+ // The sanitizer options are fixed at mount on purpose: a later, operator-driven
55
+ // value could loosen the sanitizer from state. A change is refused loudly
56
+ // rather than ignored silently.
48
57
  this.DOMPurifyOptions = props.properties.DOMPurifyOptions;
58
+ this.warnedOptionsChange = false;
49
59
  }
50
60
  };
51
61
  export default withBlockDefaults(DangerousHtml);
@@ -19,6 +19,18 @@
19
19
  cssKeys: {
20
20
  element: 'The DangerousHtml element.'
21
21
  },
22
+ hazards: [
23
+ {
24
+ id: 'dangerous-html-unsanitised',
25
+ message: 'Content is rendered without sanitising, so never pass caller-supplied or database HTML through it. Use Html for anything a user could have written.',
26
+ see: 'display-blocks/dangeroushtml'
27
+ },
28
+ {
29
+ id: 'dompurify-options-first-render',
30
+ message: 'DOMPurifyOptions is read once when the block mounts, so a value that changes after the first render has no effect. Set it statically or remount the block.',
31
+ see: 'display-blocks/dangeroushtml'
32
+ }
33
+ ],
22
34
  properties: {
23
35
  type: 'object',
24
36
  additionalProperties: false,
@@ -19,6 +19,13 @@
19
19
  cssKeys: {
20
20
  element: 'The Html element.'
21
21
  },
22
+ hazards: [
23
+ {
24
+ id: 'html-style-stripped',
25
+ message: 'Content is sanitised with DOMPurify, so <style>, <script> and inline event handlers are removed before render. Use DangerousHtml for a trusted <style> block, or style the block through its style and class properties.',
26
+ see: 'display-blocks/html'
27
+ }
28
+ ],
22
29
  events: {
23
30
  onTextSelection: 'Trigger action when text is selected and pass selected text to the event object.'
24
31
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lowdefy/blocks-basic",
3
- "version": "0.0.0-experimental-20260904141432",
3
+ "version": "0.0.0-experimental-20260905100314",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Basic html Lowdefy blocks.",
6
6
  "homepage": "https://lowdefy.com",
@@ -42,8 +42,8 @@
42
42
  "dist/*"
43
43
  ],
44
44
  "dependencies": {
45
- "@lowdefy/block-utils": "0.0.0-experimental-20260904141432",
46
- "@lowdefy/helpers": "0.0.0-experimental-20260904141432",
45
+ "@lowdefy/block-utils": "0.0.0-experimental-20260905100314",
46
+ "@lowdefy/helpers": "0.0.0-experimental-20260905100314",
47
47
  "dompurify": "3.4.2"
48
48
  },
49
49
  "peerDependencies": {
@@ -51,8 +51,8 @@
51
51
  "react-dom": ">=18"
52
52
  },
53
53
  "devDependencies": {
54
- "@lowdefy/block-dev-e2e": "0.0.0-experimental-20260904141432",
55
- "@lowdefy/e2e-utils": "0.0.0-experimental-20260904141432",
54
+ "@lowdefy/block-dev-e2e": "0.0.0-experimental-20260905100314",
55
+ "@lowdefy/e2e-utils": "0.0.0-experimental-20260905100314",
56
56
  "@playwright/test": "1.59.1",
57
57
  "@swc/cli": "0.8.1",
58
58
  "@swc/core": "1.15.32",