Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Liquid Markup
Search
Jon Daniel
October 04, 2012
Programming
1
190
Liquid Markup
Talk I gave October 4, 2012 at Pittsburgh Ruby Brigade.
Jon Daniel
October 04, 2012
Tweet
Share
More Decks by Jon Daniel
See All by Jon Daniel
Growth and Mentorship: Working with Junior Developers
binarycleric
0
69
Smart Software Design (SOA Edition)
binarycleric
0
150
Ethical and Sustainable On-Call
binarycleric
6
2.5k
Other Decks in Programming
See All in Programming
抽象化という思考のツール - 理解と活用 - / Abstraction-as-a-Tool-for-Thinking
shin1x1
1
930
副作用と戦う PHP リファクタリング ─ ドメインイベントでビジネスロジックを解きほぐす
kajitack
3
520
Jakarta EE Meets AI
ivargrimstad
0
570
MCP連携で加速するAI駆動開発/mcp integration accelerates ai-driven-development
bpstudy
0
250
AWS Summit Japan 2024と2025の比較/はじめてのKiro、今あなたは岐路に立つ
satoshi256kbyte
1
260
SwiftでMCPサーバーを作ろう!
giginet
PRO
2
220
Claude Code で Astro blog を Pages から Workers へ移行してみた
codehex
0
170
#QiitaBash TDDで(自分の)開発がどう変わったか
ryosukedtomita
1
350
Bedrock AgentCore ObservabilityによるAIエージェントの運用
licux
8
560
CLI ツールを Go ライブラリ として再実装する理由 / Why reimplement a CLI tool as a Go library
ktr_0731
3
950
Comparing decimals in Swift Testing
417_72ki
0
160
テスターからテストエンジニアへ ~新米テストエンジニアが歩んだ9ヶ月振り返り~
non0113
2
250
Featured
See All Featured
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
251
21k
Principles of Awesome APIs and How to Build Them.
keavy
126
17k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
8
420
Facilitating Awesome Meetings
lara
54
6.5k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
46
7.5k
The Power of CSS Pseudo Elements
geoffreycrofte
77
5.9k
The World Runs on Bad Software
bkeepers
PRO
70
11k
Imperfection Machines: The Place of Print at Facebook
scottboms
267
13k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
667
120k
GraphQLの誤解/rethinking-graphql
sonatard
71
11k
Documentation Writing (for coders)
carmenintech
73
5k
Typedesign – Prime Four
hannesfritz
42
2.7k
Transcript
Liquid Markup
Jon Daniel @binarycleric github.com/binarycleric
Obligatory Promotion We’re Hiring Smart People. Ruby experience NOT required.
What Is Liquid?
None
github.com/Shopify/liquid
lets clients design their own sites...
safely and securely
logic and variable manipulation
None
yay!
None
$ gem install liquid require 'liquid'
markup = "Hello, {{ thing }}!" t = Liquid::Template.parse(markup) t.render("thing"
=> "world")
Hello, world!
markup = "Welcome, {{ user.name }}" user = User.find(1337) t
= Liquid::Template.parse(markup) t.render('user' => user)
Welcome, !
Liquid Has Trust Issues
Deny By Default
class Person < ActiveRecord::Base end # denied! "{{ person.name }}"
=> "" class Person < ActiveRecord::Base liquid_methods :name end # okay! "{{ person.name }}" => "Cmdr Shepard"
markup = "Welcome, {{ user.name }}" user = User.find(1337) t
= Liquid::Template.parse(markup) t.render('user' => user)
Welcome, Jon ‘maddog’ Hall! * If you don’t know who
he is, check Wikipedia.
Live Free Or Die.
Actually Rendering Templates
# load the user from somewhere. t = Liquid::Template.parse(markup) t.render("user"
=> user)
t = Liquid::Template.parse(markup) context = Liquid::Context.new(*args) t.render(context)
The Magic Context
Liquid::Context.new local_assigns, global_assigns, registers
Liquid::Context.new local_assigns, global_assigns, registers
registers[:domain] = domain registers[:whatever] = whatever registers[:your] = your registers[:app]
= app registers[:needs] = needs registers[:file_system] = FileSystem.new
registers[:domain] = domain registers[:whatever] = whatever registers[:your] = your registers[:app]
= app registers[:needs] = needs registers[:file_system] = FileSystem.new
Some Liquid Syntax
class FileSystem def initialize(*args) # whatever end def read_template_file(name, context)
# fetches partials from wherever end end {% include 'some-partial' %}
# a block {% if liquid == 'awesome' %} You
should try Liquid! {% endif %} # a tag {% assign liquid = 'awesome' %}
class ExampleTag < Liquid::Tag def initialize(name, markup, tokens) # setup
the tag, parse stuff, ya know... # expensive stuff. end def render(context) # drop in the assigns and go! # should be cheap. end end
class ExampleTag < Liquid::Tag def initialize(name, markup, tokens) # setup
the tag, parse stuff, ya know... # expensive stuff. end def render(context) # drop in the assigns and go! # should be cheap. end end
class PersonDrop < Liquid::Drop def addresses # stupid slow operation
Address::find_by_person(@person) end end {{ user.addresses }}
{{ “hello world” | capitalize }} # shamelessly stolen from
# liquid's source. use your # imagination people! def capitalize(input) input.to_s.capitalize end
Liquid Philosophies
•assume hostile environment •white list what you need •deny everything
else
•can edit markup •is probably non-technical Assume the client
•ignore errors by default •don’t let the client break too
much
It May Not Be For You
•partial branding •full white-label •per-install customization
Views As Data
Contribute!
Questions?