Module: Kotoshu::Documents
- Defined in:
- lib/kotoshu/documents.rb,
lib/kotoshu/documents/document.rb,
lib/kotoshu/documents/text_node.rb,
lib/kotoshu/documents/source_range.rb,
lib/kotoshu/documents/source_position.rb,
lib/kotoshu/documents/plain_text_document.rb
Overview
Document model for structure-aware spell and grammar checking.
The Document abstraction pairs the flattened text a checker scans
with the source positions of each text run, so that errors can be
reported against the original markup-bearing source rather than the
stripped text. The canonical example is an AsciiDoc or Markdown
sentence like I'm an **friend** of Tom: the checker sees the
flattened I'm an friend of Tom and flags "an friend", but the
error report needs to point at the original an **friend** range
so an editor can highlight what the user actually wrote.
Kotoshu ships only the value-object layer and a trivial
PlainTextDocument. Format-specific parsers (Markdown, AsciiDoc,
reStructuredText, etc.) live in plugins — kotoshu never owns
document parsing (see the kotoshu-document-plugin-boundary design
memory). Plugins register a parser class via Documents.register
and produce Document instances whose TextNodes carry proper
SourceRanges.
Defined Under Namespace
Classes: Document, PlainTextDocument, SourcePosition, SourceRange, TextNode
Class Method Summary collapse
-
.discovered_formats ⇒ Array<Symbol>
List every format symbol that came from an auto-discovered plugin (vs. one registered explicitly at runtime).
-
.discovered_plugin_files ⇒ Array<String>
List every plugin file found on the load path via
Gem.find_files("kotoshu_plugin/document/*.rb"). -
.parse(source, format:, language_code: nil) ⇒ Document
Parse a source string with the registered parser for
format, falling back to PlainTextDocument when no parser is registered. -
.parser_for(format) ⇒ Class?
Look up the registered parser for a format.
-
.register(format, parser_class) ⇒ void
Register a document parser for a format symbol.
-
.registered_formats ⇒ Array<Symbol>
List every registered format symbol.
-
.reset! ⇒ void
Clear every registration.
Class Method Details
.discovered_formats ⇒ Array<Symbol>
List every format symbol that came from an auto-discovered plugin (vs. one registered explicitly at runtime). Useful for diagnostics and "which plugin registered this format?" UX.
137 138 139 140 |
# File 'lib/kotoshu/documents.rb', line 137 def discovered_formats ensure_plugins_discovered! @discovered_formats.dup.freeze end |
.discovered_plugin_files ⇒ Array<String>
List every plugin file found on the load path via
Gem.find_files("kotoshu_plugin/document/*.rb"). Each such
file, when required, is expected to call register for the
formats it provides. The list is the raw file paths; not
loaded into the registry yet.
128 129 130 |
# File 'lib/kotoshu/documents.rb', line 128 def discovered_plugin_files Gem.find_files("kotoshu_plugin/document/*.rb").sort end |
.parse(source, format:, language_code: nil) ⇒ Document
Parse a source string with the registered parser for format,
falling back to PlainTextDocument when no parser is
registered. Never raises — the fallback is intentional so
callers can pass arbitrary format hints without first checking
the registry.
115 116 117 118 119 |
# File 'lib/kotoshu/documents.rb', line 115 def parse(source, format:, language_code: nil) ensure_plugins_discovered! parser = parser_for(format) || PlainTextDocument parser.from_string(source, language_code: language_code) end |
.parser_for(format) ⇒ Class?
Look up the registered parser for a format.
92 93 94 95 |
# File 'lib/kotoshu/documents.rb', line 92 def parser_for(format) ensure_plugins_discovered! @parsers[format.to_sym] end |
.register(format, parser_class) ⇒ void
This method returns an undefined value.
Register a document parser for a format symbol.
The parser class must respond to:
.from_string(text, language_code:) -> Documents::Document
Optionally also:
.from_file(path, language_code:) -> Documents::Document
Parser contract ====
The returned Document's text_nodes must each carry a
SourceRange that points at the original
markup-bearing source for that node. This is the structure-aware
contract — the analyzer reads the document's flattened text
to run spelling/grammar checks, but every error is reported
against the original source so an editor or plugin can
highlight the user's actual markup, not the stripped text.
Example: for the source
"I'm an **friend** of Tom"
the parser produces TextNodes whose SourceRanges cover the original range, not the flattened "I'm an friend of Tom". A grammar error "an friend" → "a friend" then carries a SourceRange pointing at "an friend" (the bold span plus the preceding "an ").
Format symbol ====
format is the canonical symbol callers pass to parse. The
gem ships :plain (via PlainTextDocument). Plugins
commonly add :markdown, :asciidoc, :rst, :latex, etc.
Format symbols are global — two plugins registering the same
symbol is a name clash; the last one wins.
Discovery ====
Plugins ship a file under kotoshu_plugin/document/*.rb in
their gem. The first lookup of parser_for / parse walks
Gem.find_files for those files and requires each one. Each
file's body is expected to call register for the formats
it provides. See discovered_plugin_files and
discovered_formats.
84 85 86 |
# File 'lib/kotoshu/documents.rb', line 84 def register(format, parser_class) @parsers[format.to_sym] = parser_class end |
.registered_formats ⇒ Array<Symbol>
List every registered format symbol.
100 101 102 103 |
# File 'lib/kotoshu/documents.rb', line 100 def registered_formats ensure_plugins_discovered! @parsers.keys end |
.reset! ⇒ void
This method returns an undefined value.
Clear every registration. Test-only — production code should register once at load time. Also resets the discovery flag so the next lookup re-runs Gem.find_files.
147 148 149 150 151 |
# File 'lib/kotoshu/documents.rb', line 147 def reset! @parsers.clear @discovered_formats.clear @discovered_plugins_loaded = false end |