Skip to content
0

JavaScript

js 相关

youch ---> 在控制台和 Web 打印错误

配合 hono 框架的一个例子

import { Hono } from 'hono'
import { Youch } from 'youch'

const app = new Hono()
const IN_DEV = process.env.NODE_ENV === 'development'

app.onError(async (error, c) => {
  if (IN_DEV) {
    const youch = new Youch()
    const html = await youch.toHTML(error)
    return c.html(html)
  }
  return c.text(error.message)
})

minisearch ---> 轻量级搜索引擎

支持自动补全建议,模糊查询,自定义分词逻辑,字段提取

// A collection of documents for our examples
const documents = [
  {
    id: 1,
    title: 'Moby Dick',
    text: 'Call me Ishmael. Some years ago...',
    category: 'fiction'
  },
  // ...and more
]

let miniSearch = new MiniSearch({
  fields: ['title', 'text'], // fields to index for full-text search
  storeFields: ['title', 'category'] // fields to return with search results
})

// Index all documents
miniSearch.addAll(documents)

// Search with default options
let results = miniSearch.search('zen art motorcycle')
// => [
//   { id: 2, title: 'Zen and the Art of Motorcycle Maintenance', category: 'fiction', score: 2.77258, match: { ... } },
//   { id: 4, title: 'Zen and the Art of Archery', category: 'non-fiction', score: 1.38629, match: { ... } }
// ]

es-toolkit ---> JS 方法库

相比于 lodash-es,有着更好的性能

// import from '@es-toolkit/es-toolkit' in jsr.
import { debounce, chunk } from 'es-toolkit';

const debouncedLog = debounce(message => {
  console.log(message);
}, 300);

// This call will be debounced
debouncedLog('Hello, world!');

const array = [1, 2, 3, 4, 5, 6];
const chunkedArray = chunk(array, 2);

console.log(chunkedArray);
// Output: [[1, 2], [3, 4], [5, 6]]

pretty-bytes ---> 字节格式化处理

import prettyBytes from 'pretty-bytes';

prettyBytes(1337);
//=> '1.34 kB'

prettyBytes(100);
//=> '100 B'

相似仓库:avoidwork/filesize.js

obfuscator ---> javascript 混淆器

var JavaScriptObfuscator = require('javascript-obfuscator');

var obfuscationResult = JavaScriptObfuscator.obfuscate(`
  (function(){
      var variable1 = '5' - 3;
      var variable2 = '5' + 3;
      console.log(variable3);
      console.log(variable4);
      console.log(variable5);
  })();
`);

console.log(obfuscationResult.getObfuscatedCode());

flexsearch ---> 搜索引擎

可以搜索文本、对象、数组等df

const FlexSearch = require('flexsearch');

// 创建 FlexSearch 实例
const index = new FlexSearch({
  encode: 'advanced',
  tokenize: 'forward',
  threshold: 0,
  resolution: 9,dsfa
});

// 准备搜索的数据
const data = [
  { id: 1, name: 'John Doe', email: 'john@example.com' },
  { id: 2, name: 'Jane Doe', email: 'jane@example.com' },
];

// 向索引中添加数据
data.forEach(item => {
  index.add(item.id, [item.name, item.email]);
});

// 执行搜索操作
console.log(index.search('jane')); // [2]

flatted ---> JSON 解析器

可以用来解析循环的 JS 对象

import {toJSON, fromJSON} from 'flatted';

class RecursiveMap extends Map {
  static fromJSON(any) {
    return new this(fromJSON(any));
  }
  toJSON() {
    return toJSON([...this.entries()]);
  }
}

const recursive = new RecursiveMap;
const same = {};
same.same = same;
recursive.set('same', same);

const asString = JSON.stringify(recursive);
const asMap = RecursiveMap.fromJSON(JSON.parse(asString));
asMap.get('same') === asMap.get('same').same;
// true

public-ip ---> 获得当前 IP 地址

浏览器和 NodeJs 都适用

import {publicIp, publicIpv4, publicIpv6} from 'public-ip';

console.log(await publicIp()); // Falls back to IPv4
//=> 'fe80::200:f8ff:fe21:67cf'

console.log(await publicIpv6());
//=> 'fe80::200:f8ff:fe21:67cf'

