mirror of
https://github.com/arthur-pbty/portfolio2023.git
synced 2026-06-07 06:45:23 +02:00
modified
This commit is contained in:
-9
@@ -1,9 +0,0 @@
|
||||
# The MIT License
|
||||
|
||||
Copyright 2022 Harminder Virk, contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
-428
@@ -1,428 +0,0 @@
|
||||
<div align="center"><img src="https://res.cloudinary.com/adonis-js/image/upload/v1620150474/edge-banner_tzmnox.jpg" width="600px"></div>
|
||||
|
||||
# Edge Parser
|
||||
> Parser to convert edge templates to invokable functions
|
||||
|
||||
[![gh-workflow-image]][gh-workflow-url] [![npm-image]][npm-url] ![][typescript-image] [![license-image]][license-url] [![synk-image]][synk-url]
|
||||
|
||||
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
||||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
||||
|
||||
## Table of contents
|
||||
|
||||
- [Table of contents](#table-of-contents)
|
||||
- [Usage](#usage)
|
||||
- [Parser API](#parser-api)
|
||||
- [generateAST(jsExpression, lexerLoc, filename)](#generateastjsexpression-lexerloc-filename)
|
||||
- [transformAst(acornAst, filename)](#transformastacornast-filename)
|
||||
- [tokenize (template, options: { filename })](#tokenize-template-options--filename-)
|
||||
- [stringify(expression)](#stringifyexpression)
|
||||
- [processToken(token, buffer)](#processtokentoken-buffer)
|
||||
- [Supported Expressions](#supported-expressions)
|
||||
- [Identifier](#identifier)
|
||||
- [Literal](#literal)
|
||||
- [ArrayExpression](#arrayexpression)
|
||||
- [ObjectExpression](#objectexpression)
|
||||
- [UnaryExpression](#unaryexpression)
|
||||
- [BinaryExpression](#binaryexpression)
|
||||
- [LogicalExpression](#logicalexpression)
|
||||
- [MemberExpression](#memberexpression)
|
||||
- [ConditionalExpression](#conditionalexpression)
|
||||
- [CallExpression](#callexpression)
|
||||
- [SequenceExpression](#sequenceexpression)
|
||||
- [TemplateLiteral](#templateliteral)
|
||||
- [ArrowFunctionExpression](#arrowfunctionexpression)
|
||||
- [AwaitExpression](#awaitexpression)
|
||||
- [FunctionDeclaration](#functiondeclaration)
|
||||
- [BlockStatement](#blockstatement)
|
||||
- [ChainExpression](#chainexpression)
|
||||
|
||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||
|
||||
This repo is the **parser to convert edge templates** to a self invoked Javascript function.
|
||||
|
||||
## Usage
|
||||
|
||||
Install the package from npm registry as follows:
|
||||
|
||||
```sh
|
||||
npm i edge-parser
|
||||
|
||||
# yarn
|
||||
yarn add edge-parser
|
||||
```
|
||||
|
||||
and then use it as follows
|
||||
|
||||
```js
|
||||
import { Parser, EdgeBuffer, Stack } from 'edge-parser'
|
||||
|
||||
const filename = 'eval.edge'
|
||||
const statePropertyName = 'state'
|
||||
const escapeCallPath = 'escape'
|
||||
const outputVar = 'out'
|
||||
const rethrowCallPath = 'reThrow'
|
||||
|
||||
const parser = new Parser({}, new Stack(), {
|
||||
statePropertyName,
|
||||
escapeCallPath,
|
||||
})
|
||||
|
||||
const buffer = new EdgeBuffer(filename, { outputVar, rethrowCallPath })
|
||||
|
||||
parser
|
||||
.tokenize('Hello {{ username }}', { filename })
|
||||
.forEach((token) => parser.processToken(token, buffer))
|
||||
```
|
||||
|
||||
- All the first set of `const` declarations are the config values that impacts the compiled output.
|
||||
- `filename` is required to ensure that exceptions stack traces point back to the correct filename.
|
||||
- `statePropertyName` is the variable name from which the values should be accessed. For example: `{{ username }}` will be compiled as `state.username`. Leave it to empty, if state is not nested inside an object.
|
||||
- `escapeCallPath` Reference to the `escape` method for escaping interpolation values. For example: `{{ username }}` will be compiled as `escape(state.username)`. The `escape` method should escape only strings and return the other data types as it is.
|
||||
- `outputVar` is the variable name that holds the output of the compiled template.
|
||||
- `rethrowCallPath` Reference to the `reThrow` method to raise the template exceptions with the current `$filename` and `$lineNumber`. Check the following compiled output to see how this function is called.
|
||||
|
||||
**Compiled output**
|
||||
|
||||
```js
|
||||
let out = ''
|
||||
let $lineNumber = 1
|
||||
let $filename = 'eval.edge'
|
||||
try {
|
||||
out += 'Hello '
|
||||
out += `${escape(state.username)}`
|
||||
} catch (error) {
|
||||
reThrow(error, $filename, $lineNumber)
|
||||
}
|
||||
return out
|
||||
```
|
||||
|
||||
You can wrap the compiled output inside a function and invoke it as follows
|
||||
|
||||
```ts
|
||||
/**
|
||||
* Convert string to a function
|
||||
*/
|
||||
const fn = new Function('', `return function template (state, escape, reThrow) { ${output} }`)()
|
||||
|
||||
/**
|
||||
* Template state
|
||||
*/
|
||||
const state = { username: 'virk' }
|
||||
|
||||
/**
|
||||
* Escape function
|
||||
*/
|
||||
function escape(value: any) {
|
||||
return value
|
||||
}
|
||||
|
||||
/**
|
||||
* Rethrow function
|
||||
*/
|
||||
function reThrow(error: Error) {
|
||||
throw error
|
||||
}
|
||||
|
||||
console.log(fn(state, escape, reThrow))
|
||||
```
|
||||
|
||||
## Parser API
|
||||
|
||||
Along with parsing the main template, the parser also exposes the API, that tags can use to selectively parse the content of a tag.
|
||||
|
||||
#### generateAST(jsExpression, lexerLoc, filename)
|
||||
|
||||
Parses a string as a Javascript expression. The output is a valid [Estree expression](https://github.com/estree/estree)
|
||||
|
||||
The following example returns a [BinaryExpression](https://astexplorer.net/#/gist/0b6250a81804270a026fe39e3bc33fb6/latest)
|
||||
|
||||
```ts
|
||||
const loc = {
|
||||
start: { line: 1, col: 1 },
|
||||
end: { line: 1, col: 1 },
|
||||
}
|
||||
const filename = 'eval.edge'
|
||||
|
||||
parser.utils.generateAST('2 + 2', loc, filename)
|
||||
```
|
||||
|
||||
#### transformAst(acornAst, filename)
|
||||
|
||||
Transform the acorn AST and make it compatible with Edge runtime. This method mutates the inner nodes of the original AST.
|
||||
|
||||
```ts
|
||||
const loc = {
|
||||
start: { line: 1, col: 1 },
|
||||
end: { line: 1, col: 1 },
|
||||
}
|
||||
const filename = 'eval.edge'
|
||||
|
||||
parser.utils.transformAst(parser.utils.generateAST('2 + 2', loc, filename), filename)
|
||||
```
|
||||
|
||||
#### tokenize (template, options: { filename })
|
||||
|
||||
Returns an array of [lexer tokens](https://github.com/edge-js/lexer) for the given template. The method is a shortcut to self import the lexer module and then generating tokens.
|
||||
|
||||
```ts
|
||||
const tokens = parser.tokenize('Hello {{ username }}', {
|
||||
filename: 'eval.edge',
|
||||
})
|
||||
```
|
||||
|
||||
**Output**
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"type": "raw",
|
||||
"line": 1,
|
||||
"value": "Hello "
|
||||
},
|
||||
{
|
||||
"type": "mustache",
|
||||
"filename": "eval.edge",
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"col": 8
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"col": 20
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"jsArg": " username "
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
#### stringify(expression)
|
||||
|
||||
Convert edge or acorn expression back to a string. This is helpful, when you mutate some nodes inside the expression and now want a valid Javascript string out of it.
|
||||
|
||||
```ts
|
||||
const expression = parser.utils.generateAST(
|
||||
'2 + 2',
|
||||
{
|
||||
start: { line: 1, col: 1 },
|
||||
end: { line: 1, col: 1 },
|
||||
},
|
||||
'eval.edge'
|
||||
)
|
||||
|
||||
expression.left.value = 3
|
||||
parser.utils.stringify(expression) // returns 3 + 2
|
||||
```
|
||||
|
||||
#### processToken(token, buffer)
|
||||
|
||||
You will often find yourself using this method as a tag author, when you want to recursively process all children of your tag
|
||||
|
||||
```ts
|
||||
const byPass = {
|
||||
block: true,
|
||||
seekable: false,
|
||||
name: 'bypass',
|
||||
|
||||
compile(parser, buffer, token) {
|
||||
token.children.forEach((child) => parser.processToken(child, buffer))
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
and then use it as
|
||||
|
||||
```edge
|
||||
@bypass
|
||||
Hello {{ username }}
|
||||
@endbypass
|
||||
```
|
||||
|
||||
## Supported Expressions
|
||||
|
||||
The following expressions are supported by the parser. Can you also access the list of supported expressions as
|
||||
|
||||
```js
|
||||
import { expressions } from 'edge-parser'
|
||||
```
|
||||
|
||||
#### Identifier
|
||||
|
||||
The identifier are prefixed with `state.` In following statement `username` is the identifier
|
||||
|
||||
```
|
||||
Hello {{ username }}
|
||||
```
|
||||
|
||||
#### Literal
|
||||
|
||||
A string literal
|
||||
|
||||
```
|
||||
Hello {{ 'Guest' }}
|
||||
```
|
||||
|
||||
#### ArrayExpression
|
||||
|
||||
The `[1, 2, 3, 4]` is an array expression.
|
||||
|
||||
```
|
||||
Evens are {{
|
||||
[1, 2, 3, 4].filter((num) => num % 2 === 0)
|
||||
}}
|
||||
```
|
||||
|
||||
#### ObjectExpression
|
||||
|
||||
The `{ username: 'virk' }` is an Object expression
|
||||
|
||||
```
|
||||
{{ toJSON({ username: 'virk' }) }}
|
||||
```
|
||||
|
||||
#### UnaryExpression
|
||||
|
||||
Following are examples of `UnaryExpression`.
|
||||
|
||||
```
|
||||
{{ typeof(username) }}
|
||||
|
||||
{{ !!username }}
|
||||
```
|
||||
|
||||
#### BinaryExpression
|
||||
|
||||
Here `{{ 2 + 2 }}` is the binary expression
|
||||
|
||||
```
|
||||
{{ 2 + 2 }} = 4
|
||||
```
|
||||
|
||||
#### LogicalExpression
|
||||
|
||||
Following is the example of `LogicalExpression`.
|
||||
|
||||
```
|
||||
{{ username || admin.username }}
|
||||
```
|
||||
|
||||
#### MemberExpression
|
||||
|
||||
```
|
||||
{{ username.toUpperCase() }}
|
||||
```
|
||||
|
||||
#### ConditionalExpression
|
||||
|
||||
```
|
||||
{{ username ? username : 'Guest' }}
|
||||
```
|
||||
|
||||
#### CallExpression
|
||||
|
||||
```
|
||||
{{ upper(username) }}
|
||||
```
|
||||
|
||||
#### SequenceExpression
|
||||
|
||||
Sequence is not supported in mustache blocks and instead used inside tags. For example:
|
||||
|
||||
Everything inside `()` is a sequence expression.
|
||||
|
||||
```
|
||||
@component('button', text = 'Submit', type = 'Primary')
|
||||
```
|
||||
|
||||
#### TemplateLiteral
|
||||
|
||||
```
|
||||
{{ Hello `${username}` }}
|
||||
```
|
||||
|
||||
#### ArrowFunctionExpression
|
||||
|
||||
```
|
||||
{{
|
||||
users.map((user) => {
|
||||
return user.username
|
||||
})
|
||||
}}
|
||||
```
|
||||
|
||||
#### AwaitExpression
|
||||
|
||||
```
|
||||
{{ await foo() }}
|
||||
```
|
||||
|
||||
#### FunctionDeclaration
|
||||
|
||||
```
|
||||
{{ function foo () {} }}
|
||||
```
|
||||
|
||||
#### BlockStatement
|
||||
|
||||
Here the `map` callback is the block statement
|
||||
|
||||
```
|
||||
{{
|
||||
users.map(() => {})
|
||||
}}
|
||||
```
|
||||
|
||||
#### ChainExpression
|
||||
|
||||
Support for optional chaining
|
||||
|
||||
```
|
||||
{{ user?.username }}
|
||||
```
|
||||
|
||||
#### NewExpression
|
||||
|
||||
```js
|
||||
{{ new User() }}
|
||||
```
|
||||
|
||||
#### ReturnStatement
|
||||
In the following example `return` keyword is a return statement
|
||||
|
||||
```js
|
||||
users.map((user) => {
|
||||
return user.username
|
||||
})
|
||||
```
|
||||
|
||||
#### ThisExpression
|
||||
Support for the this keyword
|
||||
|
||||
```js
|
||||
{{ this.state }}
|
||||
```
|
||||
|
||||
#### SpreadElement
|
||||
Support for the spread element
|
||||
|
||||
```js
|
||||
{{ [...users] }}
|
||||
```
|
||||
|
||||
[gh-workflow-image]: https://img.shields.io/github/workflow/status/edge-js/parser/test?style=for-the-badge
|
||||
[gh-workflow-url]: https://github.com/edge-js/parser/actions/workflows/test.yml "Github action"
|
||||
|
||||
[npm-image]: https://img.shields.io/npm/v/edge-parser.svg?style=for-the-badge&logo=npm
|
||||
[npm-url]: https://npmjs.org/package/edge-parser 'npm'
|
||||
|
||||
[typescript-image]: https://img.shields.io/badge/Typescript-294E80.svg?style=for-the-badge&logo=typescript
|
||||
|
||||
[license-url]: LICENSE.md
|
||||
[license-image]: https://img.shields.io/github/license/edge-js/lexer?style=for-the-badge
|
||||
|
||||
[synk-image]: https://img.shields.io/snyk/vulnerabilities/github/edge-js/parser?label=Synk%20Vulnerabilities&style=for-the-badge
|
||||
[synk-url]: https://snyk.io/test/github/edge-js/parser?targetFile=package.json 'synk'
|
||||
-141
@@ -1,141 +0,0 @@
|
||||
{
|
||||
"name": "edge-parser",
|
||||
"version": "8.2.2",
|
||||
"description": "Parser for edge template engine",
|
||||
"main": "build/index.js",
|
||||
"files": [
|
||||
"build/src",
|
||||
"build/index.d.ts",
|
||||
"build/index.js"
|
||||
],
|
||||
"scripts": {
|
||||
"pretest": "npm run lint",
|
||||
"test": "node .bin/test.js",
|
||||
"build": "npm run compile",
|
||||
"mrm": "mrm --preset=@adonisjs/mrm-preset",
|
||||
"commit": "git-cz",
|
||||
"test:win": "node ./node_modules/japa-cli/index.js",
|
||||
"clean": "del build",
|
||||
"compile": "npm run lint && npm run clean && tsc",
|
||||
"release": "np --message=\"chore(release): %s\"",
|
||||
"version": "npm run build",
|
||||
"lint": "eslint . --ext=.ts",
|
||||
"prepublishOnly": "npm run build",
|
||||
"sync-labels": "github-label-sync --labels ./node_modules/@adonisjs/mrm-preset/gh-labels.json edge-js/parser",
|
||||
"format": "prettier --write ."
|
||||
},
|
||||
"keywords": [
|
||||
"edge",
|
||||
"template",
|
||||
"template-engine"
|
||||
],
|
||||
"author": "virk",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"acorn": "^8.8.2",
|
||||
"astring": "^1.8.4",
|
||||
"edge-error": "^3.0.0",
|
||||
"edge-lexer": "^5.0.2",
|
||||
"js-stringify": "^1.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@adonisjs/mrm-preset": "^5.0.3",
|
||||
"@adonisjs/require-ts": "^2.0.13",
|
||||
"@types/acorn": "^6.0.0",
|
||||
"@types/astring": "^1.7.0",
|
||||
"@types/node": "^18.15.3",
|
||||
"commitizen": "^4.3.0",
|
||||
"cz-conventional-changelog": "^3.3.0",
|
||||
"dedent-js": "^1.0.1",
|
||||
"del-cli": "^5.0.0",
|
||||
"doctoc": "^2.2.1",
|
||||
"eslint": "^8.36.0",
|
||||
"eslint-config-prettier": "^8.7.0",
|
||||
"eslint-plugin-adonis": "^2.1.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"github-label-sync": "^2.3.1",
|
||||
"husky": "^8.0.3",
|
||||
"japa": "^4.0.0",
|
||||
"mrm": "^4.1.14",
|
||||
"np": "^7.6.4",
|
||||
"prettier": "^2.8.5",
|
||||
"typescript": "^5.0.2",
|
||||
"youch": "^3.2.3"
|
||||
},
|
||||
"config": {
|
||||
"commitizen": {
|
||||
"path": "cz-conventional-changelog"
|
||||
}
|
||||
},
|
||||
"nyc": {
|
||||
"exclude": [
|
||||
"test"
|
||||
],
|
||||
"extension": [
|
||||
".ts"
|
||||
]
|
||||
},
|
||||
"gitHooks": {
|
||||
"commit-msg": "node ./node_modules/@adonisjs/mrm-preset/validateCommit/conventional/validate.js"
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"commit-msg": "node ./node_modules/@adonisjs/mrm-preset/validateCommit/conventional/validate.js"
|
||||
}
|
||||
},
|
||||
"np": {
|
||||
"contents": ".",
|
||||
"anyBranch": false
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/edge-js/parser.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/edge-js/parser/issues"
|
||||
},
|
||||
"homepage": "https://github.com/edge-js/parser#readme",
|
||||
"mrmConfig": {
|
||||
"core": false,
|
||||
"license": "MIT",
|
||||
"services": [
|
||||
"github-actions"
|
||||
],
|
||||
"minNodeVersion": "14.15.4",
|
||||
"probotApps": [
|
||||
"stale",
|
||||
"lock"
|
||||
],
|
||||
"runGhActionsOnWindows": true
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": [
|
||||
"plugin:adonis/typescriptPackage",
|
||||
"prettier"
|
||||
],
|
||||
"plugins": [
|
||||
"prettier"
|
||||
],
|
||||
"rules": {
|
||||
"prettier/prettier": [
|
||||
"error",
|
||||
{
|
||||
"endOfLine": "auto"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"eslintIgnore": [
|
||||
"build"
|
||||
],
|
||||
"prettier": {
|
||||
"trailingComma": "es5",
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"useTabs": false,
|
||||
"quoteProps": "consistent",
|
||||
"bracketSpacing": true,
|
||||
"arrowParens": "always",
|
||||
"printWidth": 100
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user