Skip to content

Instantly share code, notes, and snippets.

@okonet
Created August 28, 2012 09:50
Show Gist options
  • Save okonet/3496682 to your computer and use it in GitHub Desktop.
Save okonet/3496682 to your computer and use it in GitHub Desktop.
SVG post-processing
fs = require 'fs'
path = require 'path'
ensureDir = require 'ensureDir'
jsdom = require 'jsdom'
phantom = require 'phantom'
{exec} = require 'child_process'
# ANSI Terminal Colors.
# bold = '\033[0;1m'
# red = '\033[0;31m'
# green = '\033[0;32m'
# reset = '\033[0m'
task 'process', 'Pre-process SVG files to work with JavaScript configurator', (options) ->
unless process.env.APP?
return console.error "Make sure to set APP before running 'cake process'."
else
app_name = process.env.APP
src_path = "#{__dirname}/src/avatars/#{app_name}/"
target_path = "#{__dirname}/public/avatars/#{app_name}/"
# Get all SVG sources
fs.readdir src_path, (err, files) ->
throw err if err
files.forEach (file) ->
return unless file.match(/\.svg$/i)
# Read and process each file
fs.readFile src_path + file, (err, data) ->
throw err if err
content = data.toString()
plugins = [
'http://code.jquery.com/jquery-1.5.min.js'
]
jsdom.env content, plugins, (errors, window) ->
throw errors if errors
# Scope
$ = window.$
# Each avatar section becomes an appropriate class name for better DOM traversing
for section in ['front', 'back', 'body', 'head','torso', 'arms', 'headshapes', 'hair', 'brows', 'eyes', 'noses', 'mouths', 'shirt', 'trousers', 'extras', 'fill', 'outline']
$('*[id^="' + section + '"]').addClass section
# console.log "Processed #{section}"
# For every element with "selection[1...n]" and "dependentSelection[1...n]" add an appropriate class name
for section in ['selection', 'dependentSelection']
$('*[id^="' + section + '"]').each (idx, el) ->
class_name = $(el).attr("id").split("_")[0]
$(el).addClass("#{section} #{class_name}").attr("style", "visibility:hidden")
# Produce speedy selectors.
# Speedy selectors are used to speedup coloring parts of avatar.
# So each group of sections gets unique class name which is used to apply color from picker.
# This improved $ performance dramatically (x200 times)
speedySelectors = body: ['torso', 'arms', 'headshapes'], hair: ['hair'], brows: ['brows'], shirt: ['shirt'], trousers: ['trousers'], eyes: ['eyes'], extras: ['extras']
for type in ["fill", "outline"]
for group, sections of speedySelectors
selectors = for section in sections
".#{section} .#{type}, .#{section} .#{type} path"
selectors.join(",")
for selector in selectors
$(selector).addClass(group + "_" + type)
# console.log "Processed #{selector} in #{group}_#{type}"
# Cleaning SVG up by removing unused attributes to reduce file size.
for attr in ['fill-rule', 'clip-rule', 'stroke-linecap', 'stroke-miterlimit']
$("[#{attr}]").removeAttr(attr)
$("[id]:not([id^=SVGID])").removeAttr('id')
data = $('body').html()
# For some reason the pre-processor converts camelcased svg tags to lowercase which is wrong. Work around it.
data = data.replace("viewbox", "viewBox")
data = data.replace(/lineargradient/g, "linearGradient")
data = data.replace(/radialgradient/g, "radialGradient")
data = data.replace(/gradientunits/g, "gradientUnits")
data = data.replace(/gradienttransform/g, "gradientTransform")
enhgsureDir target_path, 0o0755, (err) ->
throw err if err
fs.writeFile "#{target_path}#{file}", data, (err) ->
throw err if err
console.log "Processed: #{file}";
# Generate thumbnails
phantom.create (ph) ->
ph.createPage (page) ->
width = 240
height = 360
page.set "clipRect", { top: 10, left: 10, width: width, height: height }
html = data.replace("250px", "#{width}px").replace("550px", "#{height}px")
page.set('content', html)
page.includeJs plugins[0], () ->
page.evaluate ->
$(".selection, .dependentSelection").attr("style", "visibility:hidden")
$(".selection1, .dependentSelection1").attr("style", "")
$(".extras .selection, .extras .dependentSelection").attr("style", "visibility:hidden") # Hide all extras
page.render "#{target_path}#{file}.png", () ->
console.log "Generated screenshot for #{target_path}#{file}.png"
ph.exit()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment