kordoc 4.22.16 → 4.22.18
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.md +3 -1
- package/dist/{-3XSSQOP6.js → -OTAPIBUW.js} +25 -11
- package/dist/{chunk-HXV4V6IH.js → chunk-3AVHW7UT.js} +2 -2
- package/dist/{chunk-WMJPOOBJ.js → chunk-3GVPNEIG.js} +2 -2
- package/dist/{chunk-NDO4XZMT.js → chunk-6LTGCEGP.js} +2 -2
- package/dist/{chunk-RMNJTPSR.js → chunk-7QLKNWMN.js} +4 -4
- package/dist/{chunk-UDG4L37H.cjs → chunk-B3Z2PY4R.cjs} +2 -2
- package/dist/{chunk-UDG4L37H.cjs.map → chunk-B3Z2PY4R.cjs.map} +1 -1
- package/dist/{chunk-FFQLQLRE.cjs → chunk-BXZW4Q5G.cjs} +6 -6
- package/dist/{chunk-FFQLQLRE.cjs.map → chunk-BXZW4Q5G.cjs.map} +1 -1
- package/dist/{chunk-IUVFOBQM.cjs → chunk-DKZZVFTK.cjs} +3 -3
- package/dist/{chunk-IUVFOBQM.cjs.map → chunk-DKZZVFTK.cjs.map} +1 -1
- package/dist/{chunk-L5HFJV5O.js → chunk-DQBY4PQ4.js} +17 -4
- package/dist/chunk-DQBY4PQ4.js.map +1 -0
- package/dist/{chunk-TI534EYY.js → chunk-G4PPT5CR.js} +8 -6
- package/dist/{chunk-TI534EYY.js.map → chunk-G4PPT5CR.js.map} +1 -1
- package/dist/{chunk-2ZGVOGHM.js → chunk-HX24KLQN.js} +2 -2
- package/dist/{chunk-SDIKLPMY.js → chunk-JO5OR4F5.js} +2 -2
- package/dist/{chunk-Z7URWVQH.js → chunk-M7SCUHXE.js} +4 -4
- package/dist/{chunk-VTVPHZJ6.js → chunk-MI2YNEQJ.js} +494 -15
- package/dist/chunk-MI2YNEQJ.js.map +1 -0
- package/dist/{chunk-VVOURQFY.js → chunk-MKEBORZM.js} +2 -2
- package/dist/{chunk-VVOURQFY.js.map → chunk-MKEBORZM.js.map} +1 -1
- package/dist/{chunk-3BQYVNOW.js → chunk-MW42GCQ4.js} +2 -2
- package/dist/{chunk-JTRP3OO2.js → chunk-N5QRS6VT.js} +2 -2
- package/dist/{chunk-JZCBDX34.cjs → chunk-NUQG356J.cjs} +3 -3
- package/dist/{chunk-JZCBDX34.cjs.map → chunk-NUQG356J.cjs.map} +1 -1
- package/dist/{chunk-W5SRR7W6.js → chunk-NV3WEN4C.js} +3 -3
- package/dist/{chunk-VJ6UNTC7.js → chunk-OWO3RVJY.js} +2 -2
- package/dist/{chunk-75YWX55A.js → chunk-RTFUKVOX.js} +3 -3
- package/dist/{chunk-2WAKSO2Z.js → chunk-S2WH5IZ3.js} +2 -2
- package/dist/{chunk-GDTSPYWP.js → chunk-SJYHFKKB.js} +2 -2
- package/dist/{chunk-3NYFGUOJ.cjs → chunk-TLGOPNMC.cjs} +24 -24
- package/dist/{chunk-3NYFGUOJ.cjs.map → chunk-TLGOPNMC.cjs.map} +1 -1
- package/dist/{chunk-RVZVCHUE.js → chunk-TLU4OKIO.js} +2 -2
- package/dist/{chunk-XD4B7B55.js → chunk-VCGGP7SY.js} +2 -2
- package/dist/{chunk-XD4B7B55.js.map → chunk-VCGGP7SY.js.map} +1 -1
- package/dist/{chunk-5EISWK2J.js → chunk-VROCP4X4.js} +2 -2
- package/dist/{chunk-C3XICONM.js → chunk-WITGYMV5.js} +4 -4
- package/dist/{chunk-JL3IR45L.cjs → chunk-XIDMSNU2.cjs} +23 -23
- package/dist/{chunk-JL3IR45L.cjs.map → chunk-XIDMSNU2.cjs.map} +1 -1
- package/dist/{chunk-RWLGFHZO.js → chunk-XOX5L7WN.js} +2 -2
- package/dist/chunks-GMADIKNS.js +10 -0
- package/dist/cli.js +96 -39
- package/dist/cli.js.map +1 -1
- package/dist/{formula-XSJKSTPU.cjs → formula-2ISHDHXF.cjs} +9 -9
- package/dist/{formula-XSJKSTPU.cjs.map → formula-2ISHDHXF.cjs.map} +1 -1
- package/dist/{formula-YWCFQN7M.js → formula-E5G3A3NZ.js} +3 -3
- package/dist/{formula-JMFME265.js → formula-WHYRNHRE.js} +4 -4
- package/dist/{image-ocr-W52R3U55.js → image-ocr-5WJQITNQ.js} +6 -6
- package/dist/{image-ocr-HH4WLRMA.js → image-ocr-6J7B5UVA.js} +9 -9
- package/dist/{image-ocr-2OWPVTWD.cjs → image-ocr-MRTNIUZQ.cjs} +17 -17
- package/dist/{image-ocr-2OWPVTWD.cjs.map → image-ocr-MRTNIUZQ.cjs.map} +1 -1
- package/dist/index.cjs +1301 -809
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +92 -1
- package/dist/index.d.ts +92 -1
- package/dist/index.js +520 -28
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +47 -28
- package/dist/mcp.js.map +1 -1
- package/dist/{model-bundle-LAMGDBR5.js → model-bundle-CNNDBCIQ.js} +5 -5
- package/dist/{models-UW6K53RI.js → models-PQYMCKFR.js} +5 -5
- package/dist/{parse-worker-v2-TCYTBP2P.js → parse-worker-v2-Z3W53OUZ.js} +12 -12
- package/dist/{parser-JXAIWIOE.cjs → parser-2YUGVORR.cjs} +157 -157
- package/dist/{parser-JXAIWIOE.cjs.map → parser-2YUGVORR.cjs.map} +1 -1
- package/dist/{parser-J37C64DT.js → parser-UYBCCGY4.js} +12 -12
- package/dist/{parser-Y2OKEGM4.js → parser-YHUWM4KF.js} +9 -9
- package/dist/{pdf-ocr-NUQHXJJR.js → pdf-ocr-6JSBUWUO.js} +9 -9
- package/dist/pdf-ocr-6Q34QQ7A.cjs +31 -0
- package/dist/{pdf-ocr-HPC5BVB7.cjs.map → pdf-ocr-6Q34QQ7A.cjs.map} +1 -1
- package/dist/{pdf-ocr-BDNBONES.js → pdf-ocr-DE7PYWN7.js} +6 -6
- package/dist/{profile-io-SET4RRP2.js → profile-io-DCZ4DINU.js} +3 -3
- package/dist/{rasterize-O7ZM2CRL.js → rasterize-6XD2LLEN.js} +3 -3
- package/dist/{redact-doc-Z3ISHGTJ.js → redact-doc-2BLB3IOP.js} +11 -11
- package/dist/{render-MLKOC2PN.js → render-YPZMJSZL.js} +7 -7
- package/dist/seal-32KIG7OS.js +10 -0
- package/dist/{setup-CUB6RCSD.js → setup-GUE2OUWB.js} +3 -3
- package/dist/visual-Y32AKOM4.js +21 -0
- package/dist/{watch-YPDHDT4N.js → watch-EILA6XGX.js} +12 -12
- package/package.json +2 -2
- package/dist/chunk-L5HFJV5O.js.map +0 -1
- package/dist/chunk-VTVPHZJ6.js.map +0 -1
- package/dist/chunks-XXPD5OV5.js +0 -10
- package/dist/pdf-ocr-HPC5BVB7.cjs +0 -31
- package/dist/seal-7QUWLHB6.js +0 -10
- package/dist/visual-QLWVIUQS.js +0 -21
- /package/dist/{-3XSSQOP6.js.map → -OTAPIBUW.js.map} +0 -0
- /package/dist/{chunk-HXV4V6IH.js.map → chunk-3AVHW7UT.js.map} +0 -0
- /package/dist/{chunk-WMJPOOBJ.js.map → chunk-3GVPNEIG.js.map} +0 -0
- /package/dist/{chunk-NDO4XZMT.js.map → chunk-6LTGCEGP.js.map} +0 -0
- /package/dist/{chunk-RMNJTPSR.js.map → chunk-7QLKNWMN.js.map} +0 -0
- /package/dist/{chunk-2ZGVOGHM.js.map → chunk-HX24KLQN.js.map} +0 -0
- /package/dist/{chunk-SDIKLPMY.js.map → chunk-JO5OR4F5.js.map} +0 -0
- /package/dist/{chunk-Z7URWVQH.js.map → chunk-M7SCUHXE.js.map} +0 -0
- /package/dist/{chunk-3BQYVNOW.js.map → chunk-MW42GCQ4.js.map} +0 -0
- /package/dist/{chunk-JTRP3OO2.js.map → chunk-N5QRS6VT.js.map} +0 -0
- /package/dist/{chunk-W5SRR7W6.js.map → chunk-NV3WEN4C.js.map} +0 -0
- /package/dist/{chunk-VJ6UNTC7.js.map → chunk-OWO3RVJY.js.map} +0 -0
- /package/dist/{chunk-75YWX55A.js.map → chunk-RTFUKVOX.js.map} +0 -0
- /package/dist/{chunk-2WAKSO2Z.js.map → chunk-S2WH5IZ3.js.map} +0 -0
- /package/dist/{chunk-GDTSPYWP.js.map → chunk-SJYHFKKB.js.map} +0 -0
- /package/dist/{chunk-RVZVCHUE.js.map → chunk-TLU4OKIO.js.map} +0 -0
- /package/dist/{chunk-5EISWK2J.js.map → chunk-VROCP4X4.js.map} +0 -0
- /package/dist/{chunk-C3XICONM.js.map → chunk-WITGYMV5.js.map} +0 -0
- /package/dist/{chunk-RWLGFHZO.js.map → chunk-XOX5L7WN.js.map} +0 -0
- /package/dist/{chunks-XXPD5OV5.js.map → chunks-GMADIKNS.js.map} +0 -0
- /package/dist/{formula-YWCFQN7M.js.map → formula-E5G3A3NZ.js.map} +0 -0
- /package/dist/{formula-JMFME265.js.map → formula-WHYRNHRE.js.map} +0 -0
- /package/dist/{image-ocr-W52R3U55.js.map → image-ocr-5WJQITNQ.js.map} +0 -0
- /package/dist/{image-ocr-HH4WLRMA.js.map → image-ocr-6J7B5UVA.js.map} +0 -0
- /package/dist/{model-bundle-LAMGDBR5.js.map → model-bundle-CNNDBCIQ.js.map} +0 -0
- /package/dist/{models-UW6K53RI.js.map → models-PQYMCKFR.js.map} +0 -0
- /package/dist/{parse-worker-v2-TCYTBP2P.js.map → parse-worker-v2-Z3W53OUZ.js.map} +0 -0
- /package/dist/{parser-J37C64DT.js.map → parser-UYBCCGY4.js.map} +0 -0
- /package/dist/{parser-Y2OKEGM4.js.map → parser-YHUWM4KF.js.map} +0 -0
- /package/dist/{pdf-ocr-BDNBONES.js.map → pdf-ocr-6JSBUWUO.js.map} +0 -0
- /package/dist/{pdf-ocr-NUQHXJJR.js.map → pdf-ocr-DE7PYWN7.js.map} +0 -0
- /package/dist/{profile-io-SET4RRP2.js.map → profile-io-DCZ4DINU.js.map} +0 -0
- /package/dist/{rasterize-O7ZM2CRL.js.map → rasterize-6XD2LLEN.js.map} +0 -0
- /package/dist/{redact-doc-Z3ISHGTJ.js.map → redact-doc-2BLB3IOP.js.map} +0 -0
- /package/dist/{render-MLKOC2PN.js.map → render-YPZMJSZL.js.map} +0 -0
- /package/dist/{seal-7QUWLHB6.js.map → seal-32KIG7OS.js.map} +0 -0
- /package/dist/{setup-CUB6RCSD.js.map → setup-GUE2OUWB.js.map} +0 -0
- /package/dist/{visual-QLWVIUQS.js.map → visual-Y32AKOM4.js.map} +0 -0
- /package/dist/{watch-YPDHDT4N.js.map → watch-EILA6XGX.js.map} +0 -0
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
FLAG_DISTRIBUTION,
|
|
6
6
|
FLAG_DRM,
|
|
7
7
|
FLAG_ENCRYPTED,
|
|
8
|
+
FLAG_TRACK_CHANGES,
|
|
8
9
|
INLINE_TABLE_MARK,
|
|
9
10
|
MIDDLE_CONVERT_MAP,
|
|
10
11
|
SPACE_EM_FIXED,
|
|
@@ -50,10 +51,10 @@ import {
|
|
|
50
51
|
resolveParaHeading,
|
|
51
52
|
simulateWrap,
|
|
52
53
|
takeTocLeaders
|
|
53
|
-
} from "./chunk-
|
|
54
|
+
} from "./chunk-G4PPT5CR.js";
|
|
54
55
|
import {
|
|
55
56
|
blocksToPages
|
|
56
|
-
} from "./chunk-
|
|
57
|
+
} from "./chunk-TLU4OKIO.js";
|
|
57
58
|
import {
|
|
58
59
|
bmpToPng,
|
|
59
60
|
inlineImagesIntoMarkdown
|
|
@@ -75,7 +76,7 @@ import {
|
|
|
75
76
|
tidyScriptTags,
|
|
76
77
|
unframeLayoutTables,
|
|
77
78
|
wrapScript
|
|
78
|
-
} from "./chunk-
|
|
79
|
+
} from "./chunk-MKEBORZM.js";
|
|
79
80
|
import {
|
|
80
81
|
MAX_COLS,
|
|
81
82
|
MAX_ROWS,
|
|
@@ -97,7 +98,7 @@ import {
|
|
|
97
98
|
noteTableHtml,
|
|
98
99
|
sanitizeText,
|
|
99
100
|
visibleText
|
|
100
|
-
} from "./chunk-
|
|
101
|
+
} from "./chunk-3AVHW7UT.js";
|
|
101
102
|
import {
|
|
102
103
|
ANNOTATION_BLANK_RE,
|
|
103
104
|
ValueCursor,
|
|
@@ -130,7 +131,7 @@ import {
|
|
|
130
131
|
resolveUnmatched,
|
|
131
132
|
scanInlineSegments,
|
|
132
133
|
scanSectionXml
|
|
133
|
-
} from "./chunk-
|
|
134
|
+
} from "./chunk-DQBY4PQ4.js";
|
|
134
135
|
import {
|
|
135
136
|
MAX_DECOMPRESS_SIZE,
|
|
136
137
|
MAX_XML_DEPTH,
|
|
@@ -147,7 +148,7 @@ import {
|
|
|
147
148
|
localName,
|
|
148
149
|
rawTextContent,
|
|
149
150
|
readZipEntry
|
|
150
|
-
} from "./chunk-
|
|
151
|
+
} from "./chunk-OWO3RVJY.js";
|
|
151
152
|
import {
|
|
152
153
|
KordocError,
|
|
153
154
|
classifyError,
|
|
@@ -163,7 +164,7 @@ import {
|
|
|
163
164
|
toArrayBuffer,
|
|
164
165
|
unescapeHtml,
|
|
165
166
|
unzipLimitBytes
|
|
166
|
-
} from "./chunk-
|
|
167
|
+
} from "./chunk-S2WH5IZ3.js";
|
|
167
168
|
|
|
168
169
|
// src/table/visual.ts
|
|
169
170
|
import { readFile as readFile2 } from "fs/promises";
|
|
@@ -19327,7 +19328,7 @@ var MIN_SIDE = 24;
|
|
|
19327
19328
|
async function ocrEmbeddedImages(blocks, options, warnings) {
|
|
19328
19329
|
const ocr = options?.ocr;
|
|
19329
19330
|
if (ocr !== true && ocr !== "force" && typeof ocr !== "function") return false;
|
|
19330
|
-
const { parseImageDocument } = await import("./image-ocr-
|
|
19331
|
+
const { parseImageDocument } = await import("./image-ocr-6J7B5UVA.js");
|
|
19331
19332
|
let inserted = false, unreadable = 0;
|
|
19332
19333
|
let failed = null;
|
|
19333
19334
|
const walk = async (list, depth) => {
|
|
@@ -27372,6 +27373,468 @@ function muncheLintWarnings(text, limit = 10) {
|
|
|
27372
27373
|
return shown;
|
|
27373
27374
|
}
|
|
27374
27375
|
|
|
27376
|
+
// src/hwpx/slop-lint.ts
|
|
27377
|
+
var RULES2 = [
|
|
27378
|
+
// 결산 피벗 — 개조식 공문은 장 이름(향후계획·조치계획)이 마무리를 맡는다. 사람 글 838건 중 0건
|
|
27379
|
+
{
|
|
27380
|
+
code: "SLOP_PIVOT",
|
|
27381
|
+
severity: "error",
|
|
27382
|
+
pattern: /결론적으로|요약하면|정리하면|요컨대|종합해 ?보면/g,
|
|
27383
|
+
message: "\uACB0\uC0B0 \uC811\uC18D\uC5B4 \u2014 \uACF5\uBB38\uC740 \uC7A5 \uC774\uB984\uC774 \uB9C8\uBB34\uB9AC\uB97C \uB9E1\uC74C(\uC0DD\uC131\uD615 AI \uBB38\uCCB4)",
|
|
27384
|
+
suggest: "\uC9C0\uC6B0\uACE0 \uD310\uB2E8\xB7\uC870\uCE58\uB97C \uBC14\uB85C \uC801\uC74C"
|
|
27385
|
+
},
|
|
27386
|
+
// 평론 상투구 — 사람 글 0건
|
|
27387
|
+
{
|
|
27388
|
+
code: "SLOP_SIGNATURE",
|
|
27389
|
+
severity: "error",
|
|
27390
|
+
pattern: /시사하는 바가|시사점이 크|주목할 만하|본질적으로|핵심적으로|게임 ?체인저|새로운 지평|새로운 장을 열|의미 있는 첫걸음/g,
|
|
27391
|
+
message: "\uD3C9\uB860\xB7\uD64D\uBCF4 \uC0C1\uD22C\uAD6C(\uC0DD\uC131\uD615 AI \uBB38\uCCB4)",
|
|
27392
|
+
suggest: "\uBB34\uC5C7\uC774 \uB2EC\uB77C\uC9C0\uB294\uC9C0 \uC218\uCE58\xB7\uC0AC\uC2E4\uB85C"
|
|
27393
|
+
},
|
|
27394
|
+
// 사람도 쓰지만 AI 초안에 몰리는 홍보 상투구
|
|
27395
|
+
{
|
|
27396
|
+
code: "SLOP_HYPE",
|
|
27397
|
+
severity: "warning",
|
|
27398
|
+
pattern: /패러다임(?:의)? 전환|한 단계 도약|지금이야말로|초석이 될|발판이 될|획기적|압도적|파격적|비약적|전례 ?없는|극대화/g,
|
|
27399
|
+
message: "\uACFC\uC7A5\xB7\uD64D\uBCF4 \uC0C1\uD22C\uAD6C",
|
|
27400
|
+
suggest: "\uBAA9\uD45C\uCE58\xB7\uB300\uC0C1\xB7\uAE30\uAC04\uC73C\uB85C \uBC14\uAFD4 \uC500"
|
|
27401
|
+
},
|
|
27402
|
+
// 시대 상투구 — 배경을 사실 대신 분위기로 여는 서두. 사람 글 문서 적중 1.5%(급변하는 26회가 대부분)
|
|
27403
|
+
{
|
|
27404
|
+
code: "SLOP_ERA_CLICHE",
|
|
27405
|
+
severity: "warning",
|
|
27406
|
+
pattern: /중요성이 (?:날로|점차|더욱|갈수록)|(?:관심|요구|필요성)이 (?:날로|점차|더욱|갈수록) (?:높아|커지|증대|증가)|급변하는|시대적 (?:요구|흐름|과제)|요구되는 시점|4차 산업혁명 시대|대전환 시대|뉴노멀/g,
|
|
27407
|
+
message: "\uC2DC\uB300\xB7\uBD84\uC704\uAE30\uB85C \uC5EC\uB294 \uC0C1\uD22C \uC11C\uB450 \u2014 \uBC30\uACBD\uC740 \uC0AC\uC2E4\uB85C \uC5F0\uB2E4",
|
|
27408
|
+
suggest: "\uC608) \u300C\u25CB\u25CB\uBC95\u300D \uAC1C\uC815(2026. 3. 1. \uC2DC\uD589), \uBBFC\uC6D0 412\uAC74(\uC804\uB144 \uB300\uBE44 38%\u2191)"
|
|
27409
|
+
},
|
|
27410
|
+
// 체감·만족도 상투구 — AI 초안 29%, 사람 글 2% 이하
|
|
27411
|
+
{
|
|
27412
|
+
code: "SLOP_FEEL_GOOD",
|
|
27413
|
+
severity: "warning",
|
|
27414
|
+
pattern: /체감(?:도|형)? ?(?:높은|향상|제고)|만족도 (?:향상|제고|증진)|삶의 질 (?:향상|제고)|행복 ?(?:지수 )?(?:증진|향상)/g,
|
|
27415
|
+
message: "\uCCB4\uAC10\xB7\uB9CC\uC871\uB3C4 \uC0C1\uD22C\uAD6C \u2014 \uBB34\uC5C7\uC774 \uC5BC\uB9C8\uB098 \uB098\uC544\uC9C0\uB294\uC9C0 \uC5C6\uC74C",
|
|
27416
|
+
suggest: "\uC608) \uB300\uAE30\uC2DC\uAC04 25\uBD84\u219210\uBD84, \uBBFC\uC6D0 30% \uAC10\uC18C"
|
|
27417
|
+
},
|
|
27418
|
+
// 번역투 — 보도자료에도 흔해 문서 안 3회 이상만
|
|
27419
|
+
{
|
|
27420
|
+
code: "SLOP_TRANSLATIONESE",
|
|
27421
|
+
severity: "warning",
|
|
27422
|
+
minCount: 3,
|
|
27423
|
+
pattern: /에 있어서?(?![가-힣])|함에 있어|되어지|되어진|[을를] 가지고 있|에 대해서/g,
|
|
27424
|
+
message: "\uBC88\uC5ED\uD22C \uBC18\uBCF5",
|
|
27425
|
+
suggest: "\uC5D0 \uC788\uC5B4\u2192\uC5D0\uC11C, \uB418\uC5B4\uC9C0\uB2E4\u2192\uB418\uB2E4, \uAC00\uC9C0\uACE0 \uC788\uB2E4\u2192\uC788\uB2E4, \uC5D0 \uB300\uD574\uC11C\u2192\uB97C"
|
|
27426
|
+
},
|
|
27427
|
+
{
|
|
27428
|
+
code: "SLOP_TRIAD",
|
|
27429
|
+
severity: "warning",
|
|
27430
|
+
pattern: /, 그리고 /g,
|
|
27431
|
+
message: "'A, B, \uADF8\uB9AC\uACE0 C' \uB098\uC5F4 \u2014 \uC601\uC5B4\uC2DD 3\uD56D \uBCD1\uB82C",
|
|
27432
|
+
suggest: "A\xB7B\xB7C \uB610\uB294 A, B \uBC0F C"
|
|
27433
|
+
},
|
|
27434
|
+
// 메타 진입 — 줄 첫머리의 지시어가 앞 줄을 다시 받는 글쓰기(개조식은 줄마다 새 사실)
|
|
27435
|
+
{
|
|
27436
|
+
code: "SLOP_META_LEAD",
|
|
27437
|
+
severity: "warning",
|
|
27438
|
+
minCount: 2,
|
|
27439
|
+
pattern: /^[ \t]*(?:[-□○ㅇ❍◦ㆍ·•*>][ \t]*)?(?:이는|이를 통해|이러한|이와 같이|이에 따라|이로써)[ \t]/g,
|
|
27440
|
+
message: "\uC904 \uCCAB\uBA38\uB9AC \uC9C0\uC2DC\uC5B4 \uBC18\uBCF5 \u2014 \uAC1C\uC870\uC2DD\uC740 \uC904\uB9C8\uB2E4 \uC0C8 \uC0AC\uC2E4",
|
|
27441
|
+
suggest: "\uC9C0\uC2DC\uC5B4\uB97C \uC9C0\uC6B0\uACE0 \uC8FC\uC5B4\xB7\uB300\uC0C1\uC744 \uBC14\uB85C \uC500"
|
|
27442
|
+
},
|
|
27443
|
+
{
|
|
27444
|
+
code: "SLOP_EMOJI",
|
|
27445
|
+
severity: "warning",
|
|
27446
|
+
pattern: /[✅✨❌⭐\u{1F300}-\u{1FAFF}]/gu,
|
|
27447
|
+
message: "\uADF8\uB9BC \uBB38\uC790\uB294 \uACF5\uBB38\uC11C\uC5D0 \uC4F0\uC9C0 \uC54A\uC74C",
|
|
27448
|
+
suggest: "\uC9C0\uC6C0 \uB610\uB294 \u25A1\xB7\u3147\xB7\u203B \uBD80\uD638\uB85C"
|
|
27449
|
+
},
|
|
27450
|
+
// 쌍점을 앞말에 붙인 "제목: 부제" 만 — 서울 방침서 과제 소제목 "○○ 운영 : ’30년 ○○개소"(쌍점 앞뒤 띄움)는 실물 관행
|
|
27451
|
+
{
|
|
27452
|
+
code: "SLOP_COLON_HEADING",
|
|
27453
|
+
severity: "warning",
|
|
27454
|
+
pattern: /^#{1,6}[ \t]+[^\n::]{1,19}[^\s::][::][ \t]+\S/g,
|
|
27455
|
+
message: "'\uC81C\uBAA9: \uBD80\uC81C' \uAF34 \uD5E4\uB529 \u2014 \uC7A5 \uC774\uB984\uC740 \uBA85\uC0AC\uAD6C \uD558\uB098",
|
|
27456
|
+
suggest: "\uC608) \u2161. \uD604\uD669 \uBC0F \uBB38\uC81C\uC810"
|
|
27457
|
+
}
|
|
27458
|
+
];
|
|
27459
|
+
var VAGUE_END = /(?:강화|제고|도모|증진|향상|활성화|구축|기여|확립|정착|내실화|극대화|선도|실현|조성|확산|고도화)[ \t]*(?:필요|추진|도모|기대)?[.。]?$/;
|
|
27460
|
+
var CONCRETE = /\d|○○|「|[A-Z]{2,}/;
|
|
27461
|
+
var BULLET = /^[ \t]*(?:[-□○ㅇ❍◦ㆍ·•▸*]|\d+[.)])[ \t]*(.+)$/;
|
|
27462
|
+
var VAGUE_MIN_LINES = 10;
|
|
27463
|
+
var VAGUE_RATIO = 0.15;
|
|
27464
|
+
function lintSlopText(text) {
|
|
27465
|
+
const findings = [];
|
|
27466
|
+
const pending = /* @__PURE__ */ new Map();
|
|
27467
|
+
const lines = text.split(/\r?\n/);
|
|
27468
|
+
let fence = null;
|
|
27469
|
+
let bullets = 0;
|
|
27470
|
+
const vague = [];
|
|
27471
|
+
for (let i = 0; i < lines.length; i++) {
|
|
27472
|
+
const line = lines[i];
|
|
27473
|
+
const f = line.match(/^\s*(```+|~~~+)/);
|
|
27474
|
+
if (f) {
|
|
27475
|
+
if (fence === null) fence = f[1][0];
|
|
27476
|
+
else if (f[1][0] === fence) fence = null;
|
|
27477
|
+
continue;
|
|
27478
|
+
}
|
|
27479
|
+
if (fence !== null) continue;
|
|
27480
|
+
for (const r of RULES2) {
|
|
27481
|
+
r.pattern.lastIndex = 0;
|
|
27482
|
+
for (const m of line.matchAll(r.pattern)) {
|
|
27483
|
+
const hit = { line: i + 1, match: m[0].trim() || m[0], rule: r.code, severity: r.severity, message: r.message, suggest: r.suggest };
|
|
27484
|
+
if (r.minCount) {
|
|
27485
|
+
const list = pending.get(r.code) ?? [];
|
|
27486
|
+
list.push(hit);
|
|
27487
|
+
pending.set(r.code, list);
|
|
27488
|
+
} else findings.push(hit);
|
|
27489
|
+
}
|
|
27490
|
+
}
|
|
27491
|
+
if (/^\s*\|/.test(line)) continue;
|
|
27492
|
+
const b = BULLET.exec(line);
|
|
27493
|
+
if (!b) continue;
|
|
27494
|
+
const body = b[1].replace(/\*\*/g, "").trim();
|
|
27495
|
+
if (body.length < 6) continue;
|
|
27496
|
+
bullets++;
|
|
27497
|
+
if (VAGUE_END.test(body) && !CONCRETE.test(body)) vague.push({ line: i + 1, body });
|
|
27498
|
+
}
|
|
27499
|
+
for (const r of RULES2) {
|
|
27500
|
+
const list = r.minCount ? pending.get(r.code) : void 0;
|
|
27501
|
+
if (list && list.length >= r.minCount) findings.push(...list);
|
|
27502
|
+
}
|
|
27503
|
+
if (bullets >= VAGUE_MIN_LINES && vague.length >= 3 && vague.length / bullets >= VAGUE_RATIO) {
|
|
27504
|
+
const pct = Math.round(vague.length / bullets * 100);
|
|
27505
|
+
for (const v of vague) {
|
|
27506
|
+
findings.push({
|
|
27507
|
+
line: v.line,
|
|
27508
|
+
match: v.body.slice(0, 60),
|
|
27509
|
+
rule: "SLOP_VAGUE_OUTCOME",
|
|
27510
|
+
severity: "warning",
|
|
27511
|
+
message: `\uC22B\uC790\xB7\uB300\uC0C1 \uC5C6\uC774 \uCD94\uC0C1 \uC131\uACFC\uB85C \uB05D\uB098\uB294 \uC904(\uBB38\uC11C ${pct}% \u2014 \uC2E4\uACB0\uC7AC \uBCF4\uACE0\uC11C \uCD5C\uB300 11%)`,
|
|
27512
|
+
suggest: "\uBB34\uC5C7\uC744\xB7\uC5BC\uB9C8\uB098\xB7\uC5B8\uC81C\uAE4C\uC9C0 \u2014 \uC608) \uC0C1\uC2B5 \uD22C\uAE30\uC9C0\uC810 42\uACF3 CCTV \uC124\uCE58(12\uC6D4)"
|
|
27513
|
+
});
|
|
27514
|
+
}
|
|
27515
|
+
}
|
|
27516
|
+
return findings.sort((a, b) => a.line - b.line);
|
|
27517
|
+
}
|
|
27518
|
+
function slopLintWarnings(text, limit = 10) {
|
|
27519
|
+
const findings = lintSlopText(text);
|
|
27520
|
+
const shown = findings.slice(0, limit).map(
|
|
27521
|
+
(f) => `\uC724\uBB38 [${f.rule}] L${f.line} "${f.match}" \u2014 ${f.message}${f.suggest ? ` (${f.suggest})` : ""}`
|
|
27522
|
+
);
|
|
27523
|
+
if (findings.length > limit) shown.push(`\uC724\uBB38 \uACBD\uACE0 ${findings.length - limit}\uAC74 \uB354 \uC788\uC74C \u2014 kordoc lint --gate \uB85C \uC804\uCCB4 \uD655\uC778`);
|
|
27524
|
+
return shown;
|
|
27525
|
+
}
|
|
27526
|
+
|
|
27527
|
+
// src/hwpx/logic-lint.ts
|
|
27528
|
+
function usesLogicStructure(preset) {
|
|
27529
|
+
const p = normalizeGongmunPreset(preset);
|
|
27530
|
+
return p === "report" || p === "plan" || p === "gaejosik" || p === "ministry" || p === "bangchim";
|
|
27531
|
+
}
|
|
27532
|
+
var ESSAY = /^(?:서론|본론|결론|맺음말|맺는말|들어가며|들어가는 ?말|나가며|나오며|마치며|결어|요약 ?및 ?결론)$/;
|
|
27533
|
+
var ROLE_RE = [
|
|
27534
|
+
["exec", /일정|예산|재원|소요|행정사항|협조|조치계획|향후|추진체계|역할|건의|사후관리|성과관리/],
|
|
27535
|
+
["effect", /기대효과|효과/],
|
|
27536
|
+
["basis", /배경|근거|필요성|목적|경위|경과|계기/],
|
|
27537
|
+
["problem", /문제|한계|애로/],
|
|
27538
|
+
["status", /현황|실태|여건|진단|분석/],
|
|
27539
|
+
["plan", /방안|대책|개선|방향|목표|전략|과제|세부|내용|추진계획|운영계획|사업계획|기본계획|개요|검토의견|대안|결과|실적/]
|
|
27540
|
+
];
|
|
27541
|
+
function headingText(raw) {
|
|
27542
|
+
let t = raw.trim().replace(/^\*\*(.+)\*\*$/, "$1");
|
|
27543
|
+
if (/^#\s/.test(t)) return null;
|
|
27544
|
+
const md = /^#{2,6}\s+(.+)$/.exec(t);
|
|
27545
|
+
if (md) t = md[1];
|
|
27546
|
+
else if (/^□/.test(t)) t = t.slice(1);
|
|
27547
|
+
else if (!/^(?:[ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩ]+\s*[..]?|\d{1,2}\s*[..])\s*[^\s\d]/.test(t) || /^\s/.test(raw)) return null;
|
|
27548
|
+
t = t.replace(/\*\*|__/g, "").replace(/^\s*(?:[ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩ]+\s*[..]?|(?:\d{1,2}|[가-하])\s*[..)])\s*/, "").trim();
|
|
27549
|
+
if (t.length < 2 || t.length > 24 || /[.。]$|다$|함$|음$|,/.test(t)) return null;
|
|
27550
|
+
return t;
|
|
27551
|
+
}
|
|
27552
|
+
function rolesOf(title) {
|
|
27553
|
+
const c = title.replace(/\s/g, "");
|
|
27554
|
+
const roles = /* @__PURE__ */ new Set();
|
|
27555
|
+
for (const [r, re] of ROLE_RE) if (re.test(c)) roles.add(r);
|
|
27556
|
+
if (roles.has("exec") && !/방안|대책|전략|과제|내용/.test(c)) roles.delete("plan");
|
|
27557
|
+
return roles;
|
|
27558
|
+
}
|
|
27559
|
+
var PURPOSE = /(?:고자|려고)\s*함\.?$|보고(?:드림|함)\.?$/;
|
|
27560
|
+
function splitSections(text) {
|
|
27561
|
+
const sections = [];
|
|
27562
|
+
let purpose = false;
|
|
27563
|
+
const essay = [];
|
|
27564
|
+
let fence = null;
|
|
27565
|
+
const lines = text.split(/\r?\n/);
|
|
27566
|
+
for (let i = 0; i < lines.length; i++) {
|
|
27567
|
+
const raw = lines[i];
|
|
27568
|
+
const f = raw.match(/^\s*(```+|~~~+)/);
|
|
27569
|
+
if (f) {
|
|
27570
|
+
if (fence === null) fence = f[1][0];
|
|
27571
|
+
else if (f[1][0] === fence) fence = null;
|
|
27572
|
+
continue;
|
|
27573
|
+
}
|
|
27574
|
+
if (fence !== null || !raw.trim()) continue;
|
|
27575
|
+
const h = /^\s*\|/.test(raw) ? null : headingText(raw);
|
|
27576
|
+
if (h !== null) {
|
|
27577
|
+
if (ESSAY.test(h.replace(/\s+/g, " "))) {
|
|
27578
|
+
essay.push({
|
|
27579
|
+
line: i + 1,
|
|
27580
|
+
match: h,
|
|
27581
|
+
rule: "LOGIC_ESSAY_HEADING",
|
|
27582
|
+
severity: "error",
|
|
27583
|
+
message: "\uC7A5 \uC774\uB984\uC744 \uC11C\uB860\xB7\uBCF8\uB860\xB7\uACB0\uB860\uC73C\uB85C \uC801\uC74C \u2014 \uACF5\uBB38\uC740 \uADF8 \uD750\uB984\uC744 \uC2E4\uBB34 \uC7A5 \uC774\uB984\uC73C\uB85C \uB4DC\uB7EC\uB0C4",
|
|
27584
|
+
suggest: "\uC65C: \uCD94\uC9C4\uBC30\uACBD\xB7\uAD00\uB828\uADFC\uAC70\xB7\uD604\uD669 \uBC0F \uBB38\uC81C\uC810 \u2192 \uBB34\uC5C7: \uCD94\uC9C4\uAC1C\uC694\xB7\uAC1C\uC120\uBC29\uC548\xB7\uC138\uBD80\uB0B4\uC6A9 \u2192 \uC5B4\uB5BB\uAC8C: \uCD94\uC9C4\uC77C\uC815\xB7\uC18C\uC694\uC608\uC0B0\xB7\uD5A5\uD6C4\uACC4\uD68D"
|
|
27585
|
+
});
|
|
27586
|
+
}
|
|
27587
|
+
const roles = rolesOf(h);
|
|
27588
|
+
if (roles.size) {
|
|
27589
|
+
sections.push({ line: i + 1, title: h, roles, body: [] });
|
|
27590
|
+
continue;
|
|
27591
|
+
}
|
|
27592
|
+
}
|
|
27593
|
+
if (!sections.length && PURPOSE.test(raw.replace(/^\s*>\s*|\*\*/g, "").trim())) purpose = true;
|
|
27594
|
+
sections.at(-1)?.body.push({ line: i + 1, text: raw });
|
|
27595
|
+
}
|
|
27596
|
+
return { sections, essay, purpose };
|
|
27597
|
+
}
|
|
27598
|
+
var FACT = /\d|「|○○|○[가-힣%]|\[\s*\]/;
|
|
27599
|
+
var STOP = /* @__PURE__ */ new Set([
|
|
27600
|
+
"\uBB38\uC81C",
|
|
27601
|
+
"\uBB38\uC81C\uC810",
|
|
27602
|
+
"\uBD80\uC871",
|
|
27603
|
+
"\uBBF8\uD761",
|
|
27604
|
+
"\uD55C\uACC4",
|
|
27605
|
+
"\uACE4\uB780",
|
|
27606
|
+
"\uD544\uC694",
|
|
27607
|
+
"\uC99D\uAC00",
|
|
27608
|
+
"\uAC10\uC18C",
|
|
27609
|
+
"\uBC1C\uC0DD",
|
|
27610
|
+
"\uD604\uD669",
|
|
27611
|
+
"\uC704\uD55C",
|
|
27612
|
+
"\uB300\uD55C",
|
|
27613
|
+
"\uAD00\uB828",
|
|
27614
|
+
"\uAC1C\uC120",
|
|
27615
|
+
"\uAC15\uD654",
|
|
27616
|
+
"\uC6B4\uC601",
|
|
27617
|
+
"\uCD94\uC9C4",
|
|
27618
|
+
"\uD655\uB300",
|
|
27619
|
+
"\uCCB4\uACC4",
|
|
27620
|
+
"\uAD00\uB9AC",
|
|
27621
|
+
"\uC9C0\uC6D0",
|
|
27622
|
+
"\uC6B0\uB824",
|
|
27623
|
+
"\uC800\uD558",
|
|
27624
|
+
"\uC5B4\uB824\uC6C0",
|
|
27625
|
+
"\uBD80\uC7AC",
|
|
27626
|
+
"\uC911\uC2EC",
|
|
27627
|
+
"\uC704\uC8FC",
|
|
27628
|
+
"\uC788\uC74C",
|
|
27629
|
+
"\uC5C6\uC74C",
|
|
27630
|
+
"\uB300\uC751",
|
|
27631
|
+
"\uC2E4\uC2DC",
|
|
27632
|
+
"\uAE30\uC874",
|
|
27633
|
+
"\uD604\uD589",
|
|
27634
|
+
"\uB530\uB978",
|
|
27635
|
+
"\uC778\uD55C",
|
|
27636
|
+
"\uD1B5\uD55C",
|
|
27637
|
+
"\uB4F1\uC758"
|
|
27638
|
+
]);
|
|
27639
|
+
var JOSA = /(?:으로|에서|에게|까지|부터|이나|과의|와의|으로의|에의|의|은|는|이|가|을|를|에|로|과|와|도|만)$/;
|
|
27640
|
+
function keyTerms(s) {
|
|
27641
|
+
const out = [];
|
|
27642
|
+
for (let w of s.replace(/\*\*|\([^)]*\)/g, " ").split(/[^가-힣]+/)) {
|
|
27643
|
+
if (w.length > 2) w = w.replace(JOSA, "");
|
|
27644
|
+
if (w.length >= 2 && !STOP.has(w)) out.push(w);
|
|
27645
|
+
}
|
|
27646
|
+
return out;
|
|
27647
|
+
}
|
|
27648
|
+
var TOP_BULLET = /^(?:[-□○ㅇ❍◦•*]|\d+[.)])\s*(.+)$/;
|
|
27649
|
+
function problemItems(sections) {
|
|
27650
|
+
const items = [];
|
|
27651
|
+
for (const s of sections) {
|
|
27652
|
+
const pure = s.roles.has("problem") && !s.roles.has("status");
|
|
27653
|
+
let inProblem = pure;
|
|
27654
|
+
let markIndent = pure ? -1 : -2;
|
|
27655
|
+
let base = -1;
|
|
27656
|
+
let col = -1;
|
|
27657
|
+
for (const b of s.body) {
|
|
27658
|
+
const t = b.text;
|
|
27659
|
+
if (/^\s*\|/.test(t)) {
|
|
27660
|
+
const cells = t.trim().replace(/^\||\|$/g, "").split("|").map((c) => c.trim());
|
|
27661
|
+
if (cells.every((c) => /^:?-{2,}:?$/.test(c))) continue;
|
|
27662
|
+
const hc = cells.findIndex((c) => /문제/.test(c) && c.length <= 8);
|
|
27663
|
+
if (hc >= 0) {
|
|
27664
|
+
col = hc;
|
|
27665
|
+
continue;
|
|
27666
|
+
}
|
|
27667
|
+
if (col >= 0 && cells[col]) items.push({ line: b.line, text: cells[col] });
|
|
27668
|
+
continue;
|
|
27669
|
+
}
|
|
27670
|
+
col = -1;
|
|
27671
|
+
const indent = t.length - t.trimStart().length;
|
|
27672
|
+
if (!pure && /문제점|\(문제\)|<\s*문제/.test(t) && t.replace(/[^가-힣]/g, "").length <= 8) {
|
|
27673
|
+
inProblem = true;
|
|
27674
|
+
markIndent = indent;
|
|
27675
|
+
base = -1;
|
|
27676
|
+
continue;
|
|
27677
|
+
}
|
|
27678
|
+
if (!inProblem) continue;
|
|
27679
|
+
const m = TOP_BULLET.exec(t.trim());
|
|
27680
|
+
if (!m) continue;
|
|
27681
|
+
if (indent <= markIndent) {
|
|
27682
|
+
inProblem = false;
|
|
27683
|
+
continue;
|
|
27684
|
+
}
|
|
27685
|
+
if (base < 0) base = indent;
|
|
27686
|
+
const item = m[1].replace(/\*/g, "").trim();
|
|
27687
|
+
if (indent === base && !/^[【\[<(].*[】\]>)]$/.test(item) && item.replace(/[^가-힣]/g, "").length >= 4) items.push({ line: b.line, text: item });
|
|
27688
|
+
}
|
|
27689
|
+
}
|
|
27690
|
+
return items;
|
|
27691
|
+
}
|
|
27692
|
+
var bodyText = (ss) => ss.flatMap((s) => [s.title, ...s.body.map((b) => b.text)]).join("\n");
|
|
27693
|
+
var has = (s, ...rs) => rs.some((r) => s.roles.has(r));
|
|
27694
|
+
function lintLogicText(text) {
|
|
27695
|
+
const { sections, essay, purpose } = splitSections(text);
|
|
27696
|
+
const findings = [...essay];
|
|
27697
|
+
if (sections.length < 3) return findings;
|
|
27698
|
+
const why = sections.filter((s) => has(s, "basis", "status", "problem"));
|
|
27699
|
+
const what = sections.filter((s) => has(s, "plan"));
|
|
27700
|
+
const how = sections.filter((s) => has(s, "exec"));
|
|
27701
|
+
const effect = sections.filter((s) => has(s, "effect"));
|
|
27702
|
+
const at = (s) => s?.line ?? 1;
|
|
27703
|
+
const add = (line, match, rule, severity, message, suggest) => findings.push({ line, match: match.slice(0, 60), rule, severity, message, suggest });
|
|
27704
|
+
const proposal = what.find((s) => /방안|대책|방향|전략|과제|세부|추진계획|운영계획|사업계획|기본계획|대안|검토의견|추진내용|주요내용/.test(s.title));
|
|
27705
|
+
if (proposal && !why.length && !purpose) {
|
|
27706
|
+
add(
|
|
27707
|
+
proposal.line,
|
|
27708
|
+
proposal.title,
|
|
27709
|
+
"LOGIC_NO_WHY",
|
|
27710
|
+
"error",
|
|
27711
|
+
"\uC65C \uD574\uC57C \uD558\uB294\uC9C0(\uCD94\uC9C4\uBC30\uACBD\xB7\uAD00\uB828\uADFC\uAC70\xB7\uD604\uD669\xB7\uBB38\uC81C\uC810) \uC7A5\uC774 \uC5C6\uC74C \u2014 \uBC29\uC548\uBD80\uD130 \uB0B4\uBC00\uBA74 \uACB0\uC7AC\uAD8C\uC790\uAC00 \uC124\uB4DD\uB418\uC9C0 \uC54A\uC74C",
|
|
27712
|
+
"\uCCAB \uC7A5\uC5D0 \uCD94\uC9C4\uBC30\uACBD(\uACC4\uAE30\xB7\uBC95\uB839\xB7\uC9C0\uC2DC\xB7\uC218\uCE58) \uB610\uB294 \uD604\uD669 \uBC0F \uBB38\uC81C\uC810"
|
|
27713
|
+
);
|
|
27714
|
+
}
|
|
27715
|
+
if (proposal && !how.length) {
|
|
27716
|
+
add(
|
|
27717
|
+
at(what.at(-1)),
|
|
27718
|
+
what.at(-1).title,
|
|
27719
|
+
"LOGIC_NO_HOW",
|
|
27720
|
+
"warning",
|
|
27721
|
+
"\uC5B4\uB5BB\uAC8C\xB7\uC5B8\uC81C\xB7\uC5BC\uB9C8(\uCD94\uC9C4\uC77C\uC815\xB7\uC18C\uC694\uC608\uC0B0\xB7\uD5A5\uD6C4\uACC4\uD68D\xB7\uD589\uC815\uC0AC\uD56D) \uC7A5\uC774 \uC5C6\uC74C \u2014 \uACB0\uC7AC \uB4A4 \uC2E4\uD589\uC774 \uC548 \uBCF4\uC784",
|
|
27722
|
+
"\uB9C8\uC9C0\uB9C9 \uC7A5\uC5D0 \uCD94\uC9C4\uC77C\uC815\xB7\uC18C\uC694\uC608\uC0B0\xB7\uD5A5\uD6C4\uACC4\uD68D(\uB2F4\uB2F9\xB7\uAE30\uD55C)"
|
|
27723
|
+
);
|
|
27724
|
+
}
|
|
27725
|
+
if (why.length && proposal && why[0].line > proposal.line) {
|
|
27726
|
+
add(
|
|
27727
|
+
at(why[0]),
|
|
27728
|
+
why[0].title,
|
|
27729
|
+
"LOGIC_ORDER",
|
|
27730
|
+
"warning",
|
|
27731
|
+
`'${why[0].title}'\uC774(\uAC00) '${proposal.title}' \uB4A4\uC5D0 \uC634 \u2014 \uC65C(\uBC30\uACBD\xB7\uD604\uD669)\uB97C \uBA3C\uC800 \uC138\uC6B0\uACE0 \uBB34\uC5C7(\uBC29\uC548)\uC744 \uB0C4`
|
|
27732
|
+
);
|
|
27733
|
+
}
|
|
27734
|
+
if (why.length && !FACT.test(bodyText(why))) {
|
|
27735
|
+
add(
|
|
27736
|
+
at(why[0]),
|
|
27737
|
+
why[0].title,
|
|
27738
|
+
"LOGIC_BASIS_NO_FACT",
|
|
27739
|
+
"warning",
|
|
27740
|
+
"\uBC30\uACBD\xB7\uD604\uD669 \uC7A5\uC5D0 \uC0AC\uC2E4(\uC218\uCE58\xB7\uBC95\uB839\xB7\uC9C0\uC2DC\xB7\uB0A0\uC9DC)\uC774 \uC5C6\uC74C \u2014 \uC65C \uC9C0\uAE08 \uD574\uC57C \uD558\uB294\uC9C0\uAC00 \uC548 \uBCF4\uC784",
|
|
27741
|
+
"\uC608) \u300C\u25CB\u25CB\uBC95\u300D \uAC1C\uC815(2026. 3. 1. \uC2DC\uD589), \uCD5C\uADFC 3\uB144 \uBBFC\uC6D0 1,240\uAC74(\uC5F0 18%\u2191), \uAD6C\uCCAD\uC7A5 \uC9C0\uC2DC(2026. 9. 1.)"
|
|
27742
|
+
);
|
|
27743
|
+
}
|
|
27744
|
+
const problems = problemItems(sections);
|
|
27745
|
+
if (problems.length && what.length) {
|
|
27746
|
+
const sol = bodyText([...what, ...how, ...effect]);
|
|
27747
|
+
for (const p of problems) {
|
|
27748
|
+
const terms = keyTerms(p.text);
|
|
27749
|
+
if (terms.length && !terms.some((t) => sol.includes(t))) {
|
|
27750
|
+
add(
|
|
27751
|
+
p.line,
|
|
27752
|
+
p.text,
|
|
27753
|
+
"LOGIC_PROBLEM_UNANSWERED",
|
|
27754
|
+
"warning",
|
|
27755
|
+
"\uC774 \uBB38\uC81C\uC810\uC5D0 \uB300\uC751\uD558\uB294 \uBC29\uC548\uC774 \uBCF4\uC774\uC9C0 \uC54A\uC74C \u2014 \uBB38\uC81C\uC810\uACFC \uBC29\uC548\uC740 \uC9DD\uC744 \uC774\uB8F8",
|
|
27756
|
+
"\uBC29\uC548 \uC7A5\uC5D0 \uC774 \uBB38\uC81C\uC758 \uD574\uBC95\uC744 \uD55C \uC904 \uC774\uC0C1"
|
|
27757
|
+
);
|
|
27758
|
+
}
|
|
27759
|
+
}
|
|
27760
|
+
}
|
|
27761
|
+
if (problems.length && !what.length) {
|
|
27762
|
+
add(
|
|
27763
|
+
problems[0].line,
|
|
27764
|
+
problems[0].text,
|
|
27765
|
+
"LOGIC_PROBLEM_UNANSWERED",
|
|
27766
|
+
"warning",
|
|
27767
|
+
"\uBB38\uC81C\uC810\uB9CC \uC788\uACE0 \uBC29\uC548\xB7\uB300\uCC45 \uC7A5\uC774 \uC5C6\uC74C",
|
|
27768
|
+
"\uAC1C\uC120\uBC29\uC548 \uC7A5\uC744 \uBB38\uC81C\uC810 \uC21C\uC11C\uB300\uB85C"
|
|
27769
|
+
);
|
|
27770
|
+
}
|
|
27771
|
+
const remedy = what.find((s) => /개선|대책|방안/.test(s.title));
|
|
27772
|
+
if (remedy && !sections.some((s) => has(s, "status", "problem"))) {
|
|
27773
|
+
add(
|
|
27774
|
+
remedy.line,
|
|
27775
|
+
remedy.title,
|
|
27776
|
+
"LOGIC_UNGROUNDED",
|
|
27777
|
+
"warning",
|
|
27778
|
+
"\uAC1C\uC120\uBC29\uC548\uC758 \uADFC\uAC70(\uD604\uD669\xB7\uBB38\uC81C\uC810) \uC7A5\uC774 \uC5C6\uC74C \u2014 \uBB34\uC5C7\uC744 \uACE0\uCE58\uB294\uC9C0 \uBA3C\uC800 \uBCF4\uC5EC\uC57C \uD568",
|
|
27779
|
+
"\uAC1C\uC120\uBC29\uC548 \uC55E\uC5D0 \uD604\uD669 \uBC0F \uBB38\uC81C\uC810"
|
|
27780
|
+
);
|
|
27781
|
+
}
|
|
27782
|
+
for (const s of effect) {
|
|
27783
|
+
if (s.body.length && !FACT.test(bodyText([s]))) {
|
|
27784
|
+
add(
|
|
27785
|
+
s.line,
|
|
27786
|
+
s.title,
|
|
27787
|
+
"LOGIC_EFFECT_VAGUE",
|
|
27788
|
+
"warning",
|
|
27789
|
+
"\uAE30\uB300\uD6A8\uACFC\uC5D0 \uBAA9\uD45C\uCE58\uAC00 \uC5C6\uC74C \u2014 \uBB38\uC81C\uC810\uC5D0\uC11C \uB4E0 \uC9C0\uD45C\uAC00 \uC5BC\uB9C8\uB098 \uB098\uC544\uC9C0\uB294\uC9C0\uB85C",
|
|
27790
|
+
"\uC608) \uC0C1\uC2B5 \uD22C\uAE30\uC9C0\uC810 \uBBFC\uC6D0 \uC5F0 412\uAC74 \u2192 200\uAC74(51%\u2193)"
|
|
27791
|
+
);
|
|
27792
|
+
}
|
|
27793
|
+
}
|
|
27794
|
+
for (const s of how) {
|
|
27795
|
+
if (s.body.length && !FACT.test(bodyText([s])) && !/협조|역할|체계|건의|행정/.test(s.title)) {
|
|
27796
|
+
add(
|
|
27797
|
+
s.line,
|
|
27798
|
+
s.title,
|
|
27799
|
+
"LOGIC_EXEC_VAGUE",
|
|
27800
|
+
"warning",
|
|
27801
|
+
"\uC77C\uC815\xB7\uC608\uC0B0 \uC7A5\uC5D0 \uB0A0\uC9DC\xB7\uAE08\uC561\xB7\uAE30\uD55C\uC774 \uC5C6\uC74C",
|
|
27802
|
+
"\uC608) 2026. 11.\u223C12. \uC124\uCE58, \uCD1D 84,000,000\uC6D0(\uAD6C\uBE44 100%)"
|
|
27803
|
+
);
|
|
27804
|
+
}
|
|
27805
|
+
}
|
|
27806
|
+
return findings.sort((a, b) => a.line - b.line);
|
|
27807
|
+
}
|
|
27808
|
+
function logicLintWarnings(text, limit = 10) {
|
|
27809
|
+
const findings = lintLogicText(text);
|
|
27810
|
+
const shown = findings.slice(0, limit).map(
|
|
27811
|
+
(f) => `\uAD6C\uC131 [${f.rule}] L${f.line} "${f.match}" \u2014 ${f.message}${f.suggest ? ` (${f.suggest})` : ""}`
|
|
27812
|
+
);
|
|
27813
|
+
if (findings.length > limit) shown.push(`\uAD6C\uC131 \uACBD\uACE0 ${findings.length - limit}\uAC74 \uB354 \uC788\uC74C \u2014 kordoc lint --gate \uB85C \uC804\uCCB4 \uD655\uC778`);
|
|
27814
|
+
return shown;
|
|
27815
|
+
}
|
|
27816
|
+
|
|
27817
|
+
// src/hwpx/gongmun-gate.ts
|
|
27818
|
+
function gongmunGate(text, opts) {
|
|
27819
|
+
const tag = (axis, fs) => fs.map((f) => ({ line: f.line, match: f.match, rule: f.rule, severity: f.severity, message: f.message, suggest: f.suggest, axis }));
|
|
27820
|
+
const preset = opts?.preset;
|
|
27821
|
+
const munche = opts?.munche || preset !== void 0 && usesGaejosikMunche(preset);
|
|
27822
|
+
const logic = preset === void 0 || usesLogicStructure(preset);
|
|
27823
|
+
const strict = [
|
|
27824
|
+
...tag("\uD45C\uAE30\uBC95", lintGongmunText(text, { document: opts?.document, parsed: opts?.parsed })),
|
|
27825
|
+
...munche ? tag("\uBB38\uCCB4", lintMuncheText(text)) : []
|
|
27826
|
+
];
|
|
27827
|
+
const blocking = [
|
|
27828
|
+
...strict.filter((f) => f.severity === "error"),
|
|
27829
|
+
...tag("\uC724\uBB38", lintSlopText(text)),
|
|
27830
|
+
...logic ? tag("\uAD6C\uC131", lintLogicText(text)) : []
|
|
27831
|
+
].sort((a, b) => a.line - b.line);
|
|
27832
|
+
return { pass: blocking.length === 0, blocking, advisory: strict.filter((f) => f.severity !== "error") };
|
|
27833
|
+
}
|
|
27834
|
+
function formatGateFinding(f) {
|
|
27835
|
+
return `${f.axis} [${f.rule}] L${f.line} "${f.match}" \u2014 ${f.message}${f.suggest ? ` (${f.suggest})` : ""}`;
|
|
27836
|
+
}
|
|
27837
|
+
|
|
27375
27838
|
// src/roundtrip/patcher.ts
|
|
27376
27839
|
import JSZip10 from "jszip";
|
|
27377
27840
|
|
|
@@ -29321,6 +29784,7 @@ async function patchHwp(original, editedMarkdown, options) {
|
|
|
29321
29784
|
}
|
|
29322
29785
|
}
|
|
29323
29786
|
let data;
|
|
29787
|
+
const warnings = [];
|
|
29324
29788
|
const dirty = scans.some((s) => s.repl.size > 0 || s.inserts.size > 0);
|
|
29325
29789
|
if (!dirty) {
|
|
29326
29790
|
data = new Uint8Array(original);
|
|
@@ -29333,6 +29797,12 @@ async function patchHwp(original, editedMarkdown, options) {
|
|
|
29333
29797
|
const content = compressed ? compressWithTail(newStream) : newStream;
|
|
29334
29798
|
out = replaceOleStream(out, sectionPaths[i], content);
|
|
29335
29799
|
}
|
|
29800
|
+
if (flags & FLAG_TRACK_CHANGES) {
|
|
29801
|
+
const header = Buffer.from(fhEntry.content);
|
|
29802
|
+
header.writeUInt32LE((flags & ~FLAG_TRACK_CHANGES) >>> 0, 36);
|
|
29803
|
+
out = replaceOleStream(out, "/FileHeader", header);
|
|
29804
|
+
warnings.push("\uBCC0\uACBD \uB0B4\uC6A9 \uCD94\uC801 \uBB38\uC11C\uB77C \uD55C\uAE00\uC774 \uACE0\uCE5C \uBCF8\uBB38\uC744 \uADF8\uB9AC\uB3C4\uB85D \uCD94\uC801 \uD45C\uC2DC\uB97C \uAED0\uC2B5\uB2C8\uB2E4. \uD55C\uAE00\uC5D0\uC11C\uB294 \uC9C0\uAE08 \uB0B4\uC6A9\uB9CC \uBCF4\uC774\uACE0 \uB204\uAC00 \uBB34\uC5C7\uC744 \uBC14\uAFE8\uB294\uC9C0\uC758 \uAE30\uB85D\uC740 \uBCF4\uC774\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4(\uC6D0\uBCF8 \uD30C\uC77C\uC5D0\uB294 \uB0A8\uC544 \uC788\uC74C).");
|
|
29805
|
+
}
|
|
29336
29806
|
data = new Uint8Array(out);
|
|
29337
29807
|
} catch (err) {
|
|
29338
29808
|
return { success: false, applied: 0, skipped, error: `HWP \uC139\uD130 \uC218\uC220 \uC2E4\uD328: ${msg(err)}` };
|
|
@@ -29348,7 +29818,7 @@ async function patchHwp(original, editedMarkdown, options) {
|
|
|
29348
29818
|
return { success: false, applied, skipped, error: `\uD328\uCE58\uBCF8 \uC7AC\uD30C\uC2F1 \uC2E4\uD328 \u2014 \uD328\uCE58 \uC911\uB2E8: ${msg(err)}` };
|
|
29349
29819
|
}
|
|
29350
29820
|
}
|
|
29351
|
-
return { success: true, data, applied, skipped, verification };
|
|
29821
|
+
return { success: true, data, applied, skipped, verification, ...warnings.length ? { warnings } : {} };
|
|
29352
29822
|
function fail(error) {
|
|
29353
29823
|
return { success: false, applied: 0, skipped, error };
|
|
29354
29824
|
}
|
|
@@ -30022,7 +30492,7 @@ async function patchHwpx(original, editedMarkdown, options) {
|
|
|
30022
30492
|
const editedUnits = splitMarkdownUnits(editedMarkdown);
|
|
30023
30493
|
const pairs = alignUnits(origUnits.map((u) => looseRaw(u.raw)), editedUnits.map((u) => looseRaw(u.raw)));
|
|
30024
30494
|
const paraMap = resolveParagraphMappings(origBlocks, scans);
|
|
30025
|
-
const scanTables = scans.flatMap((s) => s.tables.filter((t) => t.rows.length > 0));
|
|
30495
|
+
const scanTables = scans.flatMap((s) => s.tables.filter((t) => t.rows.length > 0 && !t.channel));
|
|
30026
30496
|
const obTableOrdinals = buildTableOrdinals(origBlocks);
|
|
30027
30497
|
const sectionSplices = scans.map(() => []);
|
|
30028
30498
|
const structural = options?.structure !== false && origUnits.length * editedUnits.length <= 4e6;
|
|
@@ -30138,7 +30608,9 @@ function buildTableOrdinals(blocks) {
|
|
|
30138
30608
|
function resolveParagraphMappings(blocks, scans) {
|
|
30139
30609
|
const buckets = /* @__PURE__ */ new Map();
|
|
30140
30610
|
for (const scan of scans) {
|
|
30141
|
-
|
|
30611
|
+
const channel = scan.tables.flatMap((t) => t.channelCell?.paragraphs ?? []);
|
|
30612
|
+
const paras = channel.length ? [...scan.bodyParagraphs, ...channel].sort((a, b) => a.start - b.start) : scan.bodyParagraphs;
|
|
30613
|
+
for (const para2 of paras) {
|
|
30142
30614
|
const key = normForMatch(para2.text);
|
|
30143
30615
|
if (!key) continue;
|
|
30144
30616
|
let list = buckets.get(key);
|
|
@@ -30588,7 +31060,7 @@ async function buildState(bytes) {
|
|
|
30588
31060
|
scans.push(scanSectionXml(xml, i));
|
|
30589
31061
|
}
|
|
30590
31062
|
const paraMap = resolveParagraphMappings(parsed.blocks, scans);
|
|
30591
|
-
const scanTables = scans.flatMap((s) => s.tables.filter((t) => t.rows.length > 0));
|
|
31063
|
+
const scanTables = scans.flatMap((s) => s.tables.filter((t) => t.rows.length > 0 && !t.channel));
|
|
30592
31064
|
const tableOrdinals = buildTableOrdinals(parsed.blocks);
|
|
30593
31065
|
const fragmentBlocks = /* @__PURE__ */ new Set();
|
|
30594
31066
|
const unitBlocks = /* @__PURE__ */ new Set();
|
|
@@ -31025,7 +31497,7 @@ function scriptsOff(r, off) {
|
|
|
31025
31497
|
}
|
|
31026
31498
|
async function parseImage(buffer, options) {
|
|
31027
31499
|
try {
|
|
31028
|
-
const { parseImageDocument } = await import("./image-ocr-
|
|
31500
|
+
const { parseImageDocument } = await import("./image-ocr-6J7B5UVA.js");
|
|
31029
31501
|
const { blocks, warnings, lines } = await parseImageDocument(buffer, options);
|
|
31030
31502
|
stripScriptTags({ blocks });
|
|
31031
31503
|
return {
|
|
@@ -31089,7 +31561,7 @@ async function parseHwp(buffer, options) {
|
|
|
31089
31561
|
async function parsePdf(buffer, options) {
|
|
31090
31562
|
let parsePdfDocument;
|
|
31091
31563
|
try {
|
|
31092
|
-
const mod = await import("./parser-
|
|
31564
|
+
const mod = await import("./parser-UYBCCGY4.js");
|
|
31093
31565
|
parsePdfDocument = mod.parsePdfDocument;
|
|
31094
31566
|
} catch {
|
|
31095
31567
|
return {
|
|
@@ -31289,6 +31761,13 @@ export {
|
|
|
31289
31761
|
usesGaejosikMunche,
|
|
31290
31762
|
lintMuncheText,
|
|
31291
31763
|
muncheLintWarnings,
|
|
31764
|
+
lintSlopText,
|
|
31765
|
+
slopLintWarnings,
|
|
31766
|
+
usesLogicStructure,
|
|
31767
|
+
lintLogicText,
|
|
31768
|
+
logicLintWarnings,
|
|
31769
|
+
gongmunGate,
|
|
31770
|
+
formatGateFinding,
|
|
31292
31771
|
replaceOleStream,
|
|
31293
31772
|
wipeFreeSectors,
|
|
31294
31773
|
patchHwp,
|
|
@@ -31312,4 +31791,4 @@ export {
|
|
|
31312
31791
|
parseHwpml,
|
|
31313
31792
|
fillForm
|
|
31314
31793
|
};
|
|
31315
|
-
//# sourceMappingURL=chunk-
|
|
31794
|
+
//# sourceMappingURL=chunk-MI2YNEQJ.js.map
|