Skip to content

Commit

Permalink
refactor: use Pianola to evaluate the manifest
Browse files Browse the repository at this point in the history
BREAKING CHANGE:

The API of the subroutines has changed:

Before: `(evaluator, subjectValue, values)`
Now: `(subjectValue, values, {evalutor})`
  • Loading branch information
gajus committed Jan 31, 2017
1 parent b34ff8f commit 53161e9
Show file tree
Hide file tree
Showing 23 changed files with 108 additions and 550 deletions.
28 changes: 14 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ Example:
```js
const x = surgeon({
subroutines: {
mySubourtine: (evaluator, currentValue, [firstParameterValue, secondParameterValue]) => {
mySubourtine: (currentValue, [firstParameterValue, secondParameterValue]) => {
console.log(currentValue, firstParameterValue, secondParameterValue);

return parseInt(currentValue, 10) + 1;
Expand Down Expand Up @@ -381,11 +381,11 @@ x([

```

In this example, Surgeon query executor (`x`) is invoked with two expressions (`foo bar baz` and `corge grault garply`). The first subroutine is executed with the subject value "qux". The second subroutine is invoked with a value that is the result of the first proceeding subroutine.
In this example, Surgeon query executor (`x`) is invoked with two expressions (`foo bar baz` and `corge grault garply`). The first subroutine is executed with the subject value "qux". The second subroutine is executed with a value that is the result of the parent subroutine.

The result of the query is the result of the last subroutine.

