@withwiz/cms-kit 0.1.0 → 0.2.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 +4 -2
- package/README.md +4 -2
- package/dist/{chunk-JMWXVXK5.js → chunk-25GMHPCW.js} +12 -4
- package/dist/chunk-25GMHPCW.js.map +1 -0
- package/dist/{chunk-5JUIMXNF.js → chunk-2VHNZWH2.js} +3 -3
- package/dist/{chunk-5JUIMXNF.js.map → chunk-2VHNZWH2.js.map} +1 -1
- package/dist/{chunk-BWKKHCDG.mjs → chunk-3UXX27N5.mjs} +44 -3
- package/dist/{chunk-BWKKHCDG.mjs.map → chunk-3UXX27N5.mjs.map} +1 -1
- package/dist/{chunk-T7EVFD4G.mjs → chunk-47DPXAO6.mjs} +2 -2
- package/dist/{chunk-4W3X7OKF.js → chunk-5Z5XUR2K.js} +48 -27
- package/dist/chunk-5Z5XUR2K.js.map +1 -0
- package/dist/{chunk-LDFE33ML.mjs → chunk-7F5YFG2W.mjs} +10 -2
- package/dist/chunk-7F5YFG2W.mjs.map +1 -0
- package/dist/{chunk-CGVFB23E.mjs → chunk-A557FA2K.mjs} +24 -19
- package/dist/{chunk-CGVFB23E.mjs.map → chunk-A557FA2K.mjs.map} +1 -1
- package/dist/{chunk-OBNALAMG.mjs → chunk-BG4C5KZO.mjs} +2 -2
- package/dist/{chunk-DCIF4XJL.js → chunk-EPVV6655.js} +10 -10
- package/dist/{chunk-DCIF4XJL.js.map → chunk-EPVV6655.js.map} +1 -1
- package/dist/{chunk-LF5LOI7K.mjs → chunk-FCWUNCGA.mjs} +3 -3
- package/dist/{chunk-YEQFKOWD.mjs → chunk-GQJNLE34.mjs} +2 -2
- package/dist/{chunk-W4FWIZ2Y.js → chunk-HVB72GT3.js} +3 -3
- package/dist/{chunk-W4FWIZ2Y.js.map → chunk-HVB72GT3.js.map} +1 -1
- package/dist/{chunk-KWKV2GAH.js → chunk-J32BTYJZ.js} +4 -4
- package/dist/{chunk-KWKV2GAH.js.map → chunk-J32BTYJZ.js.map} +1 -1
- package/dist/{chunk-C5WFZJM4.js → chunk-JPIQU2C4.js} +6 -6
- package/dist/{chunk-C5WFZJM4.js.map → chunk-JPIQU2C4.js.map} +1 -1
- package/dist/{chunk-FEPGJ7WN.mjs → chunk-MN27HJKW.mjs} +3 -3
- package/dist/{chunk-ZULSFSDG.mjs → chunk-MWX5B4DP.mjs} +3 -3
- package/dist/{chunk-FCCCG5Z7.mjs → chunk-MXXC4U3D.mjs} +2 -2
- package/dist/{chunk-5RDMODGV.mjs → chunk-N7LMNP4W.mjs} +2 -2
- package/dist/{chunk-YY7K5CXX.js → chunk-OHJISVGC.js} +5 -5
- package/dist/{chunk-YY7K5CXX.js.map → chunk-OHJISVGC.js.map} +1 -1
- package/dist/{chunk-EM4MQEWV.mjs → chunk-SN3XOMF6.mjs} +45 -24
- package/dist/chunk-SN3XOMF6.mjs.map +1 -0
- package/dist/{chunk-BE7JDL64.js → chunk-TKOFGRU4.js} +11 -11
- package/dist/{chunk-BE7JDL64.js.map → chunk-TKOFGRU4.js.map} +1 -1
- package/dist/{chunk-EG6NVPP2.js → chunk-UVZD7GHG.js} +44 -3
- package/dist/chunk-UVZD7GHG.js.map +1 -0
- package/dist/{chunk-6EZ3QE5N.js → chunk-Y3YYIJYG.js} +3 -3
- package/dist/{chunk-6EZ3QE5N.js.map → chunk-Y3YYIJYG.js.map} +1 -1
- package/dist/{chunk-OYJRR3G2.js → chunk-ZMXNPYFS.js} +25 -20
- package/dist/chunk-ZMXNPYFS.js.map +1 -0
- package/dist/components/AdminManagerBase.js +5 -5
- package/dist/components/AdminManagerBase.mjs +4 -4
- package/dist/components/AdminShell.d.mts +1 -1
- package/dist/components/AdminShell.d.ts +1 -1
- package/dist/components/AdminShell.js +4 -4
- package/dist/components/AdminShell.mjs +3 -3
- package/dist/components/index.d.mts +1 -1
- package/dist/components/index.d.ts +1 -1
- package/dist/components/index.js +8 -8
- package/dist/components/index.mjs +7 -7
- package/dist/hooks/index.js +5 -5
- package/dist/hooks/index.mjs +4 -4
- package/dist/hooks/useImageDropZone.js +4 -4
- package/dist/hooks/useImageDropZone.mjs +3 -3
- package/dist/{index-00a40-FQ.d.ts → index-Cce8FHtI.d.mts} +38 -1
- package/dist/{index-00a40-FQ.d.mts → index-Cce8FHtI.d.ts} +38 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +19 -13
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +18 -12
- package/dist/infrastructure/index.js +3 -3
- package/dist/infrastructure/index.mjs +2 -2
- package/dist/infrastructure/middleware/index.js +3 -3
- package/dist/infrastructure/middleware/index.mjs +2 -2
- package/dist/infrastructure/middleware/wrappers.js +3 -3
- package/dist/infrastructure/middleware/wrappers.mjs +2 -2
- package/dist/services/index.js +5 -5
- package/dist/services/index.mjs +4 -4
- package/dist/utils/admin-fetch.js +3 -3
- package/dist/utils/admin-fetch.mjs +2 -2
- package/dist/utils/html-sanitizer.js +3 -3
- package/dist/utils/html-sanitizer.mjs +2 -2
- package/dist/utils/index.d.mts +1 -1
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.js +13 -7
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/index.mjs +12 -6
- package/dist/utils/jwt.js +3 -3
- package/dist/utils/jwt.mjs +2 -2
- package/dist/utils/r2-helpers.js +4 -4
- package/dist/utils/r2-helpers.mjs +3 -3
- package/dist/utils/r2-storage.js +3 -3
- package/dist/utils/r2-storage.mjs +2 -2
- package/package.json +4 -4
- package/dist/chunk-4W3X7OKF.js.map +0 -1
- package/dist/chunk-EG6NVPP2.js.map +0 -1
- package/dist/chunk-EM4MQEWV.mjs.map +0 -1
- package/dist/chunk-JMWXVXK5.js.map +0 -1
- package/dist/chunk-LDFE33ML.mjs.map +0 -1
- package/dist/chunk-OYJRR3G2.js.map +0 -1
- /package/dist/{chunk-T7EVFD4G.mjs.map → chunk-47DPXAO6.mjs.map} +0 -0
- /package/dist/{chunk-OBNALAMG.mjs.map → chunk-BG4C5KZO.mjs.map} +0 -0
- /package/dist/{chunk-LF5LOI7K.mjs.map → chunk-FCWUNCGA.mjs.map} +0 -0
- /package/dist/{chunk-YEQFKOWD.mjs.map → chunk-GQJNLE34.mjs.map} +0 -0
- /package/dist/{chunk-FEPGJ7WN.mjs.map → chunk-MN27HJKW.mjs.map} +0 -0
- /package/dist/{chunk-ZULSFSDG.mjs.map → chunk-MWX5B4DP.mjs.map} +0 -0
- /package/dist/{chunk-FCCCG5Z7.mjs.map → chunk-MXXC4U3D.mjs.map} +0 -0
- /package/dist/{chunk-5RDMODGV.mjs.map → chunk-N7LMNP4W.mjs.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/uni4love/project/workspace/211-withwiz/node-packages/withwiz-cms-kit/dist/chunk-OYJRR3G2.js","../src/utils/html-sanitizer.ts"],"names":[],"mappings":"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","file":"/Users/uni4love/project/workspace/211-withwiz/node-packages/withwiz-cms-kit/dist/chunk-OYJRR3G2.js","sourcesContent":[null,"/**\n * 서버사이드 HTML 새니타이저 (spec.md §4.6 / Sprint 1 S1).\n *\n * 위험한 요소(script, iframe, object 등)와 이벤트 핸들러 속성을 제거하면서\n * 블록 에디터가 사용하는 안전한 HTML 구조를 보존한다.\n *\n * - 1차(기본): `isomorphic-dompurify` (실제 jsdom+DOMPurify DOM/parser\n * allowlist 새니타이저 — 손수 만든 regex 가 아님). 동적으로 로드한다.\n * - fallback: regex 기반 새니타이저는 *방어 심층(defense-in-depth)* 으로만\n * 남겨둔다 (optional dep 미설치 시). 더 이상 1차 경로가 아니다.\n * - `createSanitizer(config)` 로 신뢰 iframe origin 을 주입할 수 있다.\n *\n * `sanitizeHtmlContent` 는 하위 호환을 위해 기본 안전 설정으로 동작한다\n * (I1 — 동일 이름, 동일 `string|null|undefined → string|null` 시그니처).\n * 기본 신뢰 iframe origin 은 §5 config boundary 를 통해 consumer 가\n * override 할 수 있고, 미설정 시 현재 YouTube/Vimeo 집합이 그대로 쓰인다\n * (unconfigured 동작 불변 — I3 보호).\n *\n * `../../withwiz-blog-core/src/utils/html-sanitizer.ts` 와 *메커니즘 동일*\n * (`createSanitizer` factory + `tryLoadDomPurify()` 동적 require +\n * `uponSanitizeElement` iframe-origin hook + regex defense-in-depth fallback).\n */\n\nimport { resolveTrustedIframeOrigins } from '../config';\n\n// ── 정규식 패턴 (defense-in-depth fallback 전용) ──\n\n/** 항상 제거할 태그 (내용 포함) */\nconst STRIP_TAGS_WITH_CONTENT =\n /(<\\s*\\/?\\s*(script|object|embed|applet|form|input|textarea|select|button)\\b[^>]*>)/gi;\n\n/** 신뢰되지 않는 iframe 매칭 */\nconst UNTRUSTED_IFRAME = /<\\s*iframe\\b[^>]*>[\\s\\S]*?<\\s*\\/\\s*iframe\\s*>/gi;\n\n/** script/style 태그 사이 콘텐츠 */\nconst STRIP_TAG_CONTENT = /<\\s*(script|style)\\b[^>]*>[\\s\\S]*?<\\s*\\/\\s*\\1\\s*>/gi;\n\n/** 이벤트 핸들러 속성 (onclick, onerror, onload 등) */\nconst EVENT_HANDLER_ATTRS = /\\s+on\\w+\\s*=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\s>]*)/gi;\n\n/** 위험한 URL 프로토콜 (href/src 속성 내) */\nconst DANGEROUS_PROTOCOL =\n /(href|src|action)\\s*=\\s*[\"']\\s*(javascript|vbscript|data\\s*:(?!image\\/))[^\"']*[\"']/gi;\n\n// ── 설정 인터페이스 ──\n\n/** 새니타이저 설정 */\nexport interface SanitizerConfig {\n /**\n * 신뢰할 수 있는 iframe origin 목록 (prefix 매칭).\n * 미지정 시 §5 config boundary 의 기본값(YouTube/Vimeo) 사용.\n */\n trustedIframeOrigins?: readonly string[];\n /** DOMPurify 사용 시 허용할 태그 화이트리스트. */\n allowedTags?: string[];\n /** DOMPurify 사용 시 허용할 속성 화이트리스트. */\n allowedAttributes?: Record<string, string[]>;\n}\n\n// ── DOMPurify 동적 로딩 (선택적 / 실제 사용되는 1차 경로) ──\n\ntype DOMPurifyLike = {\n sanitize: (dirty: string, options?: Record<string, unknown>) => string;\n};\n\nlet cachedDomPurify: DOMPurifyLike | null | undefined;\n\n/**\n * 선택적 의존성 `isomorphic-dompurify` (실제 DOM allowlist 새니타이저) 를\n * 동기적으로 로드한다. 설치되지 않았거나 로드 실패 시에만 null 을 반환하고,\n * 호출자는 regex defense-in-depth fallback 을 쓴다.\n */\nfunction tryLoadDomPurify(): DOMPurifyLike | null {\n if (cachedDomPurify !== undefined) return cachedDomPurify;\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const mod = require('isomorphic-dompurify') as unknown;\n const candidate =\n (mod as { default?: DOMPurifyLike }).default ?? (mod as DOMPurifyLike);\n if (candidate && typeof candidate.sanitize === 'function') {\n cachedDomPurify = candidate;\n return candidate;\n }\n } catch {\n // 모듈 미설치 — regex fallback 사용\n }\n cachedDomPurify = null;\n return null;\n}\n\n// ── 정규식 기반 새니타이저 (defense-in-depth fallback) ──\n\nfunction regexSanitize(html: string, trustedOrigins: readonly string[]): string {\n let result = html;\n\n // 1. script/style 태그 사이 콘텐츠 제거\n result = result.replace(STRIP_TAG_CONTENT, '');\n\n // 2. 위험한 태그 제거\n result = result.replace(STRIP_TAGS_WITH_CONTENT, '');\n\n // 2b. 신뢰되지 않는 iframe 제거 (신뢰 origin 유지)\n result = result.replace(UNTRUSTED_IFRAME, (match) => {\n const srcMatch = match.match(/\\bsrc\\s*=\\s*[\"']([^\"']+)[\"']/i);\n if (srcMatch) {\n const src = srcMatch[1].trim();\n if (trustedOrigins.some((origin) => src.startsWith(origin))) {\n return match;\n }\n }\n return '';\n });\n\n // 3. 이벤트 핸들러 속성 제거\n result = result.replace(EVENT_HANDLER_ATTRS, '');\n\n // 4. 위험한 URL 프로토콜 무력화\n result = result.replace(DANGEROUS_PROTOCOL, '$1=\"\"');\n\n return result;\n}\n\n// ── DOMPurify 기반 새니타이저 (1차 경로) ──\n\nfunction dompurifySanitize(\n html: string,\n purify: DOMPurifyLike,\n trustedOrigins: readonly string[],\n config: SanitizerConfig,\n): string {\n const options: Record<string, unknown> = {\n // iframe 은 hook 에서 origin 검증 후 허용\n ADD_TAGS: ['iframe'],\n ADD_ATTR: ['allowfullscreen', 'frameborder', 'allow'],\n FORBID_TAGS: [\n 'script',\n 'object',\n 'embed',\n 'applet',\n 'form',\n 'input',\n 'textarea',\n 'select',\n 'button',\n 'style',\n ],\n FORBID_ATTR: [\n 'onerror',\n 'onload',\n 'onclick',\n 'onmouseover',\n 'onfocus',\n 'onblur',\n ],\n };\n\n if (config.allowedTags) options.ALLOWED_TAGS = config.allowedTags;\n if (config.allowedAttributes) {\n const flat = new Set<string>();\n for (const attrs of Object.values(config.allowedAttributes)) {\n for (const a of attrs) flat.add(a);\n }\n options.ALLOWED_ATTR = Array.from(flat);\n }\n\n const purifyWithHook = purify as DOMPurifyLike & {\n addHook?: (hook: string, cb: (node: Element) => void) => void;\n removeHook?: (hook: string) => void;\n };\n if (typeof purifyWithHook.addHook === 'function') {\n purifyWithHook.addHook('uponSanitizeElement', (node) => {\n if (node.nodeName && node.nodeName.toLowerCase() === 'iframe') {\n const src = (node as Element).getAttribute?.('src') ?? '';\n const trusted = trustedOrigins.some((origin) =>\n src.startsWith(origin),\n );\n if (!trusted) {\n (node as Element).remove?.();\n }\n }\n });\n }\n try {\n return purify.sanitize(html, options);\n } finally {\n if (typeof purifyWithHook.removeHook === 'function') {\n purifyWithHook.removeHook('uponSanitizeElement');\n }\n }\n}\n\n// ── Public API ──\n\n/**\n * 새니타이저 팩토리.\n *\n * DOMPurify(isomorphic-dompurify) 가 설치되어 있으면 그것을 *1차* 로 사용하고,\n * 없을 때만 regex defense-in-depth fallback 으로 동작한다.\n *\n * @example\n * const sanitize = createSanitizer({\n * trustedIframeOrigins: ['https://www.youtube.com/', 'https://www.loom.com/'],\n * });\n * const safe = sanitize(userHtml);\n */\nexport function createSanitizer(\n config: SanitizerConfig = {},\n): (html: string | null | undefined) => string | null {\n return function sanitize(html: string | null | undefined): string | null {\n if (!html) return html as string | null;\n // 신뢰 origin 은 point-of-use 에서 §5 boundary 를 통해 해석한다\n // (lazy — import 시점에 config 가 없어도 throw 하지 않음).\n const trustedOrigins =\n config.trustedIframeOrigins ?? resolveTrustedIframeOrigins();\n const purify = tryLoadDomPurify();\n if (purify) {\n return dompurifySanitize(html, purify, trustedOrigins, config);\n }\n return regexSanitize(html, trustedOrigins);\n };\n}\n\n/**\n * 리치 HTML 콘텐츠에서 위험한 요소와 속성을 제거한다.\n * 기본 안전 설정으로 동작한다 (하위 호환, I1). 호스트별 신뢰 origin 확장은\n * `createSanitizer({ trustedIframeOrigins: [...] })` 또는 §5\n * `setCmsConfig({ sanitizer: { trustedIframeOrigins } })` 로 한다.\n */\nexport function sanitizeHtmlContent(\n html: string | null | undefined,\n): string | null {\n return defaultSanitize(html);\n}\n\n/** 모듈 로드 시점에 1회 만들어지는 기본 새니타이저 (실행은 lazy). */\nconst defaultSanitize = createSanitizer();\n"]}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|