claude-token-saver 3.39.0 β†’ 3.40.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 CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![npm](https://img.shields.io/npm/v/claude-token-saver.svg)](https://www.npmjs.com/package/claude-token-saver)
4
4
 
5
- 🌐 **[ν”„λ‘œμ νŠΈ μ†Œκ°œ νŽ˜μ΄μ§€](https://rootstudioyaml.github.io/claude-token-saver/)**
5
+ 🌐 **[sprag.io](https://sprag.io)** Β· ν”„λ‘œμ νŠΈ μ‚¬μ΄νŠΈ (claude-token-saverλŠ” **Sprag**둜 이름을 λ°”κΎΈλŠ” μ€‘μž…λ‹ˆλ‹€)
6
6
 
7
7
  # claude-token-saver
8
8
 
@@ -395,7 +395,7 @@ Claude Code의 output styleλ‘œλ„ 같은 일을 ν•  수 μžˆμ§€λ§Œ, output style
395
395
 
396
396
  **이전** (μ§€μΉ¨ 꺼짐)
397
397
 
398
- > λ Œλ” μ‹€νŒ¨ 원인 쒁히기 3단계: λ¨Όμ € `hn:still --check`둜 μŠ€ν‹Έμ΄ λͺ…세보닀 μ΅œμ‹ μΈμ§€(FRESH/STALE) 확인 β€” STALE이면 μž¬μƒμ„± μ•ˆ ν•΄μ„œ μ˜› μžμ‚°μœΌλ‘œ λ Œλ” μ‹œλ„ν•œ 게 원인. λ‹€μŒ caption-blocksκ°€ μ΅œμ‹  λ‚˜λ ˆμ΄μ…˜κ³Ό 단어열 μΌμΉ˜ν•˜λŠ”μ§€ 직접 λŒ€μ‘° β€” TTS μž¬μƒμ„± ν›„ blocks μž¬μƒμ„± λΉ μ§€λ©΄ μžλ§‰Β·μŒμ„± μ–΄κΈ‹λ‚˜ λ Œλ” 깨짐.
398
+ > λ Œλ” μ‹€νŒ¨ 원인 쒁히기 3단계: λ¨Όμ € `hn:still --check`둜 μŠ€ν‹Έμ΄ λͺ…세보닀 μ΅œμ‹ μΈμ§€(FRESH/STALE) ν™•μΈν•©λ‹ˆλ‹€. STALE이면 μž¬μƒμ„± μ•ˆ ν•΄μ„œ μ˜› μžμ‚°μœΌλ‘œ λ Œλ” μ‹œλ„ν•œ 게 원인. λ‹€μŒ caption-blocksκ°€ μ΅œμ‹  λ‚˜λ ˆμ΄μ…˜κ³Ό 단어열 μΌμΉ˜ν•˜λŠ”μ§€ 직접 λŒ€μ‘°ν•©λ‹ˆλ‹€. TTS μž¬μƒμ„± ν›„ blocks μž¬μƒμ„± λΉ μ§€λ©΄ μžλ§‰Β·μŒμ„± μ–΄κΈ‹λ‚˜ λ Œλ” 깨짐.
399
399
 
400
400
  **이후** (μ§€μΉ¨ 켜짐)
401
401
 
@@ -413,7 +413,7 @@ Claude Code의 output styleλ‘œλ„ 같은 일을 ν•  수 μžˆμ§€λ§Œ, output style
413
413
 
414
414
  μ„Έ 측이 λ”ν•΄μ§‘λ‹ˆλ‹€.
415
415
 
416
- - **λ²ˆμ—­νˆ¬**: 이쀑 피동, μΌλ³Έμ–΄μ—μ„œ 온 ꡳ은 ν‘œν˜„, '~에 μžˆμ–΄μ„œ', μ˜μ–΄ haveλ₯Ό μ§μ—­ν•œ 'κ°€μ§€λ‹€' λ‚¨μš©. 기계가 νŒμ •ν•  수 μžˆλŠ” 것은 μ“°κΈ° μ‹œμ  검사(μ•„λž˜)에도 ν•¨κ»˜ λ“€μ–΄κ°‘λ‹ˆλ‹€.
416
+ - **λ²ˆμ—­νˆ¬**: 이쀑 피동, μΌλ³Έμ–΄μ—μ„œ 온 ꡳ은 ν‘œν˜„, `~에 μžˆμ–΄μ„œ`, μ˜μ–΄ haveλ₯Ό μ§μ—­ν•œ 'κ°€μ§€λ‹€' λ‚¨μš©. 기계가 νŒμ •ν•  수 μžˆλŠ” 것은 μ“°κΈ° μ‹œμ  검사(μ•„λž˜)에도 ν•¨κ»˜ λ“€μ–΄κ°‘λ‹ˆλ‹€.
417
417
  - **μƒνˆ¬ νŒ¨ν„΄**: μžλ™μœΌλ‘œ λΆ™λŠ” μˆ˜μ‹μ–΄("λ‹€μ–‘ν•œ", "핡심적인"), ν‘œμ§€νŒ λ¬Έμž₯, μˆ˜μ‚¬μ  질문 λ’€ 즉닡, κ·Όκ±° μ—†λŠ” 긍정 마무리.
418
418
  - **응집성**: λ¬Έμž₯이 μ΄μ–΄μ§€λŠ” 방식이라 μ •κ·œμ‹μœΌλ‘œλŠ” κ²€μ‚¬ν•˜μ§€ λͺ»ν•©λ‹ˆλ‹€. 이 절의 λ°©ν–₯을 μ •ν•œ 연ꡬ κ²°κ³Όκ°€ μžˆμŠ΅λ‹ˆλ‹€. μ ‘μ†μ–΄Β·μ§€μ‹œμ–΄ 같은 ν‘œμΈ΅ μ—°κ²° μž₯μΉ˜λŠ” κΈ€μ˜ ν’ˆμ§ˆκ³Ό 상관이 μ—†κ±°λ‚˜ 였히렀 뢀적 상관이고, μ•ž λ¬Έμž₯이 내놓은 정보λ₯Ό λ‹€μŒ λ¬Έμž₯이 λ°›μ•„ ν’€μ–΄ μ£ΌλŠ” μƒμˆ ν˜• μ—°κ²°λ§Œ 정적 상관을 λ³΄μ˜€μŠ΅λ‹ˆλ‹€. κ·Έλž˜μ„œ 지침은 연결이 어색할 λ•Œ 접속어λ₯Ό λ”ν•˜μ§€ 말고 μ •λ³΄μ˜ λ°°μ—΄(μ•„λŠ” 것 λ¨Όμ €, μƒˆ 것 λ‚˜μ€‘)을 고치라고 λ§ν•©λ‹ˆλ‹€.
419
419
 
@@ -503,7 +503,7 @@ claude-token-saver doc2md install-converter # μ„€μΉ˜λ₯Ό 미리 끝내 두고
503
503
  λͺ‡ κ°€μ§€λŠ” μ˜λ„μ μœΌλ‘œ ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.
504
504
 
505
505
  - **μ΄λ―Έμ§€λŠ” λ³€ν™˜ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.** markitdown 이 빈 κ²°κ³Όλ₯Ό 돌렀주고, OCR 은 μ‹€μΈ‘μ—μ„œ λ¦¬μ†ŒμŠ€ 이름을 ν‹€λ¦¬κ²Œ μ½μ—ˆμŠ΅λ‹ˆλ‹€(`c5.xlarge` λ₯Ό `c.xlarge` 둜). 이름 μžμ²΄κ°€ λ‚΄μš©μΈ λ¬Έμ„œμ—μ„œλŠ” ν…μŠ€νŠΈκ°€ μ—†λŠλ‹ˆλ§Œ λͺ»ν•©λ‹ˆλ‹€. λͺ¨λΈμ΄ μ΄λ―Έμ§€λŠ” 직접 μ½μŠ΅λ‹ˆλ‹€.
506
- - **λ³€ν™˜κΈ°κ°€ μ—†μœΌλ©΄ 쑰용히 μ‹€νŒ¨ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.** μ„€μΉ˜ λͺ…령을 ν•œ 번 μ•ˆλ‚΄ν•œ λ’€ 원본 `Read` λ₯Ό κ·ΈλŒ€λ‘œ ν†΅κ³Όμ‹œν‚΅λ‹ˆλ‹€. 맀번 μ•Œλ¦¬λ©΄ κ·Έκ²ƒλŒ€λ‘œ λ°©ν•΄κ°€ 되고, 아무 말도 ν•˜μ§€ μ•ŠμœΌλ©΄ κ³ μž₯을 숨기게 λ©λ‹ˆλ‹€. `doc2md` λ₯Ό 인자 없이 μ‹€ν–‰ν•˜λ©΄ λ³€ν™˜κΈ°μ™€ ν›… 등둝 μƒνƒœλ₯Ό ν•œ λ²ˆμ— 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.
506
+ - **λ³€ν™˜κΈ°κ°€ 없어도 μ•Œλ¦¬μ§€ μ•Šκ³  μ§€λ‚˜κ°€μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.** μ„€μΉ˜ λͺ…령을 ν•œ 번 μ•ˆλ‚΄ν•œ λ’€ 원본 `Read` λ₯Ό κ·ΈλŒ€λ‘œ ν†΅κ³Όμ‹œν‚΅λ‹ˆλ‹€. 맀번 μ•Œλ¦¬λ©΄ κ·Έκ²ƒλŒ€λ‘œ λ°©ν•΄κ°€ 되고, 아무 말도 ν•˜μ§€ μ•ŠμœΌλ©΄ κ³ μž₯을 숨기게 λ©λ‹ˆλ‹€. `doc2md` λ₯Ό 인자 없이 μ‹€ν–‰ν•˜λ©΄ λ³€ν™˜κΈ°μ™€ ν›… 등둝 μƒνƒœλ₯Ό ν•œ λ²ˆμ— 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.
507
507
  - **λ³€ν™˜λ³Έμ€ ν”„λ‘œμ νŠΈ μ•ˆμ— 남기지 μ•ŠμŠ΅λ‹ˆλ‹€.** λ„κ΅¬μ˜ μƒνƒœ 디렉터리 μ•„λž˜ κΆŒν•œ `0700` 으둜 μ €μž₯ν•˜λ―€λ‘œ `.gitignore` 에 무엇을 μΆ”κ°€ν•  ν•„μš”κ°€ μ—†μŠ΅λ‹ˆλ‹€. 파일λͺ…이 κΈ‰μ—¬Β·κ³„μ•½Β·κ°œμΈμ •λ³΄ 같은 νŒ¨ν„΄μ— 걸리면 μ•„μ˜ˆ λ³€ν™˜ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.
508
508
  - **μ••μΆ• 폭탄은 λ§‰μŠ΅λ‹ˆλ‹€.** pptxΒ·xlsxΒ·docx λŠ” zip μ»¨ν…Œμ΄λ„ˆμž…λ‹ˆλ‹€. μ„ μ–Έλœ 크기λ₯Ό λ¨Όμ € 걸러 λ‚΄κ³ , 선언은 μ‘°μž‘λ  수 μžˆμœΌλ―€λ‘œ μ‹€μ œ ν•΄μ œ λ°”μ΄νŠΈλ„ μƒν•œκ³Ό λŒ€μ‘°ν•©λ‹ˆλ‹€.
509
509
  - **엑셀은 ν–‰ 수둜 μžλ¦…λ‹ˆλ‹€.** λ³€ν™˜ μ‹œκ°„μ€ 파일 크기가 μ•„λ‹ˆλΌ ν–‰ 수λ₯Ό λ”°λ¦…λ‹ˆλ‹€(μ‹€μΈ‘: PDF 6.3MB 0.9초, μ—‘μ…€ 5.8MB 47.75초). 5만 행을 λ„˜μœΌλ©΄ μ•žλΆ€λΆ„λ§Œ λ³€ν™˜ν•˜κ³ , **μž˜λžλ‹€λŠ” 사싀과 전체 ν–‰ 수λ₯Ό μ•ˆλ‚΄μ— ν•¨κ»˜ μ μŠ΅λ‹ˆλ‹€.**
@@ -610,7 +610,7 @@ npm uninstall -g claude-cache-monitor && npm i -g claude-token-saver
610
610
 
611
611
  ## ν”Όλ“œλ°±
612
612
 
613
- 버그 μ œλ³΄μ™€ κΈ°λŠ₯ μ œμ•ˆμ€ GitHub 이슈둜 λ°›μŠ΅λ‹ˆλ‹€: https://github.com/rootstudioyaml/claude-token-saver/issues
613
+ 버그 μ œλ³΄μ™€ κΈ°λŠ₯ μ œμ•ˆμ€ GitHub 이슈둜 λ°›μŠ΅λ‹ˆλ‹€: https://github.com/rootstudioyaml/sprag/issues
614
614
 
615
615
  λΈŒλΌμš°μ €λ‚˜ GitHub 둜그인이 μ–΄λ €μš΄ ν™˜κ²½(사내망, μ„Έμ…˜ 도쀑)이라면 ν„°λ―Έλ„μ—μ„œ λ°”λ‘œ μ œμΆœν•  수 있고, Claudeμ—κ²Œ λŒ€μ‹  μ œμΆœν•΄ 달라고 μš”μ²­ν•΄λ„ λ©λ‹ˆλ‹€.
616
616
 
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![npm](https://img.shields.io/npm/v/claude-token-saver.svg)](https://www.npmjs.com/package/claude-token-saver)
4
4
 
5
- 🌐 **[Project page](https://rootstudioyaml.github.io/claude-token-saver/)**
5
+ 🌐 **[sprag.io](https://sprag.io)** · project site (claude-token-saver is being renamed to **Sprag**)
6
6
 
7
7
  # claude-token-saver
8
8
 
@@ -731,7 +731,7 @@ The full history moved to [CHANGELOG.md](./CHANGELOG.md) (Korean; version headin
731
731
 
732
732
  ## Feedback
733
733
 
734
- Found a bug, or want a feature? Open an issue: https://github.com/rootstudioyaml/claude-token-saver/issues
734
+ Found a bug, or want a feature? Open an issue: https://github.com/rootstudioyaml/sprag/issues
735
735
 
736
736
  No browser or GitHub login handy (corporate network, mid-session)? Submit straight from the terminal β€” or ask Claude to do it for you:
737
737
 
package/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "claude-token-saver",
3
- "version": "3.39.0",
4
- "description": "Route the easy work your expensive Claude model keeps repeating down to haiku/sonnet β€” post-hoc session analysis, no realtime router, no extra LLM calls.",
3
+ "version": "3.40.0",
4
+ "description": "Route the easy work your expensive Claude model keeps repeating down to haiku/sonnet \u2014 post-hoc session analysis, no realtime router, no extra LLM calls.",
5
5
  "type": "module",
6
6
  "bin": {
7
+ "sprag": "bin/cli.js",
7
8
  "claude-token-saver": "bin/cli.js"
8
9
  },
9
10
  "scripts": {
@@ -48,11 +49,11 @@
48
49
  "license": "MIT",
49
50
  "repository": {
50
51
  "type": "git",
51
- "url": "git+https://github.com/rootstudioyaml/claude-token-saver.git"
52
+ "url": "git+https://github.com/rootstudioyaml/sprag.git"
52
53
  },
53
- "homepage": "https://github.com/rootstudioyaml/claude-token-saver#readme",
54
+ "homepage": "https://sprag.io",
54
55
  "bugs": {
55
- "url": "https://github.com/rootstudioyaml/claude-token-saver/issues"
56
+ "url": "https://github.com/rootstudioyaml/sprag/issues"
56
57
  },
57
58
  "author": "DeepPulse (https://www.youtube.com/@DeepPulseKR)"
58
59
  }
@@ -86,6 +86,7 @@ export async function run({ args, hasFlag }) {
86
86
  console.error(`${file}: ${e.message}`);
87
87
  continue;
88
88
  }
89
+ if (lint.isHtmlFile(file)) text = lint.stripHtml(text);
89
90
  const findings = lint.lintKoreanText(text, { code: !lint.isProseFile(file) });
90
91
  total += findings.length;
91
92
  if (findings.length) console.log(lint.formatFindings(file, findings));
@@ -35,12 +35,21 @@
35
35
  // Documents. Under the `prose` scope these are the only files checked.
36
36
  const PROSE_EXTENSIONS = new Set(['.md', '.mdx', '.markdown', '.txt', '.rst', '.adoc']);
37
37
 
38
+ // HTML is a document a reader receives, so it is checked under BOTH scopes,
39
+ // like prose β€” but through `stripHtml` first, so tags, comments, and CSS never
40
+ // trip the rules. Script bodies are kept: on a static page the Korean UI copy
41
+ // (i18n dictionaries, template strings) lives exactly there, and that gap is
42
+ // how an em dash shipped to a real landing page unchecked (2026-09-13).
43
+ const HTML_EXTENSIONS = new Set(['.html', '.htm', '.xhtml', '.vue', '.svelte']);
44
+
38
45
  // Only two kinds of path are skipped: installed dependencies and VCS
39
46
  // internals, neither of which anyone in this session wrote. Build output is
40
47
  // deliberately NOT on this list. Generated artifacts are the files a reader
41
48
  // actually receives, so exempting `dist/` or `build/` would exempt the very
42
49
  // documents the check exists for.
43
50
  const SKIP_PATH = /(^|[\\/])(node_modules|\.git|.*\.min\.[a-z]+|.*-lock\.json|.*\.lock)([\\/]|$)/i;
51
+ // This module and the hook copy that embeds it quote every banned form.
52
+ const SELF_PATH = /(^|[\\/])(korean-lint\.cjs|cache-monitor-hook\.cjs)$/i;
44
53
  const BINARY_EXTENSIONS = new Set([
45
54
  '.png', '.jpg', '.jpeg', '.gif', '.webp', '.svg', '.ico', '.pdf', '.zip', '.gz', '.tar',
46
55
  '.mp3', '.mp4', '.wav', '.mov', '.woff', '.woff2', '.ttf', '.otf', '.map', '.bin',
@@ -71,6 +80,18 @@ const METAPHOR_LEXICON = [
71
80
  { re: /벽에 λΆ€λ”ͺ|길을 μ—΄|문을 μ—΄/, fix: '무엇이 λ§‰νžˆκ³  무엇이 κ°€λŠ₯ν•΄μ§€λŠ”μ§€ κ·ΈλŒ€λ‘œ μ μŠ΅λ‹ˆλ‹€' },
72
81
  { re: /갈림길|κ°ˆλ¦¬λŠ” 지점/, fix: "'결정이 λ‚˜λ‰˜λŠ” 쑰건'으둜 λ°”κΏ‰λ‹ˆλ‹€" },
73
82
  { re: /κΉ¨μ–΄λ‚˜|μž λ“€μ–΄ 있/, fix: "'λ™μž‘μ„ μ‹œμž‘ν•˜λ‹€'Β·'μ‹€ν–‰λ˜μ§€ μ•Šκ³  μžˆλ‹€'둜 λ°”κΏ‰λ‹ˆλ‹€" },
83
+ // Added 2026-09-13. "fails loudly / fails silently" reads as idiom in English
84
+ // but lands as figurative vocabulary in Korean: a failure has no volume.
85
+ // 0 hits across 400 Korean files in yaml-sns-agent, so the confirm-request is
86
+ // not noise.
87
+ {
88
+ re: /(?:μ‹œλ„λŸ½κ²Œ|μ‹œλ„λŸ¬μš΄|쑰용히|μ‘°μš©ν•œ)\s*[κ°€-힣]*(?:μ‹€νŒ¨|틀리|λ“œλŸ¬λ‚˜|μ–΄κΈ‹)|(?:μ‹€νŒ¨|였λ₯˜|버그)[κ°€μ€λŠ”μ΄]?\s*(?:μ‹œλ„λŸ½|μ‹œλ„λŸ¬μš΄|μ‘°μš©ν•˜|μ‘°μš©ν•œ)/,
89
+ fix: "λ¬΄μ—‡μœΌλ‘œ μ‹€νŒ¨λ₯Ό ν™•μΈν•˜λŠ”μ§€ μ μŠ΅λ‹ˆλ‹€. 'μ’…λ£Œ μ½”λ“œλ‘œ λ°”λ‘œ λ“œλŸ¬λ‚˜λŠ”κ°€'Β·'검증 없이 μ§€λ‚˜κ°€λŠ”κ°€'",
90
+ },
91
+ {
92
+ re: /μ•ˆμ „λ§/,
93
+ fix: "'검증 μˆ˜λ‹¨'Β·'확인 μž₯치'처럼 무엇이 μ‹€νŒ¨λ₯Ό μž‘μ•„λ‚΄λŠ”μ§€ κ·ΈλŒ€λ‘œ μ μŠ΅λ‹ˆλ‹€",
94
+ },
74
95
  ];
75
96
 
76
97
  // Guidance 3.2/3.3: literal renderings of English noun phrases.
@@ -111,9 +132,13 @@ const NOMINAL_ENDING = /(?:음|함|됨|μž„|점|λ‘ |μ–‘|μ„±|ν™”)\.$/;
111
132
  function isLintTarget(filePath, scope = 'all') {
112
133
  if (!filePath) return false;
113
134
  if (SKIP_PATH.test(filePath)) return false;
135
+ // The rule table has to spell every banned form out, so this file always
136
+ // matches its own lexicon. Checking it reports the rules, not a breach.
137
+ if (SELF_PATH.test(filePath)) return false;
114
138
  const dot = filePath.lastIndexOf('.');
115
139
  const ext = dot === -1 ? '' : filePath.slice(dot).toLowerCase();
116
140
  if (PROSE_EXTENSIONS.has(ext)) return true;
141
+ if (HTML_EXTENSIONS.has(ext)) return true;
117
142
  if (scope !== 'all') return false;
118
143
  if (!ext) return false;
119
144
  return !BINARY_EXTENSIONS.has(ext);
@@ -124,6 +149,26 @@ function isProseFile(filePath) {
124
149
  return isLintTarget(filePath, 'prose');
125
150
  }
126
151
 
152
+ function isHtmlFile(filePath) {
153
+ const dot = String(filePath).lastIndexOf('.');
154
+ const ext = dot === -1 ? '' : String(filePath).slice(dot).toLowerCase();
155
+ return HTML_EXTENSIONS.has(ext);
156
+ }
157
+
158
+ /**
159
+ * Blank out the parts of an HTML document no reader sees β€” comments, CSS, and
160
+ * the tags themselves β€” while keeping every newline, so finding line numbers
161
+ * still point into the original file. Script bodies stay: that is where the
162
+ * page's Korean copy lives on a static site.
163
+ */
164
+ function stripHtml(text) {
165
+ const blank = (m) => m.replace(/[^\n]/g, ' ');
166
+ return String(text)
167
+ .replace(/<!--[\s\S]*?-->/g, blank)
168
+ .replace(/<style\b[^>]*>[\s\S]*?<\/style>/gi, blank)
169
+ .replace(/<[^>]+>/g, blank);
170
+ }
171
+
127
172
  /** Drop fenced code blocks and inline code so snippets never trip the rules. */
128
173
  function stripCode(text) {
129
174
  const out = [];
@@ -226,9 +271,12 @@ function lintToolUse(context, { scope = 'all' } = {}) {
226
271
  const filePath = toolInput && typeof toolInput.file_path === 'string' ? toolInput.file_path : '';
227
272
  if (!isLintTarget(filePath, scope)) return null;
228
273
 
229
- const text = writtenTextOf(toolName, toolInput);
274
+ let text = writtenTextOf(toolName, toolInput);
230
275
  if (!text || !hasKorean(text)) return null;
231
276
 
277
+ // Edits arrive as fragments, so tag-stripping only applies when the payload
278
+ // is a whole document; a fragment is still linted, just without stripping.
279
+ if (isHtmlFile(filePath) && toolName === 'Write') text = stripHtml(text);
232
280
  const findings = lintKoreanText(text, { code: !isProseFile(filePath) });
233
281
  if (findings.length === 0) return null;
234
282
  return { filePath, findings };
@@ -246,6 +294,8 @@ module.exports = {
246
294
  METAPHOR_LEXICON,
247
295
  isLintTarget,
248
296
  isProseFile,
297
+ isHtmlFile,
298
+ stripHtml,
249
299
  lintKoreanText,
250
300
  writtenTextOf,
251
301
  lintToolUse,