mime-components 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/lib/mime-components/components/builtins.rb +17 -0
- data/lib/mime-components/components/components.rb +66 -0
- data/lib/mime-components/engine/engine.rb +17 -0
- data/lib/mime-components/engine/globals.rb +30 -0
- data/lib/mime-components/engine/render.rb +36 -0
- data/lib/mime-components/extensions/erb.rb +42 -0
- data/lib/mime-components.rb +14 -0
- metadata +50 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 27afc059f5c4f3436849f350d1b6046bec7f784a1b8d16dade5a899294dc4511
|
4
|
+
data.tar.gz: faab2883fe9bec8083c59b9fd0777b8de85b70257a3a1f866d37081f497021a9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: dde53597426f25ea0ac45f05b8b06fe436d6ebc8a19412f74dcc4b80a0eca379268a647d1630af5b228b1354b99a3a07d774ab78a4e72e22b4a6f1f4a776245a
|
7
|
+
data.tar.gz: b96bf72013f2fc318a2d8a75d4bab5b96ef7b278a2f493909b1f911aebb71c60df4be7bb9bdb252c9729fafddd4902badd79874eb39f7d59751e40b48afb6a90
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# Built-in components.
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
|
5
|
+
module Mime
|
6
|
+
# Register default components to an engine. This is done when an engine is
|
7
|
+
# initialized and generally should not be done externally.
|
8
|
+
# @param engine(Mime::Engine) engine to register default components to
|
9
|
+
def self.register_defaults(engine)
|
10
|
+
component_variable = Mime::Component.new('Variable') do |attributes, vars|
|
11
|
+
value = vars[attributes[:name].to_s.to_sym]
|
12
|
+
value = Erubi.h(value) unless Component.attr_true?(attributes[:raw])
|
13
|
+
value
|
14
|
+
end
|
15
|
+
engine.register_component(component_variable)
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# Component system.
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
|
5
|
+
module Mime
|
6
|
+
# A component is a class with a 'render' function. This function's output
|
7
|
+
# will replace the final XML in the rendered document.
|
8
|
+
class Component
|
9
|
+
@name, @proc = nil
|
10
|
+
|
11
|
+
# Check if an attribute's value is truthy.
|
12
|
+
# @param value(String|Symbol) attribute to check
|
13
|
+
# @return (True|False) whether or not the value is truthy
|
14
|
+
def self.attr_true?(value)
|
15
|
+
[1, 'true', 'yes'].include?(value.to_s.strip.downcase)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Create a new component.
|
19
|
+
# @param name(String) component name
|
20
|
+
# @param proc(Proc) block to call on invocation
|
21
|
+
def initialize(name, &proc)
|
22
|
+
@name = name
|
23
|
+
@proc = proc
|
24
|
+
end
|
25
|
+
|
26
|
+
# Call this component's rendering function.
|
27
|
+
# @param attributes(Hash) rendering parameters
|
28
|
+
# @param vars(Hash) template variables
|
29
|
+
# @return (String) rendered component
|
30
|
+
def render(attributes, vars)
|
31
|
+
@proc.call(attributes, vars)
|
32
|
+
end
|
33
|
+
|
34
|
+
attr_reader :name
|
35
|
+
end
|
36
|
+
|
37
|
+
class Engine
|
38
|
+
@registered_components = {}
|
39
|
+
|
40
|
+
# Register a new component for this engine.
|
41
|
+
# @param component(Component) component to register
|
42
|
+
def register_component(component)
|
43
|
+
@registered_components[component.name.downcase] = component
|
44
|
+
end
|
45
|
+
|
46
|
+
# Render a component based on its parsed XML tag.
|
47
|
+
# @param name(String) component name
|
48
|
+
# @param xml(String) raw component XML
|
49
|
+
# @param vars(Hash) variables to pass to component
|
50
|
+
def render_component(name, xml, vars)
|
51
|
+
# get component, raising an error if it doesn't exist
|
52
|
+
if (component = @registered_components[name.downcase]).nil?
|
53
|
+
raise "#{xml}: component '#{name}' was not registered for this engine"
|
54
|
+
end
|
55
|
+
|
56
|
+
# normalize attributes
|
57
|
+
xml = Nokogiri::XML.parse(xml).root
|
58
|
+
attributes = {}
|
59
|
+
xml.attributes.map do |k, v|
|
60
|
+
attributes[k.to_s.strip.downcase.to_sym] = v
|
61
|
+
end
|
62
|
+
# render subcomponents of output
|
63
|
+
render(component.render(attributes, vars).to_s, vars)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# Engine class and initializer.
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
|
5
|
+
module Mime
|
6
|
+
# The Engine is the primary class responsible for rendering Mime documents. Each
|
7
|
+
# engine contains a component registry as well as a set of built-in components.
|
8
|
+
class Engine
|
9
|
+
# Initialize a new instance of the Mime templating engine.
|
10
|
+
def initialize
|
11
|
+
@global_vars = {}
|
12
|
+
@registered_components = {}
|
13
|
+
@component_regex = %r{(<[MmCc]:((?:[A-z0-9\:\-]+)|\#).*?/?>)}
|
14
|
+
Mime.register_defaults(self)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# Global per-engine variables.
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
|
5
|
+
module Mime
|
6
|
+
class Engine
|
7
|
+
@global_vars = {}
|
8
|
+
|
9
|
+
# Set a global template variable.
|
10
|
+
# @param name(String) name of variable to set
|
11
|
+
# @param value(Object) new value of variable (nil to unset)
|
12
|
+
# @return (Object) new value
|
13
|
+
def []=(name, value)
|
14
|
+
@global_vars[name] = value
|
15
|
+
end
|
16
|
+
|
17
|
+
# Get a global template variable.
|
18
|
+
# @param name(String) name of variable to get value of
|
19
|
+
# @return (Object) value
|
20
|
+
def [](name)
|
21
|
+
@global_vars[name]
|
22
|
+
end
|
23
|
+
|
24
|
+
# Get a list of set global variables.
|
25
|
+
# @return (Array[Object]) set keys
|
26
|
+
def keys
|
27
|
+
@global_vars.keys
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# Component tag location and rendering.
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
|
5
|
+
module Mime
|
6
|
+
class Engine
|
7
|
+
# Render all components in a 'template'.
|
8
|
+
# @param template(String) template as string
|
9
|
+
# @param vars(Hash) variables to render with
|
10
|
+
def render(template, vars)
|
11
|
+
@global_vars.each_key do |k|
|
12
|
+
vars[k] = @global_vars[k]
|
13
|
+
end
|
14
|
+
# we locate, parse and replace tags to render the template. none of these
|
15
|
+
# things work with frozen literals, so we'll make a copy to work on and return
|
16
|
+
output = template.dup
|
17
|
+
# find tags
|
18
|
+
matches = output.scan(@component_regex)
|
19
|
+
matches.each do |n|
|
20
|
+
# render tag
|
21
|
+
tag, component_name = n
|
22
|
+
tag_out = if component_name == '#'
|
23
|
+
''
|
24
|
+
else
|
25
|
+
render_component(component_name, tag, vars)
|
26
|
+
end
|
27
|
+
# replace tag in output with its rendered value
|
28
|
+
output.gsub!(tag, tag_out)
|
29
|
+
end
|
30
|
+
|
31
|
+
# freeze and return output
|
32
|
+
output.freeze
|
33
|
+
output
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# Erubi templating support.
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
|
5
|
+
module Mime
|
6
|
+
# A component wrapped around a compiled Erubi template.
|
7
|
+
class ERBComponent < Component
|
8
|
+
@erubi_engine = nil
|
9
|
+
# Create a new Mime component from an Erubi template. XML arguments will be passed to this
|
10
|
+
# template as an instance variable named `@args`, and variables will be set as instance
|
11
|
+
# varibles (for example, ':my_variable' would be accessible as '@my_variable').
|
12
|
+
def initialize(name, template)
|
13
|
+
# pre-compile template
|
14
|
+
@erubi_engine = Erubi::Engine.new(template, freeze: true, escape: true)
|
15
|
+
# execute template in a new context with few variables
|
16
|
+
super(name) do |args, vars|
|
17
|
+
# george is a sandbox instance that can only access variables and arguments
|
18
|
+
# passed to the template by this component.
|
19
|
+
george = Object.new
|
20
|
+
# pass arguments
|
21
|
+
george.instance_variable_set(:@args, args)
|
22
|
+
# pass global variables
|
23
|
+
vars.each { |var| george.instance_variable_set(:"@#{var[0]}", var[1]) }
|
24
|
+
# pass instance variables
|
25
|
+
instance_variables.each { |var| george.instance_variable_set(var, instance_variable_get(var)) }
|
26
|
+
# evaluate template as george :)
|
27
|
+
george.instance_eval(@erubi_engine.src)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class Engine
|
33
|
+
# Render an ERB template with Erubi, then post-process with this engine.
|
34
|
+
# @param template(Erubi::Engine) rendered ERB template
|
35
|
+
# @param vars(Hash) map of variables to send to template
|
36
|
+
# @return (String) rendered template
|
37
|
+
def erb(template, vars)
|
38
|
+
template_output = instance_eval(template.src)
|
39
|
+
render(template_output, vars)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# Let it be known that I do not like Gems
|
3
|
+
|
4
|
+
# Mime is a component (not templating!) system based on XML tags (components).
|
5
|
+
module Mime
|
6
|
+
require 'erubi'
|
7
|
+
require 'nokogiri'
|
8
|
+
require_relative 'mime-components/components/builtins'
|
9
|
+
require_relative 'mime-components/components/components'
|
10
|
+
require_relative 'mime-components/engine/engine'
|
11
|
+
require_relative 'mime-components/engine/globals'
|
12
|
+
require_relative 'mime-components/engine/render'
|
13
|
+
require_relative 'mime-components/extensions/erb'
|
14
|
+
end
|
metadata
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mime-components
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- talkingsodapop
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-11-08 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: A post-processing component system
|
14
|
+
email: tobskep@aol.com
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files: []
|
18
|
+
files:
|
19
|
+
- lib/mime-components.rb
|
20
|
+
- lib/mime-components/components/builtins.rb
|
21
|
+
- lib/mime-components/components/components.rb
|
22
|
+
- lib/mime-components/engine/engine.rb
|
23
|
+
- lib/mime-components/engine/globals.rb
|
24
|
+
- lib/mime-components/engine/render.rb
|
25
|
+
- lib/mime-components/extensions/erb.rb
|
26
|
+
homepage: https://rubygems.org/gems/mime-components
|
27
|
+
licenses:
|
28
|
+
- LGPL-2.1-or-later
|
29
|
+
metadata:
|
30
|
+
rubygems_mfa_required: 'true'
|
31
|
+
post_install_message:
|
32
|
+
rdoc_options: []
|
33
|
+
require_paths:
|
34
|
+
- lib
|
35
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '2.7'
|
40
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
requirements: []
|
46
|
+
rubygems_version: 3.5.16
|
47
|
+
signing_key:
|
48
|
+
specification_version: 4
|
49
|
+
summary: Mime
|
50
|
+
test_files: []
|