https://github.com/openstyles/usercss-meta
Parse usercss styles supported by the Stylus userstyle manager
https://github.com/openstyles/usercss-meta
css parser stylus usercss
Last synced: 15 days ago
JSON representation
Parse usercss styles supported by the Stylus userstyle manager
- Host: GitHub
- URL: https://github.com/openstyles/usercss-meta
- Owner: openstyles
- License: other
- Created: 2018-01-08T18:20:13.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2023-03-14T16:30:39.000Z (about 2 years ago)
- Last Synced: 2025-03-23T16:42:44.351Z (about 1 month ago)
- Topics: css, parser, stylus, usercss
- Language: JavaScript
- Homepage:
- Size: 1.74 MB
- Stars: 17
- Watchers: 5
- Forks: 5
- Open Issues: 14
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# usercss-meta
> Parse usercss metadata supported by the Stylus userstyle manager## Install
[NPM](https://www.npmjs.com/package/usercss-meta)
```
$ 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
```js
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:
* To parse metadata:
* `parse`: Function. Parse metadata and return an object.
* `createParser`: Function. Create a metadata parser.
* `ParseError`: Class.
* `util`: Object. A collection of parser utilities.
* To stringify metadata:
* `stringify`: Function. Stringify metadata object and return the string.
* `createStringifier`: Function. Create a metadata stringifier.### parse
```js
const parseResult = parse(text: String, options?: Object);
```This is a shortcut of
```js
createParser(options).parse(text);
```### createParser
```js
const parser = createParser({
unknownKey?: String,
mandatoryKeys?: Array
parseKey?: Object,
parseVar?: Object,
validateKey?: Object,
validateVar?: Object,
allowErrors?: Boolean
});
````unknownKey` decides how to parse unknown keys. Possible values are:
- `ignore`: The directive is ignored. Default.
- `assign`: Assign the text value (characters before `\s*\n`) to result object.
- `throw`: Throw a `ParseError`.`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:
```js
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:
```js
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:
```js
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](https://github.com/sindresorhus/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:
```js
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
```js
const {
metadata: Object,
errors: Array
} = parser.parse(text: String);
```Parse the text (metadata header) and return the result.
### parser.validateVar
```js
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`:
```js
const {metadata} = parse(text);/* modify metadata.vars['some-var'].value ... */
for (const varObj of Object.values(metadata.vars)) {
validateVar(varObj);
}
```### ParseError
```js
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:
* `code` - error code.
* `message` - error message.
* `index` - the string index where the error occurs.
* `args` - an array of values that is used to compose the error message. This allows other clients to generate i18n error message.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 `<