Git Product home page Git Product logo

istf-spec's Introduction

JSS Documentation site

http://cssinjs.org

Site generator features

  • Designed for multi-repo projects.
  • Loads versions using github API, allows users to select the version.
  • Renders everything at runtime.
  • Has SSR.
  • Doesn't need prepared .md files locally, loads everything via XHR from github.

Todo

Move the site engine to a separate repo. It can be actually used for any projects.

Issues

File a bug against cssinjs/jss prefixed with [site].

istf-spec's People

Contributors

kitten avatar kof avatar lencioni avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

istf-spec's Issues

Nested styles

There are cases where nesting is required, even if it is most of the time evil.

Multi values

In CSS we can do this:

border: 1px solid red, 1px solid green;

How about cssinjs?

Classnames

As we def. need to support both scoped (generated) and regular class names, there is a question how to do that in a way that doesn't introduces much troubles to the runtimes.

I think class name generation algorithm should be out of scope for the standard, instead runtime should decide. There are too many hashing algorithms and counter based solutions. If we would try to generate the class name within the standard, we would need to make sure it will work across the entire world. If we let runtimes decide on the algorithm, it just has to work within a specific project.

Camel case support

In order to allow user writing in camelcase e.g. "fontSize" libraries actually need to convert it to dash separated syntax e.g. "font-size"

Fix marker codes

// ...
const PARENT_SELECTOR = 4
const COMPOUND_SELECTOR_START = 5
const COMPOUND_SELECTOR_END = 6
const SPACE_COMBINATOR = 5 // Starting from here it's unfortunately messed up now
const DOUBLED_CHILD_COMBINATOR = 6
const CHILD_COMBINATOR = 7
const NEXT_SIBLING_COMBINATOR = 8
// ...

Versioning

I think we should have a version number from the beginning. We should also think about a migration strategy for the future in case we want to change something.

Shorthands

In CSS we can write a short notation:

border: 1px solid red;

Which is in a full form:

border-width: 1px;
border-style: solid;
border-color: red;

While shorthand is practical, it is not typable and not supported by react-native.

Should we find a replacement or even remove a support for this from this standard?

Runtime dependency injection

As a module author, I want a standard CSS-in-JS format to allow me to provide my styles agnostic of whatever runtime or UI library the parent app is using.

As a module consumer, I want to be able to collect all the styles provided in my dependency tree and pass them to my runtime of choice.

IMO this is essential if we want to allow people to publish CSS-in-JS without punishing them for picking the wrong library.

Does this sound like a good idea? Do we have any thoughts on how best to achieve this?

Add special cases for single-argument functions url() and calc()

We discovered that both url() and calc() are rather special as CSS functions.

  • url() is special because it contains... well... urls with optional quotes. This means that no matter whether the user types quotes or not, it will only contain a single value, a url.
  • calc() is special since it contains operators that don't occur in normal css, namely: /, - (normally a character that is part of a word like a class for example)...

Interpolations inside strings in values

While working on parsing CSS values I've come across some edge cases that are not sufficiently covered by the ISTF spec as it is right now.

Considering a value with a string interpolations can be put inside or around the string:

css`
  content: "${'some content'}";
  content: "some ${'content'}";
`

How do we represent an interpolation inside a string? Right now the only way for it to be represented would be:

[COMPOUND_VALUE_START],
  [VALUE, '"'],
  [JS_FUNCTION_VALUE, x], // 'some content'
  [VALUE, '"'],
[COMPOUND_VALUE_END],

and

[COMPOUND_VALUE_START],
  [VALUE, '"some '],
  [JS_FUNCTION_VALUE, x], // 'content'
  [VALUE, '"'],
[COMPOUND_VALUE_END],

The problem here is that since we see whitespaces as non-significant usually inside values, which is quite handy, here it would lead to mistakes. How do we know to join the values without a whitespace in-between them during runtime?

The easiest solution would be to introduce a string value:

// content: "${'some content'}";
[STRING_START, DOUBLE_QUOTES],
[JS_FUNCTION_VALUE],
[STRING_END]

// content: "some ${'content'}";
[STRING_START, DOUBLE_QUOTES],
  [VALUE, 'some '],
  [JS_FUNCTION_VALUE],
[STRING_END],

It's important to keep the type of quote around so we don't have to change any escapes or add more for potential conflicting quotes inside strings: " \" "; For that we could introduce more types e.g. SINGLE_QUOTES = 1 & DOUBLE_QUOTES = 2

cc @kof

Fallbacks support

In CSS we can do this:

supported-property: value;
unsupported-property: value;

What about cssinjs?

Optimization: use single array

Should we go for single array? As consequence we will only be able to express this:

  1. [MARKER]
  2. [MARKER, value]

Right now it seems to work nicely.

[
  [RULE_START, 1],
    [SELECTOR, 'body'],
    [PROPERTY, 'color'],
    [VALUE, 'red'],
  [RULE_END]
]

will become

[
  RULE_START, 1,
    SELECTOR, 'body',
    PROPERTY, 'color',
    VALUE, 'red',
  RULE_END
]

Typings

Currently the biggest blocker for typings are:

  1. No standard js objects
  2. Shorthands

Shorthands it a problem because we can't create custom types in flow or typescript for something like 1px solid red. See for e.g. facebook/flow#3933

ISTF validator

At some point, we should start with validator, which will validate the ISTF array for correctness.

Use cases

  • It will be needed to control the output from CSS parser or from a objects->istf transformer.
  • It will ease the life of those who try to implement their own *-to-istf compiler and want to be sure they are doing it right.
  • One could use it to validate a package installed from npm with istf inside and make sure the produced istf is correct.

