@jbpark/live-editor 0.2.0 β†’ 1.0.3

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.ko.md CHANGED
@@ -37,7 +37,7 @@ live-editor/
37
37
 
38
38
  ## πŸ”’ λ³΄μ•ˆ 참고사항
39
39
 
40
- - 프리뷰 `<iframe>`(`src/components/Frame/IFrame`)의 `sandbox` prop은 **μ‹€μ œ λ³΄μ•ˆ 경계가 μ•„λ‹™λ‹ˆλ‹€**. 컴파일된 프리뷰 μ½”λ“œλŠ” host νŽ˜μ΄μ§€ μžμ‹ μ˜ JS realmμ—μ„œ `new Function(...)`으둜 μ‹€ν–‰λ˜λ©°(`src/utils/index.ts`의 `compileModule`), iframeμ—λŠ” κ·Έ 결과둜 μƒμ„±λœ React μ—˜λ¦¬λ¨ΌνŠΈλ§Œ `contentDocument`에 ν¬νƒˆλ˜μ–΄ DOM/CSS λ Œλ”λ§ μš©λ„λ‘œλ§Œ μ“°μž…λ‹ˆλ‹€. iframe μžμ²΄λŠ” μ‚¬μš©μž μ½”λ“œλ₯Ό μ‹€ν–‰ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.
40
+ - 프리뷰 `<iframe>`(`src/components/frame/iframe.tsx`)의 `sandbox` prop은 **μ‹€μ œ λ³΄μ•ˆ 경계가 μ•„λ‹™λ‹ˆλ‹€**. 컴파일된 프리뷰 μ½”λ“œλŠ” host νŽ˜μ΄μ§€ μžμ‹ μ˜ JS realmμ—μ„œ `new Function(...)`으둜 μ‹€ν–‰λ˜λ©°(`src/utils/index.ts`의 `compileModule`), iframeμ—λŠ” κ·Έ 결과둜 μƒμ„±λœ React μ—˜λ¦¬λ¨ΌνŠΈλ§Œ `contentDocument`에 ν¬νƒˆλ˜μ–΄ DOM/CSS λ Œλ”λ§ μš©λ„λ‘œλ§Œ μ“°μž…λ‹ˆλ‹€. iframe μžμ²΄λŠ” μ‚¬μš©μž μ½”λ“œλ₯Ό μ‹€ν–‰ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.
41
41
  - μ‹€μ§ˆμ  의미: λ―Έλ¦¬λ³΄κΈ°λ˜λŠ” μ½”λ“œλŠ” 호슀트 μ• ν”Œλ¦¬μΌ€μ΄μ…˜κ³Ό λ™μΌν•œ μˆ˜μ€€μ˜ JS μ ‘κ·Ό κΆŒν•œ(μΏ ν‚€, DOM, λ©”λͺ¨λ¦¬μƒμ˜ μƒνƒœ λ“±)을 κ°€μ§€λ©°, iframe 경계가 이λ₯Ό 막아주지 μ•ŠμŠ΅λ‹ˆλ‹€.
42
42
  - μ‹ λ’°ν•  수 μžˆλŠ” ν”„λ‘œμ νŠΈλ§Œ μ—΄μ–΄μ„œ νŽΈμ§‘ν•˜μ„Έμš”. 직접 λ³„λ„μ˜ 격리 쑰치(예: iframe 자체 `contentWindow` realmμ—μ„œ μ»΄νŒŒμΌμ„ μ‹€ν–‰ν•˜κ³  κ²°κ³Όλ₯Ό `postMessage`둜 μ£Όκ³ λ°›λŠ” 방식)λ₯Ό μΆ”κ°€ν•˜μ§€ μ•Šμ€ μ±„λ‘œ, μ‹ λ’°ν•  수 μ—†λŠ” 제3자 ν”„λ‘œμ νŠΈ νŒŒμΌμ„ λ―Έλ¦¬λ³΄κΈ°ν•˜λŠ” μš©λ„λ‘œ μ‚¬μš©ν•˜μ§€ λ§ˆμ„Έμš” β€” 그런 κ²©λ¦¬λŠ” ν˜„μž¬ κ΅¬ν˜„λ˜μ–΄ μžˆμ§€ μ•ŠμŠ΅λ‹ˆλ‹€.
