-
-
Save danieldocki/ca81f8f67cdf9a30a2bd7f38111378d6 to your computer and use it in GitHub Desktop.
UI (UI::Component)
This file contains hidden or 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
| class UComponent2 | |
| module DataAccessor | |
| def data=(value) | |
| @data = value | |
| end | |
| def data; @data; end | |
| end | |
| def self.fn(&block) | |
| new(block) | |
| end | |
| def self.call(data = {}) | |
| new.call(data) | |
| end | |
| def self.to_proc | |
| -> (data = {}) { call(data) } | |
| end | |
| def self.template(&block) | |
| define_method(:__template) { block } | |
| end | |
| def self.defaults(data = {}) | |
| define_method(:__defaults) { data } | |
| end | |
| def initialize(fn = nil) | |
| @fn = fn || __template | |
| @defaults = respond_to?(:__defaults) ? __defaults : {} | |
| end | |
| def call(data) | |
| builder = Nokogiri::HTML::Builder.new | |
| builder.context = @builder | |
| builder.extend(DataAccessor) | |
| builder.data = apply_defaults_to(data) | |
| builder.instance_eval(&@fn) | |
| builder.to_html.sub!(/<!DOCTYPE.*[^>]/, '') | |
| end | |
| def to_proc | |
| -> (data) { call(data) } | |
| end | |
| private | |
| def apply_defaults_to(data) | |
| return @defaults.merge(data) if data.is_a?(Hash) | |
| data || @defaults | |
| end | |
| end | |
| class HelloWorldV2 < UComponent2 | |
| template do | |
| span.bar.foo! { | |
| text("Hello World") | |
| } | |
| end | |
| end | |
| HelloWorldV2.call | |
| class GreetV2 < UComponent2 | |
| defaults name: 'John Doe' | |
| template do | |
| span.bar.foo! { | |
| text("Hello #{data[:name]}") | |
| } | |
| end | |
| end | |
| GreetV2.call | |
| GreetV2.call name: 'Rodrigo' | |
| [{name: 'Rodrigo'}, {name: 'Talita'}, {}].map(&GreetV2) | |
| class NumberV2 < UComponent2 | |
| template do | |
| strong { text(data) } | |
| end | |
| end | |
| NumberV2.call 1 | |
| [1,2,3,4].map(&NumberV2) | |
| number_v2 = UComponent2.fn do | |
| strong { text(data) } | |
| end | |
| number_v2.call 1 | |
| [1,2,3,4].map(&number_v2) |
This file contains hidden or 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
| class UComponent | |
| def self.defaults | |
| {} | |
| end | |
| def self.build(_doc, _options) | |
| raise NotImplementedError | |
| end | |
| def self.call(*args) | |
| fn = args[0].is_a?(Proc) ? args[0] : method(:build) | |
| options = args[0].is_a?(Hash) ? args[0] : (args[1] || {}) | |
| new.call(options, fn) | |
| end | |
| def self.to_proc | |
| -> (*args) { call(*args) } | |
| end | |
| def initialize(fn = nil) | |
| @fn = fn | |
| end | |
| def call(opt = {}, fn = nil) | |
| func = @fn || fn | |
| options = opt.is_a?(Hash) ? self.class.defaults.merge(opt) : opt | |
| builder = Nokogiri::HTML::Builder.new do |doc| | |
| func.arity == 1 ? func.(doc) : func.(doc, options) | |
| end | |
| builder.to_html.sub!(/<!DOCTYPE.*[^>]/, '') | |
| end | |
| def to_proc | |
| -> (options) { call(options) } | |
| end | |
| end | |
| class HelloWorld < UComponent | |
| def self.build(doc) | |
| doc.span.bold { | |
| doc.text("Hello world") | |
| } | |
| end | |
| end | |
| class HelloWorld2 < UComponent | |
| def self.build(doc, message:) | |
| doc.span.bold { | |
| doc.text(message) | |
| } | |
| end | |
| end | |
| class Greet < UComponent | |
| def self.defaults | |
| { name: 'John Doe' } | |
| end | |
| def self.build(doc, name:) | |
| doc.span.bar.foo! { | |
| doc.text("Hello #{name}") | |
| } | |
| end | |
| end | |
| # == Examples == | |
| HelloWorld.call | |
| #=> "<span class=\"bold\">Hello world</span>\n" | |
| HelloWorld2.call message: 'Olá mundo' | |
| #=> "<span class=\"bold\">Olá mundo</span>\n" | |
| UComponent.call -> doc { doc.span.bold { doc.text("Hello world") } } | |
| #=> "<span class=\"bold\">Hello world</span>\n" | |
| UComponent.call( | |
| -> doc, message { doc.span.bold { doc.text(message) } }, | |
| 'Olá mundo' | |
| ) | |
| #=> "<span class=\"bold\">Olá mundo</span>\n" | |
| Greet.call | |
| #=> "<span class=\"bar\" id=\"foo\">Hello John Doe</span>\n" | |
| Greet.call name: 'Serradura' | |
| #=> "<span class=\"bar\" id=\"foo\">Hello Serradura</span>\n" | |
| [{name: 'Rodrigo'}, {name: 'Talita'}, {}].map(&Greet) | |
| #=> ["<span class=\"bar\" id=\"foo\">Hello Rodrigo</span>\n", "<span class=\"bar\" id=\"foo\">Hello Talita</span>\n", "<span class=\"bar\" id=\"foo\">Hello John Doe</span>\n"] | |
| greet = UComponent.new(-> (doc, name:) do | |
| doc.span.bar.foo! { | |
| doc.text("Hello #{name}") | |
| } | |
| end) | |
| greet.call(name: 'Bella') | |
| #=> "<span class=\"bar\" id=\"foo\">Hello Bella</span>\n" | |
| [{name: 'Rodrigo'}, {name: 'Talita'}].map(&greet) | |
| #=> ["<span class=\"bar\" id=\"foo\">Hello Rodrigo</span>\n", "<span class=\"bar\" id=\"foo\">Hello Talita</span>\n"] | |
| number = UComponent.new(-> (doc, n) do | |
| doc.strong { doc.text(n) } | |
| end) | |
| [1,2,3,4].map(&number) | |
| #=> ["<strong>1</strong>\n", "<strong>2</strong>\n", "<strong>3</strong>\n", "<strong>4</strong>\n"] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment