npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

sdm2

v1.1.3

Published

A high performance library to match discontinuous strings

Downloads

27

Readme

npm minzipped size Coverage Status typescript license

🚀 特性

  • 易于使用
  • 高性能
  • 小于 1kb
  • 支持 TypeScript

安装

# via npm
npm install sdm2

# via yarn
yarn add sdm2

Node.js, esModule, Browser引入

// commonjs(Node.js)
var { match, filterMap } = require('sdm2').default;

// esModule
import { match, filterMap } from 'sdm2';

Browser

<script src="https://unpkg.com/sdm2"></script>

用法

也许你会用它在路径搜索,树型控件选项搜索,checkbox 项搜索,或其他一些本地数据的非连续字符串搜索,它都可以满足你,请参见下面的示例。

匹配字符串

const ret = match('src/views/home.jsx', 'shojsx');
/* ret => {
  origin: 'src/views/home.jsx',
  str: 'src/views/home.jsx',
  strArr: ['src/views/home.jsx'],
  position: [0, [10, 11], [15, 17]],
  indexes: [0, 10, 11, 15, 16, 17]
}
*/

// 未匹配则返回null
const ret = match('src/views/home.jsx', 'ZZZZ');
// ret => null

返回字段解释 | 字段名 | 描述 | | ---- | ---- | | origin | 被查找字符串,match 函数的第一个参数原始值 | | str | 匹配关键字后通过onMatched转换后的字符串,如果未指定onMatched,它的值和 origin 相同 | | strArr | 关键字已匹配字符串与未匹配字符串的切分数组,如果指定了onMatched,匹配部分为onMatched转换后的值 | | position | 匹配的关键字所在被查找字符串的位置,如果连续匹配到多个关键字,会通过[startIndex, endIndex]表示 | | indexes | 匹配的关键字所在被查找字符串的位置,与position不同的是,即使连续匹配到多个关键字也会一一列出 |

匹配嵌套的字符串

如果被查找的字符串嵌套在对象内,可以使用matchStr返回被查找的字符串。

const ret = match({ name: 'src/views/home.jsx' }, 'shojsx', {
	matchStr: obj => obj.name
});
/* ret => {
  origin: { name: 'src/views/home.jsx' },
  str: 'src/views/home.jsx',
  strArr: ['src/views/home.jsx'],
  position: [0, [10, 11], [15, 17]],
  indexes: [0, 10, 11, 15, 16, 17]
}
*/

数组过滤

利用未匹配值为 null 过滤数组。

const matchedStrings = [
  'src/views/home.jsx',
  'src/views/about.jsx',
  'src/views/ad.jsx',
];
const ret = matchedStrings.filter(strItem => match(strItem, 'srchom.X', { ignoreCase: true });
/* ret => ['src/views/home.jsx'] */

高亮已匹配字符

使用onMatched函数转换匹配字符串,可以高亮匹配到的关键字。

onMatched会在每次匹配到一部分关键字时触发,它的参数分别为匹配的关键字和查找的原始值。

import { match } from 'sdm2';
const ret = match('src/views/home.jsx', 'shojsx', {
	onMatched: (matchedStr, origin) => `<span class="highlight">${matchedStr}</span>`
});
/* ret => {
  origin: 'src/views/home.jsx',
  str: '<span class="highlight">s</span>rc/views/<span class="highlight">ho</span>me.<span class="highlight">jsx</span>',
  strArr: [
    '<span class="highlight">s</span>',
    'rc/views/',
    '<span class="highlight">ho</span>',
    'me.',
    '<span class="highlight">jsx</span>'
  ],
  position: [0, [10, 11], [15, 17]],
  indexes: [0, 10, 11, 15, 16, 17]
}
*/

过滤数组并高亮已匹配字符

如果对于字符串数组,我们可以使用filterMap同时进行过滤和转换字符串。filterMap将会先过滤出符合查找关键字的项,再调用onMap转换已匹配项

import { filterMap } from 'sdm2';

const matchedStrings = ['src/views/home.jsx', 'src/views/about.jsx', 'src/views/ad.jsx'];
const ret = filterMap(matchedStrings, 'shojsx', {
	onMatched: (matchedStr, originStr) => `<span class="highlight">${matchedStr}</span>`,
	onMap: (matchedInfo, index) => matchedInfo.str
});
/* ret => ['<span class="highlight">s</span>rc/views/<span class="highlight">ho</span>me.<span class="highlight">jsx</span>']
 */

jsx 语法高亮

可能你不喜欢使用dangerouslySetInnerHTML(react)或v-html(vue)来高亮关键字,在 jsx 中,你还可以在onMatched中返回虚拟 dom,并在onMap中返回已经切分好的数组,这更符合 UI 框架的使用习惯:

const ret = filterMap(matchedStrings, 'shojsx', {
	onMatched: (matchedStr, originStr) => <span class="highlight">${matchedStr}</span>,
	onMap: (matchedInfo, index) => matchedInfo.strArr
});

/* ret => [
  VNode {
    class: 'highlight',
    children: 's'
  },
  'rc/views/',
  VNode {
    class: 'highlight',
    children: 'ho'
  },
  'me.',
  VNode {
    class: 'highlight',
    children: 'jsx'
  }
]

性能


你不需担心性能问题,每一个被搜索字符串都只会被对比一次,因此保证了高性能。下面是随机字符串的性能测试结果。

关键字符串为 50 位随机字符串 | 字符串数量 | 单字符串长度 | 忽大小写 | 性能 | | ---- | ---- | ---- | ---- | | 1000 | 5000 | ✅ | 19ms | | 1000 | 5000 | ❌ | 16ms | | 5000 | 5000 | ✅ | 42ms | | 5000 | 5000 | ❌ | 39ms | | 10000 | 5000 | ✅ | 101ms | | 10000 | 5000 | ❌ | 84ms |

欢迎提交问题

如果您在使用 sdm2 时遇到困难,无论是 bug,还是新功能,都可以 点此提交

LICENSE

MIT