openstyles / usercss-meta

Parse usercss styles supported by the Stylus userstyle manager
Other
16 stars 5 forks source link
css parser stylus usercss

usercss-meta

Parse usercss metadata supported by the Stylus userstyle manager

Install

NPM

$ npm install --save usercss-meta

unpkg.com CDN:

This module depends on URL parser. In Node.js, the module requires url module. In the browser build, it uses global variable URL.

Usage

const usercssMeta = require('usercss-meta');

const {metadata} = usercssMeta.parse(`/* ==UserStyle==
@name        test
@namespace   github.com/openstyles/stylus
@version     0.1.0
@description my userstyle
@author      Me
@var text my-color "Select a color" #123456
==/UserStyle== */`);

/* => {
  "vars": {
    "my-color": {
      "type": "text",
      "label": "Select a color",
      "name": "my-color",
      "value": null,
      "default": "#123456",
      "options": null
    }
  },
  "name": "test",
  "namespace": "github.com/openstyles/stylus",
  "version": "0.1.0",
  "description": "my userstyle",
  "author": "Me"
}
*/

usercssMeta.stringify(metadata, {alignKeys: true});

/* => `/* ==UserStyle==
@name        test
@namespace   github.com/openstyles/stylus
@version     0.1.0
@description my userstyle
@author      Me
@var         text my-color "Select a color" #123456
==/UserStyle== *\/`

*/

API Reference

This module exports following members:

parse

const parseResult = parse(text: String, options?: Object);

This is a shortcut of

createParser(options).parse(text);

createParser

const parser = createParser({
  unknownKey?: String,
  mandatoryKeys?: Array<key: String>
  parseKey?: Object,
  parseVar?: Object,
  validateKey?: Object,
  validateVar?: Object,
  allowErrors?: Boolean
});

unknownKey decides how to parse unknown keys. Possible values are:

mandatoryKeys marks multiple keys as mandatory. If some keys are missing then throw a ParseError. Default: ['name', 'namespace', 'version'].

parseKey is a key/parseFunction map. It allows users to extend the parser. Example:

const parser = createParser({
  mandatoryKeys: [],
  parseKey: {
    myKey: util.parseNumber
  }
});
const {metadata} = parser.parse(`
  /* ==UserStyle==
  @myKey 123456
  ==/UserStyle==
`);
assert.equal(metadata.myKey, 123456);

parseVar is a variableType/parseFunction map. It extends the parser to parse additional variable types. For example:

const parser = createParser({
  mandatoryKeys: [],
  parseVar: {
    myvar: util.parseNumber
  }
});
const {metadata} = parser.parse(`/* ==UserStyle==
@var myvar var-name 'Customized variable' 123456
==/UserStyle== */`);
const va = metadata.vars['var-name'];
assert.equal(va.type, 'myvar');
assert.equal(va.label, 'Customized variable');
assert.equal(va.default, 123456);

validateKey is a key/validateFunction map, which is used to validate the metadata value. The function accepts a state object:

const parser = createParser({
  validateKey: {
    updateURL: state => {
      if (/example\.com/.test(state.value)) {
        throw new ParseError({
          message: 'Example.com is not a good URL',
          index: state.valueIndex
        });
      }
    }
  }
});

There are some builtin validators, which can be overwritten:

Key Description
version Ensure the value matches semver-regex then strip the leading v or =.
homepageURL Ensure it is a valid URL and the protocol must be http or https.
updateURL Same as above.
supportURL Same as above.

validateVar is a variableType/validateFunction map, which is used to validate variables. The function accepts a state object:

const parser = createParser({
  validateVar: {
    color: state => {
      if (state.value === 'red') {
        throw new ParseError({
          message: '`red` is not allowed',
          index: state.valueIndex
        });
      }
    }
  }
});

Builtin validators:

Variable Type Description
checkbox Ensure the value is 0 or 1.
number Ensure sure the value is a number, doesn't exceed the minimum/maximum, and is a multiple of the step value.
range Same as above.

If allowErrors is true, the parser will collect parsing errors while parser.parse() and return them as parseResult.errors. Otherwise, the first parsing error will be thrown.

parser.parse

const {
  metadata: Object,
  errors: Array
} = parser.parse(text: String);

Parse the text (metadata header) and return the result.

parser.validateVar

parser.validateVar(varObj);

Validate the value of the variable object. This function uses the validators defined in createParser.

varObj is the variable object in metadata.vars:

const {metadata} = parse(text);

/* modify metadata.vars['some-var'].value ... */

for (const varObj of Object.values(metadata.vars)) {
  validateVar(varObj);
}

ParseError

throw new ParseError(properties: Object);

Use this class to initiate a parse error.

properties would be assigned to the error object. There are some special properties:

A table of errors thrown by the parser:

err.code err.args Description
invalidCheckboxDefault Expect 0 or 1.
invalidRange Variable type Expect a number or an array.
invalidRangeMultipleUnits Variable type Two different units are defined.
invalidRangeTooManyValues Variable type Too many values in the array.
invalidRangeValue Variable type Values in the array must be number, string, or null.
invalidRangeDefault Variable type The default value of @var range must be a number. This error may be thrown when parsing number or range variables.
invalidRangeMin Variable type The value is smaller than the minimum value.
invalidRangeMax Variable type The value is larger than the maximum value.
invalidRangeStep Variable type The value is not a multiple of the step value.
invalidRangeUnits [VARIABLE_TYPE, UNITS] The value is not a valid CSS unit.
invalidNumber Expect a number.
invalidSelect The value of @var select must be an array or an object.
invalidSelectValue The value in the array/object must be a string.
invalidSelectEmptyOptions The options list of @var select is empty.
invalidSelectLabel The label of the option is empty.
invalidSelectMultipleDefaults Multiple options are specified as the default value.
invalidSelectNameDuplicated Found duplicated option names.
invalidString Expect a string that is quoted with ', ", or `.
invalidURLProtocol Protocol of the URL Only http and https are allowed.
invalidVersion Version string https://github.com/sindresorhus/semver-regex
invalidWord Expect a word.
missingChar A list of valid characters Expect a specific character.
missingEOT Expect <<EOT ... data.
missingMandatory A list of missing keys This error doesn't have err.index.
missingValue Expect a non-whitespace value.
unknownJSONLiteral Literal value JSON has only 3 literals: true, false, and null.
unknownMeta [META_KEY, SUGGESTED_META_KEY] Unknown @metadata. It may suggest the correct metadata name if there is a typo. SUGGESTED_META_KEY can be null
unknownVarType [META_KEY, VARIABLE_TYPE] Unknown variable type. META_KEY could be var or advanced.

util

A collection of parser utilities. Some of them might be useful when extending the parser.

stringify

const text = stringify(metadata: Object, options?: Object);

This is a shortcut of:

createStringifier(options).stringify(metadata);

createStringifier

const stringifier = createStringifier(options?: Object);

options may contain following properties:

Related

License

MIT

Run tests

This repo includes 3 tests:

Changelog