make pdf links clickable
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Templates
|
||||
module BuildAnnotations
|
||||
module_function
|
||||
|
||||
def call(data)
|
||||
pdf = PDF::Reader.new(StringIO.new(data))
|
||||
|
||||
pdf.pages.flat_map.with_index do |page, index|
|
||||
annotations = page.objects.deref!(page.attributes[:Annots]) || []
|
||||
annotations.filter_map do |annot|
|
||||
next if annot[:A].blank? || annot[:A][:URI].blank?
|
||||
next unless annot[:Subtype] == :Link
|
||||
next if !annot[:A][:URI].starts_with?('https://') && !annot[:A][:URI].starts_with?('http://')
|
||||
|
||||
build_external_link_hash(page, annot).merge('page' => index)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def build_external_link_hash(page, annot)
|
||||
left, bottom, right, top = annot[:Rect]
|
||||
|
||||
{
|
||||
'type' => 'external_link',
|
||||
'value' => annot[:A][:URI],
|
||||
'x' => left / page.width,
|
||||
'y' => (page.height - top) / page.height,
|
||||
'w' => (right - left) / page.width,
|
||||
'h' => (top - bottom) / page.height
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,47 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Templates
|
||||
module CreateAttachments
|
||||
PDF_CONTENT_TYPE = 'application/pdf'
|
||||
|
||||
module_function
|
||||
|
||||
def call(template, params)
|
||||
find_or_create_blobs(params).map do |blob|
|
||||
document = template.documents.create!(blob:)
|
||||
|
||||
document_data = blob.download
|
||||
|
||||
if blob.content_type == PDF_CONTENT_TYPE && blob.metadata['pdf'].nil?
|
||||
blob.metadata['pdf'] = { 'annotations' => Templates::BuildAnnotations.call(document_data) }
|
||||
end
|
||||
|
||||
blob.save!
|
||||
|
||||
Templates::ProcessDocument.call(document, document_data)
|
||||
end
|
||||
end
|
||||
|
||||
def find_or_create_blobs(params)
|
||||
blobs = params[:blobs]&.map do |attrs|
|
||||
ActiveStorage::Blob.find_signed(attrs[:signed_id])
|
||||
end
|
||||
|
||||
blobs || params[:files].map do |file|
|
||||
data = file.read
|
||||
|
||||
if file.content_type == PDF_CONTENT_TYPE
|
||||
metadata = { 'identified' => true, 'analyzed' => true,
|
||||
'pdf' => { 'annotations' => Templates::BuildAnnotations.call(data) } }
|
||||
end
|
||||
|
||||
ActiveStorage::Blob.create_and_upload!(
|
||||
io: StringIO.new(data),
|
||||
filename: file.original_filename,
|
||||
metadata:,
|
||||
content_type: file.content_type
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -12,22 +12,20 @@ module Templates
|
||||
|
||||
module_function
|
||||
|
||||
def call(attachment)
|
||||
def call(attachment, data)
|
||||
if attachment.content_type == PDF_CONTENT_TYPE
|
||||
generate_pdf_preview_images(attachment)
|
||||
generate_pdf_preview_images(attachment, data)
|
||||
elsif attachment.image?
|
||||
generate_preview_image(attachment)
|
||||
generate_preview_image(attachment, data)
|
||||
end
|
||||
|
||||
attachment
|
||||
end
|
||||
|
||||
def generate_preview_image(attachment)
|
||||
binary = attachment.download
|
||||
|
||||
def generate_preview_image(attachment, data)
|
||||
ActiveStorage::Attachment.where(name: ATTACHMENT_NAME, record: attachment).destroy_all
|
||||
|
||||
image = Vips::Image.new_from_buffer(binary, '')
|
||||
image = Vips::Image.new_from_buffer(data, '')
|
||||
image = image.autorot.resize(MAX_WIDTH / image.width.to_f)
|
||||
|
||||
io = StringIO.new(image.write_to_buffer(FORMAT, Q: Q, interlace: true))
|
||||
@@ -42,14 +40,12 @@ module Templates
|
||||
)
|
||||
end
|
||||
|
||||
def generate_pdf_preview_images(attachment)
|
||||
binary = attachment.download
|
||||
|
||||
def generate_pdf_preview_images(attachment, data)
|
||||
ActiveStorage::Attachment.where(name: ATTACHMENT_NAME, record: attachment).destroy_all
|
||||
number_of_pages = HexaPDF::Document.new(io: StringIO.new(binary)).pages.size - 1
|
||||
number_of_pages = PDF::Reader.new(StringIO.new(data)).pages.size - 1
|
||||
|
||||
(0..number_of_pages).each do |page_number|
|
||||
page = Vips::Image.new_from_buffer(binary, '', dpi: DPI, page: page_number)
|
||||
page = Vips::Image.new_from_buffer(data, '', dpi: DPI, page: page_number)
|
||||
page = page.resize(MAX_WIDTH / page.width.to_f)
|
||||
|
||||
io = StringIO.new(page.write_to_buffer(FORMAT, Q: Q, interlace: true))
|
||||
|
||||
Reference in New Issue
Block a user