Read [user-defined subroutines](https://github.com/gajus/surgeon#user-defined-subroutines) documentation for broader explanation of the role of the parameter values and the subject value.
Read [user-defined subroutines](#user-defined-subroutines) documentation for broader explanation of the role of the parameter values and the subject value.

### The pipe operator (`|`)

Expand Down Expand Up @@ -459,7 +459,7 @@ x('select .title {0,} | read property textContent', subject);

### Name results

Use an [`QueryChildrenType`](./src/types.js) object to give names to descending results.
Use a [`QueryChildrenType`](./src/types.js) object to name the results of the descending expressions.

```js
const subject = `
Expand Down Expand Up @@ -524,7 +524,7 @@ import surgeon, {

const x = surgeon({
subroutines: {
isRed: (evaluator, value) => {
isRed: (value) => {
if (value === 'red') {
return value;
};
Expand Down Expand Up @@ -553,19 +553,19 @@ import surgeon, {

const x = surgeon({
subroutines: {
ra: (evaluator, subject, values) => {
return readSubroutine(evaluator, subject, ['attribute'].concat(values));
ra: (subject, values, bindle) => {
return readSubroutine(subject, ['attribute'].concat(values), bindle);
},
rp: (evaluator, subject, values) => {
return readSubroutine(evaluator, subject, ['property'].concat(values));
rp: (subject, values, bindle) => {
return readSubroutine(subject, ['property'].concat(values), bindle);
},
s: (evaluator, subject, values) => {
return selectSubroutine(evaluator, subject, [values.join(' '), '{1}']);
s: (subject, values, bindle) => {
return selectSubroutine(subject, [values.join(' '), '{1}'], bindle);
},
sm: (evaluator, subject, values) => {
return selectSubroutine(evaluator, subject, [values.join(' '), '{0,}']);
sm: (subject, values, bindle) => {
return selectSubroutine(subject, [values.join(' '), '{0,}'], bindle);
},
t: testSubroutine,
t: testSubroutine
}
});

Expand Down
20 changes: 8 additions & 12 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,12 @@
]
},
"dependencies": {
"ajv": "^5.0.1-beta.2",
"cheerio": "^0.22.0",
"debug": "^2.6.0",
"es6-error": "^4.0.1",
"flow-runtime": "^0.2.1",
"nearley": "^2.7.11",
"regex-parser": "^2.2.5",
"scalpel": "^2.1.0",
"sprintf-js": "^1.0.3"
"pianola": "^1.0.1",
"regex-parser": "^2.2.5"
},
"description": "Declarative DOM extraction expression evaluator.",
"devDependencies": {
Expand All @@ -39,7 +36,8 @@
"husky": "^0.13.1",
"nyc": "^10.1.2",
"semantic-release": "^6.3.6",
"sinon": "^2.0.0-pre.5"
"sinon": "^2.0.0-pre.5",
"sprintf-js": "^1.0.3"
},
"engines": {
"node": ">=5"
Expand All @@ -55,13 +53,12 @@
"main": "./dist/index.js",
"name": "surgeon",
"nyc": {
"exclude": [
"src/evaluators/browserEvaluator.js"
],
"include": [
"src/**/*.js"
],
"exclude": [
"src/evaluators/browserEvaluator.js",
"src/grammars/*.js"
],
"instrument": false,
"reporter": [
"text-lcov"
Expand All @@ -76,8 +73,7 @@
"url": "https://github.com/gajus/surgeon"
},
"scripts": {
"build": "npm run compile-grammar && babel ./src --out-dir ./dist --copy-files --source-maps",
"compile-grammar": "nearleyc ./src/grammars/expressionGrammar.ne --out ./src/grammars/expressionGrammar.js",
"build": "babel ./src --out-dir ./dist --copy-files --source-maps",
"lint": "eslint ./src ./test && flow",
"precommit": "npm run lint && npm run test",
"test": "ava --verbose"
Expand Down
28 changes: 0 additions & 28 deletions src/assertions/assertValidDenormalizedQuery.js

This file was deleted.

3 changes: 0 additions & 3 deletions src/assertions/index.js

This file was deleted.

50 changes: 0 additions & 50 deletions src/factories/createQuery.js

This file was deleted.

4 changes: 1 addition & 3 deletions src/factories/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
// @flow

import createConfiguration from './createConfiguration';
import createQuery from './createQuery';

export {
createConfiguration,
createQuery
createConfiguration
};
40 changes: 0 additions & 40 deletions src/grammars/expressionGrammar.ne

This file was deleted.

81 changes: 19 additions & 62 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// @flow

import pianola from 'pianola';
import {
createConfiguration,
createQuery
createConfiguration
} from './factories';
import {
InvalidDataError,
Expand Down Expand Up @@ -48,75 +48,32 @@ const builtInSubroutines = {
test: testSubroutine
};

const queryDocument = (userSubroutines, evaluator, instructions, rootNode) => {
let result = rootNode;

let index = 0;

for (const instruction of instructions) {
if (instruction.subroutine === 'adopt') {
const children = {};

if (instruction.parameters.length !== 1) {
throw new SurgeonError('Unexpected parameter length.');
}

if (typeof instruction.parameters[0] !== 'object') {
throw new SurgeonError('test');
}

const childrenNames = Object.keys(instruction.parameters[0]);

for (const childName of childrenNames) {
children[childName] = queryDocument(userSubroutines, evaluator, instruction.parameters[0][childName], result);
}

return children;
}

const lastResult = result;

if (!userSubroutines[instruction.subroutine]) {
throw new SurgeonError('Subroutine does not exist.');
}

result = userSubroutines[instruction.subroutine](evaluator, result, instruction.parameters);

if (result instanceof InvalidValueSentinel) {
throw new InvalidDataError(lastResult, result);
}

index++;

if (Array.isArray(result)) {
const remainingInstructions = instructions.slice(index);

return result.map((newRootNode) => {
return queryDocument(userSubroutines, evaluator, remainingInstructions, newRootNode);
});
}
}

return result;
};

export default (userConfiguration?: UserConfigurationType) => {
const configuration = createConfiguration(userConfiguration);

const userSubroutines = {
const subroutines = {
...configuration.subroutines,
...builtInSubroutines
};

const handleResult = (resultValue, inputValue) => {
if (resultValue instanceof InvalidValueSentinel) {
throw new InvalidDataError(inputValue, resultValue);
}
};

const x = pianola({
bindle: {
evaluator: configuration.evaluator
},
handleResult,
subroutines
});

// eslint-disable-next-line flowtype/no-weak-types
return (instructions: DenormalizedQueryType, subject: string | Object) => {
const query = createQuery(instructions);
const startValue = typeof subject === 'string' ? configuration.evaluator.parseDocument(subject) : subject;

return queryDocument(
userSubroutines,
configuration.evaluator,
query,
typeof subject === 'string' ? configuration.evaluator.parseDocument(subject) : subject
);
return x(instructions, startValue);
};
};
2 changes: 0 additions & 2 deletions src/parsers/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
// @flow

import parseExpression from './parseExpression';
import parseQuantifierExpression from './parseQuantifierExpression';

export {
parseExpression,
parseQuantifierExpression
};
Loading

0 comments on commit 53161e9

Please sign in to comment.