Thu, 23 Mar 2023 15:12:30 +0000
Serialize XML in a consistent order by default
This overrides all XML serialization to emit attributes in an ordered form, so
the XML will match across multiple runs. This can be useful for comparing
different runs, or even two stanzas printed in the same run (e.g. if there is
a mismatch).
112
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
1 | require "verse" |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
2 | local xml = require "scansion.xml"; |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
3 | local s_format, s_gsub = string.format, string.gsub; |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
4 | |
174
662bd8c5ae28
Serialize XML in a consistent order by default
Matthew Wild <mwild1@gmail.com>
parents:
152
diff
changeset
|
5 | local unsorted_pairs = pairs; |
662bd8c5ae28
Serialize XML in a consistent order by default
Matthew Wild <mwild1@gmail.com>
parents:
152
diff
changeset
|
6 | local sorted_pairs = require "util.iterators".sorted_pairs; |
662bd8c5ae28
Serialize XML in a consistent order by default
Matthew Wild <mwild1@gmail.com>
parents:
152
diff
changeset
|
7 | |
112
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
8 | local escape_table = { ["'"] = "'", ["\""] = """, ["<"] = "<", [">"] = ">", ["&"] = "&" }; |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
9 | local function xml_escape(str) return (s_gsub(str, "['&<>\"]", escape_table)); end |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
10 | |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
11 | -- Dummy functions compatible with util.termcolours, |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
12 | -- just in case we add colour in the future |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
13 | local function getstyle() return "" end |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
14 | local function getstring(style, text) |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
15 | if not style then |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
16 | text = style; |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
17 | end |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
18 | return text; |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
19 | end |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
20 | |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
21 | local default_config = { |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
22 | indent = 2; |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
23 | preserve_whitespace = false; |
174
662bd8c5ae28
Serialize XML in a consistent order by default
Matthew Wild <mwild1@gmail.com>
parents:
152
diff
changeset
|
24 | sorted = true; |
112
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
25 | }; |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
26 | |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
27 | local function new(user_config) |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
28 | local config = setmetatable({}, { __index = function (_, k) return user_config[k] or default_config[k]; end }); |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
29 | local style_attrk = getstyle("yellow"); |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
30 | local style_attrv = getstyle("red"); |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
31 | local style_tagname = getstyle("red"); |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
32 | local style_punc = getstyle("magenta"); |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
33 | |
174
662bd8c5ae28
Serialize XML in a consistent order by default
Matthew Wild <mwild1@gmail.com>
parents:
152
diff
changeset
|
34 | local pairs = user_config.sorted and sorted_pairs or unsorted_pairs; |
662bd8c5ae28
Serialize XML in a consistent order by default
Matthew Wild <mwild1@gmail.com>
parents:
152
diff
changeset
|
35 | |
112
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
36 | local attr_format = " "..getstring(style_attrk, "%s")..getstring(style_punc, "=")..getstring(style_attrv, "'%s'"); |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
37 | local open_tag_format = getstring(style_punc, "<")..getstring(style_tagname, "%s").."%s"..getstring(style_punc, ">"); |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
38 | local close_tag_format = getstring(style_punc, "</")..getstring(style_tagname, "%s")..getstring(style_punc, ">"); |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
39 | local tag_format = open_tag_format.."%s"..close_tag_format; |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
40 | local short_close_tag_format = getstring(style_punc, "<")..getstring(style_tagname, "%s").."%s"..getstring(style_punc, "/>"); |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
41 | local function pretty_print(t, ind) |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
42 | ind = ind or config.indent; |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
43 | local children_text = ""; |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
44 | for i, child in ipairs(t) do |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
45 | if type(child) == "string" then |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
46 | if config.preserve_whitespace or child:match("%S") then |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
47 | children_text = children_text .. "\n"..string.rep(" ", ind) .. xml_escape(child); |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
48 | end |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
49 | else |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
50 | children_text = children_text .. "\n" .. pretty_print(child, ind+config.indent); |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
51 | end |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
52 | end |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
53 | |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
54 | local attr_string = ""; |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
55 | if t.attr then |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
56 | for k, v in pairs(t.attr) do |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
57 | if type(k) == "string" then |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
58 | attr_string = attr_string .. s_format(attr_format, k, tostring(v)); |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
59 | end |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
60 | end |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
61 | end |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
62 | |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
63 | local use_tag_format = tag_format; |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
64 | if #t == 0 then |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
65 | use_tag_format = short_close_tag_format; |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
66 | end |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
67 | if children_text ~= "" then |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
68 | children_text = children_text .. "\n" .. string.rep(" ", ind); |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
69 | end |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
70 | |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
71 | return string.rep(" ", ind)..s_format(use_tag_format, t.name, attr_string, children_text, t.name); |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
72 | end |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
73 | |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
74 | return function (s, ind) |
152
ba8219ac7484
scansion.pretty: Just emit input on invalid XML
Matthew Wild <mwild1@gmail.com>
parents:
112
diff
changeset
|
75 | local doc = xml.parse(s); |
ba8219ac7484
scansion.pretty: Just emit input on invalid XML
Matthew Wild <mwild1@gmail.com>
parents:
112
diff
changeset
|
76 | if not doc then |
ba8219ac7484
scansion.pretty: Just emit input on invalid XML
Matthew Wild <mwild1@gmail.com>
parents:
112
diff
changeset
|
77 | return s; -- Not valid XML, don't prettify |
ba8219ac7484
scansion.pretty: Just emit input on invalid XML
Matthew Wild <mwild1@gmail.com>
parents:
112
diff
changeset
|
78 | end |
112
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
79 | return pretty_print(doc, ind); |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
80 | end |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
81 | end |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
82 | |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
83 | return { |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
84 | new = new; |
bbb49227c174
scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
85 | } |