43
43
 
package/README.md CHANGED
@@ -37,7 +37,7 @@ live-editor/
37
37
 
38
38
  ## πŸ”’ Security Notes
39
39
 
40
- - The `sandbox` prop on the preview `<iframe>` (`src/components/Frame/IFrame`) is **not a security boundary**. Compiled preview code is executed via `new Function(...)` in the host page's own JS realm (`compileModule` in `src/utils/index.ts`); only the resulting React elements are portaled into the iframe's `contentDocument` for DOM/CSS rendering. The iframe itself never evaluates user code.
40
+ - The `sandbox` prop on the preview `<iframe>` (`src/components/frame/iframe.tsx`) is **not a security boundary**. Compiled preview code is executed via `new Function(...)` in the host page's own JS realm (`compileModule` in `src/utils/index.ts`); only the resulting React elements are portaled into the iframe's `contentDocument` for DOM/CSS rendering. The iframe itself never evaluates user code.
41
41
  - Practical implication: previewed code runs with the same JS-level access as the host application (cookies, DOM, in-memory state) β€” the iframe boundary does not contain it.
42
42
  - Only open/edit projects you trust. Don't use this editor to preview arbitrary third-party project files without adding real isolation yourself (e.g. running compilation inside the iframe's own `contentWindow` realm and communicating results back via `postMessage`) β€” that isolation is not implemented here today.
43
43
 
@@ -9,21 +9,7 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
9
9
  var __getOwnPropNames = Object.getOwnPropertyNames;
10
10
  var __getProtoOf = Object.getPrototypeOf;
11
11
  var __hasOwnProp = Object.prototype.hasOwnProperty;
12
- var __esmMin = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
13
12
  var __commonJSMin = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
14
- var __exportAll = (all, no_symbols) => {
15
- let target = {};
16
- for (var name in all) {
17
- __defProp(target, name, {
18
- get: all[name],
19
- enumerable: true
20
- });
21
- }
22
- if (!no_symbols) {
23
- __defProp(target, Symbol.toStringTag, { value: "Module" });
24
- }
25
- return target;
26
- };
27
13
  var __copyProps = (to, from, except, desc) => {
28
14
  if (from && typeof from === "object" || typeof from === "function") {
29
15
  for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
@@ -42,7 +28,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
42
28
  value: mod,
43
29
  enumerable: true
44
30
  }) : target, mod));
45
- var __toCommonJS = (mod) => __hasOwnProp.call(mod, "module.exports") ? mod["module.exports"] : __copyProps(__defProp({}, "__esModule", { value: true }), mod);
46
31
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
47
32
 
48
33
  //#endregion
@@ -26800,7 +26785,11 @@ const parseBinding = (bindingValue) => {
26800
26785
  "boolean",
26801
26786
  "color",
26802
26787
  "jsx",
26803
- "richtext"
26788
+ "richtext",
26789
+ "date",
26790
+ "url",
26791
+ "icon-picker",
26792
+ "asset-picker"
26804
26793
  ].includes(typeValue)) binding.type = typeValue;
26805
26794
  }
26806
26795
  const renderProp = element.properties.find((p) => import_lib$3.isObjectProperty(p) && import_lib$3.isIdentifier(p.key) && p.key.name === "render" && import_lib$3.isObjectExpression(p.value));
@@ -26822,6 +26811,14 @@ const parseBinding = (bindingValue) => {
26822
26811
  }).filter((item) => item !== null);
26823
26812
  if (options.length > 0) binding.options = options;
26824
26813
  }
