Security News
JSR Working Group Kicks Off with Ambitious Roadmap and Plans for Open Governance
At its inaugural meeting, the JSR Working Group outlined plans for an open governance model and a roadmap to enhance JavaScript package management.
JavaScript object to CSS compiler. ~720 bytes mingzipped.
Think SASS, but in JSONish syntax.
Inspired by restlye.js and JSS, but smaller :-).
##Table of Contents
TOC generated with DocToc, then tweaked a bit.
This is mostly intended as a client-side helper to generate styles for Virtual DOM (React, Mithril, Mercury...) components.
Whether or not this is useful as a general CSS replacement remains to be seen.
For that use case, it trades off file size down the line for time lost because the rendering is blocked by executing JS. Benchmarks, especially on underpowered devices are yet to be performed.
$ npm install j2c
Please send a PR if you want to see it inclueded in other package systems.
j2c.vendors = [] // for the sake of this demo
// defaults to ["o", "ms", "moz", "webkit"].
r = j2c("ul.my_root_class")
r.add({
"@media condition": {
color: "red"
},
// properties for the main ul.my_root_class elements
font: {
size: "2em",
family: "sans-serif"
},
// underscores in property names are converted to dashes.
background_color: "#44f",
// sub-selector for children element, notice the mandatory initial space
// signifying a child element.
" li": {
padding:{
left: "5px"
top: "10px"
},
// convenient shortcut.
border: {"left/right": {width: 2px}}
}
})
console.log(r.toString())
Output (beautified):
@media condition {
ul.my_root_class {
color:red;
}
}
ul.my_root_class li {
padding-left:5px;
padding-top:10px;
border-left-width:2px;
border-right-width:2px;
}
ul.my_root_class {
font-size:2em;
font-family:sans-serif;
background-color:#44f;
}
If you don't truncate the vendors list as I did in the example above, you'll get each property prefixed for each vendor.
Most of the resulting combinations don't make any sense (-moz-color
FTW), and they are simply ignored by browsers. That's the price to pay for the small code size.
Alternatively, you can specify the prefixes by hand using the "/" operator where needed:
j2c.vendors = []
j2c("p").add({
// Notice the trailing slash, required for the unprefixed property.
"-o/-ms/-moz/-webkit/": {foo: "bar"},
hello: "world"
}).toString()
Compiles to
p {
-o-foo:bar;
-ms-foo:bar;
-moz-foo:bar;
-webkit-foo:bar;
foo:bar;
hello:world;
}
If no root selector is provided, J2C
creates one (a unique class).
r = j2c()
r.prefix // --> ".j2c_$token_$counter" where `$token` is unique per
// j2c instance, and `$counter` is incremented to
// ensure that these classes are unique.
j2c
considers that object keys matching /^[-_0-9A-Za-z\/]+$/
as properties, and everything else as (sub-)selectors.
Selectors are concatenated as is, while properties are concatenated with hyphens. {" ul": {" li": {padding: {left:10}}}}
becomes ul li{padding-left:10px;}
. {" p":{".foo":{color:"red"}}}
, is translated to p.foo:{color:red;}
.
r = j2c("ul.my_root_class")
r.add({
"font-size": ["2em", "2rem"]
})
console.log(r.toString())
becomes
.foo {
font-size:2em;
font-size:2rem;
}
Alternatively
r = j2c("ul.my_root_class")
r.add([
{
"font-size": "2em"
},
{
"font-size": "2rem"
}
])
console.log(r.toString())
becomes
ul.my_root_class {
font-size:2em;
}
ul.my_root_class {
font-size:2rem;
}
Most At-rules are handled out of the box by sheet.add()
. However, @font-face
and @keyframes
have are not covered and they are implemented respectively by sheet.font(definitions)
and sheet.keyframes(name, definitions)
. The latter automatically generates browser-specific @-vendor-keyframes
blocks.
Here's a excerpt from the j2c
port of the PocketGrid.
j2c("").add({
".block,.blockgroup":{
",:before,:after":{ // Notice the initial coma.
"box-sizing":"border-box"
}
}
}
Nesting ",:before,:after"
inside the ".block,.blockgroup"
block combines [".block", ".blockgroup"]
with ["", ":before", ":after"]
, giving
.block,.block:before,.block:after,.blockgroup,.blockgroup:before,.blockgroup:after{
box-sizing:border-box
}
Mathy folks call this as a Cartesian product.
Since sheet.add
only accepts property names that match /^[-_0-9A-Za-z]+$/
, it is not possible to express CSS hacks using objects. You can, however, work around the issue by using arrays and strings instead.
Here's another modified excerpt from the PocketGrid port:
j2c("").add({
".blockgroup": [
"*zoom: 1; /* hack */",
{
"list-style-type":"none",
padding:0,
margin:0
}
]
})
Array elements are inserted in sequence, and string literals are treated as a list of properties, and inserted as is.
Result:
.blockgroup{
*zoom: 1; /* hack */
}
.blockgroup{
list-style-type:none;
padding:0;
margin:0;
}
You can also pass th result of j2c.inline
which is less picky about property names.
Here's an example that demonstrates most of the j2c.inline
capabilities:
j2c.vendors = []
j2c.inline({
background_image: "url(bg.png)",
border: {
color: ["#33e", "rgba(64,64,255,0.8)"],
"top/left": {width: "1px"},
}
color: ,
font: {
size: "2em",
weight: 700
},
"*zoom": 1
})
Result (paired items are guaranteed to appear in order):
background-image: url(bg.png);
border-color: #33e;
border-color: rgba(64,64,255,0.8);
border-top-width: 1px;
border-left-width: 1px;
font-size: 2em;
font-weight: 700;
*zoom: 1;
If order is iportant, use Arrays
:
j2c.inline([
"margin:0",
{
margin_left:{
width: "2px",
color: "red"
}
}
])
Becomes
margin: 0;
// the above is guaranteed to occur before the next two
margin-left-color:red;
margin-left-width:2px;
Also, provided the vendors list isn't empty, each property ends up prefixed by each vendor.
console.log(j2c.inline({
float:"left";
}));
... outputs ...
-o-float:left;
-ms-float:left;
-moz-float:left;
-webkit-float:left;
float:left;
j2c
and static fieldsj2c([root:String]) : Sheet
: Creates a Sheet object.j2c.inline(props:(Object|Array|String)) : String
: returns a declaration list suitable for inline stylesj2c.vendors = ["o", "ms", "moz", "webkit"]
(r/w): list of vendor prefixes.Sheet
methodssheet.add(statements:(Object|Array|String)) : Sheet
: add a series of statements to the style sheet. Returns the Sheet
for chaining.sheet.font(definitions:(Object|Array|String)) : Sheet
: creates a @font-face
block. Returns the Sheet
for chaining.sheet.keyframes(name:String, statements:(Object|Array|String)) : Sheet
: creates a @keyframes
block. Returns the Sheet
for chaining.sheet.toString() : String
: the stylesheet in string form.j2c
relies on JS objects to define selectors and properties. As a consequence, the source order cannot be guaranteed to be respected in the output.
j2c(".hello").add({
foo:"bar",
baz:"qux"
}).toString()
This may produce either .hello{foo:bar;baz:qux;}
or .hello{baz:qux;foo:bar;}
.
If you need some elements to happen in order, use an array of objects.
j2c(".hello").add([
{foo:"bar"},
{baz:"qux"}
]).toString()
This will always yield .hello{foo:bar;}.hello{baz:qux;}
.
j2c
knows the bare minimum to output a valid stylesheet when provided with valid input. It will hapily accept invalid selectors, properties and values, and could in that case produce a broken stylesheet.
I may get around and write a validator companion, but I'm not there yet :-).
For debugging purposes, I recommend that you pipe j2c
's output through a be-au-ti-fier
FAQs
A tiny CSS in JS solution.
The npm package j2c receives a total of 68 weekly downloads. As such, j2c popularity was classified as not popular.
We found that j2c demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
At its inaugural meeting, the JSR Working Group outlined plans for an open governance model and a roadmap to enhance JavaScript package management.
Security News
Research
An advanced npm supply chain attack is leveraging Ethereum smart contracts for decentralized, persistent malware control, evading traditional defenses.
Security News
Research
Attackers are impersonating Sindre Sorhus on npm with a fake 'chalk-node' package containing a malicious backdoor to compromise developers' projects.