phlex 2.1.3 → 2.2.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 +4 -4
- data/lib/phlex/csv.rb +19 -9
- data/lib/phlex/helpers.rb +4 -0
- data/lib/phlex/html/standard_elements.rb +7 -0
- data/lib/phlex/html.rb +1 -4
- data/lib/phlex/sgml.rb +20 -44
- data/lib/phlex/svg.rb +1 -3
- data/lib/phlex/version.rb +1 -1
- data/lib/phlex.rb +14 -28
- metadata +17 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d3eae91fcc5ec985b668a5e016c518f6392cd91d6d155a1f60552282755ca0e7
|
|
4
|
+
data.tar.gz: 4bac6d025488edbc104135dc3417286cc4782d4f022caff2a8a414afa12d09c3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0a18175ffb32c8ae170f9fd2c7f4b990d39500cef81db66545c057f7ff6635a215ba257130c3715a82d1322666ec89badc9beb06fae3325d864a1630f685bea2
|
|
7
|
+
data.tar.gz: 4ee950b03d2d8f0b8efe085207ca42b139775dff4cc0a564661648995ef32f01fce22e84537194a7c37a6218031d9ab8a4ab7689b92bfeac53534aee4d2fc919
|
data/lib/phlex/csv.rb
CHANGED
|
@@ -13,6 +13,7 @@ class Phlex::CSV
|
|
|
13
13
|
@collection = collection
|
|
14
14
|
@_row_buffer = []
|
|
15
15
|
@_headers = []
|
|
16
|
+
@_row_appender = nil
|
|
16
17
|
end
|
|
17
18
|
|
|
18
19
|
attr_reader :collection
|
|
@@ -49,13 +50,7 @@ class Phlex::CSV
|
|
|
49
50
|
MESSAGE
|
|
50
51
|
end
|
|
51
52
|
|
|
52
|
-
|
|
53
|
-
if has_yielder
|
|
54
|
-
yielder(record) { |*a, **k| row = row_template(*a, **k) }
|
|
55
|
-
else
|
|
56
|
-
around_row(record)
|
|
57
|
-
end
|
|
58
|
-
|
|
53
|
+
row_appender = -> {
|
|
59
54
|
row = row_buffer
|
|
60
55
|
|
|
61
56
|
if first_row
|
|
@@ -108,13 +103,28 @@ class Phlex::CSV
|
|
|
108
103
|
buffer << "\n"
|
|
109
104
|
|
|
110
105
|
row_buffer.clear
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if has_yielder
|
|
109
|
+
each_item do |record|
|
|
110
|
+
yielder(record) do |*a, **k|
|
|
111
|
+
row_template(*a, **k)
|
|
112
|
+
row_appender.call
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
else
|
|
116
|
+
@row_appender = row_appender
|
|
117
|
+
each_item do |record|
|
|
118
|
+
around_row(record)
|
|
119
|
+
end
|
|
111
120
|
end
|
|
112
121
|
|
|
113
122
|
buffer
|
|
114
123
|
end
|
|
115
124
|
|
|
116
|
-
def around_row(
|
|
117
|
-
row_template(
|
|
125
|
+
def around_row(...)
|
|
126
|
+
row_template(...)
|
|
127
|
+
@row_appender.call
|
|
118
128
|
end
|
|
119
129
|
|
|
120
130
|
def filename
|
data/lib/phlex/helpers.rb
CHANGED
|
@@ -472,6 +472,13 @@ module Phlex::HTML::StandardElements
|
|
|
472
472
|
# [Spec](https://html.spec.whatwg.org/#the-select-element)
|
|
473
473
|
register_element def select(**attributes, &content) = nil
|
|
474
474
|
|
|
475
|
+
# [EXPERIMENTAL] Outputs a `<selectedcontent>` tag.
|
|
476
|
+
#
|
|
477
|
+
# [MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/selectedcontent)
|
|
478
|
+
# [Draft Spec](https://github.com/whatwg/html/pull/10633)
|
|
479
|
+
# [Can I Use?](https://caniuse.com/mdn-html_elements_selectedcontent)
|
|
480
|
+
register_element def selectedcontent(**attributes, &content) = nil
|
|
481
|
+
|
|
475
482
|
# Outputs a `<slot>` tag.
|
|
476
483
|
#
|
|
477
484
|
# [MDN Docs](https://developer.mozilla.org/docs/Web/HTML/Element/slot)
|
data/lib/phlex/html.rb
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
class Phlex::HTML < Phlex::SGML
|
|
4
|
-
autoload :StandardElements, "phlex/html/standard_elements"
|
|
5
|
-
autoload :VoidElements, "phlex/html/void_elements"
|
|
6
|
-
|
|
7
4
|
extend Phlex::SGML::Elements
|
|
8
5
|
include VoidElements, StandardElements
|
|
9
6
|
|
|
@@ -58,7 +55,7 @@ class Phlex::HTML < Phlex::SGML
|
|
|
58
55
|
raise Phlex::ArgumentError.new("Expected the tag name to be a Symbol.")
|
|
59
56
|
end
|
|
60
57
|
|
|
61
|
-
if (tag = StandardElements.__registered_elements__[name]) || (
|
|
58
|
+
if (tag = StandardElements.__registered_elements__[name]) || (tag = name.name.tr("_", "-")).include?("-")
|
|
62
59
|
if attributes.length > 0 # with attributes
|
|
63
60
|
if block_given # with content block
|
|
64
61
|
buffer << "<#{tag}" << (Phlex::ATTRIBUTE_CACHE[attributes] ||= __attributes__(attributes)) << ">"
|
data/lib/phlex/sgml.rb
CHANGED
|
@@ -3,13 +3,7 @@
|
|
|
3
3
|
# **Standard Generalized Markup Language** for behaviour common to {HTML} and {SVG}.
|
|
4
4
|
class Phlex::SGML
|
|
5
5
|
UNSAFE_ATTRIBUTES = Set.new(%w[srcdoc sandbox http-equiv]).freeze
|
|
6
|
-
REF_ATTRIBUTES = Set.new(%w[href src action formaction lowsrc dynsrc background ping
|
|
7
|
-
NAMED_CHARACTER_REFERENCES = {
|
|
8
|
-
"colon" => ":",
|
|
9
|
-
"tab" => "\t",
|
|
10
|
-
"newline" => "\n",
|
|
11
|
-
}.freeze
|
|
12
|
-
UNSAFE_ATTRIBUTE_NAME_CHARS = %r([<>&"'/=\s\x00])
|
|
6
|
+
REF_ATTRIBUTES = Set.new(%w[href src action formaction lowsrc dynsrc background ping]).freeze
|
|
13
7
|
|
|
14
8
|
ERBCompiler = ERB::Compiler.new("<>").tap do |compiler|
|
|
15
9
|
compiler.pre_cmd = [""]
|
|
@@ -22,11 +16,6 @@ class Phlex::SGML
|
|
|
22
16
|
end
|
|
23
17
|
end
|
|
24
18
|
|
|
25
|
-
autoload :Elements, "phlex/sgml/elements"
|
|
26
|
-
autoload :SafeObject, "phlex/sgml/safe_object"
|
|
27
|
-
autoload :SafeValue, "phlex/sgml/safe_value"
|
|
28
|
-
autoload :State, "phlex/sgml/state"
|
|
29
|
-
|
|
30
19
|
include Phlex::Helpers
|
|
31
20
|
|
|
32
21
|
class << self
|
|
@@ -529,9 +518,7 @@ class Phlex::SGML
|
|
|
529
518
|
if value != true && REF_ATTRIBUTES.include?(normalized_name)
|
|
530
519
|
case value
|
|
531
520
|
when String
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
if decoded_value.downcase.delete("^a-z:").start_with?("javascript:")
|
|
521
|
+
if value.downcase.delete("^a-z:").start_with?("javascript:")
|
|
535
522
|
# We just ignore these because they were likely not specified by the developer.
|
|
536
523
|
next
|
|
537
524
|
end
|
|
@@ -549,7 +536,7 @@ class Phlex::SGML
|
|
|
549
536
|
end
|
|
550
537
|
end
|
|
551
538
|
|
|
552
|
-
if name.match?(
|
|
539
|
+
if name.match?(/[<>&"']/)
|
|
553
540
|
raise Phlex::ArgumentError.new("Unsafe attribute name detected: #{k}.")
|
|
554
541
|
end
|
|
555
542
|
|
|
@@ -574,14 +561,20 @@ class Phlex::SGML
|
|
|
574
561
|
attributes.each do |k, v|
|
|
575
562
|
next unless v
|
|
576
563
|
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
564
|
+
if (root_key = (:_ == k))
|
|
565
|
+
name = ""
|
|
566
|
+
original_base_name = base_name
|
|
567
|
+
base_name = base_name.delete_suffix("-")
|
|
568
|
+
else
|
|
569
|
+
name = case k
|
|
570
|
+
when String then k
|
|
571
|
+
when Symbol then k.name.tr("_", "-")
|
|
572
|
+
else raise Phlex::ArgumentError.new("Attribute keys should be Strings or Symbols")
|
|
573
|
+
end
|
|
582
574
|
|
|
583
|
-
|
|
584
|
-
|
|
575
|
+
if name.match?(/[<>&"']/)
|
|
576
|
+
raise Phlex::ArgumentError.new("Unsafe attribute name detected: #{k}.")
|
|
577
|
+
end
|
|
585
578
|
end
|
|
586
579
|
|
|
587
580
|
case v
|
|
@@ -605,6 +598,10 @@ class Phlex::SGML
|
|
|
605
598
|
raise Phlex::ArgumentError.new("Invalid attribute value #{v.inspect}.")
|
|
606
599
|
end
|
|
607
600
|
|
|
601
|
+
if root_key
|
|
602
|
+
base_name = original_base_name
|
|
603
|
+
end
|
|
604
|
+
|
|
608
605
|
buffer
|
|
609
606
|
end
|
|
610
607
|
end
|
|
@@ -656,27 +653,6 @@ class Phlex::SGML
|
|
|
656
653
|
buffer.gsub('"', """)
|
|
657
654
|
end
|
|
658
655
|
|
|
659
|
-
private def decode_html_character_references(value)
|
|
660
|
-
value
|
|
661
|
-
.gsub(/&#x([0-9a-f]+);?/i) {
|
|
662
|
-
begin
|
|
663
|
-
[$1.to_i(16)].pack("U*")
|
|
664
|
-
rescue
|
|
665
|
-
""
|
|
666
|
-
end
|
|
667
|
-
}
|
|
668
|
-
.gsub(/&#(\d+);?/) {
|
|
669
|
-
begin
|
|
670
|
-
[$1.to_i].pack("U*")
|
|
671
|
-
rescue
|
|
672
|
-
""
|
|
673
|
-
end
|
|
674
|
-
}
|
|
675
|
-
.gsub(/&([a-z][a-z0-9]+);?/i) {
|
|
676
|
-
NAMED_CHARACTER_REFERENCES[$1.downcase] || ""
|
|
677
|
-
}
|
|
678
|
-
end
|
|
679
|
-
|
|
680
656
|
# Result is **unsafe**, so it should be escaped!
|
|
681
657
|
def __styles__(styles)
|
|
682
658
|
case styles
|
data/lib/phlex/svg.rb
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
class Phlex::SVG < Phlex::SGML
|
|
4
|
-
autoload :StandardElements, "phlex/svg/standard_elements"
|
|
5
|
-
|
|
6
4
|
include StandardElements
|
|
7
5
|
|
|
8
6
|
# Returns the string "image/svg+xml"
|
|
@@ -43,7 +41,7 @@ class Phlex::SVG < Phlex::SGML
|
|
|
43
41
|
raise Phlex::ArgumentError.new("Expected the tag name to be a Symbol.")
|
|
44
42
|
end
|
|
45
43
|
|
|
46
|
-
if (tag = StandardElements.__registered_elements__[name]) || (
|
|
44
|
+
if (tag = StandardElements.__registered_elements__[name]) || (tag = name.name.tr("_", "-")).include?("-")
|
|
47
45
|
if attributes.length > 0 # with attributes
|
|
48
46
|
if block_given # with content block
|
|
49
47
|
buffer << "<#{tag}" << (Phlex::ATTRIBUTE_CACHE[attributes] ||= __attributes__(attributes)) << ">"
|
data/lib/phlex/version.rb
CHANGED
data/lib/phlex.rb
CHANGED
|
@@ -2,25 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
require "erb"
|
|
4
4
|
require "set"
|
|
5
|
+
require "zeitwerk"
|
|
5
6
|
|
|
6
7
|
module Phlex
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
autoload :NameError, "phlex/errors/name_error"
|
|
21
|
-
autoload :RuntimeError, "phlex/errors/runtime_error"
|
|
22
|
-
autoload :ArgumentError, "phlex/errors/argument_error"
|
|
23
|
-
autoload :DoubleRenderError, "phlex/errors/double_render_error"
|
|
8
|
+
Loader = Zeitwerk::Loader.for_gem.tap do |loader|
|
|
9
|
+
loader.push_dir("lib/phlex/errors", namespace: Phlex)
|
|
10
|
+
loader.inflector.inflect(
|
|
11
|
+
"csv" => "CSV",
|
|
12
|
+
"fifo" => "FIFO",
|
|
13
|
+
"fifo_cache_store" => "FIFOCacheStore",
|
|
14
|
+
"html" => "HTML",
|
|
15
|
+
"sgml" => "SGML",
|
|
16
|
+
"svg" => "SVG",
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
loader.setup
|
|
20
|
+
end
|
|
24
21
|
|
|
25
22
|
Escape = ERB::Escape
|
|
26
23
|
|
|
@@ -35,17 +32,6 @@ module Phlex
|
|
|
35
32
|
end
|
|
36
33
|
end
|
|
37
34
|
|
|
38
|
-
def self.eager_load
|
|
39
|
-
queue = [self]
|
|
40
|
-
|
|
41
|
-
while (mod = queue.shift)
|
|
42
|
-
mod.constants.each do |const_name|
|
|
43
|
-
const = mod.const_get(const_name)
|
|
44
|
-
queue << const if Module === const
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
|
|
49
35
|
# Generate an HTML string using Phlex’ HTML DSL
|
|
50
36
|
def self.html(&block)
|
|
51
37
|
HTML.call do |component|
|
metadata
CHANGED
|
@@ -1,15 +1,29 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: phlex
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Joel Drapper
|
|
8
8
|
- Will Cosgrove
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
12
|
-
dependencies:
|
|
11
|
+
date: 2025-04-04 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: zeitwerk
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '0'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '0'
|
|
13
27
|
description: Build HTML, SVG and CSV views with Ruby classes.
|
|
14
28
|
email:
|
|
15
29
|
- joel@drapper.me
|