Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Liquid Markup
Search
Jon Daniel
October 04, 2012
Programming
210
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Liquid Markup
Talk I gave October 4, 2012 at Pittsburgh Ruby Brigade.
Jon Daniel
October 04, 2012
More Decks by Jon Daniel
See All by Jon Daniel
Growth and Mentorship: Working with Junior Developers
binarycleric
0
110
Smart Software Design (SOA Edition)
binarycleric
0
170
Ethical and Sustainable On-Call
binarycleric
6
18k
Other Decks in Programming
See All in Programming
スマート反転とウェブアクセシビリティ
camiha
0
220
AI が書く Go コードの品質を劇的に向上させる Linter: “declscope”
mpyw
0
440
AHC070解法紹介
eijirou
0
140
setup-vp GitLab対応の裏側
naokihaba
0
140
一人だけ、Kiroが静止する日
hideg
0
130
AWS DevOps Agentで インシデント対応をAIに任せたい
honmarkhunt
7
3.3k
技術的負債を組織課題として解く-増えすぎたマイクロサービスとの戦い-
reimaru
1
2.4k
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
380
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
320
Java 27新機能 / Java 27 new features
kishida
2
180
手動確認はもう限界 〜XCUITestでCustom URL Schemeの遷移を起動種別ごとに自動テストする〜 / Testing Custom URL Schemes with XCUITest
otouto
0
350
Security issues being discussed on Web Platforms
petamoriken
0
1.3k
Featured
See All Featured
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.8k
Jess Joyce - The Pitfalls of Following Frameworks
techseoconnect
PRO
1
420
Evolving SEO for Evolving Search Engines
ryanjones
0
300
Music & Morning Musume
bryan
48
7.4k
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
2
580
Digital Projects Gone Horribly Wrong (And the UX Pros Who Still Save the Day) - Dean Schuster
uxyall
1
3.1k
16th Malabo Montpellier Forum Presentation
akademiya2063
PRO
0
390
KATA
mclloyd
PRO
35
16k
Scaling GitHub
holman
464
140k
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
830
Fantastic passwords and where to find them - at NoRuKo
philnash
52
3.9k
[SF Ruby Conf 2025] Rails X
palkan
3
1.4k
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?