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 🙏

© 2026 – Pkg Stats / Ryan Hefner

refactor-box

v0.0.1

Published

> `demo`在`neovim`和`vscode`都能顺利运行,因为本人vscode使用经验较少,可能`vscode`有些地方描述不对,或者使用上的问题都欢迎探讨。

Readme

typescript plugin demo

demoneovimvscode都能顺利运行,因为本人vscode使用经验较少,可能vscode有些地方描述不对,或者使用上的问题都欢迎探讨。

术语:

lsp: 微软定义的语言服务协议,https://microsoft.github.io/language-server-protocol/specifications/specification-current

tsserver: vscode背后提供智能编辑体验的服务器,https://github.com/microsoft/TypeScript/wiki/Standalone-Server-%28tsserver%29

typescript plugin: tsserver插件,可以用来扩展编辑器服务,比如补全,refactor,https://github.com/microsoft/TypeScript/wiki/Writing-a-Language-Service-Plugin,可以在tsconfig配置,https://www.typescriptlang.org/tsconfig#plugins,然后npm安装到vscode语言服务插件目录,我的是在E:\app\Microsoft VS Code\resources\app\extensions\typescript-language-features\node_modules

refactor: 重构,这里指的不是大范围的重构,指的是比较小的操作。比如将箭头函数改成函数表达式,将某段if代码改成swith。

开发参考资源

  1. 入门认识,https://juejin.cn/post/6942380528456695844
  2. typescript ast查看器
  3. 可以参考typescript-transformer,因为原理基本一样,通过操作ast实现

开发简单文档

lsp基本原理

编辑器前端收到用户的需要语法解析的编辑操作(比如跳转定义,补全) 编辑器前端按照lsp标准发请求给lsp后端(vscodelsp后端是tsserver) lsp后端收到并分析返回结果(比如得到补全列表,得到定义位置) 编辑器前端通过自己的ui系统展示结果,并等待用户其他操作

lsp的意义在于让编辑器插件变得通用。比如要为neovimvscodesublimeatomtypescript,pythonc++插件,我们要写4*3一共12个。 使用lsp编写的插件只需要4+3一共7个。用时间复杂度来说就是: n为编辑器数量,m为语言数量,使用lsp将插件数量从n*m减少到了n+m

为什么是n+m呢? 因为lsp其实是一个前后端分离的架构,需要实现n个编辑器前端插件和m个语言服务插件。

简单例子

function init(modules: { typescript: typeof import("typescript/lib/tsserverlibrary") }) {
  const ts = modules.typescript;

  function create(info: ts.server.PluginCreateInfo) {
    // Set up decorator object
    const proxy: ts.LanguageService = Object.create(null);
    for (let k of Object.keys(info.languageService) as Array<keyof ts.LanguageService>) {
      const x = info.languageService[k]!;
      // @ts-expect-error - JS runtime trickery which is tricky to type tersely
      proxy[k] = (...args: Array<{}>) => x.apply(info.languageService, args);
    }
    return { create };
  }
}

info.LanguageService是服务器暴露给我们的api,当编辑器访问一些功能时会调用,比如获取补全列表,获取可以重构提示,跳转定义等。可以跳转到它的类型定义了解更多。 info.LanguageService定义位置 简单介绍一些api: getApplicableRefactors: 获取重构提示,即是返回一些重构操作的选项,供用户选择。vscode可以按ctrl+shift+R来弹出这个菜单, 或者点击代码行左边的小灯泡,都会请求服务器,服务器会执行这个api。 getEditsForRefactor: 上一步获取到重构操作的名字,当用户确定要执行这个操作时,会请求服务器,然后服务器执行这个api获取重构操作具体要干什么返回编辑器。 getCompletionsAtPosition: api补全菜单的获取需要这个

以上的代码例子意思是说可以通过代理这些api来扩展我们需要的操作。我们可以先获取原始api的结果,然后做修改,或者添加。或者不使用原始api的结果,用我们自己的方法。

简单编写流程

我们代理这些api后,具体要怎么做才能得到结果呢?一般的流程是:

  1. 我们编辑的时候,发现了一个不舒服的地方,比如有时我们写了一个React functional component,但是后来发现我们更想使用class component,所以就慢慢将一些函数写成方法,一些变量改成类属性,外面包一个class。实在是太费功夫了。
  2. 这个就是一个重构(vscode里叫做refactor),可以用typescript plugin实现的。首先我们用上面ast查看工具看看functional componentclass component的节点都是什么东西
  3. functional component其实是一个FunctionDeclarationclass component是一个ClassDeclaration。要做的东西其实就清晰了,我们要将一个FunctionDeclaration转成一个ClassDeclaration(或者相反)。
  4. 代理getApplicableRefactors方法,获取到光标位置的节点(具体可以看代码),然后判断它是不是FunctionDeclaration,是则返回这个重构操作名字,比如MyRefactor
  5. 代理getEditsForRefactor方法,获取到光标位置的节点,判断操作名是不是MyRefactor且节点是FunctionDeclaration,是则根据FunctionDeclaration创建一个ClassDeclaration,具体api可以用ts.factory(ts则是上面代码init传入的变量),然后返回重构操作

操作ast其实可以参考各种transformer,因为原理是一样的。

调试配置(暂时只会打log调试)

vscode

参考https://github.com/microsoft/TypeScript/wiki/Debugging-Language-Service-in-VS-Code 没有试过

neovim

前提是已经lsp已经配置好,以下配置wsl运行通过

  1. npm link typescript plugin模块链接到全局(即NODE_PATH
  2. built-in-lspconfig tsserver配置修改:
local bin_name = 'typescript-language-server'
local getPath = function (str)
  return str:match("(.*/)")
end
lspconfig.tsserver.setup {
  init_options = { plugins = {{ name = 'ts-plugin-test', location = getPath(os.getenv('NODE_PATH'))} }},
  cmd = { bin_name, '--stdio', '--tsserver-log-file', os.getenv('HOME') .. '/tsserver.log', '--log-level', '3' }
}

然后就可以在代码里通过这个logger模块来输出日志了。

意义

对比其他插件:

这个是更通用的方案,在所有支持语言服务器的编辑器都可以收益。

重构功能对比babel-transformertypesccript-transformer

  1. 场景不一样。当我们明确知道需要改动什么,并且要修改jsts语法,可以使用transformer。如果是一些小优化,或者说是没有强制使用的规范,比如class componentfunctional component,我们是根据具体情况使用的,再者是我们要第一时间知道我们的refactor具体做了什么,判断refactor合理与否,我们需要使用typescript plugin
  2. typescript plugin作用于编辑过程,只需要某个人修改一次就不需要再做处理了。transformer每次编译都会处理。

一些资源

关于ast 入门demo 是带我入门的一篇blog lsp specifications languager server protocol语言服务协议规范 Write a typescript plugin官方typescript plugin文档,比较简陋 ast查看器 很有用,编写插件全靠它 typescript languager servertsserver包装成一个基于lsp规范的语言服务器。比较好笑的是,tsserver并没有完全按照lsp规范,所以需要一层包装。应该是因为先有tsserver,然后再从tsserver抽离出lsp规范。