Tasks

  • Make sure validator knows all constraints we put into ISTF #44
  • Make sure it outputs meaningful error messages

Expanded values

In CSS we do this:

margin-right: 10px;
margin-left: 20px;

This is a lot of duplication though. What can we do?

Optimization using JSON.parse

Today I read a blogpost by @tomdale. It states that JSON.parse is faster by 18x than eval. When we evaluate our script with ISTF, it is basically an eval I assume.

As in our format, the only pure JS part is functions, we can put them into a separate array, stringify everything else and JSON.parse at runtime. Lets see if this can yeld any reasonable perf improvements for us.

Alternatively we can also try Array#join and Array#split, as we have no objects.

Also see #22 and #19

Intermediate format

With the work that's been progressing on styled-components static CSS extraction, we've been inching towards what I could see as a valid, cross-compatible intermediate representation of CSS-in-JS. This isn't what we're doing just yet, but it's what I had in mind to potentially solve all our edge cases:

.foo {
  prop: value;
  &:pseudo {
    foo: bar;
  }
}
[
  [ SELECTOR_OPEN ],
  [ SELECTOR, '.foo' ],
  [ PROPERTY, 'prop' ],
  [ VALUE, 'value' ],
  [ SELECTOR_OPEN ],
  [ SELECTOR, '&:psuedo' ],
  [ PROPERTY, 'foo' ],
  [ VALUE, 'bar' ],
  [ SELECTOR_CLOSE ],
  [ SELECTOR_CLOSE ],
]

This kind of intermediate representation lends itself to certain optimisations (autoprefixing could happen in-place, for example), as well as fairly compact storage (assuming the keys are some kind of compact Enum). Converting to a string or object representation would be extremely fast and unambiguous, and dynamic values are easily represented:

injectGlobal`
  .foo {
    color: ${ lighten('black', 0.2) };
    ${ manyRules };
    &:hover, ${ selectorFn } {
      foo: bar;
    }
  }
`

[
  [ SELECTOR_OPEN ],
  [ SELECTOR, '.foo' ],
  [ PROPERTY, 'color' ],
  [ VALUE, lighten('black', 0.2) ],
  [ DEFERRED, manyRules ],
  [ SELECTOR_OPEN ],
  [ SELECTOR, '&:hover' ],
  [ SELECTOR, selectorFn ],
  [ PROPERTY, 'foo' ],
  [ VALUE, 'bar' ],
  [ SELECTOR_CLOSE ],
  [ SELECTOR_CLOSE ],
]

Just a thought, but in my mind this makes static style extraction much more comprehensive, particularly if you could use Prepack or something to figure out that some function calls ( lighten('black', 0.2) for example) can be evaluated at build time.

The next step would be taking this format and understanding that, say, if a certain class x, y and z only appears in one place, don't define any nested selectors, and yet share certain properties and values, that their CSS could be "atomised" somehow to compact the resulting CSS.

It's been floating around in my head for a while now, thought it might be good to share it around.

Houdini

Not sure if Houdini developments are going to be relevant to ISTF, but figured I'd flag it for consideration: https://drafts.css-houdini.org/ if any new bits need to be added to the format

Compiler

How do we allow to convert currently used formats by all cssinjs libs to this format, so that it can be packaged?

Global styles

I assume we all agree that class names should be scoped by default. In this case we need to agree on a format on how to implement global styles. By "global" I mean fully global styles and also locally scoped but reaching into children selectors e.g. .my-scoped-3423jnfsdf button.

Reducing ISTF spec to a CSS subset for consistency

CSS has lots of inconsistencies, driven by DX they thought they are optimizing. For e.g. url can be defined as a CSS string, as a url token and as a url function.

In ISTF we

  1. don't need many ways to describe the same
  2. want to reduce complexity for transformation and strinfigification steps

Lets discuss here all possible things we would want to describe in one consistent way.

Optimization: a Stack/Heap approach

Instead of

body {
  color: red
}

producing

[
  [RULE_START, 1],
    [SELECTOR, 'body'],
    [PROPERTY, 'color'],
    [VALUE, 'red']
  [RULE_END]
]

It could instead produce

HEAP = ['body', 'color', 'red']

[
RULE_START, 0,
SELECTOR, 0,
PROPERTY, 1,
VALUE, 2,
RULE_END, 2
]

Where the ints 0,1,2 are memory addresses for the corresponding values in the HEAP.

This way you can use a flat Uint32Array typed array for maximum throughput on performance.

Autoprefixing (and other processing)

Where does autoprefixing fit into this? Should it be part of the library (like SC), or something that happens on this "standard" data format (i.e. directly before injection into the DOM). What about other processing things?

Potentially, if we went the latter, we could build a converter from this format (do we have a name!?) to PostCSS for people who really wanted it, it would be slow but maybe some people would want to make that tradeoff. For anything core (like prefixing, rtl) we could write optimised transforms, for anything else people could write their own.

Is that opening up a pandora's box of customisation/complexity?

Document different kinds of selector-combinators

I must admit I can't with certainty tell what the ones except the first one are. I could probably figure this out by thinking about all the different combinators a bit more, but it made me realise that the spec needs a section on what they are ๐Ÿ˜‰

const SPACE_COMBINATOR = 5
const DOUBLED_CHILD_COMBINATOR = 6
const CHILD_COMBINATOR = 7
const NEXT_SIBLING_COMBINATOR = 8
const SUBSEQUENT_SIBLING_COMBINATOR = 9

cc @kof

Should it be portable?

Should this format be portable like JSON is? Basically a DSL? Or we can use any JS and require and cjs?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.