Skip to content

Commit

Permalink
css: Handle data-uri
Browse files Browse the repository at this point in the history
  • Loading branch information
lauriro committed Jan 5, 2025
1 parent 87b9e04 commit 5ede267
Show file tree
Hide file tree
Showing 7 changed files with 37 additions and 13 deletions.
39 changes: 29 additions & 10 deletions css.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@ exports.CSSStyleSheet = CSSStyleSheet

var fs = require("fs")
, path = require("path")
, urlRe = /(["']).*?\1|url\((['"]?)(?!\/|data:|https?:)(.*?)\2\)/g
, clearFn = (_, q, str) => q ? (q = str.indexOf("'") == -1 ? "'" : "\"", q + str.replace(q === "'" ? /\\(")/g : /\\(')/g, "$1")) + q :
_.replace(/[\t\n]+/g, " ")
.replace(/ *([,;{}>~+\/]) */g, "$1")
.replace(/;(?=})/g, "")
.replace(/: +/g, ":")
.replace(/([ :,])0\.([0-9])/g, "$1.$2")
, clear = s => s.replace(/("|')((?:\\\1|[^\1])*?)\1|[^"']+/g, clearFn).replace(/url\(("|')([^'"()\s]+)\1\)/g, "url($2)")
, clear = s => s
.replace(/("|')((?:\\\1|[^\1])*?)\1|[^"']+/g, clearFn)
.replace(/(["']).*?\1|url\(("|')([^'"()\s]+)\2\)/g, (m,q1,q2,u) => q1 ? m : "url(" + u + ")")
, read = (sheet, url, enc = "utf8") => fs.readFileSync(path.resolve(sheet.min.root || "", sheet.baseURI, url), enc)
, toRgb = {
rgb(r, g, b) {
Expand Down Expand Up @@ -50,21 +53,40 @@ var fs = require("fs")
set(style, prop, val) {
if (prop === "cssText") {
var m, k
, re = /([*_]?[-a-z]+)\s*:((?:("|')(?:\\.|(?!\3)[^\\])*?\3|[^"';])+)/ig
, sheet = style.parentRule && style.parentRule.parentStyleSheet
, min = sheet && sheet.min
, re = /([*_]?[-a-z]+)\s*:((?:("|')(?:\\.|(?!\3)[^\\])*?\3|[^"';])+)(?:;\s*\/\*!\s*(data-uri)\s*\*\/)?/ig
, len = 0
, lastIdx = {}
for (; (m = re.exec(val)); ) {
k = m[1]
if (lastIdx[k] >= 0) style.__[lastIdx[k]] = style[k]
style[style[lastIdx[k] = len++] = k] = style[
k === "float" ? "cssFloat" : k.replace(/-([a-z])/g, (_, a) => a.toUpperCase())
] = clear(m[2]).trim()
] = clear(min && m[4] ? transformValue(m[4], m[2]) : m[2]).trim()
}
style.length = len
} else {
if (!style[prop]) style[style.length++] = prop
style[prop] = style[prop === "cssFloat" ? "float" : prop.replace(/[A-Z]/g, "-$&").toLowerCase()] = clear(val)
}
function transformValue(cmd, v) {
var { DOMParser } = require("./dom.js")
if (cmd === "data-uri") {
return v.replace(urlRe, function(_, q1, q2, url) {
if (q1) return _
var ext = url.split(".").pop()
, enc = ext === "svg" ? "utf8" : "base64"
url = read(sheet, url, enc)
if (ext === "svg") {
enc = ""
ext += "+xml"
url = new DOMParser().parseFromString(url, "application/xml").toString(true).replace("#", "%23")
}
return "url('data:image/" + ext + ";" + enc + "," + url + "')"
})
}
}
}
}
, ruleTypes = {
Expand All @@ -81,17 +103,14 @@ var fs = require("fs")
},
import: {
get cssText() {
var href
, sheet = this.parentStyleSheet
var sheet = this.parentStyleSheet
, min = sheet.min
, text = this.text
, urlRe = /(["']).*?\1|url\((['"]?)(?!\/|data:|https?:)(.*?)\2\)/g
, urlFn = (m,q1,q2,u) => q1 ? m : "url('" + path.join(text.baseURI, u) + "')"
if (min && min.import) {
href = path.join(sheet.baseURI, this.href)
text = new CSSStyleSheet({
parentStyleSheet: sheet,
href,
href: this.href,
min
}, read(sheet, this.href))
if (sheet.baseURI !== text.baseURI) {
Expand Down Expand Up @@ -135,12 +154,12 @@ var fs = require("fs")

function CSSRule(text, parentStyleSheet, atType, parentRule = null) {
// Clear comments and trim
text = text.replace(/\/\*(?:[^*]|\*(?!\/))*\*\//g, "").trim()
text = text.trim()
var type = text[0] === "@" && text.slice(1, text.indexOf(" ")) || "style"
, rule = Object.create(ruleTypes[type] || ruleTypes[type === "page" || type === "font-face" || type === "counter-style" ? "style" : atType])
rule.cssText = text
rule.parentStyleSheet = parentStyleSheet
rule.parentRule = parentRule
rule.cssText = rule.type === 1 ? text : text.replace(/\/\*(?:[^*]|\*(?!\/))*\*\//g, "")
return rule
}

Expand Down
1 change: 1 addition & 0 deletions test/data/ui/css/samp1.css
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ Expects box-sizing: border-box;
.ul, /* .nul */
ul {
list-style: thumbs;
content: url('tiny.gif') "url('icon.png')"; /*! data-uri */
background: fixed bottom right/contain no-repeat #040505 url('ul.svg'); /*! data-uri */
}

Expand Down
2 changes: 1 addition & 1 deletion test/data/ui/css/samp1.css.snap
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
@media (min-width:500px){body{color:blue}}
@font-face{font-family:'Trickster';src:local('Trickster'),url(trickster-COLRv1.otf) format('opentype') tech(color-COLRv1),url(trickster-outline.otf) format('opentype'),url(trickster-outline.woff) format('woff')}
@counter-style thumbs{system:cyclic;symbols:'\1F44D';suffix:' '}
.ul,ul{list-style:thumbs;background:fixed bottom right/contain no-repeat #040505 url(ul.svg)}
.ul,ul{list-style:thumbs;content:url(tiny.gif) "url('icon.png')";background:fixed bottom right/contain no-repeat #040505 url(ul.svg)}
a{top:1px}
svg|a{top:2px}
*|a{top:3px}
Expand Down
2 changes: 1 addition & 1 deletion test/data/ui/css/samp1.css.snap1
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
@media (min-width:500px){body{color:blue}}
@font-face{font-family:'Trickster';src:local('Trickster'),url(trickster-COLRv1.otf) format('opentype') tech(color-COLRv1),url(trickster-outline.otf) format('opentype'),url(trickster-outline.woff) format('woff')}
@counter-style thumbs{system:cyclic;symbols:'\1F44D';suffix:' '}
.ul,ul{list-style:thumbs;background:fixed bottom right/contain no-repeat #040505 url(ul.svg)}
.ul,ul{list-style:thumbs;content:url(data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=) "url('icon.png')";background:fixed bottom right/contain no-repeat #040505 url('data:image/svg+xml;,<svg xmlns="http://www.w3.org/2000/svg" height="600" width="900" viewbox="-300 -200 900 600" fill="%2300a651"><path d="M14 340a2.2 2.2 0 1 1 0 .1zm9 20a5.2 5.2 0 1 1 0 .1z"></path></svg>')}
a{top:1px}
svg|a{top:2px}
*|a{top:3px}
Expand Down
2 changes: 1 addition & 1 deletion test/data/ui/css/samp1.css.snap2
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
@media (min-width:500px){body{color:blue}}
@font-face{font-family:'Trickster';src:local('Trickster'),url(trickster-COLRv1.otf) format('opentype') tech(color-COLRv1),url(trickster-outline.otf) format('opentype'),url(trickster-outline.woff) format('woff')}
@counter-style thumbs{system:cyclic;symbols:'\1F44D';suffix:' '}
.ul,ul{list-style:thumbs;background:fixed bottom right/contain no-repeat #040505 url(ul.svg)}
.ul,ul{list-style:thumbs;content:url(data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=) "url('icon.png')";background:fixed bottom right/contain no-repeat #040505 url('data:image/svg+xml;,<svg xmlns="http://www.w3.org/2000/svg" height="600" width="900" viewbox="-300 -200 900 600" fill="%2300a651"><path d="M14 340a2.2 2.2 0 1 1 0 .1zm9 20a5.2 5.2 0 1 1 0 .1z"></path></svg>')}
a{top:1px}
svg|a{top:2px}
*|a{top:3px}
Expand Down
Binary file added test/data/ui/css/tiny.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions test/data/ui/css/ul.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 5ede267

Please sign in to comment.