console.log(await publicIpv4());
//=> '46.5.21.123'

mitt ---> 发布订阅模式库

import mitt from 'mitt'

const emitter = mitt()

// listen to an event
emitter.on('foo', e => console.log('foo', e) )

// listen to all events
emitter.on('*', (type, e) => console.log(type, e) )

// fire an event
emitter.emit('foo', { a: 'b' })

// clearing all events
emitter.all.clear()

// working with handler references:
function onFoo() {}
emitter.on('foo', onFoo)   // listen
emitter.off('foo', onFoo)  // unlisten

@preact/signals-core ---> reactive 库

preact 的 reactive 库,可集成到任何的框架当中

import { signal } from "@preact/signals-core";

const counter = signal(0);

// Read value from signal, logs: 0
console.log(counter.value);

// Write to a signal
counter.value = 1;

类似的库:modderme123/reactively

devalue ---> JSON 序列化器

序列化 JSON 中不存在的 JS 数据结构、防 XSS、执行序列化循环对象

import * as devalue from 'devalue';

let obj = { message: 'hello' };

let stringified = devalue.stringify(obj); // '[{"message":1},"hello"]'
devalue.parse(stringified); // { message: 'hello' }

obj.self = obj;

stringified = devalue.stringify(obj); // '[{"message":1,"self":0},"hello"]'
devalue.parse(stringified); // { message: 'hello', self: [Circular] }

类似的项目:blitz-js/superjson

terser ---> js 压缩器

import { minify } from 'terser'

minify(code)

rss-parser ---> RSS 解析器

import Parser from 'rss-parser';

type CustomFeed = {foo: string};
type CustomItem = {bar: number};

const parser: Parser<CustomFeed, CustomItem> = new Parser({
  customFields: {
    feed: ['foo', 'baz'],
    //            ^ will error because `baz` is not a key of CustomFeed
    item: ['bar']
  }
});

(async () => {

  const feed = await parser.parseURL('https://www.reddit.com/.rss');
  console.log(feed.title); // feed will have a `foo` property, type as a string

  feed.items.forEach(item => {
    console.log(item.title + ':' + item.link) // item will have a `bar` property type as a number
  });
})();

js-yaml ---> YAML 解析器

const yaml = require('js-yaml');
const fs   = require('fs');

// Get document, or throw exception on error
try {
  const doc = yaml.load(fs.readFileSync('/home/ixti/example.yml', 'utf8'));
  console.log(doc);
} catch (e) {
  console.log(e);
}

sucrase ----> Babel 替代品

动机:我们不再需要 Babel 生产低级产物来兼容 IE,所以无需做太多步骤的转换

由于 Sucrase 的工作层级较低,并针对其用例使用定制的解析器,因此比 Babel 快得多

import {transform} from "sucrase";
const compiledCode = transform(code, {transforms: ["typescript", "imports"]}).code;

tinyld ----> 识别语言

判断一段文字是什么语言

import { detect, detectAll } from 'tinyld'

// Detect
detect('これは日本語です.') // ja
detect('and this is english.') // en

// DetectAll
detectAll('ceci est un text en francais.')
// [ { lang: 'fr', accuracy: 0.5238 }, { lang: 'ro', accuracy: 0.3802 }, ... ]

periscopic ---> ESTree 程序分析工具

import { analyze } from 'periscopic';

const ast = acorn.parse(`
const a = b;
console.log(a);
`);

const { map, globals, scope } = analyze(ast);

acorn ---> ECMAScript parser

ECMAScript 解析器

const acorn = require("acorn")
const walk = require("acorn-walk")

walk.simple(acorn.parse("let x = 10"), {
  Literal(node) {
    console.log(`Found a literal: ${node.value}`)
  }
})

其他 parser: eslint/espree

其他 walker: Rich-Harris/estree-walker

Numeraljs ---> 数字标准化

可以解析不同格式的数字以及转化成想要的格式

var string = numeral(1000).format('0,0');
// '1,000'

var number = numeral(1000),
    value = 100;
var difference = number.difference(value);
// 900

introJs ---> lightweight intro lib

新手引导

另一个库类似的也极其推荐:kamranahmedse/driver.js,而且免费商用

p-queue ---> promise queue

