postcore / limon

:lemon: The pluggable JavaScript lexer. :tada: Limon = Lemon
http://www.tunnckocore.tk
MIT License
9 stars 0 forks source link

add json lexer example #5

Open tunnckoCore opened 8 years ago

tunnckoCore commented 8 years ago

Tokenizing JSON string, for example coming from JSON.stringify

tunnckoCore commented 8 years ago

some ref, thoughts and etc https://github.com/jsstyles/jss/issues/227:

Started from one thread in cssx - https://github.com/krasimir/cssx/issues/2, and my already started work on https://github.com/postjson/postjson, https://github.com/limonjs/limon and upcoming "pluggable" parser.

JSS Thoughts

My first thoughts are that jss have not good api, too complex and wrong by design - wrong plugin signature.

  1. plugin should return "the new style" - actually, just some "final" style, object.
  2. plugin gives only single "rule" object - which in first hand is complex and too deep, in second hand you are forced to access options and jss itself through this "rule" object coming.
  3. a lot better and es6 ready (meaning use of arrow functions) will be the signature of plugins to be something more easy and meaningful like
jss.use(app => {
  return (key, value, rule) => {
    // stuff here, where:
    // `this` if not arrow function will be the `rule` object,
    // otherwise you will have access to it through `app` - somelike "current rule" pointer 
    // in that context we can have useful metadata info for the rule like: name, className and etc 
    // `value` is "style" object as it is currently, meaning the value of selector, containing the prop:val pairs
    // `key` is the "selectorText" string
  }
})

this way you have anything not so deep and not so complex, and it won't be a problem each rule still to have own "options" and meta stuff, like "name", "originalStyle" (which can be cloned value to be able to transform/modify rule directly) and etc. Even more, plugins will be able to extend jss api itself when not returning function.

The Plugin API

All this plugin architecture can be done using http://npm.im/use, but currently (and maybe won't in future) not support passing more than one argument to .run method (meaning, what you pass to run is then passed to function return from plugin) and it must be object. So, because of that I reimplemented it in limonjs/limon/index.js#L49-L69. This way it won't be needed to "return the new/modified rule" from each plugin, which will be better.

AST a.k.a. the "JSS JSON"

Actualy, jss don't have AST, and okey because of that you calling it "JSS JSON", but when rethinking it these weeks, we really dont need AST. PostJSON will allow access to (and produce some) AST, but mainly, plugins will expose to you key, value, obj signature. I also thinking they can be separate things (two type of plugins) - AST plugins, and default plugins. In anyway, you don't have AST, you have some deep and complex (and circular) objects with metadata and some state - it can be rethinked and can be flattened. PostJSON future plugin example

var postjson = require('postjson')

postjson.use(function (app) {
  // where `app` and `this` context are the postjson instance
  // if you return function it will be called
  // with different arguments, but again context of it will be `app`
  return function (key, value, obj) {
    console.log(obj[key] === value)
  }
})

Mainly it will work .use().use().use().process(jsonStringifiedObj / orRawObject), secondly it will have "api extending plugin" which adds .parse method which will produce AST if user want to work with AST and not with main plugin signature. If this "api extending plugin" is used it maybe should change the signature of inner returned function - for example it should be

var postjson = require('postjson')

postjson.use(astPlugin).use(function (app) {
  // where `app` and `this` context are the postjson instance
  return function (ast) {
    console.log(ast)
  }
})

or preserve original signature and add the ast to app/this instance.

JSS API

Talking for the .createRule and .createStyleSheet and etc. They also can be done better and this will be able when/if we change the plugins api. They also produce deep and complex objects. What I noticed is that .createRule have name, val signature, where name is the clean selector called "name", which in turn actually represents "key" in JSON object. And where val is that "key"s value and more.. it is not limited to be always object, which is strange - it can be string and it is then apply to "originalStyle" and "style" properties. This is kinda bug. Maybe it is in that what to also be able to produce "prop: value" pairs, not only "real rules". Example which produces identical objects if not 1:1 ->

var jss = require('jss')
var style = {
  'a > b:hover': {
    color: 'red'
  }
}

var sheet = jss.createStyleSheet(style)
var rule = jss.createRule('a > b:hover', {
  color: 'red'
})
console.log(sheet)
console.log('========')
console.log(rule)

Cheers, Charlike