Class: Jekyll::Documents::TextExtractionManifest
- Inherits:
-
Object
- Object
- Jekyll::Documents::TextExtractionManifest
- Defined in:
- lib/jekyll/documents/text_extraction_manifest.rb
Overview
Manages the text extraction manifest — a persistent JSON file that tracks which documents have had their text extracted, keyed by SHA-256 digest.
The manifest lives in <site.source>/<cache_dir>/text-extraction-manifest.json and extracted text is stored in separate files under <cache_dir>/text/ (sharded by the first 2 hex chars of the digest to avoid huge directories).
This design borrows from jekyll-imgflow's ManifestManager:
- Atomic writes (temp file + rename)
- SHA-256 content digests for cache invalidation
- Cleanup of entries for deleted source files
- Survives
jekyll clean(stored in site source, not .jekyll-cache/)
Constant Summary collapse
- MANIFEST_FILENAME =
"text-extraction-manifest.json"- TEXT_SUBDIR =
"text"
Instance Attribute Summary collapse
-
#cache_dir ⇒ Object
readonly
Returns the value of attribute cache_dir.
-
#manifest_path ⇒ Object
readonly
Returns the value of attribute manifest_path.
Instance Method Summary collapse
-
#cached?(rel_path, digest) ⇒ Boolean
Check if a document is in the manifest with a matching digest.
-
#cleanup_deleted(current_rel_paths) ⇒ Integer
Remove manifest entries and their text files for source documents that no longer exist.
-
#get(rel_path, digest) ⇒ String?
Get cached text for a document if the digest matches.
-
#initialize(site, cache_dir) ⇒ TextExtractionManifest
constructor
A new instance of TextExtractionManifest.
-
#save ⇒ void
Save the manifest to disk if it has changed.
-
#set(rel_path, digest, text) ⇒ void
Store extracted text for a document.
-
#size ⇒ Integer
Number of entries in the manifest.
Constructor Details
#initialize(site, cache_dir) ⇒ TextExtractionManifest
Returns a new instance of TextExtractionManifest.
29 30 31 32 33 34 35 36 37 |
# File 'lib/jekyll/documents/text_extraction_manifest.rb', line 29 def initialize(site, cache_dir) @site = site @cache_dir = cache_dir @cache_root = File.join(site.source, cache_dir) @manifest_path = File.join(@cache_root, MANIFEST_FILENAME) @text_dir = File.join(@cache_root, TEXT_SUBDIR) @manifest = load_manifest @dirty = false end |
Instance Attribute Details
#cache_dir ⇒ Object (readonly)
Returns the value of attribute cache_dir.
25 26 27 |
# File 'lib/jekyll/documents/text_extraction_manifest.rb', line 25 def cache_dir @cache_dir end |
#manifest_path ⇒ Object (readonly)
Returns the value of attribute manifest_path.
25 26 27 |
# File 'lib/jekyll/documents/text_extraction_manifest.rb', line 25 def manifest_path @manifest_path end |
Instance Method Details
#cached?(rel_path, digest) ⇒ Boolean
Check if a document is in the manifest with a matching digest.
119 120 121 122 |
# File 'lib/jekyll/documents/text_extraction_manifest.rb', line 119 def cached?(rel_path, digest) entry = @manifest[rel_path] !!(entry && entry["digest"] == digest) end |
#cleanup_deleted(current_rel_paths) ⇒ Integer
Remove manifest entries and their text files for source documents that no longer exist.
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/jekyll/documents/text_extraction_manifest.rb', line 77 def cleanup_deleted(current_rel_paths) current_set = current_rel_paths.to_set removed = 0 @manifest.each_key do |rel_path| next if current_set.include?(rel_path) entry = @manifest[rel_path] delete_text_file(entry["text_file"]) if entry @manifest.delete(rel_path) removed += 1 @dirty = true end removed end |
#get(rel_path, digest) ⇒ String?
Get cached text for a document if the digest matches.
43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/jekyll/documents/text_extraction_manifest.rb', line 43 def get(rel_path, digest) entry = @manifest[rel_path] return nil unless entry return nil unless entry["digest"] == digest text_file = text_file_path(entry["text_file"]) return nil unless File.file?(text_file) File.read(text_file, encoding: "UTF-8") rescue StandardError => e ::Jekyll.logger.warn "jekyll-documents", "Manifest read failed for #{rel_path}: #{e.}" nil end |
#save ⇒ void
This method returns an undefined value.
Save the manifest to disk if it has changed. Uses atomic write (temp file + rename) to prevent corruption.
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/jekyll/documents/text_extraction_manifest.rb', line 97 def save return unless @dirty content = JSON.pretty_generate(@manifest) return if File.exist?(@manifest_path) && File.binread(@manifest_path) == content FileUtils.mkdir_p(@cache_root) temporary_path = "#{@manifest_path}.tmp-#{Process.pid}-#{Thread.current.object_id}" File.open(temporary_path, "wb") do |file| file.write(content) file.flush file.fsync end File.rename(temporary_path, @manifest_path) ensure FileUtils.rm_f(temporary_path) if defined?(temporary_path) && temporary_path end |
#set(rel_path, digest, text) ⇒ void
This method returns an undefined value.
Store extracted text for a document.
63 64 65 66 67 68 69 70 71 |
# File 'lib/jekyll/documents/text_extraction_manifest.rb', line 63 def set(rel_path, digest, text) text_file = write_text_file(digest, text) @manifest[rel_path] = { "digest" => digest, "text_file" => text_file, "extracted_at" => Time.now.to_i } @dirty = true end |
#size ⇒ Integer
Number of entries in the manifest.
126 127 128 |
# File 'lib/jekyll/documents/text_extraction_manifest.rb', line 126 def size @manifest.size end |