@jbpark/live-editor 0.2.0 β 1.1.0
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 +1 -1
- package/README.md +1 -1
- package/dist/{ast-6PhUZ232.mjs β ast-UXy9dqvD.mjs} +65 -18
- package/dist/ast-UXy9dqvD.mjs.map +1 -0
- package/dist/index.d.mts +84 -77
- package/dist/index.mjs +866 -7061
- package/dist/index.mjs.map +1 -1
- package/dist/utils/ast/index.d.mts +13 -2
- package/dist/utils/ast/index.mjs +2 -2
- package/package.json +4 -2
- package/dist/ast-6PhUZ232.mjs.map +0 -1
package/README.ko.md
CHANGED
|
@@ -37,7 +37,7 @@ live-editor/
|
|
|
37
37
|
|
|
38
38
|
## π 보μ μ°Έκ³ μ¬ν
|
|
39
39
|
|
|
40
|
-
- ν리뷰 `<iframe>`(`src/components/
|
|
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/
|
|
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
|
-
|
|
39664
|
-
|
|
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
|