promise queue with concurrency control

import PQueue from 'p-queue';
import got from 'got';

const queue = new PQueue({concurrency: 1});

(async () => {
	await queue.add(() => got('https://sindresorhus.com'));
	console.log('Done: sindresorhus.com');
})();

(async () => {
	await queue.add(() => got('https://avajs.dev'));
	console.log('Done: avajs.dev');
})();

(async () => {
	const task = await getUnicornTask();
	await queue.add(task);
	console.log('Done: Unicorn task');
})();

markdownlint-cli ---> markdown 文档 lint

可以和 case-police 一起使用

{
  "lint:docs": "markdownlint ./docs && case-police 'docs/**/*.md'",
  "lint:docs:fix": "markdownlint ./docs --fix && case-police 'docs/**/*.md' --fix",
}

sentry-javascript ---> 监控库

import { init, captureMessage } from '@sentry/browser';

init({
  dsn: '__DSN__',
  // ...
});

captureMessage('Hello, world!');

clipboardy ---> 剪切板工具

import clipboard from 'clipboardy';

clipboard.writeSync('🦄');

clipboard.readSync();
//=> '🦄'

anymatch ---> 模块路径匹配

import anymatch from 'anymatch'

const matchers = [ 'path/to/file.js', 'path/anyjs/**/*.js', /foo.js$/, string => string.includes('bar') && string.length > 10 ] ;

anymatch(matchers, 'path/to/file.js'); // true
anymatch(matchers, 'bar.js'); // false

// returnIndex = true
anymatch(matchers, 'foo.js', {returnIndex: true}); // 2
anymatch(matchers, 'path/anyjs/foo.js', {returnIndex: true}); // 1

// any picomatc

// using globs to match directories and their children
anymatch('node_modules', 'node_modules'); // true
anymatch('node_modules', 'node_modules/somelib/index.js'); // false
anymatch('**/node_modules/**', '/absolute/path/to/node_modules/somelib/index.js'); // true

const matcher = anymatch(matchers);
['foo.js', 'bar.js'].filter(matcher);  // [ 'foo.js' ]

类似:micromatch/micromatchmicromatch/picomatch

Featureminimatchmicromatchpicomatchnanomatchextglobbracesexpand-brackets
Wildcard matching (*?+)---
Advancing globbing----
Brace matching---
Brace expansion----
Extglobspartial---
Posix brackets----
Regular expression syntax--
File system operations-------

acorn ---> JS 语法解析

相比用 Babel 做语法解析,更加轻便好用,得到 AST

import { Parser } from "acorn";

const tree = Parser.parse(`
	function add(a, b) {
		console.log(a + b)
	}
	add(1, 2)
`, {
	ecmaVersion: 'latest'
})

console.log(tree)

nanoid ---> Hash 生成

相比于 UUID v4,特点:

  • 使用更大的 alphabet,默认情况使用 URL-friendly symbols
  • 包体积更小
import { nanoid, customAlphabet } from 'nanoid'
model.id = nanoid() //=> "V1StGXR8_Z5jdHi6B-myT"

const nanoid = customAlphabet('1234567890abcdef', 10)
model.id = nanoid(5) //=> "f01a2"

dot-prop ---> 点路径操作

使用点路径从嵌套对象获取、设置或删除属性

import {getProperty, setProperty, hasProperty, deleteProperty} from 'dot-prop';

// Getter
getProperty({foo: {bar: 'unicorn'}}, 'foo.bar');
//=> 'unicorn'

getProperty({foo: {bar: 'a'}}, 'foo.notDefined.deep');
//=> undefined

// Setter
const object = {foo: {bar: 'a'}};
setProperty(object, 'foo.bar', 'b');
console.log(object);
//=> {foo: {bar: 'b'}}

// Deleter
const object = {foo: {bar: 'a'}};
deleteProperty(object, 'foo.bar');
console.log(object);
//=> {foo: {}}

klona ---> 多种数据结构深度拷贝

import { klona } from 'klona'

const input = {
  foo: 1,
  bar: {
    baz: 2,
    bat: {
      hello: 'world'
    }
  }
};
const output = klona(input);

// exact copy of original
assert.deepStrictEqual(input, output);

Released under the MIT License.