mirror of
https://github.com/litruv/unhomoglyph.git
synced 2026-07-24 02:36:12 +10:00
first commit
This commit is contained in:
1
.eslintignore
Normal file
1
.eslintignore
Normal file
@@ -0,0 +1 @@
|
|||||||
|
coverage
|
||||||
141
.eslintrc.yml
Normal file
141
.eslintrc.yml
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
env:
|
||||||
|
node: true
|
||||||
|
es6: true
|
||||||
|
|
||||||
|
rules:
|
||||||
|
accessor-pairs: 2
|
||||||
|
array-bracket-spacing: [ 2, "always", { "singleValue": true, "objectsInArrays": true, "arraysInArrays": true } ]
|
||||||
|
block-scoped-var: 2
|
||||||
|
block-spacing: 2
|
||||||
|
brace-style: [ 2, '1tbs', { allowSingleLine: true } ]
|
||||||
|
# Postponed
|
||||||
|
#callback-return: 2
|
||||||
|
comma-dangle: 2
|
||||||
|
comma-spacing: 2
|
||||||
|
comma-style: 2
|
||||||
|
computed-property-spacing: [ 2, never ]
|
||||||
|
consistent-this: [ 2, self ]
|
||||||
|
consistent-return: 2
|
||||||
|
# ? change to multi
|
||||||
|
curly: [ 2, 'multi-line' ]
|
||||||
|
dot-notation: 2
|
||||||
|
eol-last: 2
|
||||||
|
eqeqeq: 2
|
||||||
|
func-style: [ 2, declaration ]
|
||||||
|
# Postponed
|
||||||
|
#global-require: 2
|
||||||
|
guard-for-in: 2
|
||||||
|
handle-callback-err: 2
|
||||||
|
|
||||||
|
indent: [ 2, 2, { VariableDeclarator: { var: 2, let: 2, const: 3 }, SwitchCase: 1 } ]
|
||||||
|
|
||||||
|
# key-spacing: [ 2, { "align": "value" } ]
|
||||||
|
keyword-spacing: 2
|
||||||
|
linebreak-style: 2
|
||||||
|
max-depth: [ 1, 6 ]
|
||||||
|
max-nested-callbacks: [ 1, 4 ]
|
||||||
|
# string can exceed 80 chars, but should not overflow github website :)
|
||||||
|
max-len: [ 2, 120, 1000 ]
|
||||||
|
new-cap: 2
|
||||||
|
new-parens: 2
|
||||||
|
# Postponed
|
||||||
|
#newline-after-var: 2
|
||||||
|
no-alert: 2
|
||||||
|
no-array-constructor: 2
|
||||||
|
no-bitwise: 2
|
||||||
|
no-caller: 2
|
||||||
|
#no-case-declarations: 2
|
||||||
|
no-catch-shadow: 2
|
||||||
|
no-cond-assign: 2
|
||||||
|
no-console: 1
|
||||||
|
no-constant-condition: 2
|
||||||
|
no-control-regex: 2
|
||||||
|
no-debugger: 2
|
||||||
|
no-delete-var: 2
|
||||||
|
no-div-regex: 2
|
||||||
|
no-dupe-args: 2
|
||||||
|
no-dupe-keys: 2
|
||||||
|
no-duplicate-case: 2
|
||||||
|
no-else-return: 2
|
||||||
|
# Tend to drop
|
||||||
|
# no-empty: 1
|
||||||
|
no-empty-character-class: 2
|
||||||
|
no-empty-pattern: 2
|
||||||
|
no-eq-null: 2
|
||||||
|
no-eval: 2
|
||||||
|
no-ex-assign: 2
|
||||||
|
no-extend-native: 2
|
||||||
|
no-extra-bind: 2
|
||||||
|
no-extra-boolean-cast: 2
|
||||||
|
no-extra-semi: 2
|
||||||
|
no-fallthrough: 2
|
||||||
|
no-floating-decimal: 2
|
||||||
|
no-func-assign: 2
|
||||||
|
# Postponed
|
||||||
|
#no-implicit-coercion: [2, { "boolean": true, "number": true, "string": true } ]
|
||||||
|
no-implied-eval: 2
|
||||||
|
no-inner-declarations: 2
|
||||||
|
no-invalid-regexp: 2
|
||||||
|
no-irregular-whitespace: 2
|
||||||
|
no-iterator: 2
|
||||||
|
no-label-var: 2
|
||||||
|
no-labels: 2
|
||||||
|
no-lone-blocks: 2
|
||||||
|
no-lonely-if: 2
|
||||||
|
no-loop-func: 2
|
||||||
|
no-mixed-requires: 2
|
||||||
|
no-mixed-spaces-and-tabs: 2
|
||||||
|
# Postponed
|
||||||
|
#no-native-reassign: 2
|
||||||
|
no-negated-in-lhs: 2
|
||||||
|
# Postponed
|
||||||
|
#no-nested-ternary: 2
|
||||||
|
no-new: 2
|
||||||
|
no-new-func: 2
|
||||||
|
no-new-object: 2
|
||||||
|
no-new-require: 2
|
||||||
|
no-new-wrappers: 2
|
||||||
|
no-obj-calls: 2
|
||||||
|
no-octal: 2
|
||||||
|
no-octal-escape: 2
|
||||||
|
no-path-concat: 2
|
||||||
|
no-proto: 2
|
||||||
|
no-redeclare: 2
|
||||||
|
# Postponed
|
||||||
|
#no-regex-spaces: 2
|
||||||
|
no-return-assign: 2
|
||||||
|
no-self-compare: 2
|
||||||
|
no-sequences: 2
|
||||||
|
# no-shadow: 2
|
||||||
|
no-shadow-restricted-names: 2
|
||||||
|
no-sparse-arrays: 2
|
||||||
|
no-trailing-spaces: 2
|
||||||
|
no-undef: 2
|
||||||
|
no-undef-init: 2
|
||||||
|
no-undefined: 2
|
||||||
|
no-unexpected-multiline: 2
|
||||||
|
no-unreachable: 2
|
||||||
|
no-unused-expressions: 2
|
||||||
|
no-unused-vars: 2
|
||||||
|
no-use-before-define: 2
|
||||||
|
no-void: 2
|
||||||
|
no-with: 2
|
||||||
|
object-curly-spacing: [ 2, always, { "objectsInObjects": true, "arraysInObjects": true } ]
|
||||||
|
operator-assignment: 1
|
||||||
|
# Postponed
|
||||||
|
#operator-linebreak: [ 2, after ]
|
||||||
|
semi: 2
|
||||||
|
semi-spacing: 2
|
||||||
|
space-before-function-paren: [ 2, { "anonymous": "always", "named": "never" } ]
|
||||||
|
space-in-parens: [ 2, never ]
|
||||||
|
space-infix-ops: 2
|
||||||
|
space-unary-ops: 2
|
||||||
|
# Postponed
|
||||||
|
#spaced-comment: [ 1, always, { exceptions: [ '/', '=' ] } ]
|
||||||
|
strict: [ 2, global ]
|
||||||
|
quotes: [ 2, single, avoid-escape ]
|
||||||
|
quote-props: [ 1, 'as-needed', { "keywords": true } ]
|
||||||
|
radix: 2
|
||||||
|
use-isnan: 2
|
||||||
|
valid-typeof: 2
|
||||||
|
yoda: [ 2, never, { "exceptRange": true } ]
|
||||||
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
node_modules
|
||||||
|
coverage
|
||||||
|
*.log
|
||||||
|
*.swp
|
||||||
5
.travis.yml
Normal file
5
.travis.yml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
language: node_js
|
||||||
|
node_js:
|
||||||
|
- '4'
|
||||||
|
- '6'
|
||||||
|
sudo: false
|
||||||
4
CHANGELOG.md
Normal file
4
CHANGELOG.md
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
1.0.0 / WIP
|
||||||
|
------------------
|
||||||
|
|
||||||
|
- First release.
|
||||||
22
LICENSE
Normal file
22
LICENSE
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
Copyright (c) 2016 Vitaly Puzrin.
|
||||||
|
|
||||||
|
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.
|
||||||
36
README.md
Normal file
36
README.md
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
# unhomoglyph
|
||||||
|
|
||||||
|
[](https://travis-ci.org/nodeca/unhomoglyph)
|
||||||
|
[](https://www.npmjs.org/package/unhomoglyph)
|
||||||
|
|
||||||
|
> Replace all homoglyphs with base characters. Useful to detect similar strings.
|
||||||
|
|
||||||
|
Data source - [Recommended confusable mapping for IDN](http://www.unicode.org/Public/security/latest/confusables.txt), v8.0.0.
|
||||||
|
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install unhomoglyph --save
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
const unhomoglyph = require('unhomoglyph');
|
||||||
|
|
||||||
|
console.log(unhomoglyph('AΑАᎪᗅᴀꓮ')); // => AAAAAAA
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Update
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run update
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
[MIT](https://github.com/nodeca/unhomoglyph/blob/master/LICENSE)
|
||||||
20
index.js
Normal file
20
index.js
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
|
||||||
|
var data = require('./data.json');
|
||||||
|
|
||||||
|
function escapeRegexp(str) {
|
||||||
|
return str.replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1');
|
||||||
|
}
|
||||||
|
|
||||||
|
var REPLACE_RE = RegExp(Object.keys(data).map(escapeRegexp).join('|'), 'g');
|
||||||
|
|
||||||
|
function replace_fn(match) {
|
||||||
|
return data[match];
|
||||||
|
}
|
||||||
|
|
||||||
|
function unhomoglyph(str) {
|
||||||
|
return str.replace(REPLACE_RE, replace_fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = unhomoglyph;
|
||||||
24
package.json
Normal file
24
package.json
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"name": "unhomoglyph",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Replace all homoglyphs with base characters.",
|
||||||
|
"keywords": [
|
||||||
|
"homoglyph",
|
||||||
|
"homoglyphs"
|
||||||
|
],
|
||||||
|
"repository": "nodeca/promise-memoize",
|
||||||
|
"license": "MIT",
|
||||||
|
"files": [
|
||||||
|
"index.js",
|
||||||
|
"data.json"
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"lint": "eslint .",
|
||||||
|
"test": "npm run lint && mocha",
|
||||||
|
"update": "node update.js && npm test"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"eslint": "^3.11.1",
|
||||||
|
"mocha": "^3.2.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
29
test.js
Normal file
29
test.js
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
'use strict';
|
||||||
|
/* global describe, it */
|
||||||
|
|
||||||
|
|
||||||
|
const assert = require('assert');
|
||||||
|
const unhomoglyph = require('./');
|
||||||
|
const data = require('./data.json');
|
||||||
|
|
||||||
|
|
||||||
|
describe('unhomoglyph', function () {
|
||||||
|
|
||||||
|
describe('should replace', function () {
|
||||||
|
Object.keys(data).forEach(key => {
|
||||||
|
it(`${key} => ${data[key]}`, function () {
|
||||||
|
assert.strictEqual(unhomoglyph(`${key}`), `${data[key]}`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shoult not touch ordinary strings', function () {
|
||||||
|
assert.strictEqual(unhomoglyph('abc'), 'abc');
|
||||||
|
assert.strictEqual(unhomoglyph(''), '');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should find multiple entries', function () {
|
||||||
|
assert.strictEqual(unhomoglyph('1abcаа'), 'labcaa');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
60
update.js
Normal file
60
update.js
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
// Download whitelist from http://iframely.com/qa/whitelist.json
|
||||||
|
//
|
||||||
|
'use strict';
|
||||||
|
/* eslint-disable no-console */
|
||||||
|
|
||||||
|
|
||||||
|
const http = require('http');
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
|
||||||
|
const URL = 'http://www.unicode.org/Public/security/latest/confusables.txt';
|
||||||
|
const SAVE_PATH = path.join(__dirname, 'data.json');
|
||||||
|
|
||||||
|
|
||||||
|
console.log('Downloading: ' + URL + ' ...');
|
||||||
|
|
||||||
|
// Parse & save mappings
|
||||||
|
function save(str) {
|
||||||
|
let result = {};
|
||||||
|
|
||||||
|
console.log('Writing data...');
|
||||||
|
|
||||||
|
str.split(/\r?\n/g)
|
||||||
|
.filter(line => line.length && line[0] !== '#')
|
||||||
|
.forEach(line => {
|
||||||
|
if (line.split(';').length < 2) return;
|
||||||
|
|
||||||
|
let [ src, dst ] = line.split(';').slice(0, 2).map(s => s.trim());
|
||||||
|
|
||||||
|
src = String.fromCodePoint(parseInt(src, 16));
|
||||||
|
dst = dst
|
||||||
|
.replace(/\s+/g, ' ')
|
||||||
|
.split(' ')
|
||||||
|
.map(code => !code ? '' : String.fromCodePoint(parseInt(code, 16)))
|
||||||
|
.join('');
|
||||||
|
result[src] = dst;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
fs.writeFileSync(SAVE_PATH, JSON.stringify(result, null, ' '));
|
||||||
|
console.log('Done!');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Download
|
||||||
|
http.get(URL, function (res) {
|
||||||
|
if (res.statusCode !== 200) {
|
||||||
|
console.error('Bad response code: ' + res.statusCode);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
let data = [];
|
||||||
|
|
||||||
|
res.setEncoding('utf8');
|
||||||
|
|
||||||
|
res
|
||||||
|
.on('data', chunk => data.push(chunk))
|
||||||
|
.on('error', err => { console.error(err); process.exit(1); })
|
||||||
|
.on('end', () => save(data.join('')));
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user