From 42d24fa2607df63aacfc7dbdcc99b458d4656cf2 Mon Sep 17 00:00:00 2001 From: edukisto <52005215+edukisto@users.noreply.github.com> Date: Tue, 2 Mar 2021 13:03:17 +0300 Subject: [PATCH] INI: Consistently mimic Win32 INI parsing (#2779) --- components/prism-ini.js | 45 ++++++++-- components/prism-ini.min.js | 2 +- tests/languages/ini/comment_feature.test | 65 ++++++++++---- tests/languages/ini/header_feature.test | 86 ++++++++++++++++++ tests/languages/ini/key_value_feature.test | 90 ++++++++++++++----- ..._feature.test => punctuation_feature.test} | 24 +++-- 6 files changed, 255 insertions(+), 57 deletions(-) create mode 100644 tests/languages/ini/header_feature.test rename tests/languages/ini/{selector_feature.test => punctuation_feature.test} (51%) diff --git a/components/prism-ini.js b/components/prism-ini.js index c7b45a8ba4..e950caf96a 100644 --- a/components/prism-ini.js +++ b/components/prism-ini.js @@ -1,11 +1,42 @@ Prism.languages.ini= { - 'comment': /^[ \t]*[;#].*$/m, - 'selector': /^[ \t]*\[.*?\]/m, - 'constant': /^[ \t]*[^\s=]+?(?=[ \t]*=)/m, - 'attr-value': { - pattern: /=.*/, + + /** + * The component mimics the behavior of the Win32 API parser. + * + * @see {@link https://github.com/PrismJS/prism/issues/2775#issuecomment-787477723} + */ + + 'comment': { + pattern: /(^[ \f\t\v]*)[#;][^\n\r]*/m, + lookbehind: true + }, + 'header': { + pattern: /(^[ \f\t\v]*)\[[^\n\r\]]*\]?/m, + lookbehind: true, inside: { - 'punctuation': /^[=]/ + 'section-name': { + pattern: /(^\[[ \f\t\v]*)[^ \f\t\v\]]+(?:[ \f\t\v]+[^ \f\t\v\]]+)*/, + lookbehind: true, + alias: 'selector' + }, + 'punctuation': /\[|\]/ } - } + }, + 'key': { + pattern: /(^[ \f\t\v]*)[^ \f\n\r\t\v=]+(?:[ \f\t\v]+[^ \f\n\r\t\v=]+)*(?=[ \f\t\v]*=)/m, + lookbehind: true, + alias: 'attr-name' + }, + 'value': { + pattern: /(=[ \f\t\v]*)[^ \f\n\r\t\v]+(?:[ \f\t\v]+[^ \f\n\r\t\v]+)*/, + lookbehind: true, + alias: 'attr-value', + inside: { + 'inner-value': { + pattern: /^("|').+(?=\1$)/, + lookbehind: true + } + } + }, + 'punctuation': /=/ }; diff --git a/components/prism-ini.min.js b/components/prism-ini.min.js index 620cdb55b4..a4e2d8e09b 100644 --- a/components/prism-ini.min.js +++ b/components/prism-ini.min.js @@ -1 +1 @@ -Prism.languages.ini={comment:/^[ \t]*[;#].*$/m,selector:/^[ \t]*\[.*?\]/m,constant:/^[ \t]*[^\s=]+?(?=[ \t]*=)/m,"attr-value":{pattern:/=.*/,inside:{punctuation:/^[=]/}}}; \ No newline at end of file +Prism.languages.ini={comment:{pattern:/(^[ \f\t\v]*)[#;][^\n\r]*/m,lookbehind:!0},header:{pattern:/(^[ \f\t\v]*)\[[^\n\r\]]*\]?/m,lookbehind:!0,inside:{"section-name":{pattern:/(^\[[ \f\t\v]*)[^ \f\t\v\]]+(?:[ \f\t\v]+[^ \f\t\v\]]+)*/,lookbehind:!0,alias:"selector"},punctuation:/\[|\]/}},key:{pattern:/(^[ \f\t\v]*)[^ \f\n\r\t\v=]+(?:[ \f\t\v]+[^ \f\n\r\t\v=]+)*(?=[ \f\t\v]*=)/m,lookbehind:!0,alias:"attr-name"},value:{pattern:/(=[ \f\t\v]*)[^ \f\n\r\t\v]+(?:[ \f\t\v]+[^ \f\n\r\t\v]+)*/,lookbehind:!0,alias:"attr-value",inside:{"inner-value":{pattern:/^("|').+(?=\1$)/,lookbehind:!0}}},punctuation:/=/}; \ No newline at end of file diff --git a/tests/languages/ini/comment_feature.test b/tests/languages/ini/comment_feature.test index 30e373c63a..48e1d39db0 100644 --- a/tests/languages/ini/comment_feature.test +++ b/tests/languages/ini/comment_feature.test @@ -1,15 +1,50 @@ -; -; foobar -# foobar - ----------------------------------------------------- - -[ - ["comment", ";"], - ["comment", "; foobar"], - ["comment", "# foobar"] -] - ----------------------------------------------------- - -Checks for comments. + # + ; + # + ; +# +# +# +#; +#[foo] +#foo=bar +#foobar +; +; +; +;# +;[foo] +;foo=bar +;foobar +foo#bar +foobar# +foo;bar +foobar; + +---------------------------------------------------- + +[ + ["comment", "#"], + ["comment", ";"], + ["comment", "#"], + ["comment", ";"], + ["comment", "#"], + ["comment", "#\t"], + ["comment", "# "], + ["comment", "#;"], + ["comment", "#[foo]"], + ["comment", "#foo=bar"], + ["comment", "#foobar"], + ["comment", ";"], + ["comment", ";\t"], + ["comment", "; "], + ["comment", ";#"], + ["comment", ";[foo]"], + ["comment", ";foo=bar"], + ["comment", ";foobar"], + "\nfoo#bar\nfoobar#\nfoo;bar\nfoobar;" +] + +---------------------------------------------------- + +Checks for comments. diff --git a/tests/languages/ini/header_feature.test b/tests/languages/ini/header_feature.test new file mode 100644 index 0000000000..9f0df51ac4 --- /dev/null +++ b/tests/languages/ini/header_feature.test @@ -0,0 +1,86 @@ + [foo1] +[ "foo2" ] +[ foo3 ] +[" foo4 "] +["foo5 bar5"] +["foo6"] +[foo7 +[foo8 bar8] +[foo9[bar9] +[foo10] +[foo11]bar11] + +---------------------------------------------------- + +[ + ["header", [ + ["punctuation", "["], + ["section-name", "foo1"], + ["punctuation", "]"] + ]], + + ["header", [ + ["punctuation", "["], + ["section-name", "\"foo2\""], + ["punctuation", "]"] + ]], + + ["header", [ + ["punctuation", "["], + ["section-name", "foo3"], + ["punctuation", "]"] + ]], + + ["header", [ + ["punctuation", "["], + ["section-name", "\" foo4 \""], + ["punctuation", "]"] + ]], + + ["header", [ + ["punctuation", "["], + ["section-name", "\"foo5 bar5\""], + ["punctuation", "]"] + ]], + + ["header", [ + ["punctuation", "["], + ["section-name", "\"foo6\""], + ["punctuation", "]"] + ]], + + ["header", [ + ["punctuation", "["], + ["section-name", "foo7"] + ]], + + ["header", [ + ["punctuation", "["], + ["section-name", "foo8 bar8"], + ["punctuation", "]"] + ]], + + ["header", [ + ["punctuation", "["], + ["section-name", "foo9[bar9"], + ["punctuation", "]"] + ]], + + ["header", [ + ["punctuation", "["], + ["section-name", "foo10"], + ["punctuation", "]"] + ]], + + ["header", [ + ["punctuation", "["], + ["section-name", "foo11"], + ["punctuation", "]"] + ]], + + "bar11]" +] + +---------------------------------------------------- + +Checks for headers (and section names). diff --git a/tests/languages/ini/key_value_feature.test b/tests/languages/ini/key_value_feature.test index 5d25d9d3cf..f39988bd45 100644 --- a/tests/languages/ini/key_value_feature.test +++ b/tests/languages/ini/key_value_feature.test @@ -1,21 +1,69 @@ -foo=Bar Baz -foobar=42 - ----------------------------------------------------- - -[ - ["constant", "foo"], - ["attr-value", [ - ["punctuation", "="], - "Bar Baz" - ]], - ["constant", "foobar"], - ["attr-value", [ - ["punctuation", "="], - "42" - ]] -] - ----------------------------------------------------- - -Checks for key/value pairs. \ No newline at end of file + bar1 = + "bar2" = + 'bar3' = + bar4 = +" bar5 "= +"bar6"= +' bar7 '= +'bar8'= += baz9 += "baz10" += 'baz11' += baz12 +=" baz13 " +="b14"a14"z14" +="baz15" +="baz16 +=' baz17 ' +='baz18' +=b19"a19"z19 +=b20"az20 +=ba21"z21 +=baz22 +=baz23" +bar24 +bar25 baz25=qux25 +bar26= +bar27==baz27 +bar28=baz28 +bar29=baz29 qux29 +bar30=baz30=qux30 + +---------------------------------------------------- + +[ + ["key", "bar1"], ["punctuation", "="], + ["key", "\"bar2\""], ["punctuation", "="], + ["key", "'bar3'"], ["punctuation", "="], + ["key", "bar4"], ["punctuation", "="], + ["key", "\" bar5 \""], ["punctuation", "="], + ["key", "\"bar6\""], ["punctuation", "="], + ["key", "' bar7 '"], ["punctuation", "="], + ["key", "'bar8'"], ["punctuation", "="], + ["punctuation", "="], ["value", ["baz9"]], + ["punctuation", "="], ["value", ["\"", ["inner-value", "baz10"], "\""]], + ["punctuation", "="], ["value", ["'", ["inner-value", "baz11"], "'"]], + ["punctuation", "="], ["value", ["baz12"]], + ["punctuation", "="], ["value", ["\"", ["inner-value", " baz13 "], "\""]], + ["punctuation", "="], ["value", ["\"", ["inner-value", "b14\"a14\"z14"], "\""]], + ["punctuation", "="], ["value", ["\"", ["inner-value", "baz15"], "\""]], + ["punctuation", "="], ["value", ["\"baz16"]], + ["punctuation", "="], ["value", ["'", ["inner-value", " baz17 "], "'"]], + ["punctuation", "="], ["value", ["'", ["inner-value", "baz18"], "'"]], + ["punctuation", "="], ["value", ["b19\"a19\"z19"]], + ["punctuation", "="], ["value", ["b20\"az20"]], + ["punctuation", "="], ["value", ["ba21\"z21"]], + ["punctuation", "="], ["value", ["baz22"]], + ["punctuation", "="], ["value", ["baz23\""]], + "\nbar24\n", + ["key", "bar25 baz25"], ["punctuation", "="], ["value", ["qux25"]], + ["key", "bar26"], ["punctuation", "="], + ["key", "bar27"], ["punctuation", "="], ["value", ["=baz27"]], + ["key", "bar28"], ["punctuation", "="], ["value", ["baz28"]], + ["key", "bar29"], ["punctuation", "="], ["value", ["baz29 qux29"]], + ["key", "bar30"], ["punctuation", "="], ["value", ["baz30=qux30"]] +] + +---------------------------------------------------- + +Checks for key-value pairs. diff --git a/tests/languages/ini/selector_feature.test b/tests/languages/ini/punctuation_feature.test similarity index 51% rename from tests/languages/ini/selector_feature.test rename to tests/languages/ini/punctuation_feature.test index 3158a665da..c72a16d0a1 100644 --- a/tests/languages/ini/selector_feature.test +++ b/tests/languages/ini/punctuation_feature.test @@ -1,13 +1,11 @@ -[owner] -[foobar] - ----------------------------------------------------- - -[ - ["selector", "[owner]"], - ["selector", "[foobar]"] -] - ----------------------------------------------------- - -Checks for section titles. \ No newline at end of file += + +---------------------------------------------------- + +[ + ["punctuation", "="] +] + +---------------------------------------------------- + +Checks for punctuation marks.