In input tag's attribute pattern, to pass regex pattern, even if it's RegExp object, we need to escape /.
m("input", {
"type": "text",
"value": this.data.expected_dia_ore_num_per_chunk,
"pattern": /(0|\d{1,}\.\d*)/,
"min": 0
})
produce
<input pattern="/(0|\d{1,}\.\d*)/" min="0" type="text">
"pattern": new RegExp("(0|\d{1,}\.\d*)") is same as above.
Above example code produce
<input pattern="/(0|d{1,}.d*)/" min="0" type="text">
So, I need to write like below:
m("input", {
"type": "text",
"value": this.data.expected_dia_ore_num_per_chunk,
"pattern": "(0|\\d{1,}\\.\\d*)",
"min": 0
})
I'm -1 on this. You should be passing a string, not a literal regular expression, as that's what it uses. Consider it this way: input.pattern is basically passed into new RegExp(pattern, "u") as a raw string, and the HTML interface was designed around it.
If you would still prefer to use regular expression literals, feel free to write a library function (it's pretty easy) to convert it for you.
function r(re) {
return re.toString().slice(1, re.unicode ? -2 : -1).replace(/"\\", "\\\\")
}
Both node.setAttribute(name, /regex/) and node.pattern = /regex/ auto convert the regex to its string variant so it's strange that it doesn't implicitly work(assuming mithril doesn't try to escape values before setting attributes).
@isiahmeadows OK, Ok, ok. I will forget to pass RegExp object. However, I cannot understand why "pattern": "(0|\d{1,}\.\d*)" also produce same broken html? Forcing user to call String.prototype.replace manually is dirty, isn't it?
@yumetodo Try "(0|\\d{1,}\\.\\d*)" (escaping the backslashes.)
@thysultan That's strange (and a bug if true). Mithril makes no attempt to escape anything beyond input.value checking (we have to compare values to prevent Chrome weirdness, and it's not uncommon to see value: 0, which needs converted to value: "0" when comparing).
We don't do anything special for attributes values, and, at least in Firefox, the DOM setter and setAttribute behave like Mithril does. (Edit, actually, the same happens in Chrome and Safari).
You can pass regex.source though, it does what you want @yumetodo (see the #oof input in the example).
AFAICT, the browser does the equivalent of "" + value to convert to string (it throws when you pass symbols, and converts everything else).
Try "(0|\d{1,}\.\d*)" (escaping the backslashes.)
I've already shown the workaround.
it's not uncommon to see
value: 0, which needs converted tovalue: "0"when comparing
!!
That's very kind of you.
setAttribute behave like Mithril does
oh...
That means element.setAttribute escape "(0|\d{1,}\.\d*)" to (0|d{1,}.d*)...
@yumetodo with what browser do you see that?
What I see is that when you do element.pattern = /foo/, the value of pattern becomes "/foo/", with the delimiting slashes included. It will thus try to match /\/foo\//. Escape sequences (at least those \d) are passed correctly.
/(0|\d{1,}\.\d*)/.source does what you want without double escapes.
Firefox 58.0.2.
@yumetodo That's my primary borwser as well and I can't reproduce the escaping behavior you describe...
Could you post a Flems that demonstrates the issue? Follow the previous link, cook up your example and share the URL here (it is automatically updated when you change the content of the page).
In Firefox 58.0.2:
/(0|\d{1,}\.\d*)/.source
returns "(0|\\d{1,}\\.\\d*)".
According to my understanding from here, element.setAttribute remove \.Then, finally produved html is
<input pattern="(0|\d{1,}\.\d*)" type="text">
that exactly I want.
ex.)
@pygy Is there any different behavior?
BTW, is it possible that mithril recognize input[type=text] and avoid escaping by element.setAttribute?
@yumetodo Now I understand where your confusion stems from!
The escaping rules are different for JS and HTML. Also, the way strings are printed into the console doesn't help. In Firefox, console.log( "\\d" ) prints \d, but if you do console.log(["\\d"]), you get ["\\d"] which is more helpful. Chrome criminally prints ["\d"].
Here are a few examples:
console.log("\d".length)
// 1
console.log("\d" === "d")
// true
console.log("\\d".length)
// 2
console.log("\\d".codePointAt(0))
// 92, the code point for the backshlash
console.log("\\d".codePointAt(1))
// 100, the code point for the lower case "d".
So, regarding escape sequence, JS has about a handful \\, \", \', \r, \n and more obscure ones, and invalid escape sequences (like \d) behave as if there was no backslash.
In HTML, the backslash is not used for escape sequences, it is a plain character, and <input id=foo data-x="\d"> sets foo.dataset.x to the corresponding string, which would be represented as "\\d" in JS. (Escaping in HTML is made using character references like & or &).
At long last, regexps support the same escape sequence as JS strings, and a few others to define character sets, back references, or to escape characters that are otherwise meaningful in regexps, like +, *, / or [.
So the source of a regexp that matches a single backslash, /\\/.source has a .length of 2 and is represented as "\\\\" in JS source. In HTML, it would be <input pattern="\\">.
There's no way around it. I hope I didn't add to the confusion :-)
...invalid escape sequences (like
\d) behave as if there was no backslash.
!!
I usually use C++ and almost all c++ compiler warn invalid escape sequences like
warning: unknown escape sequence: '\d'
so that I had no chance to notice.
Thank you!