Slide 1

Slide 1 text

Liquid Markup

Slide 2

Slide 2 text

Jon Daniel @binarycleric github.com/binarycleric

Slide 3

Slide 3 text

Obligatory Promotion We’re Hiring Smart People. Ruby experience NOT required.

Slide 4

Slide 4 text

What Is Liquid?

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

github.com/Shopify/liquid

Slide 7

Slide 7 text

lets clients design their own sites...

Slide 8

Slide 8 text

safely and securely

Slide 9

Slide 9 text

logic and variable manipulation

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

yay!

Slide 12

Slide 12 text

No content

Slide 13

Slide 13 text

$ gem install liquid require 'liquid'

Slide 14

Slide 14 text

markup = "Hello, {{ thing }}!" t = Liquid::Template.parse(markup) t.render("thing" => "world")

Slide 15

Slide 15 text

Hello, world!

Slide 16

Slide 16 text

markup = "Welcome, {{ user.name }}" user = User.find(1337) t = Liquid::Template.parse(markup) t.render('user' => user)

Slide 17

Slide 17 text

Welcome, !

Slide 18

Slide 18 text

Liquid Has Trust Issues

Slide 19

Slide 19 text

Deny By Default

Slide 20

Slide 20 text

class Person < ActiveRecord::Base end # denied! "{{ person.name }}" => "" class Person < ActiveRecord::Base liquid_methods :name end # okay! "{{ person.name }}" => "Cmdr Shepard"

Slide 21

Slide 21 text

markup = "Welcome, {{ user.name }}" user = User.find(1337) t = Liquid::Template.parse(markup) t.render('user' => user)

Slide 22

Slide 22 text

Welcome, Jon ‘maddog’ Hall! * If you don’t know who he is, check Wikipedia.

Slide 23

Slide 23 text

Live Free Or Die.

Slide 24

Slide 24 text

Actually Rendering Templates

Slide 25

Slide 25 text

# load the user from somewhere. t = Liquid::Template.parse(markup) t.render("user" => user)

Slide 26

Slide 26 text

t = Liquid::Template.parse(markup) context = Liquid::Context.new(*args) t.render(context)

Slide 27

Slide 27 text

The Magic Context

Slide 28

Slide 28 text

Liquid::Context.new local_assigns, global_assigns, registers

Slide 29

Slide 29 text

Liquid::Context.new local_assigns, global_assigns, registers

Slide 30

Slide 30 text

registers[:domain] = domain registers[:whatever] = whatever registers[:your] = your registers[:app] = app registers[:needs] = needs registers[:file_system] = FileSystem.new

Slide 31

Slide 31 text

registers[:domain] = domain registers[:whatever] = whatever registers[:your] = your registers[:app] = app registers[:needs] = needs registers[:file_system] = FileSystem.new

Slide 32

Slide 32 text

Some Liquid Syntax

Slide 33

Slide 33 text

class FileSystem def initialize(*args) # whatever end def read_template_file(name, context) # fetches partials from wherever end end {% include 'some-partial' %}

Slide 34

Slide 34 text

# a block {% if liquid == 'awesome' %} You should try Liquid! {% endif %} # a tag {% assign liquid = 'awesome' %}

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

class PersonDrop < Liquid::Drop def addresses # stupid slow operation Address::find_by_person(@person) end end {{ user.addresses }}

Slide 38

Slide 38 text

{{ “hello world” | capitalize }} # shamelessly stolen from # liquid's source. use your # imagination people! def capitalize(input) input.to_s.capitalize end

Slide 39

Slide 39 text

Liquid Philosophies

Slide 40

Slide 40 text

•assume hostile environment •white list what you need •deny everything else

Slide 41

Slide 41 text

•can edit markup •is probably non-technical Assume the client

Slide 42

Slide 42 text

•ignore errors by default •don’t let the client break too much

Slide 43

Slide 43 text

It May Not Be For You

Slide 44

Slide 44 text

•partial branding •full white-label •per-install customization

Slide 45

Slide 45 text

Views As Data

Slide 46

Slide 46 text

Contribute!

Slide 47

Slide 47 text

Questions?