Class: Y::Lexxy
Overview
The Lexxy renderer: Y::Lexical (core Lexical) plus the Lexxy-specific
schema, applied beneath the app's rules — an app rule for one of these
types simply replaces it. This is the byte-parity class: the fixture
tests hold Y::Lexxy.new(doc).to_html identical to a live editor's own
serialized value.
The schema doubles as the reference for augmenting a renderer: simple nodes are declarative hashes, nodes with logic are plain methods mapped in NODES.
Constant Summary collapse
- NODES =
{ # Lexxy's replacement for Lexical's CodeNode. "early_escape_code" => { tag: "pre", attrs: { "data-language" => :language } }, "horizontal_divider" => { tag: "hr", void: true }, "provisonal_paragraph" => method(:provisional_paragraph), # (sic: Lexxy's spelling) "image_gallery" => method(:gallery), "table" => { contains: :blocks, render: method(:table) }, "wrapped_table_node" => { contains: :blocks, render: method(:table) }, "tablecell" => { contains: :blocks, render: method(:table_cell) }, "listitem" => { contains: :blocks, render: method(:list_item) }, "action_text_attachment" => method(:upload), "action_text_attachment_upload" => method(:pending_upload), "custom_action_text_attachment" => method(:mention) }.freeze
Class Method Summary collapse
-
.attachment_attr(node, html_name, stored) ⇒ Object
A stored nil (unset) is skipped; a stored empty string still emits.
-
.attachment_tag(node) ⇒ Object
Lexxy's attachment tag is configurable (
Lexxy.configure's attachmentTagName, paired with ActionText::Attachment.tag_name on the Rails side), and each attachment node stores the tag it was created with. -
.gallery(node) ⇒ Object
Adjacent previewable images; the class carries the image count (ActionText's convention).
-
.list_item(node) ⇒ Object
Attribute order follows Lexxy's export — checked items put aria-checked before value; items holding a nested list append the lexxy-nested-listitem class after value.
-
.mention(node) ⇒ Object
A content attachment (mention, embed):
contentcarries the escaped inner HTML;plainTextis not exported. -
.pending_upload(_node) ⇒ Object
An in-flight upload placeholder.
-
.provisional_paragraph(node) ⇒ Object
A cursor-placement placeholder; empty ones export to nothing.
-
.table(node) ⇒ Object
Lexxy wraps tables in a styled figure.
-
.table_cell(node) ⇒ Object
Class + background match Lexxy's own header-cell export.
-
.upload(node) ⇒ Object
An upload, in the exact shape ActionText round-trips: attribute order and presence mirror Lexxy's exportDOM (nulls omitted,
previewableonly when true,presentation="gallery"always).
Instance Method Summary collapse
-
#initialize(doc, nodes: {}) ⇒ Lexxy
constructor
A new instance of Lexxy.
Methods inherited from Lexical
Constructor Details
Class Method Details
.attachment_attr(node, html_name, stored) ⇒ Object
A stored nil (unset) is skipped; a stored empty string still emits.
96 97 98 99 100 |
# File 'lib/y/lexxy.rb', line 96 def self.(node, html_name, stored) return "" if node.attrs[stored].nil? %( #{html_name}="#{RenderRules.escape_attr(node.attrs[stored])}") end |
.attachment_tag(node) ⇒ Object
Lexxy's attachment tag is configurable (Lexxy.configure's
attachmentTagName, paired with ActionText::Attachment.tag_name on the
Rails side), and each attachment node stores the tag it was created
with. Emit the stored tag. The value is stored document data, not
markup, so anything that doesn't look like a tag name falls back to
ActionText's default.
83 84 85 86 |
# File 'lib/y/lexxy.rb', line 83 def self.(node) tag = node.attrs["tagName"].to_s tag.match?(/\A[a-zA-Z][a-zA-Z0-9-]*\z/) ? tag : "action-text-attachment" end |
.gallery(node) ⇒ Object
Adjacent previewable images; the class carries the image count (ActionText's convention).
21 22 23 |
# File 'lib/y/lexxy.rb', line 21 def self.gallery(node) %(<div class="attachment-gallery attachment-gallery--#{node.child_types.length}">#{node.content}</div>) end |
.list_item(node) ⇒ Object
Attribute order follows Lexxy's export — checked items put aria-checked before value; items holding a nested list append the lexxy-nested-listitem class after value.
42 43 44 45 46 47 48 49 |
# File 'lib/y/lexxy.rb', line 42 def self.list_item(node) out = +"<li" checked = node.attrs["__checked"] out << %( aria-checked="#{checked}") unless checked.nil? out << %( value="#{node.attrs["__value"] || 1}") out << %( class="lexxy-nested-listitem") if node.child_types.include?("list") "#{out}>#{node.content}</li>" end |
.mention(node) ⇒ Object
A content attachment (mention, embed): content carries the escaped
inner HTML; plainText is not exported.
68 69 70 71 72 73 74 75 |
# File 'lib/y/lexxy.rb', line 68 def self.mention(node) tag = (node) out = "<#{tag}" out << (node, "sgid", "sgid") out << (node, "content", "innerHtml") out << (node, "content-type", "contentType") "#{out}></#{tag}>" end |
.pending_upload(_node) ⇒ Object
An in-flight upload placeholder. Only the uploader's browser can complete it, so it is never finished content -- materialized output (Action Text bodies, search text) must not carry it.
91 92 93 |
# File 'lib/y/lexxy.rb', line 91 def self.pending_upload(_node) "" end |
.provisional_paragraph(node) ⇒ Object
A cursor-placement placeholder; empty ones export to nothing.
15 16 17 |
# File 'lib/y/lexxy.rb', line 15 def self.provisional_paragraph(node) node.content.empty? ? "" : "<p>#{node.content}</p>" end |
.table(node) ⇒ Object
Lexxy wraps tables in a styled figure.
26 27 28 |
# File 'lib/y/lexxy.rb', line 26 def self.table(node) %(<figure class="lexxy-content__table-wrapper"><table><tbody>#{node.content}</tbody></table></figure>) end |
.table_cell(node) ⇒ Object
Class + background match Lexxy's own header-cell export.
31 32 33 34 35 36 37 |
# File 'lib/y/lexxy.rb', line 31 def self.table_cell(node) header = node.attrs["__headerState"].is_a?(Numeric) && node.attrs["__headerState"].positive? return "<td>#{node.content}</td>" unless header style = %(style="background-color: rgb(242, 243, 245);") %(<th class="lexxy-content__table-cell--header" #{style}>#{node.content}</th>) end |
.upload(node) ⇒ Object
An upload, in the exact shape ActionText round-trips: attribute order
and presence mirror Lexxy's exportDOM (nulls omitted, previewable
only when true, presentation="gallery" always).
54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/y/lexxy.rb', line 54 def self.upload(node) tag = (node) out = "<#{tag}" out << (node, "sgid", "sgid") out << %( previewable="true") if node.attrs["previewable"] == true [%w[url src], %w[alt altText], %w[caption caption], %w[content-type contentType], %w[filename fileName], %w[filesize fileSize], %w[width width], %w[height height]] .each { |html_name, stored| out << (node, html_name, stored) } %(#{out} presentation="gallery"></#{tag}>) end |