require 'nokogiri' require 'htmlbeautifier' module Stylish module Importers class StartupFrameworkImporter < Stylish::Theme::Importer ImagePathConversions = { '../../common-files/img/' => 'startup-framework/', '../../common-files/icons/' => 'startup-framework/icons/', /.*common-files\/img\// => 'startup-framework/', /.*common-files\/icons\// => 'startup-framework/icons/' } StylesheetReplacements = { } AllScripts = %w( modernizr.custom jquery-2.0.3.min jquery.ui.touch-punch.min bootstrap.min bootstrap-select bootstrap-switch jquery.tagsinput flatui-checkbox flatui-radio easing.min froogaloop.min jquery.backgroundvideo.min jquery.bxslider.min jquery.parallax.min jquery.placeholder jquery.scrollTo-1.4.3.1-min jquery.sharrre.min jquery-svg jquery-svganim masonry.pkgd.min page-transitions typeahead ) def name "startup-framework" end def logger @logger ||= ::Logger.new(STDOUT) end def map_source_paths # the importer will be created with a pointer to the source folder # distribution of the startup framework. We want the Developer folder # to be considered our source. if source.basename != 'Developer' && source.join('Developer').exist? self.source = source.join('Developer') end define_path :samples_path, source.join('samples') define_path :components_path, source.join('ui-kit') define_path :default_layout_path, samples_path.join('template','template-less.html') folders = components_path.children.reduce({}) do |memo, folder| key = folder.basename.to_s.gsub(/ui-kit-/,'').pluralize.capitalize memo[key] = folder.expand_path memo end set :component_folders, folders set :default_layout_fragment, Nokogiri::HTML(default_layout_path.read) set :stylesheet_dependencies_path, stylesheets_output_path.join('dependencies') set :javascript_dependencies_path, javascripts_output_path.join('dependencies') export :component_categories, folders.keys end def move_common_javascript_dependencies_into_global_theme info "== Moving JS dependencies into place" paths = Dir[source.join("common-files/js/**/*.js")].reject do |path| path.match(/startup-kit|jquery-ui-|jquery-1/) end paths += Dir[source.join('flat-ui/js/**/*.js')].reject do |path| path.match(/html5shiv|icon-font-ie7|application|respond|jquery-1|jquery-ui-1/) end paths.each do |path| info " - copying #{ File.basename(path) }" filename = File.basename(path).to_s filename.gsub! 'jquery.svg', 'jquery-svg' FileUtils.cp(path, javascript_dependencies_path.join(filename)) end info "== Adding dependency paths" self.dependency_paths << javascript_dependencies_path self.dependency_paths << javascript_dependencies_path.parent javascript_dependencies_path.join("all.js").open("w+") do |fh| content = AllScripts.map {|script| "//= require #{script}" }.join("\n") fh.write(content) end end def move_common_stylesheet_dependencies_into_global_theme paths = Dir[source.join('common-files/less/**/*.less')].reject do |path| path.match(/startup-kit_header|gallery/) end FileUtils.mkdir_p stylesheet_dependencies_path.join('startup-framework') info "== Adding import path: #{ stylesheet_dependencies_path.join('startup-framework') }" self.import_paths << stylesheet_dependencies_path self.import_paths << stylesheet_dependencies_path.parent info "== Coppying Common CSS" paths.each do |path| info " - copying #{ File.basename(path) }" FileUtils.cp(path, stylesheet_dependencies_path.join('startup-framework',File.basename(path))) end unless options[:skip_flat_ui] info "== Importing Flat-UI Stylesheets" FileUtils.cp_r source.join('flat-ui','less'), stylesheet_dependencies_path.join('flat-ui') FileUtils.cp source.join('flat-ui','bootstrap','css', 'bootstrap.css'), stylesheet_dependencies_path.join('flat-ui-bootstrap.css') info "== Adding import path: #{ stylesheet_dependencies_path.join('flat-ui') }" end self.dependency_paths.push stylesheet_dependencies_path self.dependency_paths.push stylesheet_dependencies_path.parent copy_fonts copy_images end def copy_fonts info "== Copying Fonts" paths = Dir[source.join('flat-ui','fonts/**/*.*')] + Dir[source.join('flat-ui','bootstrap/fonts/glyphicons-*.*')] + Dir[source.join('common-files','fonts','**/*.*')] paths.each do |path| FileUtils.cp(path, fonts_output_path) end self.dependency_paths.push(fonts_output_path.parent) end def copy_images info "== Copying Images" FileUtils.cp_r source.join('common-files','icons'), images_output_path source.join('common-files','img').children.each do |child| info " - copying #{ File.basename(child) }" FileUtils.cp_r(child, images_output_path) end self.dependency_paths.push images_output_path.parent end def info(msg) logger.info(msg) end def extract_component_markup_from path, group_name path = Pathname(path) contents = path.read fragment = Nokogiri::HTML(contents) markers = find_component_markers_in_file(path) do |marker| marker.include?(group_name.downcase) || marker.include?(group_name.downcase.singularize) end markers.map do |marker| markup = fragment.css(".#{marker}, .#{marker}-sub").to_html.to_s.gsub(/\r\n\s+/,'') markup = HtmlBeautifier.beautify(markup) ["#{marker}.html", markup] end end def extract_component_markup info "== Extracting component markup" component_folders.each do |folder_name, path| component_output_base = components_output_path.join(folder_name.to_s.downcase.parameterize) ['index.html','index2.html'].each do |html_file| html_file = path.join(html_file) next unless html_file.exist? extracted = extract_component_markup_from(html_file, folder_name) info "== Extracting from #{ html_file }: #{ extracted.length }" extracted.each do |item| marker, markup = item info " -- Extracted: #{ marker }" component_output_base.join(marker).open("w+") {|fh| fh.write(markup) } end end end end def extract_component_dependency_stylesheets component_folders.each do |folder_name, path| base = stylesheets_output_path.join(folder_name.to_s.downcase.parameterize) files = Dir[path.join('less/**/*.less')].reject {|file| file.match(/styles?\.less/) } files.each {|f| FileUtils.cp(f, base.join(File.basename(f))) } end end # @private pulls out the per component javascript and associated it properly # # @note here we go through and extract the namespaced javascript functions # that may or may not be defined on a per component basis def extract_component_dependency_javascripts end def find_component_markers_in_file path_to_file, &filter lines = Pathname(path_to_file).read.to_s.lines.map(&:strip) marker_lines = lines.grep(/\<\!\-\-\s?.*\s?\-\-\>/) marker_lines.select!(&filter) if block_given? marker_lines.map do |line| line.match(/--(.*)--/)[1].to_s.strip end end end end end # The Startup Framework Importer is responsible for taking the # startup framework distribution, as it is divided up, and move # the dependencies to a more asset pipeline friendly organization. # # We will also decompose the sample templates, into the Stylish organizational # model of themes, layouts, and categorized components. # # In practice for the CSS this means: # # startup base path has the flat ui dependency, and the common files # # then there are common files to each ui-kit category (blog, price, project) # # and then specific css files for each component in the ui-kit category # # For the javascript it means # # loop through the index html files for each of the ui kit folders # # find all of the dependencies that get loaded before startup-kit.js # # generate a generic dependencies manifest file # # parse the startup-kit.js file and separate the namespaced functions # for each startupKit.uiKitContent functions and associate them with the components