First Commit

This commit is contained in:
2025-11-02 22:52:08 +01:00
commit 73fbbf1be2
5821 changed files with 977526 additions and 0 deletions

View File

@@ -0,0 +1,15 @@
lib-cov
*.seed
*.log
*.csv
*.dat
*.out
*.pid
*.gz
pids
logs
results
node_modules
npm-debug.log

View File

@@ -0,0 +1,8 @@
sudo: false
language: node_js
node_js:
- "6"
- "8"
- "10"
before_install:
- npm install -g npm@2

23
html/sternwarte/checkfuehrung/node_modules/redeyed/LICENSE generated vendored Executable file
View File

@@ -0,0 +1,23 @@
Copyright 2012 Thorsten Lorenz.
All rights reserved.
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.

206
html/sternwarte/checkfuehrung/node_modules/redeyed/README.md generated vendored Executable file
View File

@@ -0,0 +1,206 @@
# redeyed [![build status](https://secure.travis-ci.org/thlorenz/redeyed.svg?branch=master)](http://travis-ci.org/thlorenz/redeyed)
<a href="https://www.patreon.com/bePatron?u=8663953"><img alt="become a patron" src="https://c5.patreon.com/external/logo/become_a_patron_button.png" height="35px"></a>
*Add color to your JavaScript!*
![frog](http://allaboutfrogs.org/gallery/photos/redeyes/red1.gif)
[Red Eyed Tree Frog](http://allaboutfrogs.org/info/species/redeye.html) *(Agalychnis callidryas)*
## What?
Takes JavaScript code, along with a config and returns the original code with tokens wrapped and/or replaced as configured.
## Where?
- server side using nodejs
- in the [browser](#browser-support)
## What for?
One usecase is adding metadata to your code that can then be used to apply syntax highlighting.
## How?
- copy the [config.js](https://github.com/thlorenz/redeyed/blob/master/config.js) and edit it in order to specify how
certain tokens are to be surrounded/replaced
- replace the `undefined` of each token you want to configure with one of the following
### {String} config
`'before:after'`
wraps the token inside before/after
### {Object} config
`{ _before: 'before', _after: 'after' }`
wraps token inside before/after
#### Missing before and after resolution for {String} and {Object} config
For the `{String}` and `{Object}` configurations, 'before' or 'after' may be omitted:
- `{String}`:
- `'before:'` (omitting 'after')
- `':after'` (omitting 'before')
- `{Object}`:
- `{ _before: 'before' }` (omitting '_after')
- `{ _after: 'after' }` (omitting '_before')
In these cases the missing half is resolved as follows:
- from the `parent._default` (i.e., `Keyword._default`) if found
- otherwise from the `config._default` if found
- otherwise `''` (empty string)
### {Function} config
`function (tokenString, info) { return {String}|{Object}; }`
#### Inputs
- tokenString: the content of the token that is currently being processed
- info: an object with the following structure
```js
{
// {Int}
// the index of the token being processed inside tokens
tokenIndex
// {Array}
// all tokens that are being processed including comments
// (i.e. the result of merging esprima tokens and comments)
, tokens
// {Object}
// the abstract syntax tree of the parsed code
, ast
// {String}
// the code that was parsed (same string as the one passed to redeyed(code ..)
, code
}
```
In most cases the `tokenString` is all you need. The extra info object is passed in case you need to gather more
information about the `token`'s surroundings in order to decide how to transform it.
See: [replace-log-example](https://github.com/thlorenz/redeyed/blob/master/examples/replace-log.js)
#### Output
You can return a {String} or an {Object} from a {Function} config.
- when returning a {String}, the token value will be replaced with it
- when returning an {Object}, it should be of the following form:
```js
{
// {String}
// the string that should be substituted for the value of the current and all skipped tokens
replacement
// {Object} (Token)
// the token after which processing should continue
// all tokens in between the current one and this one inclusive will be ignored
, skipPastToken
}
```
### Transforming JavaScript code
***redeyed(code, config[, opts])***
Invoke redeyed with your **config**uration, a **code** snippet and maybe **opts** as in the below example:
```javascript
var redeyed = require('redeyed')
, config = require('./path/to/config')
, code = 'var a = 3;'
, result;
// redeyed will throw an error (caused by the esprima parser) if the code has invalid javascript
try {
result = redeyed(code, config);
console.log(result.code);
} catch(err) {
console.error(err);
}
```
***opts***:
```js
{ // {Boolean}
// if true `result.ast` property contains the abstract syntax tree of the code
// if false (default) `result.ast` is not assigned and therefore `undefined`
buildAst: true|false
// {Boolean}
// if `true`, jsx syntax is supported, default `false`
// due to how esprima works, the AST is built when this option is `true`, even if
// `buildAST` is `false`
, jsx: true|false
// {Boolean}
// if true `result.code` is not assigned and therefore `undefined`
// if false (default) `result.code` property contains the result of `split.join`
nojoin: true|false
// {Object}
// overrides default parser `esprima-fb` and needs to be compatible with it
parser: require('esprima')
}
```
***return value***:
```js
{ ast
, tokens
, comments
, splits
, code
}
```
- ast `{Array}`: [abstract syntax tree](http://en.wikipedia.org/wiki/Abstract_syntax_tree) as returned by [esprima
parse](http://en.wikipedia.org/wiki/Abstract_syntax_tree)
- tokens `{Array}`: [tokens](http://en.wikipedia.org/wiki/Token_(parser)) provided by esprima (excluding
comments)
- comments `{Array}`: block and line comments as provided by esprima
- splits `{Array}`: code pieces split up, some of which where transformed as configured
- code `{String}`: transformed code, same as `splits.join('')` unless this step has been skipped (see opts)
## Browser Support
### AMD
Ensure to include [esprima](https://github.com/ariya/esprima) as one of your dependencies
```js
define(['redeyed'], function (redeyed) {
[ .. ]
});
```
### Attached to global window object
The `redeyed {Function}` will be exposed globally as `window.redeyed` - big surprise!
```html
<script type="text/javascript" src="https://unpkg.com/esprima"></script>
<script type="text/javascript" src="https://unpkg.com/redeyed"></script>
```
## redeyed in the wild
- [cardinal](https://github.com/thlorenz/cardinal): Syntax highlights JavaScript code with ANSI colors to be printed to
the terminal
- [peacock](http://thlorenz.github.com/peacock/): JavaScript syntax highlighter that generates html that is compatible
with pygments styles.
## Examples
- `npm explore redeyed; npm demo` will let you try the [browser example](https://github.com/thlorenz/redeyed/tree/master/examples/browser)
- `npm explore redeyed; npm demo-log` will let you try the [replace log example](https://github.com/thlorenz/redeyed/blob/master/examples/replace-log.js)

View File

@@ -0,0 +1,140 @@
/*
* This config only contains ES5 tokens while the default config.js contains
* ES6 tokens as well.
*
* Copy this file and use it as a starting point for your redeyed config.
* Just fill in the tokens you want to surround/replace.
* Keep in mind that more specific configurations override less specific ones.
*/
module.exports = {
'Boolean': {
'true' : undefined
, 'false' : undefined
, _default : undefined
}
, 'Identifier': {
_default: undefined
}
, 'Null': {
_default: undefined
}
, 'Numeric': {
_default: undefined
}
, 'String': {
_default: undefined
}
, 'Keyword': {
'break' : undefined
, 'case' : undefined
, 'catch' : undefined
, 'continue' : undefined
, 'debugger' : undefined
, 'default' : undefined
, 'delete' : undefined
, 'do' : undefined
, 'else' : undefined
, 'finally' : undefined
, 'for' : undefined
, 'function' : undefined
, 'if' : undefined
, 'in' : undefined
, 'instanceof' : undefined
, 'new' : undefined
, 'return' : undefined
, 'switch' : undefined
, 'this' : undefined
, 'throw' : undefined
, 'try' : undefined
, 'typeof' : undefined
, 'var' : undefined
, 'void' : undefined
, 'while' : undefined
, 'with' : undefined
, _default : undefined
}
, 'Punctuator': {
';': undefined
, '.': undefined
, ',': undefined
, '{': undefined
, '}': undefined
, '(': undefined
, ')': undefined
, '[': undefined
, ']': undefined
, '<': undefined
, '>': undefined
, '+': undefined
, '-': undefined
, '*': undefined
, '%': undefined
, '&': undefined
, '|': undefined
, '^': undefined
, '!': undefined
, '~': undefined
, '?': undefined
, ':': undefined
, '=': undefined
, '<=': undefined
, '>=': undefined
, '==': undefined
, '!=': undefined
, '++': undefined
, '--': undefined
, '<<': undefined
, '>>': undefined
, '&&': undefined
, '||': undefined
, '+=': undefined
, '-=': undefined
, '*=': undefined
, '%=': undefined
, '&=': undefined
, '|=': undefined
, '^=': undefined
, '/=': undefined
, '===': undefined
, '!==': undefined
, '>>>': undefined
, '<<=': undefined
, '>>=': undefined
, '>>>=': undefined
, _default: undefined
}
// line comment
, Line: {
_default: undefined
}
/* block comment */
, Block: {
_default: undefined
}
, _default: undefined
}

195
html/sternwarte/checkfuehrung/node_modules/redeyed/config.js generated vendored Executable file
View File

@@ -0,0 +1,195 @@
/*
* Copy this file and use it as a starting point for your redeyed config.
* Just fill in the tokens you want to surround/replace.
* Keep in mind that more specific configurations override less specific ones.
*/
module.exports = {
'Boolean': {
'true' : undefined
, 'false' : undefined
, _default : undefined
}
, 'Identifier': {
_default: undefined
}
, 'Null': {
_default: undefined
}
, 'Numeric': {
_default: undefined
}
, 'String': {
_default: undefined
}
, 'Keyword': {
'break' : undefined
, 'case' : undefined
, 'catch' : undefined
, 'class' : undefined
, 'const' : undefined
, 'continue' : undefined
, 'debugger' : undefined
, 'default' : undefined
, 'delete' : undefined
, 'do' : undefined
, 'else' : undefined
, 'enum' : undefined
, 'export' : undefined
, 'extends' : undefined
, 'finally' : undefined
, 'for' : undefined
, 'function' : undefined
, 'if' : undefined
, 'implements' : undefined
, 'import' : undefined
, 'in' : undefined
, 'instanceof' : undefined
, 'interface' : undefined
, 'let' : undefined
, 'new' : undefined
, 'package' : undefined
, 'private' : undefined
, 'protected' : undefined
, 'public' : undefined
, 'return' : undefined
, 'static' : undefined
, 'super' : undefined
, 'switch' : undefined
, 'this' : undefined
, 'throw' : undefined
, 'try' : undefined
, 'typeof' : undefined
, 'var' : undefined
, 'void' : undefined
, 'while' : undefined
, 'with' : undefined
, 'yield' : undefined
, _default : undefined
}
, 'Punctuator': {
';': undefined
, '.': undefined
, ',': undefined
, '{': undefined
, '}': undefined
, '(': undefined
, ')': undefined
, '[': undefined
, ']': undefined
, '<': undefined
, '>': undefined
, '+': undefined
, '-': undefined
, '*': undefined
, '%': undefined
, '&': undefined
, '|': undefined
, '^': undefined
, '!': undefined
, '~': undefined
, '?': undefined
, ':': undefined
, '=': undefined
, '<=': undefined
, '>=': undefined
, '==': undefined
, '!=': undefined
, '++': undefined
, '--': undefined
, '<<': undefined
, '>>': undefined
, '&&': undefined
, '||': undefined
, '+=': undefined
, '-=': undefined
, '*=': undefined
, '%=': undefined
, '&=': undefined
, '|=': undefined
, '^=': undefined
, '/=': undefined
, '=>': undefined
, '**': undefined
, '===': undefined
, '!==': undefined
, '>>>': undefined
, '<<=': undefined
, '>>=': undefined
, '...': undefined
, '**=': undefined
, '>>>=': undefined
, _default: undefined
}
// line comment
, Line: {
_default: undefined
}
/* block comment */
, Block: {
_default: undefined
}
// JSX
, JSXAttribute: {
_default: undefined
}
, JSXClosingElement: {
_default: undefined
}
, JSXElement: {
_default: undefined
}
, JSXEmptyExpression: {
_default: undefined
}
, JSXExpressionContainer: {
_default: undefined
}
, JSXIdentifier: {
// many more identifies are possible, div, table, etc.
className: undefined
, _default: undefined
}
, JSXMemberExpression: {
_default: undefined
}
, JSXNamespacedName: {
_default: undefined
}
, JSXOpeningElement: {
_default: undefined
}
, JSXSpreadAttribute: {
_default: undefined
}
, JSXText: {
_default: undefined
}
, _default: undefined
}

View File

@@ -0,0 +1,31 @@
.code {
width: 500px;
height: 500px;
display: block;
}
.config {
width: 500px;
height: 400px;
display: block;
}
.go {
display: block;
float: right;
font-size: 18px;
}
.result {
width: 500px;
height: 1000px;
display: block;
}
.edit {
float: left;
}
.results {
float: left;
}

View File

@@ -0,0 +1,35 @@
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title></title>
<link rel="stylesheet" type="text/css" media="screen" href="index.css" />
</head>
<body>
<header>
<span>Change the config and/or the original code in order to affect the "redeyed" result</span>
</header>
<section class="edit">
<section>
<h3>Redeyed Config </h3>
<textarea class="config"></textarea>
<button class="go">Go</button>
</section>
<section>
<h3>Original Code</h3>
<textarea class="code"></textarea>
</section>
</section>
<section class="results">
<h3>Result</h3>
<textarea class="result" readonly="readonly"></textarea>
</section>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
<script type="text/javascript" src="https://unpkg.com/esprima"></script>
<script type="text/javascript" src="../../redeyed.js"></script>
<script type="text/javascript" src="./sample-config.js"></script>
<script type="text/javascript" src="./index.js"></script>
</body>
</html>

View File

@@ -0,0 +1,32 @@
/* global $ redeyed */
var $code = $('.code')
var $config = $('.config')
var $result = $('.result')
function go() {
var config
try {
config = JSON.parse($config.val())
} catch (e) {
$result.val('In "Redeyed Config": ' + e.toString())
return
}
try {
var code = $code.val()
var result = redeyed(code, config)
$result.val(result.code)
} catch (e) {
$result.val('In "Original Code": ' + e.toString())
}
}
$code.val(window.redeyed.toString())
$config.val(JSON.stringify(window.sampleConfig, false, 2))
$('.go').click(go)
go()

View File

@@ -0,0 +1,131 @@
window.sampleConfig = {
'Boolean': {
'true' : undefined
, 'false' : undefined
, _default : '?:?'
}
, 'Identifier': {
_default: '-> : <-'
}
, 'Null': {
_default: '**:**'
}
, 'Numeric': {
_default: 'n:N'
}
, 'String': {
_default: 'string -> :'
}
, 'Keyword': {
'break' : undefined
, 'case' : undefined
, 'catch' : undefined
, 'continue' : undefined
, 'debugger' : undefined
, 'default' : undefined
, 'delete' : undefined
, 'do' : undefined
, 'else' : undefined
, 'finally' : undefined
, 'for' : undefined
, 'function' : undefined
, 'if' : undefined
, 'in' : undefined
, 'instanceof' : undefined
, 'new' : undefined
, 'return' : undefined
, 'switch' : undefined
, 'this' : undefined
, 'throw' : undefined
, 'try' : undefined
, 'typeof' : undefined
, 'var' : undefined
, 'void' : undefined
, 'while' : undefined
, 'with' : undefined
, _default : ': <- keyword'
}
, 'Punctuator': {
';': undefined
, '.': undefined
, ',': undefined
, '{': undefined
, '}': undefined
, '(': undefined
, ')': undefined
, '[': undefined
, ']': undefined
, '<': undefined
, '>': undefined
, '+': undefined
, '-': undefined
, '*': undefined
, '%': undefined
, '&': undefined
, '|': undefined
, '^': undefined
, '!': undefined
, '~': undefined
, '?': undefined
, ':': undefined
, '=': undefined
, '<=': undefined
, '>=': undefined
, '==': undefined
, '!=': undefined
, '++': undefined
, '--': undefined
, '<<': undefined
, '>>': undefined
, '&&': undefined
, '||': undefined
, '+=': undefined
, '-=': undefined
, '*=': undefined
, '%=': undefined
, '&=': undefined
, '|=': undefined
, '^=': undefined
, '/=': undefined
, '===': undefined
, '!==': undefined
, '>>>': undefined
, '<<=': undefined
, '>>=': undefined
, '>>>=': undefined
, _default: undefined
}
// line comment
, Line: {
_default: undefined
}
/* block comment */
, Block: {
_default: undefined
}
, _default: undefined
}

View File

@@ -0,0 +1,58 @@
var path = require('path')
var fs = require('fs')
var redeyed = require('..')
var vm = require('vm')
var samplePath = path.join(__dirname, 'sources', 'log.js')
var origCode = fs.readFileSync(samplePath, 'utf-8')
var kinds = [ 'silly', 'info', 'warn', 'error' ]
function replaceConsole(s, info) {
var code = info.code
var idx = info.tokenIndex
var tokens = info.tokens
var next = tokens[idx + 1].value
var kind = tokens[idx + 2].value
var openParen = tokens[idx + 3].value
var firstArgTkn = tokens[idx + 4]
var argIdx = idx + 3
var open
var tkn
if (kind === 'log') kind = 'silly'
// not a console.xxx(...) statement? -> just return original
if (next !== '.' || !~kinds.indexOf(kind) || openParen !== '(') return s
// skip past arguments to console.xxx all args from ( to )
open = 1
while (open) {
tkn = tokens[++argIdx]
// count open parens vs. closed ones to handle things like console.log(new Error('..'));
if (tkn.value === '(') open++
if (tkn.value === ')') open--
}
// tkn now is the last closing paren
var argsIncludingClosingParen = code.slice(firstArgTkn.range[0], tkn.range[1])
var result = 'log.' + kind + '("main-logger", ' + argsIncludingClosingParen
// tell redeyed to skip the entire console.xxx(..) statement since we are replacing it all
return { replacement: result, skipPastToken: tkn }
}
function transformAndRun() {
var config = {
Identifier: { console: replaceConsole }
}
var code = redeyed(origCode, config).code
var context = vm.createContext({ require: require })
console.log('Original code:\n', origCode)
console.log('\nlog calls replaced:\n', code)
console.log('\nLets run it:')
vm.runInContext(code, context, 'transformed-log.vm')
}
transformAndRun()

View File

@@ -0,0 +1,8 @@
// First two lines will be needed when we replaced all console.xxx statements with log.xxx
var log = require('npmlog')
log.level = 'silly'
console.info('info ', 1)
console.log('log ', 2)
console.warn('warn ', 3)
console.error('error ', new Error('oh my!'))

View File

@@ -0,0 +1,69 @@
{
"_from": "redeyed@~2.1.0",
"_id": "redeyed@2.1.1",
"_inBundle": false,
"_integrity": "sha1-iYS1gV2ZyyIEacme7v/jiRPmzAs=",
"_location": "/redeyed",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "redeyed@~2.1.0",
"name": "redeyed",
"escapedName": "redeyed",
"rawSpec": "~2.1.0",
"saveSpec": null,
"fetchSpec": "~2.1.0"
},
"_requiredBy": [
"/cardinal"
],
"_resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz",
"_shasum": "8984b5815d99cb220469c99eeeffe38913e6cc0b",
"_spec": "redeyed@~2.1.0",
"_where": "/Users/rxf/Projekte/SternDBase/sternwarte/checkfuehrung/node_modules/cardinal",
"author": {
"name": "Thorsten Lorenz",
"email": "thlorenz@gmx.de",
"url": "thlorenz.com"
},
"bugs": {
"url": "https://github.com/thlorenz/redeyed/issues"
},
"bundleDependencies": false,
"dependencies": {
"esprima": "~4.0.0"
},
"deprecated": false,
"description": "Takes JavaScript code, along with a config and returns the original code with tokens wrapped as configured.",
"devDependencies": {
"cardinal": "~1.0.0",
"readdirp": "~2.1.0",
"standart": "^6.1.0",
"tape": "~4.9.0"
},
"homepage": "https://github.com/thlorenz/redeyed#readme",
"keywords": [
"ast",
"syntax",
"tree",
"source",
"wrap",
"metadata"
],
"license": "MIT",
"main": "redeyed.js",
"name": "redeyed",
"repository": {
"type": "git",
"url": "git://github.com/thlorenz/redeyed.git"
},
"scripts": {
"demo": "cd examples/browser; open index.html",
"demo-log": "node examples/replace-log",
"lint": "standart",
"run-test": "tape test/*.js",
"test": "npm run run-test && npm run lint"
},
"version": "2.1.1"
}

313
html/sternwarte/checkfuehrung/node_modules/redeyed/redeyed.js generated vendored Executable file
View File

@@ -0,0 +1,313 @@
;(function() {
'use strict'
/* global define */
var esprima
var exportFn
var toString = Object.prototype.toString
if (typeof module === 'object' && typeof module.exports === 'object' && typeof require === 'function') {
// server side
esprima = require('esprima')
exportFn = function(redeyed) { module.exports = redeyed }
bootstrap(esprima, exportFn)
} else if (typeof define === 'function' && define.amd) {
// client side
// amd
define(['esprima'], function(esprima) {
return bootstrap(esprima)
})
} else if (typeof window === 'object') {
// no amd -> attach to window if it exists
// Note that this requires 'esprima' to be defined on the window, so that script has to be loaded first
window.redeyed = bootstrap(window.esprima)
}
function bootstrap(esprima, exportFn) {
function isFunction(obj) {
return toString.call(obj) === '[object Function]'
}
function isString(obj) {
return toString.call(obj) === '[object String]'
}
function isObject(obj) {
return toString.call(obj) === '[object Object]'
}
function surroundWith(before, after) {
return function(s) { return before + s + after }
}
function isNonCircular(key) {
return key !== '_parent'
}
function objectizeString(value) {
var vals = value.split(':')
if (vals.length === 0 || vals.length > 2) {
throw new Error(
'illegal string config: ' + value +
'\nShould be of format "before:after"'
)
}
if (vals.length === 1 || vals[1].length === 0) {
return vals.indexOf(':') < 0 ? { _before: vals[0] } : { _after: vals[0] }
} else {
return { _before: vals[0], _after: vals[1] }
}
}
function objectize(node) {
// Converts 'bef:aft' to { _before: bef, _after: aft }
// and resolves undefined before/after from parent or root
function resolve(value, key) {
// resolve before/after from root or parent if it isn't present on the current node
if (!value._parent) return undefined
// Immediate parent
if (value._parent._default && value._parent._default[key]) return value._parent._default[key]
// Root
var root = value._parent._parent
if (!root) return undefined
return root._default ? root._default[key] : undefined
}
function process(key) {
var value = node[key]
if (!value) return
if (isFunction(value)) return
// normalize all strings to objects
if (isString(value)) {
node[key] = value = objectizeString(value)
}
value._parent = node
if (isObject(value)) {
if (!value._before && !value._after) return objectize(value)
// resolve missing _before or _after from parent(s)
// in case we only have either one on this node
value._before = value._before || resolve(value, '_before')
value._after = value._after || resolve(value, '_after')
return
}
throw new Error('nodes need to be either {String}, {Object} or {Function}.' + value + ' is neither.')
}
// Process _default ones first so children can resolve missing before/after from them
if (node._default) process('_default')
Object.keys(node)
.filter(function(key) {
return isNonCircular(key)
&& node.hasOwnProperty(key)
&& key !== '_before'
&& key !== '_after'
&& key !== '_default'
})
.forEach(process)
}
function functionize(node) {
Object.keys(node)
.filter(function(key) {
return isNonCircular(key) && node.hasOwnProperty(key)
})
.forEach(function(key) {
var value = node[key]
if (isFunction(value)) return
if (isObject(value)) {
if (!value._before && !value._after) return functionize(value)
// at this point before/after were "inherited" from the parent or root
// (see objectize)
var before = value._before || ''
var after = value._after || ''
node[key] = surroundWith(before, after)
return node[key]
}
})
}
function normalize(root) {
objectize(root)
functionize(root)
}
function mergeTokensAndComments(tokens, comments) {
var all = {}
function addToAllByRangeStart(t) { all[ t.range[0] ] = t }
tokens.forEach(addToAllByRangeStart)
comments.forEach(addToAllByRangeStart)
// keys are sorted automatically
return Object.keys(all)
.map(function(k) { return all[k] })
}
function redeyed(code, config, opts) {
opts = opts || {}
var parser = opts.parser || esprima
var jsx = !!opts.jsx
// tokenizer doesn't support JSX at this point (esprima@4.0.0)
// therefore we need to generate the AST via the parser not only to
// avoid the tokenizer from erroring but also to get JSXIdentifier tokens
var buildAst = jsx || !!opts.buildAst
var hashbang = ''
var ast
var tokens
var comments
var lastSplitEnd = 0
var splits = []
var transformedCode
var all
var info
// Replace hashbang line with empty whitespaces to preserve token locations
if (code[0] === '#' && code[1] === '!') {
hashbang = code.substr(0, code.indexOf('\n') + 1)
code = Array.apply(0, Array(hashbang.length)).join(' ') + '\n' + code.substr(hashbang.length)
}
if (buildAst) {
ast = parser.parse(code, { tokens: true, comment: true, range: true, loc: true, tolerant: true, jsx: true })
tokens = ast.tokens
comments = ast.comments
} else {
tokens = []
comments = []
parser.tokenize(code, { range: true, loc: true, comment: true }, function(token) {
if (token.type === 'LineComment') {
token.type = 'Line'
comments.push(token)
} else if (token.type === 'BlockComment') {
token.type = 'Block'
comments.push(token)
} else {
// Optimistically upgrade 'static' to a keyword
if (token.type === 'Identifier' && token.value === 'static') token.type = 'Keyword'
tokens.push(token)
}
})
}
normalize(config)
function tokenIndex(tokens, tkn, start) {
var current
var rangeStart = tkn.range[0]
for (current = start; current < tokens.length; current++) {
if (tokens[current].range[0] === rangeStart) return current
}
throw new Error('Token %s not found at or after index: %d', tkn, start)
}
function process(surround) {
var result
var currentIndex
var nextIndex
var skip = 0
var splitEnd
result = surround(code.slice(start, end), info)
if (isObject(result)) {
splits.push(result.replacement)
currentIndex = info.tokenIndex
nextIndex = tokenIndex(info.tokens, result.skipPastToken, currentIndex)
skip = nextIndex - currentIndex
splitEnd = skip > 0 ? tokens[nextIndex - 1].range[1] : end
} else {
splits.push(result)
splitEnd = end
}
return { skip: skip, splitEnd: splitEnd }
}
function addSplit(start, end, surround, info) {
var result
var skip = 0
if (start >= end) return
if (surround) {
result = process(surround)
skip = result.skip
lastSplitEnd = result.splitEnd
} else {
splits.push(code.slice(start, end))
lastSplitEnd = end
}
return skip
}
all = mergeTokensAndComments(tokens, comments)
for (var tokenIdx = 0; tokenIdx < all.length; tokenIdx++) {
var token = all[tokenIdx]
var surroundForType = config[token.type]
var surround
var start
var end
// At least the type (e.g., 'Keyword') needs to be specified for the token to be surrounded
if (surroundForType) {
// root defaults are only taken into account while resolving before/after otherwise
// a root default would apply to everything, even if no type default was specified
surround = surroundForType
&& surroundForType.hasOwnProperty(token.value)
&& surroundForType[token.value]
&& isFunction(surroundForType[token.value])
? surroundForType[token.value]
: surroundForType._default
start = token.range[0]
end = token.range[1]
addSplit(lastSplitEnd, start)
info = { tokenIndex: tokenIdx, tokens: all, ast: ast, code: code }
tokenIdx += addSplit(start, end, surround, info)
}
}
if (lastSplitEnd < code.length) {
addSplit(lastSplitEnd, code.length)
}
if (!opts.nojoin) {
transformedCode = splits.join('')
if (hashbang.length > 0) {
transformedCode = hashbang + transformedCode.substr(hashbang.length)
}
}
return {
ast : ast
, tokens : tokens
, comments : comments
, splits : splits
, code : transformedCode
}
}
return exportFn ? exportFn(redeyed) : redeyed
}
})()

View File

@@ -0,0 +1,54 @@
'use strict'
var test = require('tape')
var util = require('util')
var redeyed = require('..')
function inspect(obj) {
return util.inspect(obj, false, 5, true)
}
test('adding custom asserts ... ', function(t) {
t.constructor.prototype.assertSurrounds = function(code, opts, expected) {
var result = redeyed(code, opts).code
this.equals(result, expected, inspect(code) + ' => ' + inspect(expected))
return this
}
t.end()
})
test('\nbefore/after config, keywords', function(t) {
var opts001 = { Keyword: { _default: { _before: '*', _after: '&' } } }
t.test('\n# ' + inspect(opts001), function(t) {
t.assertSurrounds('this', opts001, '*this&')
t.assertSurrounds('if (a == 1) return', opts001, '*if& (a == 1) *return&')
t.assertSurrounds('var n = new Test();', opts001, '*var& n = *new& Test();')
t.end()
})
var opts002 = {
Keyword: {
'function': { _before: '^' }
, 'return': { _before: '(', _after: ')' }
, _default: { _before: '*', _after: '&' }
}
}
t.test('\n# ' + inspect(opts002), function(t) {
t.assertSurrounds(
[ 'function foo (bar) {'
, ' var a = 3;'
, ' return bar + a;'
, '}'
].join('\n')
, opts002
, [ '^function& foo (bar) {'
, ' *var& a = 3;'
, ' (return) bar + a;'
, '}'
].join('\n'))
t.end()
})
t.end()
})

View File

@@ -0,0 +1,72 @@
'use strict'
var test = require('tape')
var util = require('util')
var redeyed = require('..')
function inspect(obj) {
return util.inspect(obj, false, 5, true)
}
test('adding custom asserts ... ', function(t) {
t.constructor.prototype.assertSurrounds = function(code, opts, expected) {
var result = redeyed(code, opts)
this.equals(result.code, expected, inspect(code) + ' => ' + inspect(expected))
return this
}
t.end()
})
test('\nstring config, Line comments', function(t) {
var opts = { Line: { _default: '*:&' } }
t.test('\n# ' + inspect(opts), function(t) {
t.assertSurrounds(
'// a comment'
, opts
, '*// a comment&'
)
t.assertSurrounds(
'// comment then new line\nif (a == 1) return'
, opts
, '*// comment then new line&\nif (a == 1) return'
)
t.assertSurrounds(
'var n = new Test();// some comment after\n//more comment\nvar s = 3;'
, opts
, 'var n = new Test();*// some comment after&\n*//more comment&\nvar s = 3;'
)
t.end()
})
t.end()
})
test('\nstring config, Block comments', function(t) {
var opts = { Block: { _default: '_:-' } }
t.test('\n# ' + inspect(opts), function(t) {
t.assertSurrounds(
'/* a comment */'
, opts
, '_/* a comment */-'
)
t.assertSurrounds(
'/* comment then new line*/\nif (a == 1) /* inline */ return'
, opts
, '_/* comment then new line*/-\nif (a == 1) _/* inline */- return'
)
t.assertSurrounds(
'var n = new Test();/* some comment after*/\n/*more comment*/\nvar s = 3;'
, opts
, 'var n = new Test();_/* some comment after*/-\n_/*more comment*/-\nvar s = 3;'
)
t.assertSurrounds(
'var a = 4;\n/* Multi line comment\n * Next line\n * and another\n*/ var morecode = "here";'
, opts
, 'var a = 4;\n_/* Multi line comment\n * Next line\n * and another\n*/- var morecode = "here";'
)
t.end()
})
t.end()
})

View File

@@ -0,0 +1,59 @@
'use strict'
var test = require('tape')
var util = require('util')
var redeyed = require('..')
function inspect(obj) {
return util.inspect(obj, false, 5, true)
}
test('adding custom asserts ... ', function(t) {
t.constructor.prototype.assertSurrounds = function(code, opts, expected) {
var optsi = inspect(opts)
var result = redeyed(code, opts).code
this.equals(result
, expected
, util.format('%s: %s => %s', optsi, inspect(code), inspect(expected))
)
return this
}
t.end()
})
test('\n undefineds only', function(t) {
t.assertSurrounds('1 + 2', { Numeric: { _default: undefined } }, '1 + 2')
t.assertSurrounds('1 + 2', { Numeric: { _default: undefined }, _default: undefined }, '1 + 2')
t.assertSurrounds(
'return true'
, { 'Boolean': { 'true': undefined, 'false': undefined, _default: undefined }, _default: undefined }
, 'return true'
)
t.end()
})
test('\n mixed', function(t) {
t.assertSurrounds(
'return true || false'
, { 'Boolean': { 'true': '&:', 'false': undefined, _default: undefined }, _default: undefined }
, 'return &true || false'
)
t.assertSurrounds(
'return true || false'
, { 'Boolean': { 'true': '&:', 'false': undefined, _default: ':?' }, _default: undefined }
, 'return &true? || false?'
)
t.assertSurrounds(
'return true || false'
, { 'Boolean': { 'true': '&:', 'false': undefined, _default: undefined }, _default: ':?' }
, 'return &true? || false'
)
t.end()
})

View File

@@ -0,0 +1,53 @@
'use strict'
var test = require('tape')
var util = require('util')
var redeyed = require('..')
function inspect(obj) {
return util.inspect(obj, false, 5, true)
}
test('function - config passing idx and tokens', function(t) {
var args = []
var opts001 = {
Boolean: {
_default: identity
}
, Keyword: {
_default: identity
}
, Identifier: {
_default: identity
}
, Punctuator: {
_default: identity
}
}
var code = 'var fn = function () { return true; }'
function identity(s, info) {
args.push({ value: s, idx: info.tokenIndex, tokens: info.tokens, code: info.code })
// returning unchanged string will keep the splits be equal to the original tokens
return s
}
t.test(inspect(opts001) + ' -- ' + code, function(t) {
var result = redeyed(code, opts001, { splits: true })
var tokens = result.tokens
t.equals(args.length, tokens.length, 'called with all tokens')
for (var i = 0; i < tokens.length; i++) {
var token = tokens[i]
var arg = args[i]
t.equals(arg.value, token.value, 'passes correct value: ' + inspect([ arg.value, token.value ]))
t.equals(arg.idx, i, 'passes correct index')
t.equals(arg.code, code, 'passes code')
t.deepEquals(arg.tokens, tokens, 'passes all tokens')
}
t.end()
})
t.end()
})

View File

@@ -0,0 +1,78 @@
'use strict'
var test = require('tape')
var redeyed = require('..')
test('given i skip 2 more tokens after each semicolon', function(t) {
var calls = 0
var opts = {
Punctuator: {
';': function identity(s, info) {
// tell it to skip past second to last token that is 2 ahead of the current one
calls++
var skipToken = info.tokens[info.tokenIndex + 2]
return skipToken ? { replacement: s, skipPastToken: skipToken } : s
}
}
}
;[ { code: ';;;', expectedCalls: 1 }
, { code: ';;;;', expectedCalls: 2 }
, { code: '; ; ; ;', expectedCalls: 2 }
, { code: ';;; ;;; ;;; ;', expectedCalls: 4 }
, { code: ';;; ;;; ;;; ;;; ;', expectedCalls: 5 }
, { code: ';;; ;;; ;;; ;;; ;;;', expectedCalls: 5 }
, { code: ';;; ;;; ;;; ;;; ;;; ;', expectedCalls: 6 }
].forEach(function(x) {
calls = 0
redeyed(x.code, opts)
t.equals(calls, x.expectedCalls, 'calls ' + x.expectedCalls + ' times for ' + x.code)
})
t.end()
})
test('replace log', function(t) {
var opts = {
Identifier: {
console: function replaceLog(s, info) {
var code = info.code
var idx = info.tokenIndex
var tokens = info.tokens
var kind = tokens[idx + 2].value
var firstArgTkn = tokens[idx + 4]
var argIdx = idx + 3
var open
var tkn
open = 1
while (open) {
tkn = tokens[++argIdx]
if (tkn.value === '(') open++
if (tkn.value === ')') open--
}
var argsIncludingClosingParen = code.slice(firstArgTkn.range[0], tkn.range[1])
var result = 'log.' + kind + '("main-logger", ' + argsIncludingClosingParen
return { replacement: result, skipPastToken: tkn }
}
}
}
var origCode = [
'console.info("info ", 1);'
, 'console.warn("warn ", 3);'
, 'console.error("error ", new Error("oh my!"));'
].join('\n')
var expectedCode = [
'log.info("main-logger", "info ", 1));'
, 'log.warn("main-logger", "warn ", 3));'
, 'log.error("main-logger", "error ", new Error("oh my!")));'
].join('\n')
var code = redeyed(origCode, opts).code
t.equals(code, expectedCode, 'transforms all log statements')
t.end()
})

View File

@@ -0,0 +1,146 @@
'use strict'
var test = require('tape')
var util = require('util')
var redeyed = require('..')
function inspect(obj) {
return util.inspect(obj, false, 5, true)
}
test('adding custom asserts ... ', function(t) {
t.constructor.prototype.assertSurrounds = function(code, opts, expected) {
var result = redeyed(code, opts).code
this.equals(result, expected, inspect(code) + ' => ' + inspect(expected))
return this
}
t.end()
})
test('\nfunction config, keywords', function(t) {
var opts001 = { Keyword: { _default: function(s) { return '*' + s + '&' } } }
t.test('\n# ' + inspect(opts001), function(t) {
t.assertSurrounds('this', opts001, '*this&')
t.assertSurrounds('this ', opts001, '*this& ')
t.assertSurrounds(' this', opts001, ' *this&')
t.assertSurrounds(' this ', opts001, ' *this& ')
t.assertSurrounds('if (a == 1) return', opts001, '*if& (a == 1) *return&')
t.assertSurrounds('var n = new Test();', opts001, '*var& n = *new& Test();')
t.assertSurrounds(
[ 'function foo (bar) {'
, ' var a = 3;'
, ' return bar + a;'
, '}'
].join('\n')
, opts001
, [ '*function& foo (bar) {'
, ' *var& a = 3;'
, ' *return& bar + a;'
, '}'
].join('\n'))
t.end()
})
var opts002 = {
Keyword: {
'function': function(s) { return '^' + s + '&' }
, 'return': function(s) { return '(' + s + ')' }
, _default: function(s) { return '*' + s + '&' }
}
}
t.test('\n# ' + inspect(opts002), function(t) {
t.assertSurrounds(
[ 'function foo (bar) {'
, ' var a = 3;'
, ' return bar + a;'
, '}'
].join('\n')
, opts002
, [ '^function& foo (bar) {'
, ' *var& a = 3;'
, ' (return) bar + a;'
, '}'
].join('\n'))
t.end()
})
t.end()
})
test('#\n functin config - resolving', function(t) {
var opts001 = {
Keyword: {
'var': function(s) { return '^' + s + '&' }
}
, _default: function(s) { return '*' + s + '&' }
}
t.test('\n# specific but no type default and root default - root default not applied' + inspect(opts001), function(t) {
t.assertSurrounds('var n = new Test();', opts001, '^var& n = new Test();').end()
})
var opts002 = {
Keyword: {
'var': function(s) { return '^' + s + '&' }
, _default: function(s) { return '*' + s + '&' }
}
, _default: function(s) { return '(' + s + ')' }
}
t.test('\n# no type default but root default' + inspect(opts002), function(t) {
t.assertSurrounds('var n = new Test();', opts002, '^var& n = *new& Test();').end()
})
t.end()
})
test('#\n function config - replacing', function(t) {
var opts001 = {
Keyword: {
'var': function() { return 'const' }
}
}
t.test('\n# type default and root default (type wins)' + inspect(opts001), function(t) {
t.assertSurrounds('var n = new Test();', opts001, 'const n = new Test();').end()
})
var opts002 = {
Keyword: {
_default: function() { return 'const' }
}
}
t.test('\n# type default' + inspect(opts002), function(t) {
t.assertSurrounds('var n = new Test();', opts002, 'const n = const Test();').end()
})
var opts003 = {
Keyword: {
'new': function() { return 'NEW' }
, _default: function() { return 'const' }
}
}
t.test('\n# specific and type default' + inspect(opts003), function(t) {
t.assertSurrounds('var n = new Test();', opts003, 'const n = NEW Test();').end()
})
var opts004 = {
Keyword: {
_default: function(s) { return s.toUpperCase() }
}
, _default: function(s) { return 'not applied' }
}
t.test('\n# type default and root default (type wins)' + inspect(opts004), function(t) {
t.assertSurrounds('var n = new Test();', opts004, 'VAR n = NEW Test();').end()
})
var opts005 = {
Keyword: { }
, _default: function(s) { return s.toUpperCase() }
}
t.test('\n# no type default only root default - not applied' + inspect(opts005), function(t) {
t.assertSurrounds('var n = new Test();', opts005, 'var n = new Test();').end()
})
t.end()
})

View File

@@ -0,0 +1,37 @@
'use strict'
var test = require('tape')
var util = require('util')
var redeyed = require('..')
function inspect(obj) {
return util.inspect(obj, false, 5, true)
}
test('adding custom asserts ... ', function(t) {
t.constructor.prototype.assertSurrounds = function(code, opts, expected) {
var optsi = inspect(opts)
var result = redeyed(code, opts).code
this.equals(result
, expected
, util.format('%s: %s => %s', optsi, inspect(code), inspect(expected))
)
return this
}
t.end()
})
test('incomplete statement', function(t) {
t.test('\n# Keyword', function(t) {
var keyconfig = { 'Keyword': { _default: '$:%' } }
t.assertSurrounds('if(foo) { x', keyconfig, '$if%(foo) { x')
t.assertSurrounds('class Foo { constructor(name)', keyconfig, '$class% Foo { constructor(name)')
t.assertSurrounds('const x = ', keyconfig, '$const% x = ')
t.assertSurrounds('function g() { yield', keyconfig, '$function% g() { $yield%')
t.end()
})
t.end()
})

View File

@@ -0,0 +1,39 @@
'use strict'
/* eslint-disable no-template-curly-in-string */
var test = require('tape')
var util = require('util')
var redeyed = require('..')
function inspect(obj) {
return util.inspect(obj, false, 5, true)
}
test('adding custom asserts ... ', function(t) {
t.constructor.prototype.assertSurrounds = function(code, opts, expected) {
var result = redeyed(code, opts, { jsx: true }).code
if (expected == null) console.log(result)
else this.equals(result, expected, inspect(code) + ' => ' + inspect(expected))
return this
}
t.end()
})
test('\njsx support', function(t) {
var config = {
'JSXIdentifier': {
className: '$xc:cx%'
, _default: '$x:x%'
}
, 'Punctuator': { _default: '$:%'
}
}
t.assertSurrounds(
'<Component start={1} className="hello" />'
, config
, '$<%$xComponentx% $xstartx%$=%${%1$}% $xcclassNamecx%$=%"hello" $/%$>%'
)
t.end()
})

View File

@@ -0,0 +1,44 @@
'use strict'
var test = require('tape')
var util = require('util')
var redeyed = require('..')
function inspect(obj) {
return util.inspect(obj, false, 5, true)
}
test('adding custom asserts ... ', function(t) {
t.constructor.prototype.assertSurrounds = function(code, opts, expected) {
var optsi = inspect(opts)
var result = redeyed(code, opts).code
this.equals(result
, expected
, util.format('%s: %s => %s', optsi, inspect(code), inspect(expected))
)
return this
}
t.end()
})
test('types', function(t) {
t.test('\n# Keyword', function(t) {
var keyconfig = { 'Keyword': { _default: '$:%' } }
t.assertSurrounds('import foo from \'foo\';', keyconfig, '$import% foo from \'foo\';')
t.assertSurrounds('export default foo;', keyconfig, '$export% $default% foo;')
t.assertSurrounds('if(foo) { let bar = 1;}', keyconfig, '$if%(foo) { $let% bar = 1;}')
t.assertSurrounds('const x = "foo";', keyconfig, '$const% x = "foo";')
t.assertSurrounds('"use strict";(function* () { yield *v })', keyconfig, '"use strict";($function%* () { $yield% *v })')
t.assertSurrounds('"use strict"; (class A { static constructor() { super() }})', keyconfig
, '"use strict"; ($class% A { $static% constructor() { $super%() }})')
t.assertSurrounds('class Foo { constructor(name){this.name = name;}}', keyconfig
, '$class% Foo { constructor(name){$this%.name = name;}}')
t.assertSurrounds('class Foo extends Bar { constructor(name,value){super(value);this.name = name;}}', keyconfig
, '$class% Foo $extends% Bar { constructor(name,value){$super%(value);$this%.name = name;}}')
t.end()
})
t.end()
})

View File

@@ -0,0 +1,47 @@
'use strict'
var test = require('tape')
var util = require('util')
var redeyed = require('..')
function inspect(obj) {
return util.inspect(obj, false, 5, true)
}
test('adding custom asserts ... ', function(t) {
t.constructor.prototype.assertSurrounds = function(code, opts, expected) {
var result = redeyed(code, opts).code
this.equals(result, expected, inspect(code) + ' => ' + inspect(expected))
return this
}
t.end()
})
test('\nmixed config, keywords', function(t) {
var opts001 = {
Keyword: {
'this': function(s) { return '_' + s }
, 'if': { _before: '^' }
, _default: '*:&'
}
}
t.test('\n# ' + inspect(opts001), function(t) {
t.assertSurrounds('if (this.hello) return "world";', opts001, '^if& (_this.hello) *return& "world";').end()
})
var opts002 = {
Keyword: {
'this': function(s) { return '_' + s }
, 'if': { _before: '^' }
, 'return': ':)'
, _default: ':&'
}
, _default: '*:&'
}
t.test('\n# ' + inspect(opts002), function(t) {
t.assertSurrounds('if (this.hello) return "world";', opts002, '^if& (_this.hello) *return) "world";').end()
})
t.end()
})

View File

@@ -0,0 +1,56 @@
'use strict'
var test = require('tape')
var redeyed = require('..')
var esprima = require('esprima')
test('redeyed result does not have esprima ast by default', function(t) {
var code = '// a comment\nvar a = 3;'
var conf = { Keyword: { _default: '_:-' } }
var ast = esprima.parse(code, { tokens: true, comment: true, range: true, loc: true, tolerant: true })
var tokens = ast.tokens
var comments = ast.comments
var result = redeyed(code, conf)
t.equal(typeof result.ast, 'undefined', 'ast')
t.deepEquals(result.tokens, tokens, 'tokens')
t.deepEquals(result.comments, comments, 'comments')
t.notEquals(result.code, undefined, 'code')
t.end()
})
test('redeyed result has esprima ast, tokens, comments and splits and transformed code', function(t) {
var code = '// a comment\nvar a = 3;'
var conf = { Keyword: { _default: '_:-' } }
var ast = esprima.parse(code, { tokens: true, comment: true, range: true, loc: true, tolerant: true })
var tokens = ast.tokens
var comments = ast.comments
var result = redeyed(code, conf, { buildAst: true })
t.deepEquals(result.ast, ast, 'ast')
t.deepEquals(result.tokens, tokens, 'tokens')
t.deepEquals(result.comments, comments, 'comments')
t.notEquals(result.code, undefined, 'code')
t.end()
})
test('redeyed result - { nojoin } has esprima ast, tokens, comments and splits but no transformed code', function(t) {
var code = '// a comment\nvar a = 3;'
var conf = { Keyword: { _default: '_:-' } }
var ast = esprima.parse(code, { tokens: true, comment: true, range: true, loc: true, tolerant: true })
var tokens = ast.tokens
var comments = ast.comments
var result = redeyed(code, conf, { nojoin: true, buildAst: true })
t.deepEquals(result.ast, ast, 'ast')
t.deepEquals(result.tokens, tokens, 'tokens')
t.deepEquals(result.comments, comments, 'comments')
t.equals(result.code, undefined, 'code')
t.end()
})

View File

@@ -0,0 +1,22 @@
'use strict'
var test = require('tape')
var util = require('util')
var redeyed = require('..')
function inspect(obj) {
return util.inspect(obj, false, 5, true)
}
test('properly handles script level return -- no blow up', function(t) {
var code = [
''
, 'return 1;'
].join('\n')
var opts = { Keyword: { 'return': '%:^' } }
var expected = '\n%return^ 1;'
var res = redeyed(code, opts).code
t.equals(res, expected, inspect(code) + ' opts: ' + inspect(opts) + ' => ' + inspect(expected))
t.end()
})

View File

@@ -0,0 +1,25 @@
'use strict'
var test = require('tape')
var util = require('util')
var redeyed = require('..')
function inspect(obj) {
return util.inspect(obj, false, 5, true)
}
test('preserves shebang', function(t) {
var code = [
'#!/usr/bin/env node'
, 'var util = require("util");'
].join('\n')
var opts = { Keyword: { 'var': '%:^' } }
var expected = [
'#!/usr/bin/env node'
, '%var^ util = require("util");'
].join('\n')
var res = redeyed(code, opts).code
t.equals(res, expected, inspect(code) + ' opts: ' + inspect(opts) + ' => ' + inspect(expected))
t.end()
})

View File

@@ -0,0 +1,38 @@
'use strict'
// applying redeyed to a bunch of files of contained libraries as a smoke test
var test = require('tape')
var path = require('path')
var fs = require('fs')
var readdirp = require('readdirp')
var redeyed = require('..')
var nodeModules = path.join(__dirname, '..', 'node_modules')
var esprimadir = path.join(nodeModules, 'esprima')
test('esprima', function(t) {
readdirp({ root: esprimadir, fileFilter: '*.js' })
.on('data', function(entry) {
var code = fs.readFileSync(entry.fullPath, 'utf-8')
var resultAst = redeyed(code, { Keyword: { 'var': '+:-' } }, { buildAst: true }).code
var resultTokenize = redeyed(code, { Keyword: { 'var': '+:-' } }, { buildAst: false }).code
t.assert(~resultAst.indexOf('+var-') || !(~resultAst.indexOf('var ')), 'redeyed ' + entry.path)
t.assert(~resultTokenize.indexOf('+var-') || !(~resultTokenize.indexOf('var ')), 'redeyed ' + entry.path)
})
.on('end', t.end.bind(t))
})
test('redeyed', function(t) {
readdirp({
root: path.join(__dirname, '..')
, fileFilter: '*.js'
, directoryFilter: [ '!.git', '!node_modules' ]
})
.on('data', function(entry) {
var code = fs.readFileSync(entry.fullPath, 'utf-8')
var result = redeyed(code, { Keyword: { 'var': '+:-' } }).code
t.assert(~result.indexOf('+var-') || !(~result.indexOf('var ')), 'redeyed ' + entry.path)
})
.on('end', t.end.bind(t))
})

View File

@@ -0,0 +1,125 @@
'use strict'
var test = require('tape')
var util = require('util')
var redeyed = require('..')
function inspect(obj) {
return util.inspect(obj, false, 5, true)
}
test('adding custom asserts ... ', function(t) {
t.constructor.prototype.assertSurrounds = function(code, opts, expected) {
var result = redeyed(code, opts).code
this.equals(result, expected, inspect(code) + ' => ' + inspect(expected))
return this
}
t.end()
})
test('\nstring config, keywords', function(t) {
var opts001 = { Keyword: { _default: '*:&' } }
t.test('\n# ' + inspect(opts001), function(t) {
t.assertSurrounds('this', opts001, '*this&')
t.assertSurrounds('if (a == 1) return', opts001, '*if& (a == 1) *return&')
t.assertSurrounds('var n = new Test();', opts001, '*var& n = *new& Test();')
t.end()
})
var opts002 = {
Keyword: {
'function': '^:'
, 'return': '(:)'
, _default: '*:&'
}
}
t.test('\n# ' + inspect(opts002), function(t) {
t.assertSurrounds(
[ 'function foo (bar) {'
, ' var a = 3;'
, ' return bar + a;'
, '}'
].join('\n')
, opts002
, [ '^function& foo (bar) {'
, ' *var& a = 3;'
, ' (return) bar + a;'
, '}'
].join('\n'))
t.end()
})
t.end()
})
test('\nstring configs resolve from type and root', function(t) {
var code = 'var a = new Test();'
function run(t, conf, expected, code_) {
t.test('\n# ' + inspect(conf), function(t) {
t.assertSurrounds(code_ || code, conf, expected)
t.end()
})
}
// at least the token kind has to be configured in order for the root_default to be applied
// otherwise a root._default would affect all tokens, even the ones we want to leave unchanged
run(t, { _default: '*:' }, 'var a = new Test();')
t.test('\n\n# only before or after specified, but no root._default', function(t) {
run(t, { Keyword: { _default: '*:' } }, '*var a = *new Test();')
run(t, { Keyword: { _default: ':-' } }, 'var- a = new- Test();')
t.end()
})
t.test('\n\n# resolve missing from root._default', function(t) {
run(t, { Keyword: { _default: '*:' }, _default: '(:-' }, '*var- a = *new- Test();')
run(t, { Keyword: { _default: ':-' }, _default: '*:)' }, '*var- a = *new- Test();')
t.end()
})
t.test('\n\n# no resolve if all specified', function(t) {
run(t, { Keyword: { _default: '+:-' }, _default: '*:)' }, '+var- a = +new- Test();')
run(t, { Keyword: { _default: ':-' }, _default: ':)' }, 'var- a = new- Test();')
t.end()
})
t.test('\n\n# resolve specific token no defaults', function(t) {
run(t, { Keyword: { 'var': '*:' } }, '*var a = new Test();')
run(t, { Keyword: { 'var': ':-' } }, 'var- a = new Test();')
t.end()
})
t.test('\n\n# resolve specific token with type defaults', function(t) {
run(t, { Keyword: { 'var': '*:', _default: ':-' } }, '*var- a = new- Test();')
run(t, { Keyword: { 'var': '*:', _default: '(:-' } }, '*var- a = (new- Test();')
run(t, { Keyword: { 'var': ':-', _default: '*:' } }, '*var- a = *new Test();')
run(t, { Keyword: { 'var': ':-', _default: '*:)' } }, '*var- a = *new) Test();')
run(t, { Keyword: { 'var': ':-', 'new': ':&', _default: '*:' } }, '*var- a = *new& Test();')
t.end()
})
t.test(
'\n\n# resolve specific token with root defaults, but no type default - root default not applied to unspecified tokens'
, function(t) {
run(t, { Keyword: { 'var': '*:' }, _default: ':-' }, '*var- a = new Test();')
run(t, { Keyword: { 'var': ':-' }, _default: '*:' }, '*var- a = new Test();')
t.end()
}
)
t.test('\n\n# resolve specific token with type and root defaults', function(t) {
run(t, { Keyword: { 'var': '*:', _default: '+:-' }, _default: ':)' }, '*var- a = +new- Test();')
run(t, { Keyword: { 'var': ':-', _default: '*:+' }, _default: '(:' }, '*var- a = *new+ Test();')
t.end()
})
t.test('all exact tokens undefined, but type default', function(t) {
run(t, { 'Boolean': { 'true': undefined, 'false': undefined, _default: '+:-' } }, 'return +true- || +false-;', 'return true || false;')
t.end()
})
t.end()
})

View File

@@ -0,0 +1,78 @@
'use strict'
/* eslint-disable no-template-curly-in-string */
var test = require('tape')
var util = require('util')
var redeyed = require('..')
function inspect(obj) {
return util.inspect(obj, false, 5, true)
}
test('adding custom asserts ... ', function(t) {
t.constructor.prototype.assertSurrounds = function(code, opts, expected) {
var optsi = inspect(opts)
var result = redeyed(code, opts).code
this.equals(result
, expected
, util.format('%s: %s => %s', optsi, inspect(code), inspect(expected))
)
return this
}
t.end()
})
test('types', function(t) {
t.test('\n# Boolean', function(t) {
t.assertSurrounds('return true;', { 'Boolean': { _default: '$:%' } }, 'return $true%;')
t.assertSurrounds('return true; return false;'
, { 'Boolean': { 'false': '#:', _default: '$:%' } }
, 'return $true%; return #false%;')
t.end()
})
t.test('\n# Identifier', function(t) {
t.assertSurrounds('var a = 1;', { 'Identifier': { _default: '$:%' } }, 'var $a% = 1;')
t.assertSurrounds('var a = 1; const b = 2;'
, { 'Identifier': { 'b': '#:', _default: '$:%' } }
, 'var $a% = 1; const #b% = 2;')
t.end()
})
t.test('\n# Null', function(t) {
t.assertSurrounds('return null;', { 'Null': { _default: '$:%' } }, 'return $null%;').end()
})
t.test('\n# Numeric', function(t) {
t.assertSurrounds('return 1;', { 'Numeric': { _default: '$:%' } }, 'return $1%;')
t.assertSurrounds('return 1; return 2;'
, { 'Numeric': { '2': '#:', _default: '$:%' } }
, 'return $1%; return #2%;')
t.end()
})
t.test('\n# Punctuator', function(t) {
var punctuator = { 'Punctuator': { _default: '$:%' } }
t.assertSurrounds('return 2 * 2;', punctuator, 'return 2 $*% 2$;%')
t.assertSurrounds('return 2 * 2;'
, { 'Punctuator': { '*': '#:', _default: '$:%' } }
, 'return 2 #*% 2$;%')
t.assertSurrounds('var {op, lhs, rhs} = getASTNode()', punctuator, 'var ${%op$,% lhs$,% rhs$}% $=% getASTNode$(%$)%')
t.assertSurrounds('function f(x, y=12) { return x + y;}', punctuator, 'function f$(%x$,% y$=%12$)% ${% return x $+% y$;%$}%')
t.assertSurrounds('function f(x, ...y) { return x * y.length;}', punctuator, 'function f$(%x$,% $...%y$)% ${% return x $*% y$.%length$;%$}%')
t.end()
})
t.test('\n# String', function(t) {
t.assertSurrounds('return "hello";', { 'String': { _default: '$:%' } }, 'return $"hello"%;')
t.assertSurrounds('return "hello"; return "world";'
, { 'String': { '"world"': '#:', _default: '$:%' } }
, 'return $"hello"%; return #"world"%;')
t.end()
})
t.end()
})

View File

@@ -0,0 +1,45 @@
'use strict'
/* eslint-disable no-template-curly-in-string */
var test = require('tape')
var util = require('util')
var redeyed = require('..')
function inspect(obj) {
return util.inspect(obj, false, 5, true)
}
test('adding custom asserts ... ', function(t) {
t.constructor.prototype.assertSurrounds = function(code, opts, expected) {
var optsi = inspect(opts)
var result = redeyed(code, opts).code
this.equals(result
, expected
, util.format('%s: %s => %s', optsi, inspect(code), inspect(expected))
)
return this
}
t.end()
})
test('upcoming syntax: rest and spread properties', function(t) {
t.test('\n# Punctuator', function(t) {
var punctuator = { 'Punctuator': { _default: '$:%' } }
t.assertSurrounds('{a,...b} = c', punctuator, '${%a$,%$...%b$}% $=% c')
t.assertSurrounds('x={y,...z}', punctuator, 'x$=%${%y$,%$...%z$}%')
t.assertSurrounds('x ** y', punctuator, 'x $**% y')
t.assertSurrounds('x **= y', punctuator, 'x $**=% y')
t.end()
})
t.test('\n# Identifier', function(t) {
var identifier = { 'Identifier': { _default: '$:%' } }
t.assertSurrounds('{a,...b} = c', identifier, '{$a%,...$b%} = $c%')
t.assertSurrounds('x={y,...z}', identifier, '$x%={$y%,...$z%}')
t.end()
})
t.end()
})