
Research
/Security News
10 npm Typosquatted Packages Deploy Multi-Stage Credential Harvester
Socket researchers found 10 typosquatted npm packages that auto-run on install, show fake CAPTCHAs, fingerprint by IP, and deploy a credential stealer.
edge-parser
Advanced tools
Parser to convert edge templates to invokable functions
This repo is the parser to convert edge templates to a self invoked Javascript function.
Install the package from npm registry as follows:
npm i edge-parser
# yarn
yarn add edge-parser
and then use it as follows
import { Parser, EdgeBuffer, Stack } from 'edge-parser'
const filename = 'eval.edge'
const parser = new Parser({}, new Stack(), {
statePropertyName: 'state',
escapeCallPath: 'escape',
toAttributesCallPath: 'toAttributes',
})
const buffer = new EdgeBuffer(filename, {
outputVar: 'out',
rethrowCallPath: 'reThrow'
})
parser
.tokenize('Hello {{ username }}', { filename })
.forEach((token) => parser.processToken(token, buffer))
const output = buffer.flush()
console.log(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.toAttributesCallPath: Reference to the function that will convert an object to HTML attributes.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
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
/**
* Convert string to a function
*/
const fn = new Function('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))
Along with parsing the main template, the parser also exposes the API, that tags can use to selectively parse the content of a tag.
Parses a string as a Javascript expression. The output is a valid Estree expression
The following example returns a BinaryExpression
const loc = {
start: { line: 1, col: 1 },
end: { line: 1, col: 1 },
}
const filename = 'eval.edge'
parser.utils.generateAST('2 + 2', loc, filename)
Transform the acorn AST and make it compatible with Edge runtime. This method mutates the inner nodes of the original AST.
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)
Returns an array of lexer tokens for the given template. The method is a shortcut to self import the lexer module and then generating tokens.
const tokens = parser.tokenize('Hello {{ username }}', {
filename: 'eval.edge',
})
Output
[
{
"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 "
}
}
]
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.
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
You will often find yourself using this method as a tag author, when you want to recursively process all children of your tag
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
@bypass
Hello {{ username }}
@endbypass
The following expressions are supported by the parser. Can you also access the list of supported expressions as
import { expressions } from 'edge-parser'
The identifier are prefixed with state. In following statement username is the identifier
Hello {{ username }}
A string literal
Hello {{ 'Guest' }}
The [1, 2, 3, 4] is an array expression.
Evens are {{
[1, 2, 3, 4].filter((num) => num % 2 === 0)
}}
The { username: 'virk' } is an Object expression
{{ toJSON({ username: 'virk' }) }}
Following are examples of UnaryExpression.
{{ typeof(username) }}
{{ !!username }}
Here {{ 2 + 2 }} is the binary expression
{{ 2 + 2 }} = 4
Following is the example of LogicalExpression.
{{ username || admin.username }}
{{ username.toUpperCase() }}
{{ username ? username : 'Guest' }}
{{ upper(username) }}
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')
{{ Hello `${username}` }}
{{
users.map((user) => {
return user.username
})
}}
{{ await foo() }}
{{ function foo () {} }}
Here the map callback is the block statement
{{
users.map(() => {})
}}
Support for optional chaining
{{ user?.username }}
{{ new User() }}
In the following example return keyword is a return statement
users.map((user) => {
return user.username
})
Support for the this keyword
{{ this.state }}
Support for the spread element
{{ [...users] }}
FAQs
Parser for edge template engine
The npm package edge-parser receives a total of 23,340 weekly downloads. As such, edge-parser popularity was classified as popular.
We found that edge-parser demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
/Security News
Socket researchers found 10 typosquatted npm packages that auto-run on install, show fake CAPTCHAs, fingerprint by IP, and deploy a credential stealer.

Product
Socket Firewall Enterprise is now available with flexible deployment, configurable policies, and expanded language support.

Security News
Open source dashboard CNAPulse tracks CVE Numbering Authorities’ publishing activity, highlighting trends and transparency across the CVE ecosystem.