Class: Pdfrb::Conformance::VeraPdfBridge

Inherits:
Object
  • Object
show all
Defined in:
lib/pdfrb/conformance/verapdf_bridge.rb

Overview

Bridge to veraPDF for authoritative PDF/A validation. veraPDF is the official open-source PDF/A conformance checker.

If veraPDF is not installed, all methods return a Result with available: false. Install veraPDF from https://verapdf.org/.

Usage:

result = Pdfrb::Conformance::VeraPdfBridge.validate(pdf_bytes, profile: "1b")
result.passed?

Defined Under Namespace

Classes: Result, Violation

Class Method Summary collapse

Class Method Details

.available?Boolean

Returns:

  • (Boolean)


29
30
31
32
33
34
# File 'lib/pdfrb/conformance/verapdf_bridge.rb', line 29

def available?
  _, status = Open3.capture2e("verapdf --version")
  status.success?
rescue StandardError
  false
end

.dig_string_path(hash, path) ⇒ Object



75
76
77
78
79
80
81
82
# File 'lib/pdfrb/conformance/verapdf_bridge.rb', line 75

def dig_string_path(hash, path)
  path.reduce(hash) do |current, key|
    case current
    when ::Hash then current[key]
    when ::Array then key.is_a?(::Integer) ? current[key] : nil
    end
  end
end

.parse_violations(json_output) ⇒ Object



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/pdfrb/conformance/verapdf_bridge.rb', line 56

def parse_violations(json_output)
  return [] unless json_output && !json_output.empty?

  require "json"
  data = safe_parse(json_output)
  return [] unless data

  assertions = dig_string_path(data, ["report", "jobs", 0, "validationResult", "details", "assertions"])
  return [] unless assertions

  assertions.map do |a|
    Violation.new(
      rule_id: a["ruleId"],
      message: a["message"],
      spec_clause: a["clause"]
    )
  end
end

.safe_parse(json_output) ⇒ Object



84
85
86
87
88
# File 'lib/pdfrb/conformance/verapdf_bridge.rb', line 84

def safe_parse(json_output)
  JSON.parse(json_output)
rescue StandardError
  nil
end

.validate(pdf_bytes, profile: "2b") ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/pdfrb/conformance/verapdf_bridge.rb', line 36

def validate(pdf_bytes, profile: "2b")
  return Result.new(available: false) unless available?

  Tempfile.create(["pdfrb", ".pdf"], binmode: true) do |file|
    file.write(pdf_bytes)
    file.flush

    output, status = Open3.capture2e("verapdf --profile #{profile} --format json #{file.path}")

    Result.new(
      available: true,
      passed: status.success?,
      violations: parse_violations(output),
      raw_output: output
    )
  end
rescue StandardError => e
  Result.new(available: false, raw_output: e.message)
end