# frozen_string_literal: true require_dependency 'scribo/application_service' require 'mime/types' require 'yaml' module Scribo class SiteImportService < ApplicationService attr_reader :path, :scribable, :properties_override IGNORED_FILES = [%r[^__MACOSX/], %r[/\.DS_Store], %r[^/_site], /^node_modules/].freeze def initialize(path, scribable: nil, properties: {}) super() @path = path @scribable = scribable @properties_override = properties end def perform Dir.mktmpdir do |dir| Dir.chdir(dir) do unzip(dir) all_files = Dir.glob('**/*') all_files = all_files.reject { |p| p == '_config.yml' } if properties_override.present? all_files.each do |name| parent = if File.dirname(name) == name nil else site.contents.located(File.dirname(name), restricted: false).first end content = parent.children.find_by(path: File.basename(name)) if parent content = site.contents.find_by(path: File.basename(name), parent_id: nil) if parent.nil? && content.nil? content = site.contents.create!(path: File.basename(name), parent: parent) if content.nil? if File.directory?(name) content.kind = 'folder' else File.open(name) do |f| content.kind = Scribo::Utility.kind_for_path(name) content.data_with_frontmatter = f.read end end content.save! end end end site.contents.create(path: '_config.yml', data: YAML.dump(site.properties)) if properties_override.present? site end private def unzip(dir) Zip::File.open(path) do |zipfile| zipfile.reject { |e| IGNORED_FILES.any? { |r| r.match(e.name) } }.each do |f| file_path = File.join(dir, f.name[base_path(zipfile).length..-1]) FileUtils.mkdir_p(File.dirname(file_path)) unless File.exist?(File.dirname(file_path)) f.extract(file_path) unless File.exist?(file_path) end end end def base_path(zipfile) return @base_path if @base_path base_paths = zipfile.reject { |e| IGNORED_FILES.any? { |r| r.match(e.name) } } .map { |f| f.name.split('/').first }.uniq @base_path = base_paths.size == 1 ? base_paths.first : '' end def site return @site if @site @site = Site.where(scribable: scribable) %w[host title baseurl].each do |property| if properties[property].nil? @site = @site.where("properties->>'#{property}' IS NULL") else @site = @site.where("properties->>'#{property}' = ?", properties[property]) end end @site = @site.first @site ||= Site.create!(scribable: scribable, properties: properties.merge(properties_override)) end def properties @properties = Scribo::Utility.yaml_safe_parse(File.read('_config.yml')) if File.exist?('_config.yml') @properties ||= {} end end end