class DocRipper::Formats::SketchRipper

Public Class Methods

new(file_path) click to toggle source
Calls superclass method DocRipper::Ripper::Base::new
# File lib/doc_ripper/formats/sketch_ripper.rb, line 49
def initialize(file_path)
  raise Sqlite3NotFound if !defined?(SQLite3)
  super
end

Public Instance Methods

blacklist() click to toggle source
# File lib/doc_ripper/formats/sketch_ripper.rb, line 60
def blacklist
  %w(\$null MSAttributedStringFontAttribute NSColor NSParagraphStyle)
end
rip() click to toggle source
# File lib/doc_ripper/formats/sketch_ripper.rb, line 54
def rip
  db = SQLite3::Database.new(file_path)
  data = db.execute("SELECT value FROM payload").flatten.first
  @text ||= text_objects(data).join(" ").strip
end
text_objects(data) click to toggle source
# File lib/doc_ripper/formats/sketch_ripper.rb, line 64
def text_objects(data)
  objects = CFPropertyList::List.new(data: data).value.value['$objects'].value

  evaluator = Proc.new do |object, previous_object, n_2_previous_object, next_object|
    coordinatesRegex = /\{\{\d*, \d*}, \{\d*, \d*\}\}|\{[\d.e-]*, [\d.]*\}/

    object.is_a?(CFPropertyList::CFString) &&
      #ignore other blacklisted properties
      blacklist.select { |bl| object.value.match(/#{bl}/) }.empty? &&
      #ignore uuids
      !object.value.match(/\w{8}-\w{4}-\w{4}-\w{4}-\w{12}/) &&
      #ignore coordinates
      !object.value.match(coordinatesRegex) &&
      #ignore font definitions
      previous_object.value != "NSFontNameAttribute" &&
      # labels always have an dictionary defined afterwards
      next_object.is_a?(CFPropertyList::CFDictionary) &&
      # Check if the string is defining the name of an artboard or font
      !(previous_object.respond_to?(:blacklisted_class?) && previous_object.blacklisted_class?) &&
      !(n_2_previous_object.respond_to?(:blacklisted_class?) && n_2_previous_object.blacklisted_class?)
    end

  objects.select.with_index do |object,i|
    next_object = objects[i+1]
    previous_object = objects[i-1]
    n_2_previous_object = objects[i-2]

    evaluator.call(object, previous_object, n_2_previous_object, next_object)
  end
end