diff --git a/CHANGES.md b/CHANGES.md
index dce2373af4..75e435d373 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -48,6 +48,7 @@ Language Improvements:
- enh(erlang) Add underscore separators to numeric literals (#2554) [Sergey Prokhorov][]
- enh(handlebars) Support for sub-expressions, path-expressions, hashes, block-parameters and literals (#2344) [Nils Knappmeier][]
- enh(protobuf) Support multiline comments (#2597) [Pavel Evstigneev][]
+- fix(toml) Improve key parsing (#2595) [Antoine du Hamel][]
[Josh Goebel]: https://github.com/yyyc514
[Peter Plantinga]: https://github.com/pplantinga
@@ -62,6 +63,7 @@ Language Improvements:
[Jim Mason]: https://github.com/RocketMan
[lioshi]: https://github.com/lioshi
[Pavel Evstigneev]: https://github.com/Paxa
+[Antoine du Hamel]: https://github.com/aduh95
## Version 10.0.2
diff --git a/src/languages/ini.js b/src/languages/ini.js
index 73c19409b2..0f4aaf527f 100644
--- a/src/languages/ini.js
+++ b/src/languages/ini.js
@@ -1,3 +1,5 @@
+import * as regex from '../lib/regex';
+
/*
Language: TOML, also INI
Description: TOML aims to be a minimal configuration file format that's easy to read due to obvious semantics.
@@ -54,6 +56,17 @@ export default function(hljs) {
relevance:0
};
+ var BARE_KEY = /[A-Za-z0-9_-]+/;
+ var QUOTED_KEY_DOUBLE_QUOTE = /"(\\"|[^"])*"/;
+ var QUOTED_KEY_SINGLE_QUOTE = /'[^']*'/;
+ var ANY_KEY = regex.either(
+ BARE_KEY, QUOTED_KEY_DOUBLE_QUOTE, QUOTED_KEY_SINGLE_QUOTE
+ );
+ var DOTTED_KEY = regex.concat(
+ ANY_KEY, '(\\s*\\.\\s*', ANY_KEY, ')*',
+ regex.lookahead(/\s*=\s*[^#\s]/)
+ );
+
return {
name: 'TOML, also INI',
aliases: ['toml'],
@@ -66,7 +79,7 @@ export default function(hljs) {
begin: /\[+/, end: /\]+/
},
{
- begin: /^[a-z0-9\[\]_\.-]+(?=\s*=\s*)/,
+ begin: DOTTED_KEY,
className: 'attr',
starts: {
end: /$/,
diff --git a/test/markup/ini/keys.expect.txt b/test/markup/ini/keys.expect.txt
new file mode 100644
index 0000000000..b80c964599
--- /dev/null
+++ b/test/markup/ini/keys.expect.txt
@@ -0,0 +1,32 @@
+
+key = "value"
+bare_key = "value"
+bare-key = "value"
+1234 = "value"
+
+
+"127.0.0.1" = "value"
+"character encoding" = "value"
+"ʎǝʞ" = "value"
+'key2' = "value"
+'quoted "value"' = "value"
+
+"key \"containing\" backslash" = 6
+'key \"containing" backslash\' = 6
+
+
+"" = "blank"
+'' = 'blank'
+
+
+name = "Orange"
+physical.color = "orange"
+physical.shape = "round"
+site."google.com" = true
+3.14159 = "pi"
+
+
+hello . world = "!"
+
+
+ hello = "World!"
diff --git a/test/markup/ini/keys.txt b/test/markup/ini/keys.txt
new file mode 100644
index 0000000000..5fdbe52b0e
--- /dev/null
+++ b/test/markup/ini/keys.txt
@@ -0,0 +1,32 @@
+# Bare keys:
+key = "value"
+bare_key = "value"
+bare-key = "value"
+1234 = "value"
+
+# Quoted keys:
+"127.0.0.1" = "value"
+"character encoding" = "value"
+"ʎǝʞ" = "value"
+'key2' = "value"
+'quoted "value"' = "value"
+
+"key \"containing\" backslash" = 6
+'key \"containing" backslash\' = 6
+
+# empty quoted key is allowed
+"" = "blank" # VALID but discouraged
+'' = 'blank' # VALID but discouraged
+
+# Dotted keys:
+name = "Orange"
+physical.color = "orange"
+physical.shape = "round"
+site."google.com" = true
+3.14159 = "pi"
+
+# Whitespace around dot-separated parts is ignored:
+hello . world = "!"
+
+# Whitespace is ignored around key names and values
+ hello = "World!"