Last active
December 10, 2015 08:48
-
-
Save machty/4409814 to your computer and use it in GitHub Desktop.
Rake Pipeline filter for syncing already-published static content on production with the generated local file via Nokogiri and css selectors
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "rake-pipeline-web-filters" | |
require "./remote-replace-filter" | |
# specify output, other configuration | |
input "app" do | |
match "slim/whatever.slim" do | |
tilt { |input| input.sub(/\.slim$/, '.html') } | |
copy "index.html" | |
# If you don't want to perform the remote query while using | |
# `rakep server`, you can append "defined?(::Rake::Pipeline::Server)" | |
# to this line. | |
# NOTE: make sure this line comes after the last filter to change | |
# the output path (e.g. copy "index.html" from above) so that the filter | |
# can determine the remote location of the already published file. | |
remote_replace "http://www.yourstaticsite.com", ".content" | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "rake-pipeline" | |
require "rake-pipeline-web-filters" | |
require "pathname" | |
require 'net/http' | |
require 'uri' | |
# A filter that uses Nokogiri to replace input content | |
# with remote content. | |
# Use case: you deploy a static website that is maintained | |
# by someone editing HTML and pushing via FTP, and you need | |
# to make a change to non-content portion of the page. So that | |
# you don't overwrite the client-generated content, you can | |
# use this filter to specify the CSS selectors that will be | |
# copied from the remote server into your generated output. | |
class RemoteReplaceFilter < Rake::Pipeline::Filter | |
class MissingLocalContent < StandardError; end | |
include Rake::Pipeline::Web::Filters::FilterWithDependencies | |
# @param [String] host (required) a valid http address that'll | |
# be used in conjunction with the relative path | |
# of the input file to resolve the remote file | |
# | |
# selectors: CSS selectors | |
# @param [Proc] block the output name generator block | |
def initialize(host, *selectors, &block) | |
super(&block) | |
@host = Pathname.new host | |
raise ArgumentError, "at least one CSS selector required" if selectors.empty? || selectors.first.empty? | |
@selectors = selectors | |
end | |
# The body of the filter. Query the remote equivalent of | |
# each input file and swap out the local file's selected content | |
# with the remote file's selected conttent. | |
# | |
# @param [Array] inputs an Array of FileWrapper objects. | |
# @param [FileWrapper] output a FileWrapper object | |
def generate_output(inputs, output) | |
inputs.each do |input| | |
remote_url = @host.join(input.path).to_s | |
remote_doc = Nokogiri::HTML(Net::HTTP.get(URI.parse(remote_url))) | |
local_doc = Nokogiri::HTML(input.read) | |
# Replace content for each selector | |
@selectors.each do |sel| | |
remote_element = remote_doc.at_css(sel) | |
remote_content = remote_element ? remote_element.content : "Couldn't find remote content for selector: #{sel}" | |
local_element = local_doc.at_css(sel) | |
raise MissingLocalContent, "Couldn't find local element in #{input.path} via selector: #{sel}" unless local_element | |
local_element.content = remote_content | |
end | |
# Write the replaced HTML to output | |
output.write local_doc | |
end | |
end | |
def external_dependencies | |
[ "nokogiri" ] | |
end | |
end | |
# Add convenience function so that all you have to put in your | |
# Asset file is `remote_replace` vs filter(RemoteReplaceFilter)... | |
Rake::Pipeline::DSL::PipelineDSL.module_eval do | |
# Add a new {RemoteReplaceFilter} to the pipeline. | |
# @see RemoteReplaceFilter#initialize | |
def remote_replace(*args, &block) | |
filter(RemoteReplaceFilter, *args, &block) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment