Module: Vivlio::Starter::CLI::Lint::Tokenizer
- Defined in:
- lib/vivlio/starter/cli/lint/tokenizer.rb
Overview
Markdownファイルから英単語トークンを抽出する
Constant Summary collapse
- FENCE_PATTERN =
/^```/- FRONTMATTER_SEP =
/^---\s*$/- VS_LINT_DISABLE =
vs-lint コメント記法の定義
/^\s*<!--\s*vs-lint-disable\s*-->\s*$/- VS_LINT_ENABLE =
/^\s*<!--\s*vs-lint-enable\s*-->\s*$/- VS_LINT_DISABLE_NEXT_LINE =
/^\s*<!--\s*vs-lint-disable-next-line\s*-->\s*$/
Class Method Summary collapse
-
.build_excluded_lines(content) ⇒ Array(Set<Integer>, Integer?)
vs-lint コメントに基づいて除外すべき行番号のセットを構築する.
-
.extract_words(line) ⇒ Array<String>
抽出された英単語の配列.
-
.tokenize(content, check_code_blocks: false, path: nil) ⇒ Array<[String, Integer]>
- word, line_no
-
のペア配列.
-
.warn_unclosed_disable(path, opened_at) ⇒ Object
vs-lint-disable が閉じられないままファイル末尾に達した場合に警告を出す。 著者が誤って enable を書き忘れたケースを検知するためのガード。.
Class Method Details
.build_excluded_lines(content) ⇒ Array(Set<Integer>, Integer?)
vs-lint コメントに基づいて除外すべき行番号のセットを構築する
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/vivlio/starter/cli/lint/tokenizer.rb', line 69 def build_excluded_lines(content) excluded_lines = Set.new disable_opened_at = nil line_no = 0 content.each_line do |line| line_no += 1 # vs-lint-disable コメント行自体を除外 if line.match?(VS_LINT_DISABLE) disable_opened_at ||= line_no excluded_lines.add(line_no) next end # vs-lint-enable コメント行自体を除外 if line.match?(VS_LINT_ENABLE) disable_opened_at = nil excluded_lines.add(line_no) next end # vs-lint-disable-next-line コメント行自体を除外し、次の行も除外 if line.match?(VS_LINT_DISABLE_NEXT_LINE) excluded_lines.add(line_no) excluded_lines.add(line_no + 1) next end # disable ブロック内の行を除外 excluded_lines.add(line_no) if disable_opened_at end [excluded_lines, disable_opened_at] end |
.extract_words(line) ⇒ Array<String>
Returns 抽出された英単語の配列.
117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/vivlio/starter/cli/lint/tokenizer.rb', line 117 def extract_words(line) cleaned = line.dup cleaned.gsub!(/`[^`]*`/, ' ') # インラインコードを除去 cleaned.gsub!(/<[^>]+>/, ' ') # HTMLタグを除去 cleaned.gsub!(/\{[^}]*\}/, ' ') # Vivliostyle拡張記法 {.aki} 等 cleaned.gsub!(/!?\[([^\]]*)\]\([^)]*\)/, '\1') # Markdownリンク・画像 cleaned.gsub!(/!?\[([^\]]*)\]\[[^\]]*\]/, '\1') # 参照リンク cleaned.gsub!(%r{https?://\S+}, ' ') # URLを除去 cleaned.gsub!(/^#+\s*/, '') # 見出し記号を除去 cleaned.scan(/[a-zA-Z]+(?:-[a-zA-Z]+)*/).select { it.length >= 2 } end |
.tokenize(content, check_code_blocks: false, path: nil) ⇒ Array<[String, Integer]>
Returns [word, line_no] のペア配列.
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/vivlio/starter/cli/lint/tokenizer.rb', line 23 def tokenize(content, check_code_blocks: false, path: nil) tokens = [] in_code_fence = false in_frontmatter = false line_no = 0 # vs-lint コメントによる除外行番号セットを構築 excluded_lines, unclosed_disable_at = build_excluded_lines(content) warn_unclosed_disable(path, unclosed_disable_at) if unclosed_disable_at content.each_line do |line| line_no += 1 # YAMLフロントマター(先頭 --- 〜 --- )をスキップ if line_no == 1 && line.match?(FRONTMATTER_SEP) in_frontmatter = true next end if in_frontmatter in_frontmatter = false if line.match?(FRONTMATTER_SEP) next end # コードフェンスのトグル if line.match?(FENCE_PATTERN) in_code_fence = !in_code_fence next end # コードブロック内のスキップ next if in_code_fence && !check_code_blocks # vs-lint コメントによる除外 next if excluded_lines.include?(line_no) extract_words(line).each { |word| tokens << [word, line_no] } end tokens end |
.warn_unclosed_disable(path, opened_at) ⇒ Object
vs-lint-disable が閉じられないままファイル末尾に達した場合に警告を出す。著者が誤って enable を書き忘れたケースを検知するためのガード。
109 110 111 112 113 |
# File 'lib/vivlio/starter/cli/lint/tokenizer.rb', line 109 def warn_unclosed_disable(path, opened_at) location = path ? "#{path}:#{opened_at}" : "line #{opened_at}" warn "[vs-lint] 警告: #{location} の <!-- vs-lint-disable --> が " \ '<!-- vs-lint-enable --> で閉じられていません。ファイル末尾まで lint が無効化されます。' end |