hanlint 0.0.16 → 0.0.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.
Files changed (54) hide show
  1. package/README.md +12 -10
  2. package/data/calqueFrame.json +60 -0
  3. package/data/cliches.json +10 -0
  4. package/data/collocationStops.txt +28 -0
  5. package/data/easyWords.json +0 -234
  6. package/data/exemplars.json +23 -2
  7. package/data/koreanProse.txt +64 -0
  8. package/data/patterns.json +2 -2
  9. package/data/phraseRepeat.json +11 -0
  10. package/data/ruleCategories.json +2 -0
  11. package/data/ruleDocs.json +18 -16
  12. package/data/ruleMechanisms.json +2 -0
  13. package/data/screenNarration.json +7 -7
  14. package/data/screenSentence.json +56 -8
  15. package/data/screenTone.json +4 -4
  16. package/data/screenWord.json +48 -88
  17. package/data/spacing.json +1 -1
  18. package/data/usageCounts.report.json +1676 -0
  19. package/data/version.json +1 -1
  20. package/package.json +1 -1
  21. package/src/analysis/index.js +1 -1
  22. package/src/analysis/tokenize.js +30 -15
  23. package/src/cli/help.js +3 -2
  24. package/src/cli/main.js +227 -88
  25. package/src/cli/walk.js +1 -1
  26. package/src/cli/welcome.js +1 -1
  27. package/src/config/settings.js +17 -0
  28. package/src/data/profiles.js +2 -2
  29. package/src/data/prose.js +27 -0
  30. package/src/document/sourceText.js +199 -36
  31. package/src/fingerprint/build.js +13 -4
  32. package/src/fingerprint/dictionaries.js +31 -4
  33. package/src/fingerprint/markers.js +22 -0
  34. package/src/index.js +3 -1
  35. package/src/report/compactReport.js +7 -3
  36. package/src/report/jsonReport.js +2 -2
  37. package/src/report/sheet.js +0 -0
  38. package/src/report/textReport.js +27 -8
  39. package/src/report/writingSpec.js +3 -3
  40. package/src/rules/registry.js +5 -1
  41. package/src/rules/screen/screenWord.js +2 -1
  42. package/src/rules/sentence/calqueFrame.js +11 -0
  43. package/src/rules/sentence/cliche.js +7 -3
  44. package/src/rules/sentence/hardWord.js +6 -3
  45. package/src/rules/sentence/japaneseLoan.js +7 -3
  46. package/src/rules/sentence/nounPile.js +10 -4
  47. package/src/rules/sentence/phraseRepeat.js +53 -0
  48. package/src/rules/sentence/redundantPair.js +7 -3
  49. package/src/rules/sentence/translationese.js +7 -3
  50. package/src/rules/shared/dictionaryRule.js +37 -6
  51. package/src/text.js +1 -1
  52. package/src/usage/counts.js +54 -0
  53. package/src/usage/index.js +8 -0
  54. package/src/usage/sentences.js +681 -0