26814
+ const minProp = element.properties.find((p) => import_lib$3.isObjectProperty(p) && import_lib$3.isIdentifier(p.key) && p.key.name === "min" && import_lib$3.isNumericLiteral(p.value));
26815
+ if (minProp) binding.min = minProp.value.value;
26816
+ const maxProp = element.properties.find((p) => import_lib$3.isObjectProperty(p) && import_lib$3.isIdentifier(p.key) && p.key.name === "max" && import_lib$3.isNumericLiteral(p.value));
26817
+ if (maxProp) binding.max = maxProp.value.value;
26818
+ const patternProp = element.properties.find((p) => import_lib$3.isObjectProperty(p) && import_lib$3.isIdentifier(p.key) && p.key.name === "pattern" && import_lib$3.isStringLiteral(p.value));
26819
+ if (patternProp) binding.pattern = patternProp.value.value;
26820
+ const requiredProp = element.properties.find((p) => import_lib$3.isObjectProperty(p) && import_lib$3.isIdentifier(p.key) && p.key.name === "required" && import_lib$3.isBooleanLiteral(p.value));
26821
+ if (requiredProp) binding.required = requiredProp.value.value;
26825
26822
  return binding;
26826
26823
  }
26827
26824
  }
@@ -39660,5 +39657,55 @@ const clone = (element, generateId = () => nanoid(6)) => {
39660
39657
  };
39661
39658
 
39662
39659
  //#endregion
39663
- export { __exportAll as C, __toESM as E, __esmMin as S, __toCommonJS as T, getCurrentValue as _, update as a, require_lib$7 as b, nanoid as c, extractNodeValue as d, extractObjectProperties as f, findEditableChildren as g, generateCode as h, bulkUpdate as i, arrayExpressionToCode as l, parseValue as m, fillIds as n, clearExtractCache as o, parseArrayExpression as p, replaceIds as r, extract as s, clone as t, createNodeFromValue as u, parseBinding as v, __require as w, __commonJSMin as x, require_lib$4 as y };
39664
- //# sourceMappingURL=ast-6PhUZ232.mjs.map
39660
+ //#region src/utils/ast/validate.ts
39661
+ const VALID = { valid: true };
39662
+ const validateBindingValue = (binding, value) => {
39663
+ if (value === "" || value === null || value === void 0) {
39664
+ if (binding.required) return {
39665
+ valid: false,
39666
+ message: "This field is required."
39667
+ };
39668
+ return VALID;
39669
+ }
39670
+ if (typeof value === "number") {
39671
+ if (binding.min !== void 0 && value < binding.min) return {
39672
+ valid: false,
39673
+ message: `Must be at least ${binding.min}.`
39674
+ };
39675
+ if (binding.max !== void 0 && value > binding.max) return {
39676
+ valid: false,
39677
+ message: `Must be at most ${binding.max}.`
39678
+ };
39679
+ }
39680
+ if (typeof value === "string" && binding.pattern) {
39681
+ let regex;
39682
+ try {
39683
+ regex = new RegExp(binding.pattern);
39684
+ } catch {
39685
+ return VALID;
39686
+ }
39687
+ if (!regex.test(value)) return {
39688
+ valid: false,
39689
+ message: "Value does not match the required format."
39690
+ };
39691
+ }
39692
+ if (typeof value === "string" && binding.type === "url") try {
39693
+ new URL(value);
39694
+ } catch {
39695
+ return {
39696
+ valid: false,
39697
+ message: "Must be a valid URL."
39698
+ };
39699
+ }
39700
+ if (typeof value === "string" && binding.type === "date") {
39701
+ if (Number.isNaN(Date.parse(value))) return {
39702
+ valid: false,
39703
+ message: "Must be a valid date."
39704
+ };
39705
+ }
39706
+ return VALID;
39707
+ };
39708
+
39709
+ //#endregion
39710
+ export { __toESM as S, findEditableChildren as _, bulkUpdate as a, require_lib$4 as b, extract as c, createNodeFromValue as d, extractNodeValue as f, generateCode as g, parseValue as h, replaceIds as i, nanoid as l, parseArrayExpression as m, clone as n, update as o, extractObjectProperties as p, fillIds as r, clearExtractCache as s, validateBindingValue as t, arrayExpressionToCode as u, getCurrentValue as v, require_lib$7 as x, parseBinding as y };
39711
+ //# sourceMappingURL=ast-UXy9dqvD.mjs.map