Class: Code::Object::Html
Constant Summary
collapse
- CLASS_DOCUMENTATION =
{
name: "Html",
description: "builds, escapes, parses, and queries html fragments.",
examples: [
"Html.p { :hello }",
"Html.escape(\"<p>a</p>\")",
"Html.raw(\"<p>a</p>\").css(\"p\")"
]
}.freeze
- CLASS_FUNCTIONS =
{
"escape" => {
name: "escape",
description: "escapes a value for html text.",
examples: [
"Html.escape(\"<p>\")",
"Html.escape(:hello)",
"Html.escape(() => { \"<strong>hello</strong>\" })"
]
},
"unescape" => {
name: "unescape",
description: "converts html entities and tags to text.",
examples: [
"Html.unescape(\"<p>\")",
"Html.unescape(\"<p>hello</p>\")",
"Html.unescape(() => { \"&\" })"
]
},
"join" => {
name: "join",
description: "joins html or text values with an optional separator.",
examples: [
"Html.join([:a, :b], \", \")",
"Html.join([Html.text(\"a\"), Html.text(\"b\")])",
"Html.join(\"<br>\", () => { [\"a\", \"b\"] })"
]
},
"text" => {
name: "text",
description: "builds an escaped html text fragment.",
examples: [
"Html.text(:hello)",
"Html.text(\"<strong>hello</strong>\")",
"Html.text(() => { :hello })"
]
},
"raw" => {
name: "raw",
description:
"parses markup into an html fragment without escaping text.",
examples: [
"Html.raw(\"<strong>hello</strong>\")",
"Html.raw(Html.text(:hello))",
"Html.raw(() => { \"<em>hello</em>\" })"
]
}
}.freeze
- INSTANCE_FUNCTIONS =
{
"css" => {
name: "css",
description: "returns all html nodes matching a css selector.",
examples: [
"Html.raw(\"<p>a</p><p>b</p>\").css(\"p\")",
"Html.raw(\"<main><p>a</p></main>\").css(\"main p\")",
"Html.raw(\"<p class='x'>a</p>\").css(\".x\")"
]
},
"at_css" => {
name: "at_css",
description: "returns the first html node matching a css selector.",
examples: [
"Html.raw(\"<p>a</p><p>b</p>\").at_css(\"p\")",
"Html.raw(\"<main><p>a</p></main>\").at_css(\"main p\")",
"Html.raw(\"<p class='x'>a</p>\").at_css(\".x\")"
]
},
"map" => {
name: "map",
description:
"returns a list by calling a function for each html node.",
examples: [
"Html.raw(\"<p>a</p><p>b</p>\").css(\"p\").map((node) => { node.to_string })",
"Html.raw(\"<p>a</p>\").css(:p).map((node, index) => { index })",
"Html.raw(\"<p>a</p>\").css(:p).map((node, index, nodes) => { nodes.to_string })"
]
},
"to_string" => {
name: "to_string",
description: "returns the html fragment's text content.",
examples: [
"Html.raw(\"<p>hello</p>\").to_string",
"Html.text(:hello).to_string",
"Html.raw(\"<p><strong>hello</strong></p>\").to_string"
]
},
"to_html" => {
name: "to_html",
description: "returns the html fragment as html markup.",
examples: [
"Html.raw(\"<p>hello</p>\").to_html",
"Html.text(:p).to_html",
"Html.raw(\"<strong>hello</strong>\").to_html"
]
},
"inner_text" => {
name: "inner_text",
description: "returns the html fragment's text content.",
examples: [
"Html.raw(\"<p>hello</p>\").inner_text",
"Html.text(:hello).inner_text",
"Html.raw(\"<p><strong>hello</strong></p>\").inner_text"
]
},
"attribute" => {
name: "attribute",
description: "returns an html node attribute by name.",
examples: [
"Html.raw(\"<a href='/'>home</a>\").at_css(:a).attribute(:href)",
"Html.raw(\"<p class='x'>a</p>\").at_css(:p).attribute(:class)",
"Html.raw(\"<img alt='logo'>\").at_css(:img).attribute(:alt)"
]
},
"attributes" => {
name: "attributes",
description: "returns an html node's attributes as a dictionary.",
examples: [
"Html.raw(\"<a href='/'>home</a>\").at_css(:a).attributes",
"Html.raw(\"<p class='x'>a</p>\").at_css(:p).attributes",
"Html.raw(\"<img alt='logo'>\").at_css(:img).attributes"
]
}
}.freeze
- TAGS =
%w[
a
abbr
address
area
article
aside
audio
b
base
bdi
bdo
blockquote
body
br
button
canvas
caption
cite
code
col
colgroup
data
datalist
dd
del
details
dfn
dialog
div
dl
dt
em
embed
fieldset
figcaption
figure
footer
form
h1
h2
h3
h4
h5
h6
head
header
hgroup
hr
html
i
iframe
img
input
ins
kbd
label
legend
li
link
main
map
mark
meta
meter
nav
noscript
object
ol
optgroup
option
output
p
picture
pre
progress
q
rp
rt
ruby
s
samp
script
section
select
slot
small
source
span
strong
style
sub
summary
sup
table
tbody
td
template
textarea
tfoot
th
thead
time
title
tr
track
u
ul
var
video
wbr
].freeze
Constants inherited
from Code::Object
NUMBER_CLASSES
Concerns::Shared::COMPOUND_ASSIGNMENT_OPERATORS, Concerns::Shared::OPERATOR_METHOD_ALIASES, Concerns::Shared::SHARED_OPERATORS
Instance Attribute Summary
#functions, #raw
Class Method Summary
collapse
Instance Method Summary
collapse
class_documentation, class_functions, code_new, #code_new, documentation, documentation_for, documented_functions_for, function_documentation_for, function_documentation_registry_for, functions, inherited_function_documentation_for, instance_functions, maybe, #name, repeat, sorted_dictionary, |
#<=>, #==, #as_json, #blank?, #code_and, #code_as_json, #code_blank?, #code_class_functions, #code_compare, #code_deep_duplicate, #code_different, #code_documentable_functions, #code_documentation, #code_duplicate, #code_dynamic_call, #code_equal, #code_exclamation_mark, #code_exclusive_range, #code_false?, #code_falsy?, code_fetch, #code_fetch, #code_functions, code_get, #code_get, #code_greater, #code_greater_or_equal, #code_has_key?, #code_inclusive_range, #code_inspect, #code_instance_functions, #code_instance_of?, #code_is_a?, #code_itself, #code_less, #code_less_or_equal, #code_name, #code_nothing?, #code_or, #code_presence, #code_presence_in, #code_present?, #code_respond_to?, #code_same_object?, #code_self, #code_send, code_set, #code_set, #code_something?, #code_strict_different, #code_strict_equal, #code_tap, #code_then, #code_to_boolean, #code_to_class, #code_to_date, #code_to_decimal, #code_to_dictionary, #code_to_duration, #code_to_integer, #code_to_json, #code_to_list, #code_to_nothing, #code_to_parameter, #code_to_range, #code_to_time, #code_true?, #code_truthy?, #eql?, #falsy?, #hash, #inspect, #multi_fetch, #nothing?, #present?, #sig, #something?, #succ, #to_code, #to_i, #to_json, #truthy?
Constructor Details
#initialize(*args, **_kargs, &_block) ⇒ Html
Returns a new instance of Html.
259
260
261
262
263
264
265
266
267
268
269
270
271
|
# File 'lib/code/object/html.rb', line 259
def initialize(*args, **_kargs, &_block)
self.raw =
if args.first.is_an?(Html)
args.first.raw
elsif args.first.is_a?(::Nokogiri::XML::NodeSet) ||
args.first.is_a?(Nokogiri::XML::Node)
args.first
else
source = args.first.to_s
::Code.ensure_input_size!(source, label: "html")
Nokogiri.HTML(source)
end
end
|
Class Method Details
.call(**args) ⇒ Object
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
|
# File 'lib/code/object/html.rb', line 273
def self.call(**args)
code_operator = args.fetch(:operator, nil).to_code
code_arguments = args.fetch(:arguments, []).to_code
globals = multi_fetch(args, *GLOBALS)
case code_operator.to_s
when "escape"
sig(args) { Object.maybe }
code_escape(*code_arguments.raw, **globals)
when "unescape"
sig(args) { Object.maybe }
code_unescape(*code_arguments.raw, **globals)
when "join"
sig(args) { [Object.maybe, Object.maybe] }
code_join(*code_arguments.raw, **globals)
when "text"
sig(args) { Object.maybe }
code_text(code_arguments.code_first, **globals)
when "raw"
sig(args) { Object.maybe }
code_raw(code_arguments.code_first, **globals)
else
if TAGS.include?(code_operator.to_s.downcase)
sig(args) { [Dictionary.maybe, Function.maybe] }
code_tag(code_operator, *code_arguments.raw, **globals)
else
super
end
end
end
|
.code_escape(value_or_function = nil, **globals) ⇒ Object
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
|
# File 'lib/code/object/html.rb', line 359
def self.code_escape(value_or_function = nil, **globals)
code_value =
if value_or_function.is_a?(Function)
begin
value_or_function.to_code.call(**globals)
rescue Error::Next => e
e.code_value
end
else
value_or_function.to_code
end
String.new(CGI.escapeHTML(code_value.to_s))
rescue Error::Break => e
e.code_value
end
|
.code_join(first = nil, second = nil, **globals) ⇒ Object
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
|
# File 'lib/code/object/html.rb', line 396
def self.code_join(first = nil, second = nil, **globals)
if second.is_a?(Function)
code_contents =
begin
second.to_code.call(**globals)
rescue Error::Next => e
e.code_value
end
code_separator = first.to_code
else
code_contents = first.to_code
code_separator = second.to_code
end
fragment = Nokogiri::HTML::DocumentFragment.parse("")
return Html.new(fragment) if code_contents.nothing?
return Html.new(fragment) unless code_contents.is_a?(List)
code_contents.raw.each.with_index do |code_content, index|
content =
if code_content.is_an?(Html)
fragment_from_html(code_content)
else
Nokogiri::XML::Text.new(code_content.to_s, fragment.document)
end
separator =
if code_separator.is_an?(Html)
fragment_from_html(code_separator)
else
Nokogiri::XML::Text.new(code_separator.to_s, fragment.document)
end
fragment.add_child(separator) unless index.zero?
fragment.add_child(content)
end
Html.new(fragment)
rescue Error::Break => e
e.code_value
end
|
.code_raw(value_or_function = nil, **globals) ⇒ Object
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
|
# File 'lib/code/object/html.rb', line 461
def self.code_raw(value_or_function = nil, **globals)
code_value =
if value_or_function.is_a?(Function)
begin
value_or_function.to_code.call(**globals)
rescue Error::Next => e
e.code_value
end
else
value_or_function.to_code
end
if code_value.is_an?(Html)
Html.new(fragment_from_html(code_value))
else
source = code_value.to_s
::Code.ensure_input_size!(source, label: "html")
Html.new(Nokogiri::HTML::DocumentFragment.parse(source))
end
rescue Error::Break => e
e.code_value
end
|
.code_tag(name, attributes_or_function = {}, function = nil, **globals) ⇒ Object
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
|
# File 'lib/code/object/html.rb', line 304
def self.code_tag(
name,
attributes_or_function = {},
function = nil,
**globals
)
code_name = name.to_code
if attributes_or_function.is_a?(Function)
code_attributes = {}.to_code
code_function = attributes_or_function.to_code
else
code_attributes = attributes_or_function.to_code
code_function = function.to_code
end
fragment = Nokogiri::HTML::DocumentFragment.parse("")
node =
Nokogiri::XML::Node.new(code_name.to_s.downcase, fragment.document)
code_attributes.raw.each do |code_key, code_value|
next if code_key.nothing?
next if code_value.nothing?
node[code_key.to_s] = code_value.to_s
end
if code_function.something?
code_content =
begin
code_function.call(
arguments: List.new([code_name, code_attributes]),
**globals
)
rescue Error::Next => e
e.code_value
end
content =
if code_content.is_an?(Html)
fragment_from_html(code_content)
else
Nokogiri::XML::Text.new(code_content.to_s, fragment.document)
end
node.add_child(content)
end
fragment.add_child(node)
Html.new(fragment)
rescue Error::Break => e
e.code_value
end
|
.code_text(value_or_function = nil, **globals) ⇒ Object
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
|
# File 'lib/code/object/html.rb', line 439
def self.code_text(value_or_function = nil, **globals)
code_value =
if value_or_function.is_a?(Function)
begin
value_or_function.to_code.call(**globals)
rescue Error::Next => e
e.code_value
end
else
value_or_function.to_code
end
fragment = Nokogiri::HTML::DocumentFragment.parse("")
fragment.add_child(
Nokogiri::XML::Text.new(code_value.to_s, fragment.document)
)
Html.new(fragment)
rescue Error::Break => e
e.code_value
end
|
.code_unescape(value_or_function = nil, **globals) ⇒ Object
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
|
# File 'lib/code/object/html.rb', line 376
def self.code_unescape(value_or_function = nil, **globals)
code_value =
if value_or_function.is_a?(Function)
begin
value_or_function.to_code.call(**globals)
rescue Error::Next => e
e.code_value
end
else
value_or_function.to_code
end
source = code_value.to_s
::Code.ensure_input_size!(source, label: "html")
String.new(Nokogiri::HTML.fragment(source).text)
rescue Error::Break => e
e.code_value
end
|
.fragment_from_html(html) ⇒ Object
484
485
486
487
488
|
# File 'lib/code/object/html.rb', line 484
def self.fragment_from_html(html)
source = html.to_html
::Code.ensure_input_size!(source, label: "html")
Nokogiri::HTML::DocumentFragment.parse(source)
end
|
.function_documentation(scope) ⇒ Object
139
140
141
142
143
144
|
# File 'lib/code/object/html.rb', line 139
def self.function_documentation(scope)
return INSTANCE_FUNCTIONS if scope == :instance
return CLASS_FUNCTIONS if scope == :class
{}
end
|
Instance Method Details
#call(**args) ⇒ Object
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
|
# File 'lib/code/object/html.rb', line 490
def call(**args)
code_operator = args.fetch(:operator, nil).to_code
code_arguments = args.fetch(:arguments, []).to_code
code_value = code_arguments.code_first
globals = multi_fetch(args, *GLOBALS)
case code_operator.to_s
when "css"
sig(args) { String }
code_css(code_value)
when "at_css"
sig(args) { String }
code_at_css(code_value)
when "map"
sig(args) { Function }
code_map(code_value, **globals)
when "to_string"
sig(args)
code_to_string
when "to_html"
sig(args)
code_to_html
when "inner_text"
sig(args)
code_inner_text
when "attribute"
sig(args) { String }
code_attribute(code_value)
when "attributes"
sig(args)
code_attributes
else
super
end
end
|
#code_at_css(query) ⇒ Object
532
533
534
535
536
|
# File 'lib/code/object/html.rb', line 532
def code_at_css(query)
code_query = query.to_code
Html.new(raw.at_css(code_query.raw))
end
|
#code_attribute(value = nil) ⇒ Object
575
576
577
578
|
# File 'lib/code/object/html.rb', line 575
def code_attribute(value = nil)
code_value = value.to_code
String.new(raw.attr(code_value.to_s))
end
|
#code_attributes ⇒ Object
580
581
582
583
584
585
586
587
588
589
|
# File 'lib/code/object/html.rb', line 580
def code_attributes
node = raw.is_a?(::Nokogiri::XML::NodeSet) ? raw.first : raw
return Dictionary.new if node.blank?
Dictionary.new(
node.attribute_nodes.to_h do |attribute|
[attribute.name.to_code, attribute.value.to_code]
end
)
end
|
#code_css(query) ⇒ Object
526
527
528
529
530
|
# File 'lib/code/object/html.rb', line 526
def code_css(query)
code_query = query.to_code
Html.new(raw.css(code_query.raw))
end
|
#code_inner_text ⇒ Object
571
572
573
|
# File 'lib/code/object/html.rb', line 571
def code_inner_text
code_to_string
end
|
#code_map(argument, **globals) ⇒ Object
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
|
# File 'lib/code/object/html.rb', line 538
def code_map(argument, **globals)
code_argument = argument.to_code
List.new(
raw.map.with_index do |element, index|
code_argument.call(
arguments: List.new([element.to_code, Integer.new(index), self]),
**globals
)
rescue Error::Next => e
e.code_value
end
)
rescue Error::Break => e
e.code_value
end
|
#code_to_html ⇒ Object
563
564
565
|
# File 'lib/code/object/html.rb', line 563
def code_to_html
String.new(raw.to_html)
end
|
#code_to_string ⇒ Object
567
568
569
|
# File 'lib/code/object/html.rb', line 567
def code_to_string
String.new(raw.text)
end
|
559
560
561
|
# File 'lib/code/object/html.rb', line 559
def to_html
raw.to_html
end
|
555
556
557
|
# File 'lib/code/object/html.rb', line 555
def to_s
raw.text
end
|