package/README.md CHANGED
@@ -50,7 +50,7 @@ for (const finding of lintText(text, config)) {
50
50
  파일과 설정 경로를 읽는 API는 Node 전용이다. 문자열 API에 설정을 생략하면 기본 설정을 쓴다.
51
51
 
52
52
  `blog`, `report`, `docs`, `guide`, `essay`, `fiction`, `encyclopedia`, `chat`, `screen`의 아홉 프리셋이 있다.
53
- `screen`은 화면의 글 (단추, 이름표, 상태, 빈 상태) 이다. 낱말 자리의 문장과 화면 해설, 접객 말투를 잡고 산문 규칙은 끈다.
53
+ `screen`은 화면의 글 (버튼, 라벨, 상태, 빈 상태) 이다. 낱말 자리의 문장과 화면 해설, 접객 말투를 잡고 산문 규칙은 끈다.
54
54
  프로젝트 설정은 `npx hanlint init --preset docs`로 만들고 `npx hanlint doctor`로 확인한다.
55
55
  규칙 목록은 `npx hanlint rules`, 개별 규칙의 근거는 `npx hanlint explain translationese`에서 본다.
56
56
 
@@ -80,30 +80,32 @@ console.log(result);
80
80
  사실의 진실, 의미 보존과 자연스러움은 사람이 판단한다.
81
81
 
82
82
  JSON 형식과 전체 조건은
83
- [Reader Contract](https://github.com/eddmpython/hanlint/blob/main/skills/specs/start/readerContract.md)가 정본이다.
83
+ [Reader Contract](https://github.com/eddmpython/hanlint/blob/main/skills/specs/start/readerContract.md)가 기준이다.
84
84
 
85
85
  ## 브라우저와 수정 사례
86
86
 
87
87
  [한린트 편집기](https://eddmpython.github.io/hanlint/)는 같은 npm 코어로 검사, 고침,
88
- 원문 비교와 개인 기록을 제공한다. 사용 방법은
88
+ 원문 비교와 개인 기록, 그리고 공개 GitHub 저장소 주소 하나로 만드는 화면 글 시트를 제공한다. 사용 방법은
89
89
  [편집기 안내](https://eddmpython.github.io/hanlint/guide.html)에서 확인한다.
90
90
 
91
- 다음 API는 **main과 현재 웹 편집기에 먼저 반영되어 있으며, npm 0.0.10에는 없다.**
92
- 배포 여부는 [변경 이력](https://github.com/eddmpython/hanlint/blob/main/CHANGELOG.md)에서 확인한다.
91
+ 다음 API는 **main과 현재 웹 편집기에 먼저 반영된다.** 어느 npm 버전에 들어갔는지는
92
+ [변경 이력](https://github.com/eddmpython/hanlint/blob/main/CHANGELOG.md)에서 확인한다.
93
93
 
94
94
  | API | 결과 |
95
95
  |---|---|
96
- | `inspectText(text, config)` | 지적, 문체 본보기, 승인 고침 후보와 지문 |
96
+ | `inspectText(text, config)` | 지적, 문체 본보기, 승인 고침 후보와 분석표 |
97
97
  | `learnText(before, after, config)` | 사람이 확인하고 승인할 문장 고침과 표면 치환 후보 |
98
98
  | `compareRevision(before, after, config)` | 자유 원고의 숫자, 링크, 코드와 H2 제목 변화 |
99
+ | `sheetRows(sources, config, everything)` | `{ label, source }` 마다 화면 글을 뽑아 규칙을 돌린 시트 행. CLI `sheet` 와 브라우저가 같은 함수를 쓴다 |
99
100
 
100
101
  브라우저에서 코어를 실행하려면 사전과 모듈을 함께 조립한다.
101
102
  저장소의 [정적 사이트 빌드 절차](https://github.com/eddmpython/hanlint/blob/main/skills/specs/operation/webEditor.md)를 따른다.
102
103
 
103
104
  Python의 `hanlint learn 전.md 승인본.md --format toml`로 만든 후보는 사람이 검토한 뒤
104
- `hanlint.toml`의 `[[patches]]`와 `[[operations]]`로 승인할 수 있다. 두 판이 같은 설정을 읽는다.
105
- 원문 일치와 문맥 조건을 통과한 고침만 제안하며, 모호한 곳에서는 기권한다.
106
- 보호할 고유명사와 프로젝트 용어는 `protectedTerms`에 넣는다.
105
+ `hanlint.toml`의 `[[patches]]`와 `[[operations]]`로 승인할 수 있다. 두 구현이 같은 설정을 읽는다.
106
+ 원문 일치와 문맥 조건을 통과한 고침만 제안하며, 모호한 곳에서는 고침을 내지 않는다.
107
+ 보호할 고유명사와 프로젝트 용어는 `protectedTerms`에 넣는다. 이 용어와 한 글자라도 겹치는 자리는 사전 규칙,
108
+ 지시어, 이중 피동도 짚지 않는다.
107
109
  후보 생성, 개인 승인과 공통 규칙 반영은 별도 단계다.
108
110
 
109
111
  ## 자동화와 지원 범위
@@ -112,7 +114,7 @@ GitHub Actions, pre-commit과 Claude Code 훅의 전체 설정은
112
114
  [자동화 연결 안내](https://github.com/eddmpython/hanlint/blob/main/skills/specs/start/integrations.md)에 있다.
113
115
  훅은 후속 작업에 지적을 전달하며, CI의 종료 코드 검사와는 목적이 다르다.
114
116
 
115
- Python 판과 공유하는 검사는 같은 사전과 적합성 자료로 검증한다.
117
+ Python 구현과 공유하는 검사는 같은 사전과 적합성 자료로 검증한다.
116
118
  `audit`, `map`, `diff`, `learn`, `profile`, `coverage` 등 분석·실험 명령은 Python 쪽에 있다.
117
119
  전체 명령의 구분은 [명령과 설정](https://github.com/eddmpython/hanlint/blob/main/skills/specs/start/cli.md)을 참고한다.
118
120
 
@@ -0,0 +1,60 @@
1
+ {
2
+ "entry": [
3
+ {
4
+ "pattern": "(?<![가-힣])[가-힣]*(?:글|포스팅|게시물|게시글|상품|링크|페이지|화면|영상|세트|기록|파일|카드|문서|블로그|캡션|대본|목록|투두리스트|메시지)(?:에|에게|으로|로)[,)'\"’”]*(?:\\s+\\S*[^\\s을를]){0,2}\\s+(?:잇(?:다|고|지|는|기|게|습|던|자(?!국)|니|겠)|이어(?:요|야|도)(?![가-힣])|이었|이을(?![가-힣]))",
5
+ "why": "link 를 옮긴 말이다. `글에 잇다` 는 `글에 연결하다` 다. 잇다 는 줄이나 이야기처럼 끊긴 것을 이어 붙일 때 쓴다",
6
+ "source": "돈값 운영자 지적 2026-10-29, 글에 잇지 못했어요"
7
+ },
8
+ {
9
+ "pattern": "(?<![가-힣])[가-힣]*(?:상품|링크|포스팅|게시물|게시글|페이지|세트|캡션|투두리스트)(?:을|를)[,)'\"’”]*(?:\\s+\\S*[^\\s을를]){0,2}\\s+(?:잇(?:다|고|지|는|기|게|습|던|자(?!국)|니|겠)|이어(?:요|야|도)(?![가-힣])|이었|이은(?![가-힣])(?!\\s+[0-9]+(?:위|등))|이을(?![가-힣]))",
10
+ "unless": "(?<![가-힣])[가-힣]*(?:글|포스팅|게시물|게시글|상품|링크|페이지|화면|영상|세트|기록|파일|카드|문서|블로그|캡션|대본|목록|투두리스트|메시지)(?:에|에게|으로|로)[,)'\"’”]*(?:\\s+\\S*[^\\s을를]){0,2}\\s+(?:잇(?:다|고|지|는|기|게|습|던|자(?!국)|니|겠)|이어(?:요|야|도)(?![가-힣])|이었|이을(?![가-힣]))",
11
+ "why": "link 를 옮긴 말이다. `상품을 글에 잇다` 는 `상품을 글에 연결하다` 다",
12
+ "source": "돈값 운영자 지적 2026-10-29, 글에 잇지 못했어요"
13
+ },
14
+ {
15
+ "pattern": "(?<![가-힣])[가-힣]*(?:상품|링크|포스팅|게시물|게시글|페이지|세트|캡션)\\s+잇기",
16
+ "why": "link 를 옮긴 말이다. `상품 잇기` 는 `상품 연결` 이다",
17
+ "source": "돈값 운영자 지적 2026-10-29, 상품 잇기"
18
+ },
19
+ {
20
+ "pattern": "(?<![가-힣])[가-힣]*(?:(?<!스)팀|팀장|부서|세션|담당자?|제작자|대표님?|독자|시청자|사용자)(?:에|에게|한테|께|으로|로)[,)'\"’”]*(?:\\s+\\S+){0,2}\\s+닿(?:다|고|지|는|기|게|습|던|은|을|아|았|으|니|겠)",
21
+ "unless": "(?:연락|소식|손길|목소리|마음|진심)(?:이|가|은|는|도|만)?(?![가-힣])",
22
+ "why": "reach 를 옮긴 말이다. `그 팀에 닿는 줄` 은 `그 팀에 해당하는 규칙` 이다. 닿다 는 몸과 물건이 맞붙거나 연락이 될 때 쓴다",
23
+ "source": "돈값 운영자 지적 2026-10-24, 그 팀에 닿는 줄"
24
+ },
25
+ {
26
+ "pattern": "(?<![가-힣])(?:숫자|값|글자|텍스트)(?:가|이|는|은)[,)'\"’”]*\\s+그려(?:지[기면고는지자며니]|집|져(?!\\s*있)|졌)",
27
+ "unless": "그래프|곡선|차트|도표|막대|붓|연필|물감|크레파스|선으로",
28
+ "why": "render 를 옮긴 말이다. `숫자가 그려지기 전` 은 `숫자가 화면에 뜨기 전` 이다. 그려지다 는 그림을 그릴 때 쓴다",
29
+ "source": "돈값 운영자 지적 2026-10-27, 숫자가 그려지기 전"
30
+ },
31
+ {
32
+ "pattern": "(?<![가-힣])[가-힣]*(?:는지|은지)[,)'\"’”]*\\s+갈(?:리|립|렸|린|릴|려)",
33
+ "why": "tell apart 를 옮긴 말이다. `어디가 막혔는지 갈린다` 는 `어디가 막혔는지 알 수 있다` 다. 갈리다 는 의견이나 승부가 나뉠 때 쓴다",
34
+ "source": "돈값 운영자 지적 2026-10-27, 어디가 막혔는지 갈립니다"
35
+ },
36
+ {
37
+ "pattern": "(?<![가-힣])같은\\s+자리를\\s+(?:맴)?(?:돌(?:고|며|면|았|다|던|지|기)|돈다|돕니|도는)",
38
+ "why": "going in circles 를 옮긴 말이다. `같은 자리를 돌고 있다` 는 `진도가 나가지 않는다` 다",
39
+ "source": "돈값 운영자 지적 2026-11-01, 같은 자리를 돌고 있습니다"
40
+ },
41
+ {
42
+ "pattern": "(?<![가-힣])[가-힣]*[아어여워줘져혀겨려]\\s+봄(?:과|와|을|이|도|은)(?![가-힣])",
43
+ "unless": "여름|가을|겨울|꽃|계절|날씨|봄철|봄날|봄바람|새싹|따뜻|입춘|벚꽃|추위|얼음|햇살|봄이\\s+(?:오|왔|와|옵|온|되)|봄을\\s+(?:맞|알리|느끼|기다)",
44
+ "why": "해 보다 를 ㅁ 으로 줄인 이름이다. 요즘 글에서는 쓰지 않는다. `열어 봄과 누름` 은 `조회와 클릭` 이다",
45
+ "source": "돈값 운영자 지적 2026-10-27, 열어 봄과 누름"
46
+ },
47
+ {
48
+ "pattern": "(?<![가-힣])맡(?:겼|긴|겨\\s?두었|겨\\s?둔|겨\\s?뒀)",
49
+ "unless": "(?:에게|한테|께|에게서|에다|에다가|한테서|께서)(?![가-힣])|[가-힣](?:님|팀|세션)(?:이|은|는)(?![가-힣])|[가-힣A-Za-z)](?<![시분초일날때뒤후전중주월년간밤낮쯤안])(?<!동안)(?<!무렵)(?<!아침)(?<!저녁)(?<!오전)(?<!오후)에(?![가-힣])|믿고\\s+맡|몸을\\s+맡",
50
+ "why": "받는 이가 문장에 없다. 누구에게 맡겼는지 쓰거나 `예약 발행 대기에 올렸습니다` 처럼 한 일을 쓴다",
51
+ "source": "돈값 운영자 지적 2026-10-23, 예약 발행으로 맡겼습니다"
52
+ },
53
+ {
54
+ "pattern": "(?<![가-힣])걸어\\s?(?:두었|뒀)",
55
+ "unless": "(?:에게|한테|께|에게서|에다|에다가|한테서|께서)(?![가-힣])|[가-힣](?:님|팀|세션)(?:이|은|는)(?![가-힣])|[가-힣A-Za-z)](?<![시분초일날때뒤후전중주월년간밤낮쯤안])(?<!동안)(?<!무렵)(?<!아침)(?<!저녁)(?<!오전)(?<!오후)에(?![가-힣])|(?:링크|시동|자물쇠|잠금|조건|기대|희망|전화|예약|알람)(?:을|를|도)?\\s+걸어",
56
+ "why": "어디에 걸었는지가 문장에 없다. 무엇을 언제 하도록 예약했는지 쓴다. `고침을 걸어 두었습니다` 는 `06:10 뒤에 제목을 고치도록 예약해 두었습니다` 다",
57
+ "source": "돈값 운영자 지적 2026-10-26, 고침을 걸어 두었습니다"
58
+ }
59
+ ]
60
+ }
package/data/cliches.json CHANGED
@@ -94,6 +94,16 @@
94
94
  "pattern": "획기적",
95
95
  "why": "광고 문구다",
96
96
  "source": "다른 세션 제안"
97
+ },
98
+ {
99
+ "pattern": "이유[가는]? 여기",
100
+ "why": "설명을 차려 놓고 손가락으로 가리키는 말이다. 이유를 말했으면 그것으로 끝이다",
101
+ "source": "사람 글 0.10%, 기계 글 7.50% 가 쓴다 (75배, probeDensity 2026-09-20)"
102
+ },
103
+ {
104
+ "pattern": "^그다음",
105
+ "why": "산문에 번호를 매기는 말이다. 진짜 목록이면 목록으로 쓰고, 산문이면 앞 문장의 이름을 불러 잇는다",
106
+ "source": "사람 글 0.47%, 기계 글 6.11% 가 쓴다 (13배, probeDensity 2026-09-20)"
97
107
  }
98
108
  ]
99
109
  }
@@ -0,0 +1,28 @@
1
+ # 함께 쓰는 말 (usage 의 collocations) 을 셀 때 이웃으로 세지 않는 어절. 꼬리 사전이 못 가르는 연결 어절과 접속 부사다.
2
+ # 뜻을 잇는 낱말이지 앞 낱말과 결합하는 말이 아니다. 실측: 사업보고서 색인에서 `리스부채` 의 앞 명사 상위가
3
+ # `및`, `중`, `경우`, `따라`, `않아` 였다 (2026-09-19). 판정은 usage/sentences.py 의 neighbourOf 다.
4
+ 및
5
+ 등
6
+ 즉
7
+ 또는
8
+ 또한
9
+ 따라
10
+ 따르면
11
+ 인해
12
+ 위해
13
+ 통해
14
+ 대해
15
+ 의해
16
+ 관해
17
+ 비해
18
+ 대하여
19
+ 위하여
20
+ 통하여
21
+ 의하여
22
+ 관하여
23
+ 비하여
24
+ 않아
25
+ 않고
26
+ 아니라
27
+ 더불어
28
+ 이어
@@ -30,54 +30,6 @@
30
30
  "why": "쉬운 말 이번 이 있다",
31
31
  "source": "국립국어원 다듬은 말"
32
32
  },
33
- {
34
- "pattern": "(?<![가-힣])차후{조사}",
35
- "fix": "앞으로",
36
- "why": "쉬운 말 앞으로 가 있다",
37
- "source": "국립국어원 다듬은 말"
38
- },
39
- {
40
- "pattern": "(?<![가-힣])상기 (?=[가-힣])",
41
- "fix": "위 ",
42
- "why": "위에서 말한 것은 위 라고 쓴다",
43
- "source": "국립국어원 다듬은 말"
44
- },
45
- {
46
- "pattern": "(?<![가-힣])소정의",
47
- "fix": "정해진",
48
- "why": "쉬운 말 정해진 이 있다",
49
- "source": "국립국어원 다듬은 말"
50
- },
51
- {
52
- "pattern": "(?<![가-힣])여타{조사}",
53
- "fix": "다른",
54
- "why": "쉬운 말 다른 이 있다",
55
- "source": "국립국어원 다듬은 말"
56
- },
57
- {
58
- "pattern": "(?<![가-힣])제반{조사}",
59
- "fix": "여러",
60
- "why": "쉬운 말 여러 가 있다",
61
- "source": "국립국어원 다듬은 말"
62
- },
63
- {
64
- "pattern": "(?<![가-힣])납득{조사}",
65
- "fix": "이해",
66
- "why": "쉬운 말 이해 가 있다",
67
- "source": "국립국어원 다듬은 말"
68
- },
69
- {
70
- "pattern": "(?<![가-힣])납득(?=하|했|합|한|할|해)",
71
- "fix": "이해",
72
- "why": "쉬운 말 이해하다 가 있다",
73
- "source": "국립국어원 다듬은 말"
74
- },
75
- {
76
- "pattern": "(?<![가-힣])수취인{조사}",
77
- "fix": "받는 사람",
78
- "why": "쉬운 말 받는 사람 이 있다",
79
- "source": "국립국어원 다듬은 말"
80
- },
81
33
  {
82
34
  "pattern": "(?<![가-힣])불입{조사}",
83
35
  "fix": "납입",
@@ -90,42 +42,12 @@
90
42
  "why": "쉬운 말 잠금장치 가 있다",
91
43
  "source": "국립국어원 다듬은 말"
92
44
  },
93
- {
94
- "pattern": "(?<![가-힣])견본{조사}",
95
- "fix": "본보기",
96
- "why": "쉬운 말 본보기 가 있다",
97
- "source": "국립국어원 다듬은 말"
98
- },
99
- {
100
- "pattern": "(?<![가-힣])요망{조사}",
101
- "fix": "바람",
102
- "why": "협조 요망 은 협조 바람 이다",
103
- "source": "국립국어원 다듬은 말"
104
- },
105
45
  {
106
46
  "pattern": "(?<![가-힣])필히(?![가-힣])",
107
47
  "fix": "반드시",
108
48
  "why": "쉬운 말 반드시 가 있다",
109
49
  "source": "국립국어원 다듬은 말"
110
50
  },
111
- {
112
- "pattern": "(?<![가-힣])별첨{조사}",
113
- "fix": "따로 붙임",
114
- "why": "쉬운 말 따로 붙임 이 있다",
115
- "source": "국립국어원 다듬은 말"
116
- },
117
- {
118
- "pattern": "(?<![가-힣])회신{조사}",
119
- "fix": "답장",
120
- "why": "쉬운 말 답장 이 있다",
121
- "source": "국립국어원 다듬은 말"
122
- },
123
- {
124
- "pattern": "(?<![가-힣])잔여 (?=[가-힣])",
125
- "fix": "남은 ",
126
- "why": "쉬운 말 남은 이 있다",
127
- "source": "국립국어원 다듬은 말"
128
- },
129
51
  {
130
52
  "pattern": "(?<![가-힣])사료(?=됩|된|되)",
131
53
  "fix": "생각",
@@ -137,162 +59,6 @@
137
59
  "fix": "마땅히",
138
60
  "why": "쉬운 말 마땅히 가 있다",
139
61
  "source": "국립국어원 다듬은 말"
140
- },
141
- {
142
- "pattern": "(?<![가-힣])노하우{조사}",
143
- "fix": "비법",
144
- "why": "쉬운 말 비법 이 있다",
145
- "source": "국립국어원 다듬은 말"
146
- },
147
- {
148
- "pattern": "(?<![가-힣])매뉴얼{조사}",
149
- "fix": "설명서",
150
- "why": "쉬운 말 설명서 가 있다",
151
- "source": "표준국어대사전 (매뉴얼 = 설명서)"
152
- },
153
- {
154
- "pattern": "(?<![가-힣])피드백{조사}",
155
- "fix": "의견",
156
- "why": "쉬운 말 의견 이 있다",
157
- "source": "국립국어원 다듬은 말"
158
- },
159
- {
160
- "pattern": "(?<![가-힣])니즈{조사}",
161
- "fix": "요구",
162
- "why": "쉬운 말 요구 가 있다",
163
- "source": "국립국어원 다듬은 말"
164
- },
165
- {
166
- "pattern": "(?<![가-힣])어젠다{조사}",
167
- "fix": "의제",
168
- "why": "쉬운 말 의제 가 있다",
169
- "source": "국립국어원 다듬은 말"
170
- },
171
- {
172
- "pattern": "(?<![가-힣])가이드라인{조사}",
173
- "fix": "지침",
174
- "why": "쉬운 말 지침 이 있다",
175
- "source": "국립국어원 다듬은 말"
176
- },
177
- {
178
- "pattern": "(?<![가-힣])로드맵{조사}",
179
- "fix": "단계별 계획",
180
- "why": "쉬운 말 단계별 계획 이 있다",
181
- "source": "국립국어원 다듬은 말"
182
- },
183
- {
184
- "pattern": "(?<![가-힣])마인드{조사}",
185
- "fix": "마음가짐",
186
- "why": "쉬운 말 마음가짐 이 있다",
187
- "source": "국립국어원 다듬은 말"
188
- },
189
- {
190
- "pattern": "(?<![가-힣])컨펌{조사}",
191
- "fix": "확인",
192
- "why": "쉬운 말 확인 이 있다",
193
- "source": "국립국어원 다듬은 말"
194
- },
195
- {
196
- "pattern": "(?<![가-힣])데드라인{조사}",
197
- "fix": "마감",
198
- "why": "쉬운 말 마감 이 있다",
199
- "source": "국립국어원 다듬은 말"
200
- },
201
- {
202
- "pattern": "(?<![가-힣])리뷰{조사}",
203
- "fix": "검토",
204
- "why": "쉬운 말 검토 가 있다",
205
- "source": "국립국어원 다듬은 말"
206
- },
207
- {
208
- "pattern": "(?<![가-힣])멘토{조사}",
209
- "fix": "조언자",
210
- "why": "쉬운 말 조언자 가 있다",
211
- "source": "국립국어원 다듬은 말"
212
- },
213
- {
214
- "pattern": "(?<![가-힣])인센티브{조사}",
215
- "fix": "성과급",
216
- "why": "쉬운 말 성과급 이 있다",
217
- "source": "국립국어원 다듬은 말"
218
- },
219
- {
220
- "pattern": "(?<![가-힣])바우처{조사}",
221
- "fix": "이용권",
222
- "why": "쉬운 말 이용권 이 있다",
223
- "source": "국립국어원 다듬은 말"
224
- },
225
- {
226
- "pattern": "(?<![가-힣])팝업{조사}",
227
- "fix": "알림창",
228
- "why": "쉬운 말 알림창 이 있다",
229
- "source": "국립국어원 다듬은 말"
230
- },
231
- {
232
- "pattern": "(?<![가-힣])언택트{조사}",
233
- "fix": "비대면",
234
- "why": "쉬운 말 비대면 이 있다",
235
- "source": "국립국어원 다듬은 말"
236
- },
237
- {
238
- "pattern": "(?<![가-힣])팬데믹{조사}",
239
- "fix": "감염병 대유행",
240
- "why": "쉬운 말 감염병 대유행 이 있다",
241
- "source": "국립국어원 다듬은 말"
242
- },
243
- {
244
- "pattern": "(?<![가-힣])컨소시엄{조사}",
245
- "fix": "연합체",
246
- "why": "쉬운 말 연합체 가 있다",
247
- "source": "국립국어원 다듬은 말"
248
- },
249
- {
250
- "pattern": "(?<![가-힣])마스터플랜{조사}",
251
- "fix": "종합 계획",
252
- "why": "쉬운 말 종합 계획 이 있다",
253
- "source": "국립국어원 다듬은 말"
254
- },
255
- {
256
- "pattern": "(?<![가-힣])킥오프{조사}",
257
- "fix": "시작 회의",
258
- "why": "쉬운 말 시작 회의 가 있다",
259
- "source": "국립국어원 다듬은 말"
260
- },
261
- {
262
- "pattern": "(?<![가-힣])벤치마킹{조사}",
263
- "fix": "본보기 삼기",
264
- "why": "쉬운 말 본보기 삼기 가 있다",
265
- "source": "국립국어원 다듬은 말"
266
- },
267
- {
268
- "pattern": "(?<![가-힣])레퍼런스{조사}",
269
- "fix": "참고 자료",
270
- "why": "쉬운 말 참고 자료 가 있다",
271
- "source": "국립국어원 다듬은 말"
272
- },
273
- {
274
- "pattern": "(?<![가-힣])워크숍{조사}",
275
- "fix": "연수회",
276
- "why": "쉬운 말 연수회 가 있다",
277
- "source": "국립국어원 다듬은 말"
278
- },
279
- {
280
- "pattern": "(?<![가-힣])리스크{조사}",
281
- "fix": "위험",
282
- "why": "쉬운 말 위험 이 있다",
283
- "source": "국립국어원 다듬은 말"
284
- },
285
- {
286
- "pattern": "(?<![가-힣])체크리스트{조사}",
287
- "fix": "점검표",
288
- "why": "쉬운 말 점검표 가 있다",
289
- "source": "국립국어원 다듬은 말"
290
- },
291
- {
292
- "pattern": "(?<![가-힣])필터링{조사}",
293
- "fix": "거르기",
294
- "why": "쉬운 말 거르기 가 있다",
295
- "source": "국립국어원 다듬은 말"
296
62
  }
297
63
  ]
298
64
  }
@@ -12,6 +12,12 @@
12
12
  "after": "## 파일 열기\n\n파일을 엽니다. 열린 파일은 아직 비어 있습니다.\n\n## 값은 어디에 넣나?\n\n값을 넣습니다. 넣은 값은 아직 표가 아닙니다.\n\n## 표가 만들어지는 자리\n\n표를 만듭니다. 만든 표는 아직 파일에 없습니다.\n\n## 저장\n\n저장합니다.\n",
13
13
  "moved": "절마다 되풀이되던 예고 대신 방금 만든 것을 이름으로 부르고 아직 못 하는 일을 적었다"
14
14
  },
15
+ {
16
+ "rule": "calqueFrame",
17
+ "before": "캐스팅 장갑은 아직 원투 글에 잇지 못했습니다.",
18
+ "after": "캐스팅 장갑은 아직 원투 글에 연결하지 못했습니다.",
19
+ "moved": "글과 상품을 묶는 말을 사람들이 쓰는 연결하다 로 바꿨다"
20
+ },
15
21
  {
16
22
  "rule": "cliche",
17
23
  "before": "핵심은 속도입니다.",
@@ -30,6 +36,12 @@
30
36
  "after": "그런데 표가 큽니다. 필요한 열은 두 개뿐입니다.",
31
37
  "moved": "둘째 문장의 접속부사를 지우고 앞 문장이 만든 것을 이어받게 했다"
32
38
  },
39
+ {
40
+ "rule": "phraseRepeat",
41
+ "before": "물은 온도가 중요하다. 원두를 바꾸는 것이 아니라 온도를 맞추는 것이 먼저다. 갈기도 마찬가지다. 굵기를 바꾸는 것이 아니라 시간을 재는 것이 먼저다. 저울을 쓴다. 눈대중은 흔들린다. 같은 잔을 쓴다. 물을 먼저 붓는다.",
42
+ "after": "물은 온도가 중요하다. 원두를 바꾸는 것이 아니라 온도를 맞추는 것이 먼저다. 갈기도 마찬가지다. 굵기를 재어 둔다. 저울을 쓴다. 눈대중은 흔들린다. 같은 잔을 쓴다. 물을 먼저 붓는다.",
43
+ "moved": "되풀이된 둘 가운데 하나를 곧은 문장으로 바꿔 한 번만 남겼다"
44
+ },
33
45
  {
34
46
  "rule": "countMismatch",
35
47
  "before": "여섯 가지를 소개합니다.\n\n## 절\n\n다섯 가지를 봤습니다.\n",
@@ -128,8 +140,8 @@
128
140
  },
129
141
  {
130
142
  "rule": "hardWord",
131
- "before": "금일 중으로 소정의 양식을 제출합니다.",
132
- "after": "오늘 안에 정해진 양식을 냅니다.",
143
+ "before": "금일 중으로 양식을 제출합니다.",
144
+ "after": "오늘 안에 양식을 냅니다.",
133
145
  "moved": "관청 말을 평소에 쓰는 말로 바꿨다"
134
146
  },
135
147
  {
@@ -423,6 +435,15 @@
423
435
  "before": "매 시간마다 확인",
424
436
  "after": "매시간 확인",
425
437
  "moved": "겹말을 하나로 줄였다"
438
+ },
439
+ {
440
+ "rule": "calqueFrame",
441
+ "presets": [
442
+ "screen"
443
+ ],
444
+ "before": "상품 잇기",
445
+ "after": "상품 연결",
446
+ "moved": "사람들이 쓰는 낱말로 바꿨다"
426
447
  }
427
448
  ]
428
449
  }
@@ -0,0 +1,64 @@
1
+ # 한국어 산문 일곱 줄
2
+
3
+ 한국어 글을 쓰기 전에 읽는다.
4
+
5
+ 초보자용 설명에서도 표준 용어와 실제 UI 명칭을 유지한다. 쉬운 설명은 정의와 예시를 덧붙이는 일이다.
6
+ 마우스는 클릭, 터치는 탭, 체크박스는 선택·해제, 키보드는 키 입력, 명령은 실행으로 동작을 구분한다.
7
+ 클릭을 누른다로 바꾸거나 필터를 거르개, 래핑을 감싸개로 번역하지 않는다. 필터는 조건에 맞는 항목을
8
+ 선택하는 기능이며, 래핑은 기존 기능을 다른 코드로 감싸 호출 방식이나 동작을 조정하는 기법처럼 설명한다.
9
+ Excel의 셀·행·열·시트도 이름을 유지한다. 파일 내용 수정, 설정 변경, 오류 해결처럼 작업 대상을 명시한다.
10
+ 문맥을 판단해야 하는 제안은 오류 수를 줄이려고 적용하지 않는다. 검사 결과보다 사실과 용어의 정확성을 먼저 확인한다.
11
+
12
+ 아래 일곱 항목 중 앞의 여섯은 사람이 쓴 한국어 155만 문장 (백과사전, 지침, 토론, 보고서) 과
13
+ 기계가 쓴 360편을 견줘 나온 표지다. 붙은 수는 천 문장당 비율이다 (긴 문장만 글 안의 비율).
14
+ 사람 쪽은 장르 넷 가운데 **가장 높은** 값이다.
15
+ 일곱째는 이 수치를 적용할 때 글의 뜻과 독자의 말을 지키는 원칙이다.
16
+
17
+ ## 1. 긴 문장을 아예 안 쓰면 기계 글이다
18
+
19
+ 사람은 서른 어절 넘는 문장을 스무 문장에 하나 꼴로 쓰는데 (4.6~15.5%) 기계는 0.3% 라서 15배 넘게 벌어진다.
20
+
21
+ 짧게 끊는 것이 미덕이라고 배웠겠지만, 사람 글의 리듬은 **가끔 길게 가는 문장**에서 나온다.
22
+ 한 단락에 하나쯤은 숨을 길게 끌고 가는 문장을 두고, 조건과 이유와 결과를 한 문장 안에 엮어라
23
+
24
+ ## 2. `~하는 이유가 여기 있다` 로 설명을 가리키지 마라
25
+
26
+ 사람 0.01, 기계 6.30. **630배.**
27
+
28
+ 설명을 차려 놓고 손가락으로 가리키는 짓이다. 이유를 말했으면 그것으로 끝이다.
29
+ `그래서 도마는 나무를 쓴다` 로 끝내고 `도마를 나무로 쓰는 이유가 여기 있다` 를 덧붙이지 마라
30
+
31
+ ## 3. 산문 안에서 번호를 매기지 마라
32
+
33
+ `그다음` 사람 0.06, 기계 6.93 (116배). `첫 번째는 / 두 번째는` 사람 0.22, 기계 9.14 (42배).
34
+
35
+ 목록을 문장으로 위장한 것이라 읽는 쪽이 헤맨다. 진짜 목록이면 목록으로 쓰고,
36
+ 산문이면 `먼저`, `그런데`, `대신` 같은 말로 잇거나, 아무것도 안 붙이고 그냥 다음 문장을 써라
37
+
38
+ ## 4. `~하는 편이 낫다` 로 권고를 뭉개지 마라
39
+
40
+ 사람 0.47, 기계 16.07. **34배.**
41
+
42
+ 단언을 피하면서 조언한 척하는 꼴이다. 권하려면 권하고 (`아침에 달려라`), 정말 갈리는 문제면
43
+ 무엇에 따라 갈리는지를 말해라 (`무릎이 아프면 걷고, 안 아프면 달려라`)
44
+
45
+ ## 5. `~인 셈이다`, `~인 식이다` 로 되짚지 마라
46
+
47
+ 사람 0.13, 기계 4.10. **32배.**
48
+
49
+ 방금 한 말을 한 번 더 말하는 자리다. 한 번 말했으면 됐다.
50
+
51
+ ## 6. `X가 아니라 Y다` 를 남발하지 마라
52
+
53
+ 사람 7.05, 기계 65.55. **9.3배.**
54
+
55
+ 안 물어본 오해를 세워 놓고 바로잡는 수법이다. 한 편에 한 번이면 힘이 있고, 세 번 넘으면 버릇이다.
56
+ `Y다` 라고 바로 말해라
57
+
58
+ ## 7. 앞의 여섯을 피하느라 글을 망치지 마라
59
+
60
+ 이 목록은 피할 것의 목록이지 쓸 것의 목록이 아니다. 그러니 하고 싶은 말을 먼저 정하고, 그 말을 가장 곧게
61
+ 쓴 다음, 1번부터 6번까지가 습관으로 끼어들었는지만 보아라
62
+
63
+ 사용자 원문과 분야 자료에 나온 용어의 이름을 먼저 확인하고, 풀어 쓴다는 이유로 새 번역 명사를 만들지 말고
64
+ 그 이름을 두고 필요한 뜻이나 동작을 문장으로 설명하라
@@ -4,7 +4,7 @@
4
4
  "name": "행동과 결과",
5
5
  "form": "{대상}을 {행동}하면 {결과}가 {어디}에 {생깁니다}",
6
6
  "when": "독자에게 무엇을 시킬 때. 가능성만 말하지 않고 손이 할 일과 눈에 보일 것을 한 문장에 담는다",
7
- "example": "`저장` 버튼을 누르면 `report.csv` 가 그 폴더에 만들어집니다.",
7
+ "example": "`저장` 버튼을 클릭하면 `report.csv` 가 그 폴더에 만들어집니다.",
8
8
  "instead": "이 기능을 통해 파일 생성이 가능합니다.",
9
9
  "avoids": [
10
10
  "translationese"
@@ -81,7 +81,7 @@
81
81
  "name": "결핍 도입",
82
82
  "form": "{독자가 지금 하려는 일}입니다. {왜 지금 방법으로는 안 되는지}. 끝까지 읽으면 {손에 남는 것}이 남습니다",
83
83
  "when": "글의 첫 문단. 정의로 시작하지 않고 독자가 막힌 자리로 시작한다",
84
- "example": "거래 기록을 CSV로 내려받았더니 5백만 줄입니다. 엑셀로 열면 1,048,576줄에서 잘립니다. 끝까지 읽으면 그 표를 여는 코드가 손에 남습니다.",
84
+ "example": "거래 기록을 CSV로 다운로드했더니 5백만 줄입니다. 엑셀로 열면 1,048,576줄에서 잘립니다. 끝까지 읽으면 그 표를 여는 코드가 손에 남습니다.",
85
85
  "instead": "핵심은 속도입니다.",
86
86
  "avoids": [
87
87
  "cliche"
@@ -0,0 +1,11 @@
1
+ {
2
+ "entry": [
3
+ {
4
+ "pattern": "[이가] 아니라[^.!?]{0,40}(?:이다|입니다|이에요|예요|이야|다\\.|요\\.)",
5
+ "share": 0.08,
6
+ "label": "X가 아니라 Y다",
7
+ "why": "안 물어본 오해를 세워 놓고 바로잡는 수법이다. 한 편에 한 번이면 힘이 있고 되풀이하면 버릇이다. Y다 라고 바로 쓴다",
8
+ "source": "사람 4,021편의 99분위 7.1%, 기계 360편의 33%가 8% 위 (probeDensity 2026-09-20)"
9
+ }
10
+ ]
11
+ }
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "blockUnread": "structure",
3
3
  "bridgeRepeat": "structure",
4
+ "calqueFrame": "sentence",
4
5
  "cliche": "sentence",
5
6
  "confusable": "orthography",
6
7
  "connectorRepeat": "sentence",
@@ -41,6 +42,7 @@
41
42
  "numberOrphan": "sentence",
42
43
  "outsideProfile": "sentence",
43
44
  "paraFragment": "paragraph",
45
+ "phraseRepeat": "sentence",
44
46
  "platformApi": "code",
45
47
  "promiseRecall": "document",
46
48
  "redundantPair": "sentence",