@ts-graphviz/react 0.12.1 → 0.12.2

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
  # @ts-graphviz/react
2
2
 
3
+ ## 0.12.2
4
+
5
+ ### Patch Changes
6
+
7
+ - [#1763](https://github.com/ts-graphviz/ts-graphviz/pull/1763) [`24cc46e`](https://github.com/ts-graphviz/ts-graphviz/commit/24cc46ebf0078440fa498f89b21e7224725c16b6) Thanks [@kamiazya](https://github.com/kamiazya)! - `renderHTMLLike` writes strings as text, as React DOM does: text children and attribute values are written with character references where needed, so a string that already contains a character reference such as ` ` is written as that literal text (use `' '` instead). Names that are not valid tag or attribute names, and React's `key` / `ref`, are not written. `renderHTMLLike`, `renderToDot` and `createRoot` read their options and props from own properties only.
8
+
9
+ - Updated dependencies [[`24cc46e`](https://github.com/ts-graphviz/ts-graphviz/commit/24cc46ebf0078440fa498f89b21e7224725c16b6)]:
10
+ - ts-graphviz@3.0.9
11
+
3
12
  ## 0.12.1
4
13
 
5
14
  ### Patch Changes
package/README.md CHANGED
@@ -21,7 +21,7 @@ React Components and Renderer for ts-graphviz
21
21
 
22
22
  [![GitHub](https://img.shields.io/badge/-GitHub-181717?logo=GitHub&style=flat)](https://github.com/ts-graphviz/ts-graphviz)
23
23
  [![npm](https://img.shields.io/badge/-npm-CB3837?logo=npm&style=flat)](https://www.npmjs.com/package/ts-graphviz)
24
- [![Reference](https://img.shields.io/badge/-API_Reference-3178C6?logo=TypeScript&style=flat&logoColor=fff)](https://ts-graphviz.github.io/ts-graphviz/)
24
+ [![Reference](https://img.shields.io/badge/-API_Reference-3178C6?logo=TypeScript&style=flat&logoColor=fff)](https://ts-graphviz.github.io/api/)
25
25
  [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/ts-graphviz/ts-graphviz)
26
26
 
27
27
  [![Sponsor](https://img.shields.io/badge/-GitHub%20Sponsor-fff?logo=GitHub%20Sponsors&style=flat)](https://github.com/sponsors/ts-graphviz)
@@ -725,6 +725,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
725
725
  <td align="center" valign="top" width="14.28%"><a href="http://www.walterra.dev"><img src="https://avatars.githubusercontent.com/u/230104?v=4?s=100" width="100px;" alt="Walter Rafelsberger"/><br /><sub><b>Walter Rafelsberger</b></sub></a><br /><a href="#question-walterra" title="Answering Questions">💬</a></td>
726
726
  <td align="center" valign="top" width="14.28%"><a href="https://github.com/grsjst"><img src="https://avatars.githubusercontent.com/u/4739018?v=4?s=100" width="100px;" alt="grsjst"/><br /><sub><b>grsjst</b></sub></a><br /><a href="https://github.com/ts-graphviz/ts-graphviz/issues?q=author%3Agrsjst" title="Bug reports">🐛</a></td>
727
727
  <td align="center" valign="top" width="14.28%"><a href="https://github.com/stephenirven"><img src="https://avatars.githubusercontent.com/u/4293560?v=4?s=100" width="100px;" alt="Steve"/><br /><sub><b>Steve</b></sub></a><br /><a href="https://github.com/ts-graphviz/ts-graphviz/issues?q=author%3Astephenirven" title="Bug reports">🐛</a></td>
728
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/btomaj"><img src="https://avatars.githubusercontent.com/u/2638986?v=4?s=100" width="100px;" alt="poetry by"/><br /><sub><b>poetry by</b></sub></a><br /><a href="https://github.com/ts-graphviz/ts-graphviz/issues?q=author%3Abtomaj" title="Bug reports">🐛</a></td>
728
729
  </tr>
729
730
  </tbody>
730
731
  </table>
package/lib/react.js CHANGED
@@ -81,6 +81,17 @@ ModelCollectorContext.displayName = "ModelCollectorContext";
81
81
  function useModelCollector() {
82
82
  return useContext(ModelCollectorContext);
83
83
  }
84
+ function ownOptions(options) {
85
+ const own = /* @__PURE__ */ Object.create(null);
86
+ if (options != null) {
87
+ const descriptors = Object.getOwnPropertyDescriptors(options);
88
+ for (const key of Object.getOwnPropertyNames(descriptors)) {
89
+ const descriptor = descriptors[key];
90
+ own[key] = "value" in descriptor ? descriptor.value : descriptor.get?.call(options);
91
+ }
92
+ }
93
+ return own;
94
+ }
84
95
  const DEFAULT_MAX_RECURSION_DEPTH = 1e3;
85
96
  const DOT_ELEMENT_MAP = {
86
97
  "dot:table": "table",
@@ -99,6 +110,9 @@ const DOT_ELEMENT_MAP = {
99
110
  "dot:hr": "hr",
100
111
  "dot:vr": "vr"
101
112
  };
113
+ function ownChildren(props) {
114
+ return props != null && Object.hasOwn(props, "children") ? props.children : void 0;
115
+ }
102
116
  function manuallyRenderElement(element, depth, inStack, maxDepth) {
103
117
  if (depth >= maxDepth) {
104
118
  throw new Error(
@@ -133,7 +147,7 @@ function manuallyRenderElement(element, depth, inStack, maxDepth) {
133
147
  if (tagName === "dot:port") {
134
148
  const propsWithChildren2 = props;
135
149
  const childrenString2 = renderChildrenToString(
136
- propsWithChildren2?.children,
150
+ ownChildren(propsWithChildren2),
137
151
  depth + 1,
138
152
  inStack,
139
153
  maxDepth
@@ -146,12 +160,20 @@ function manuallyRenderElement(element, depth, inStack, maxDepth) {
146
160
  tagName = htmlElement;
147
161
  }
148
162
  }
163
+ if (!NAME.test(tagName)) {
164
+ return renderChildrenToString(
165
+ ownChildren(props),
166
+ depth + 1,
167
+ inStack,
168
+ maxDepth
169
+ );
170
+ }
149
171
  const attributes = [];
150
172
  const propsWithChildren = props;
151
173
  Object.entries(propsWithChildren || {}).forEach(([key, value]) => {
152
- if (key !== "children" && value != null) {
174
+ if (key !== "children" && key !== "key" && key !== "ref" && value != null && NAME.test(key)) {
153
175
  if (typeof value === "string" || typeof value === "number") {
154
- attributes.push(`${key}="${String(value)}"`);
176
+ attributes.push(`${key}="${escapeAttribute(String(value))}"`);
155
177
  } else if (typeof value === "boolean" && value) {
156
178
  attributes.push(key);
157
179
  }
@@ -159,7 +181,7 @@ function manuallyRenderElement(element, depth, inStack, maxDepth) {
159
181
  });
160
182
  const attrsString = attributes.length > 0 ? ` ${attributes.join(" ")}` : "";
161
183
  const childrenString = renderChildrenToString(
162
- propsWithChildren?.children,
184
+ ownChildren(propsWithChildren),
163
185
  depth + 1,
164
186
  inStack,
165
187
  maxDepth
@@ -174,17 +196,24 @@ function manuallyRenderElement(element, depth, inStack, maxDepth) {
174
196
  inStack.delete(element);
175
197
  }
176
198
  }
199
+ function escapeText(text) {
200
+ return text.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
201
+ }
202
+ function escapeAttribute(value) {
203
+ return escapeText(value).replaceAll('"', "&quot;");
204
+ }
205
+ const NAME = /^[A-Za-z][A-Za-z0-9_:-]*$/;
177
206
  function renderChildrenToString(children, depth, inStack, maxDepth) {
178
207
  if (children == null || typeof children === "boolean") {
179
208
  return "";
180
209
  }
181
210
  if (typeof children === "string" || typeof children === "number") {
182
- return String(children);
211
+ return escapeText(String(children));
183
212
  }
184
213
  if (Array.isArray(children)) {
185
214
  return children.map((child) => renderChildrenToString(child, depth, inStack, maxDepth)).join("");
186
215
  }
187
- if (typeof children === "object" && children !== null && "type" in children) {
216
+ if (typeof children === "object" && children !== null && Object.hasOwn(children, "type")) {
188
217
  return manuallyRenderElement(
189
218
  children,
190
219
  depth,
@@ -198,9 +227,10 @@ function renderHTMLLike(label, options) {
198
227
  if (!label) {
199
228
  return "<>";
200
229
  }
230
+ const { maxDepth: givenMaxDepth } = ownOptions(options);
201
231
  let maxDepth = DEFAULT_MAX_RECURSION_DEPTH;
202
- if (options?.maxDepth != null && Number.isFinite(options.maxDepth) && options.maxDepth > 0) {
203
- maxDepth = Math.floor(options.maxDepth);
232
+ if (givenMaxDepth != null && Number.isFinite(givenMaxDepth) && givenMaxDepth > 0) {
233
+ maxDepth = Math.floor(givenMaxDepth);
204
234
  }
205
235
  try {
206
236
  const markup = manuallyRenderElement(label, 0, /* @__PURE__ */ new WeakSet(), maxDepth);
@@ -729,7 +759,8 @@ async function renderInternal(containerInfo, fiberRoot, wrappedElement, original
729
759
  });
730
760
  }
731
761
  function createRoot(options = {}) {
732
- const { container, ...otherOptions } = options;
762
+ const { container, ...rest } = ownOptions(options);
763
+ const otherOptions = ownOptions(rest);
733
764
  const containerInfo = {
734
765
  renderedModels: []
735
766
  };
@@ -788,7 +819,8 @@ function createRoot(options = {}) {
788
819
  };
789
820
  }
790
821
  async function renderToDot(element, options = {}) {
791
- const { container, ...rootOptions } = options;
822
+ const { container, ...rest } = ownOptions(options);
823
+ const rootOptions = ownOptions(rest);
792
824
  if (container) {
793
825
  const root = createRoot({ container, ...rootOptions });
794
826
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ts-graphviz/react",
3
- "version": "0.12.1",
3
+ "version": "0.12.2",
4
4
  "description": "Graphviz-dot Renderer for React.",
5
5
  "keywords": [
6
6
  "graphviz",
@@ -39,7 +39,7 @@
39
39
  "dependencies": {
40
40
  "react-reconciler": "^0.32.0",
41
41
  "@ts-graphviz/common": "^3.0.5",
42
- "ts-graphviz": "^3.0.8"
42
+ "ts-graphviz": "^3.0.9"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@testing-library/react": "^16.3.0",