kuromoji.js is a Node.js version of kuromoji, the main purpose of which is to perform morphological analysis of Japanese, providing information on the segmentation and pronunciation of Japanese text.
I developed Furigana Maker, a browser extension that adds ruby character annotations to Japanese text on any page, like the example below. And the core logic of this extension is morphological analysis of Japanese text, so I was in great need of such a library to do this task for me.
私の言語の境界は、私の世界の境界を意味する。
Considering the npm landscape, kuromoji.js remains the primary solution for Japanese morphological analysis in JavaScript. Most packages related to "Japanese morphological" indirectly rely on kuromoji.js, leaving minimal alternatives.
Firstly kuromoji.js disrespects the kuromoji API in its porting, changing a large number of field names, and worst of all it goes so far as to change the word_position field, which starts at 0, to start at 1. This certainly greatly diminishes the happiness of programmers.
Secondly kuromoji.js doesn't support promise, only callback function, which can make the code structure messy, this can be solved by manually writing code to encapsulate it as a promise, a solution will be provided at the end of the article.
By default, integrating kuromoji.js into the browser involves referencing a CDN or directly including build/kuromoji.js in the project. However, this method negates many advantages of build tools, disrupts project structures, and crucially restricts ESM usage, because build/kuromoji.js is not an ES module.
Using a build tool to package a project dependent on kuromoji.js and running it in the browser leads to a cascade of errors:
kuromoji.js uses zlib.js, which does not run in the browser.
kuromoji.js uses path , which is part of the Node.js core module.
Also kuromoji.js consumes a steady 130MB (not extensively tested) of memory once it is active, which is a huge overhead, whereas browser extensions can very easily take advantage of Service Worker by starting it only when it is needed, and killing the process when it is not needed, rather than just letting it reside in memory.
But Service Worker only supports the Fetch API, and kuromoji.js uses XMLHttpRequest, which will bring another error in Service Worker.
Don't try to solve these problems with polyfill, I've wasted a lot of time with that, modifying the kuromoji.js source code is necessary to solve the issues.
And with the last commit of the kuromoji.js project in 2018 and the author Takuya Asano's last activity on github in 2022, it's to be expected that we won't be able to get any help from him, including merge Pull Request.
The only solution was to fork this repo and then commit, publish, and luckily when I was about to start solving it myself, I was pleasantly surprised at NPM to find someone who had done everything I needed not too long ago, namely @sglkc/kuromoji, a fork of kuromoji.js.
Transitioning from XMLHttpRequest to the Fetch API.
This solves all the key issues, and now we can easily package it up with the build tool and run it in the browser and Service Worker without any errors, and @sglkc/kuromoji doesn't have any changes to the kuromoji.js API.
For processing Japanese text, there is a very nice library WanaKana that handles [romoji, hiragana, katakana] interconversions, as well as determining which of [kanji, romoji, hiragana, katakana] a Unicode character is.
Note that this is not as simple as you might think, and I recommend using WanaKana directly to bypass the complexity behind this, and only use the regex if the results don't meet your needs.
I accomplished something similar by extracting the kanji pronunciations from the Japanese text in the following form.
typescript
// It's not just kanji, such as "市ヶ谷" (イチガヤ), "我々" (ワレワレ).exporttypeKanjiToken= {original:stringreading:stringstart:number// Indexes start from 0end:number}
// It's not just kanji, such as "市ヶ谷" (イチガヤ), "我々" (ワレワレ).exporttypeKanjiToken= {original:stringreading:stringstart:number// Indexes start from 0end:number}
Getting started with browser extension development can be quite challenging, often leading inexperienced developers to spend hours or even days troubleshooting issues that are unrelated to the application logic.
This article aims to address the common pain points encountered in conventional browser development and explore how Plasmo alleviates these issues, ultimately enhancing the developer experience.
The structure of browser extensions in the Chrome Extension Documentation appears deceptively simple, resembling the most basic web development. However, this structure, as described in the documentation, is primarily a release structure, often representing the final stage of the development process.
Similar to how most developers prefer using tools like React, TypeScript, or TailwindCSS, a good library or framework significantly accelerates development. Few opt for hand-writing CSS, JavaScript, or HTML due to the low development efficiency and maintainability it implies.
According to a simple data analysis of the top 50 browser extensions on Github sorted by star count, the majority employ webpack or manually scripted builds, with nearly one-third utilizing TypeScript. This data serves as a testament to the issue at hand.
After reviewing the various building methods used by the top 50 browser extensions on GitHub, only one employed Plasmo. However, after experimenting with numerous methods, I discovered that Plasmo was the only tool that truly proved to be effective, significantly reducing the burdens on developers.
Tools like Webpack or Vite aren’t inherently tailored for browser extension development. Existing ecosystem plugins for browser extension development rely on intricate configurations, causing frustration, particularly when these plugins frequently don’t align well with certain common tech stacks.
For instance, when I aimed to develop a browser plugin to inject the translate="no" attribute into pre elements on a page to prevent erroneous translations by translators, it should have been a task requiring less than 400 lines of code, excluding various configuration files. However, before I used Plasmo, it took me a week to figure out how to integrate Vue, TypeScript, TailwindCSS, and more into browser extension development.
So, when I opened the Plasmo README.md, I was immediately captivated. It's a tool built specifically for browser extension development, offering key features like:
First-class support for React and Typescript
Declarative Development
Live-reloading and React HMR
Optional support for Svelte and Vue
Plasmo provides everything I need in browser development. It’s nearly zero-config and doesn’t even require a manifest.json.
Simply install dependencies, include tailwind.config.ts, tsconfig.json, and more. Write TS files directly in the contents directory or Vue files in the popup directory (of course, React is also an option). Then, start the development server with pnpm dev, open Developer mode in the browser, click on Load unpacked, load the build/chrome-mv3-dev directory, and enjoy it.
All of these elements should be fundamental in a modern JavaScript project. However, browser development before using Plasmo was an exasperating experience. The work done by @PlasmoHQ is commendable, as they've made browser development feel like a breeze instead of a struggle!
If you're eager to dive straight into developing the application logic for your browser extension, don't hesitate—immediately check out the Plasmo documentation!
Given the wealth of plugins and themes in the Zsh ecosystem, Oh-My-Zsh serves as an out-of-the-box tool for managing plugins and themes, simplifying Zsh configuration.
Here's the list of readily available themes and plugins on GitHub:
However, these lists lack succinct descriptions. Many plugins are mainly used by developers and may not be of significant use. One must navigate through the links, wasting time. Hence, this list is more suitable for users interested in extensive exploration, particularly those seeking alias plugins. For regular users, the recommended plugins and themes suffice.
Moreover, numerous Zsh plugins and themes are not integrated into Oh-My-Zsh, such as Powerlevel10k, zsh-autosuggestions, requiring downloads from the respective GitHub repositories to be used in Zsh.
The only recommended theme is Powerlevel10k. No other Zsh theme is suggested due to Powerlevel10k's succinct and elegant design.
P10K is presently the most commonly used theme for Zsh and is not included in Oh-My-Zsh default configuration. This underlines Powerlevel10k's excellence and popularity.
Powerlevel10k is a Zsh theme that emphasizes speed, flexibility, and out-of-the-box experience.
The Powerlevel10k theme offers multiple customizable options. Upon its initial installation or using the p10k configure command, prompts appear for configuring the display, such as whether to show Unicode characters or gaps between multiple commands.
Linux users must be aware of the differences between Zsh and Bash to avoid pitfalls:
Zsh is compatible with most Bash syntax but lacks compatibility with some Bash file wildcards, specifically the use of *.
Zsh offers additional syntax extensions absent in Bash. Given the current prevalence of Bash in default Linux installations, it is advisable not to use Zsh extended syntax. Shell scripts should also utilize #!/bin/bash to ensure compatibility.
This format is undoubtedly unsightly and requires a configuration directory change. The solution for this can be found on StackOverflow.
The code below efficiently accomplishes the aforementioned three tasks. Linux users employing the apt package manager can use this script directly, while users of other package managers may need to modify the code accordingly.
Regarding the third action, files in the /etc/skel/ directory are automatically copied to the corresponding home directory during the creation of a new Linux user, sparing the hassle of reconfiguring Zsh for each user.
The code below efficiently accomplishes the aforementioned three tasks. Linux users employing the apt package manager can use this script directly, while users of other package managers may need to modify the code accordingly.
bash
#!/bin/bashsudoaptinstallzsh-y# Install oh-my-zsh.0>/dev/null sh -c "$(wget-O- https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"ZSH_CUSTOM="$HOME/.oh-my-zsh/custom"exportZSH_CUSTOM# Configure plugins.gitclonehttps://github.com/zsh-users/zsh-syntax-highlighting.git"${ZSH_CUSTOM}"/plugins/zsh-syntax-highlightinggitclonehttps://github.com/zsh-users/zsh-autosuggestions.git"${ZSH_CUSTOM}"/plugins/zsh-autosuggestionsgitclonehttps://github.com/zsh-users/zsh-history-substring-search"${ZSH_CUSTOM}"/plugins/zsh-history-substring-searchsed-i's/^plugins=.*/plugins=(git\n extract\n sudo\n autojump\n jsontools\n colored-man-pages\n zsh-autosuggestions\n zsh-syntax-highlighting\n zsh-history-substring-search\n)/g'~/.zshrc# Install powerlevel10k and configure it.gitclone--depth=1https://github.com/romkatv/powerlevel10k.git"${ZSH_CUSTOM}"/themes/powerlevel10ksed-i's/^ZSH_THEME=.*/ZSH_THEME="powerlevel10k\/powerlevel10k"/g'~/.zshrc# Move ".zcompdump-*" file to "$ZSH/cache" directory.sed-i-e'/source \$ZSH\/oh-my-zsh.sh/i export ZSH_COMPDUMP=\$ZSH\/cache\/.zcompdump-\$HOST'~/.zshrc# Configure the default ZSH configuration for new users.sudocp~/.zshrc/etc/skel/sudocp~/.p10k.zsh/etc/skel/sudocp-r~/.oh-my-zsh/etc/skel/sudochmod-R755/etc/skel/sudochown-Rroot:root/etc/skel/
#!/bin/bashsudoaptinstallzsh-y# Install oh-my-zsh.0>/dev/null sh -c "$(wget-O- https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"ZSH_CUSTOM="$HOME/.oh-my-zsh/custom"exportZSH_CUSTOM# Configure plugins.gitclonehttps://github.com/zsh-users/zsh-syntax-highlighting.git"${ZSH_CUSTOM}"/plugins/zsh-syntax-highlightinggitclonehttps://github.com/zsh-users/zsh-autosuggestions.git"${ZSH_CUSTOM}"/plugins/zsh-autosuggestionsgitclonehttps://github.com/zsh-users/zsh-history-substring-search"${ZSH_CUSTOM}"/plugins/zsh-history-substring-searchsed-i's/^plugins=.*/plugins=(git\n extract\n sudo\n autojump\n jsontools\n colored-man-pages\n zsh-autosuggestions\n zsh-syntax-highlighting\n zsh-history-substring-search\n)/g'~/.zshrc# Install powerlevel10k and configure it.gitclone--depth=1https://github.com/romkatv/powerlevel10k.git"${ZSH_CUSTOM}"/themes/powerlevel10ksed-i's/^ZSH_THEME=.*/ZSH_THEME="powerlevel10k\/powerlevel10k"/g'~/.zshrc# Move ".zcompdump-*" file to "$ZSH/cache" directory.sed-i-e'/source \$ZSH\/oh-my-zsh.sh/i export ZSH_COMPDUMP=\$ZSH\/cache\/.zcompdump-\$HOST'~/.zshrc# Configure the default ZSH configuration for new users.sudocp~/.zshrc/etc/skel/sudocp~/.p10k.zsh/etc/skel/sudocp-r~/.oh-my-zsh/etc/skel/sudochmod-R755/etc/skel/sudochown-Rroot:root/etc/skel/
Getting started with browser extension development can be quite challenging, often leading inexperienced developers to spend hours or even days troubleshooting issues that are unrelated to the application logic.
This article aims to address the common pain points encountered in conventional browser development and explore how Plasmo alleviates these issues, ultimately enhancing the developer experience.
The structure of browser extensions in the Chrome Extension Documentation appears deceptively simple, resembling the most basic web development. However, this structure, as described in the documentation, is primarily a release structure, often representing the final stage of the development process.
Similar to how most developers prefer using tools like React, TypeScript, or TailwindCSS, a good library or framework significantly accelerates development. Few opt for hand-writing CSS, JavaScript, or HTML due to the low development efficiency and maintainability it implies.
According to a simple data analysis of the top 50 browser extensions on Github sorted by star count, the majority employ webpack or manually scripted builds, with nearly one-third utilizing TypeScript. This data serves as a testament to the issue at hand.
After reviewing the various building methods used by the top 50 browser extensions on GitHub, only one employed Plasmo. However, after experimenting with numerous methods, I discovered that Plasmo was the only tool that truly proved to be effective, significantly reducing the burdens on developers.
Tools like Webpack or Vite aren’t inherently tailored for browser extension development. Existing ecosystem plugins for browser extension development rely on intricate configurations, causing frustration, particularly when these plugins frequently don’t align well with certain common tech stacks.
For instance, when I aimed to develop a browser plugin to inject the translate="no" attribute into pre elements on a page to prevent erroneous translations by translators, it should have been a task requiring less than 400 lines of code, excluding various configuration files. However, before I used Plasmo, it took me a week to figure out how to integrate Vue, TypeScript, TailwindCSS, and more into browser extension development.
So, when I opened the Plasmo README.md, I was immediately captivated. It's a tool built specifically for browser extension development, offering key features like:
First-class support for React and Typescript
Declarative Development
Live-reloading and React HMR
Optional support for Svelte and Vue
Plasmo provides everything I need in browser development. It’s nearly zero-config and doesn’t even require a manifest.json.
Simply install dependencies, include tailwind.config.ts, tsconfig.json, and more. Write TS files directly in the contents directory or Vue files in the popup directory (of course, React is also an option). Then, start the development server with pnpm dev, open Developer mode in the browser, click on Load unpacked, load the build/chrome-mv3-dev directory, and enjoy it.
All of these elements should be fundamental in a modern JavaScript project. However, browser development before using Plasmo was an exasperating experience. The work done by @PlasmoHQ is commendable, as they've made browser development feel like a breeze instead of a struggle!
If you're eager to dive straight into developing the application logic for your browser extension, don't hesitate—immediately check out the Plasmo documentation!
Given the wealth of plugins and themes in the Zsh ecosystem, Oh-My-Zsh serves as an out-of-the-box tool for managing plugins and themes, simplifying Zsh configuration.
Here's the list of readily available themes and plugins on GitHub:
However, these lists lack succinct descriptions. Many plugins are mainly used by developers and may not be of significant use. One must navigate through the links, wasting time. Hence, this list is more suitable for users interested in extensive exploration, particularly those seeking alias plugins. For regular users, the recommended plugins and themes suffice.
Moreover, numerous Zsh plugins and themes are not integrated into Oh-My-Zsh, such as Powerlevel10k, zsh-autosuggestions, requiring downloads from the respective GitHub repositories to be used in Zsh.
The only recommended theme is Powerlevel10k. No other Zsh theme is suggested due to Powerlevel10k's succinct and elegant design.
P10K is presently the most commonly used theme for Zsh and is not included in Oh-My-Zsh default configuration. This underlines Powerlevel10k's excellence and popularity.
Powerlevel10k is a Zsh theme that emphasizes speed, flexibility, and out-of-the-box experience.
The Powerlevel10k theme offers multiple customizable options. Upon its initial installation or using the p10k configure command, prompts appear for configuring the display, such as whether to show Unicode characters or gaps between multiple commands.
Linux users must be aware of the differences between Zsh and Bash to avoid pitfalls:
Zsh is compatible with most Bash syntax but lacks compatibility with some Bash file wildcards, specifically the use of *.
Zsh offers additional syntax extensions absent in Bash. Given the current prevalence of Bash in default Linux installations, it is advisable not to use Zsh extended syntax. Shell scripts should also utilize #!/bin/bash to ensure compatibility.
This format is undoubtedly unsightly and requires a configuration directory change. The solution for this can be found on StackOverflow.
The code below efficiently accomplishes the aforementioned three tasks. Linux users employing the apt package manager can use this script directly, while users of other package managers may need to modify the code accordingly.
Regarding the third action, files in the /etc/skel/ directory are automatically copied to the corresponding home directory during the creation of a new Linux user, sparing the hassle of reconfiguring Zsh for each user.
The code below efficiently accomplishes the aforementioned three tasks. Linux users employing the apt package manager can use this script directly, while users of other package managers may need to modify the code accordingly.
bash
#!/bin/bashsudoaptinstallzsh-y# Install oh-my-zsh.0>/dev/null sh -c "$(wget-O- https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"ZSH_CUSTOM="$HOME/.oh-my-zsh/custom"exportZSH_CUSTOM# Configure plugins.gitclonehttps://github.com/zsh-users/zsh-syntax-highlighting.git"${ZSH_CUSTOM}"/plugins/zsh-syntax-highlightinggitclonehttps://github.com/zsh-users/zsh-autosuggestions.git"${ZSH_CUSTOM}"/plugins/zsh-autosuggestionsgitclonehttps://github.com/zsh-users/zsh-history-substring-search"${ZSH_CUSTOM}"/plugins/zsh-history-substring-searchsed-i's/^plugins=.*/plugins=(git\n extract\n sudo\n autojump\n jsontools\n colored-man-pages\n zsh-autosuggestions\n zsh-syntax-highlighting\n zsh-history-substring-search\n)/g'~/.zshrc# Install powerlevel10k and configure it.gitclone--depth=1https://github.com/romkatv/powerlevel10k.git"${ZSH_CUSTOM}"/themes/powerlevel10ksed-i's/^ZSH_THEME=.*/ZSH_THEME="powerlevel10k\/powerlevel10k"/g'~/.zshrc# Move ".zcompdump-*" file to "$ZSH/cache" directory.sed-i-e'/source \$ZSH\/oh-my-zsh.sh/i export ZSH_COMPDUMP=\$ZSH\/cache\/.zcompdump-\$HOST'~/.zshrc# Configure the default ZSH configuration for new users.sudocp~/.zshrc/etc/skel/sudocp~/.p10k.zsh/etc/skel/sudocp-r~/.oh-my-zsh/etc/skel/sudochmod-R755/etc/skel/sudochown-Rroot:root/etc/skel/
#!/bin/bashsudoaptinstallzsh-y# Install oh-my-zsh.0>/dev/null sh -c "$(wget-O- https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"ZSH_CUSTOM="$HOME/.oh-my-zsh/custom"exportZSH_CUSTOM# Configure plugins.gitclonehttps://github.com/zsh-users/zsh-syntax-highlighting.git"${ZSH_CUSTOM}"/plugins/zsh-syntax-highlightinggitclonehttps://github.com/zsh-users/zsh-autosuggestions.git"${ZSH_CUSTOM}"/plugins/zsh-autosuggestionsgitclonehttps://github.com/zsh-users/zsh-history-substring-search"${ZSH_CUSTOM}"/plugins/zsh-history-substring-searchsed-i's/^plugins=.*/plugins=(git\n extract\n sudo\n autojump\n jsontools\n colored-man-pages\n zsh-autosuggestions\n zsh-syntax-highlighting\n zsh-history-substring-search\n)/g'~/.zshrc# Install powerlevel10k and configure it.gitclone--depth=1https://github.com/romkatv/powerlevel10k.git"${ZSH_CUSTOM}"/themes/powerlevel10ksed-i's/^ZSH_THEME=.*/ZSH_THEME="powerlevel10k\/powerlevel10k"/g'~/.zshrc# Move ".zcompdump-*" file to "$ZSH/cache" directory.sed-i-e'/source \$ZSH\/oh-my-zsh.sh/i export ZSH_COMPDUMP=\$ZSH\/cache\/.zcompdump-\$HOST'~/.zshrc# Configure the default ZSH configuration for new users.sudocp~/.zshrc/etc/skel/sudocp~/.p10k.zsh/etc/skel/sudocp-r~/.oh-my-zsh/etc/skel/sudochmod-R755/etc/skel/sudochown-Rroot:root/etc/skel/
kuromoji.js is a Node.js version of kuromoji, the main purpose of which is to perform morphological analysis of Japanese, providing information on the segmentation and pronunciation of Japanese text.
I developed Furigana Maker, a browser extension that adds ruby character annotations to Japanese text on any page, like the example below. And the core logic of this extension is morphological analysis of Japanese text, so I was in great need of such a library to do this job for me.
私の言語の境界は、私の世界の境界を意味する。
Considering the npm landscape, kuromoji.js remains the primary solution for Japanese morphological analysis in JavaScript. Most packages related to "Japanese morphological" indirectly rely on kuromoji.js, leaving minimal alternatives.
Firstly kuromoji.js disrespects the kuromoji API in its porting, changing a large number of field names, and worst of all it goes so far as to change the word_position field, which starts at 0, to start at 1. This certainly greatly diminishes the happiness of programmers.
Secondly kuromoji.js doesn't support promise, only callback function, which can make the code structure messy, this can be solved by manually writing code to encapsulate it as a promise, a solution will be provided at the end of the article.
By default, integrating kuromoji.js into the browser involves referencing a CDN or directly including build/kuromoji.js in the project. However, this method negates many advantages of build tools, disrupts project structures, and crucially restricts ESM usage, because build/kuromoji.js is not an ES module.
Using a build tool to package a project dependent on kuromoji.js and running it in the browser leads to a cascade of errors:
kuromoji.js uses zlib.js, which does not run in the browser.
kuromoji.js uses path , which is part of the Node.js core module.
Also kuromoji.js consumes a steady 130MB (not extensively tested) of memory once it is active, which is a huge overhead, whereas browser extensions can very easily take advantage of Service Worker by starting it only when it is needed, and killing the process when it is not needed, rather than just letting it reside in memory.
But Service Worker only supports the Fetch API, and kuromoji.js uses XMLHttpRequest, which will bring another error in Service Worker.
Don't try to solve these problems with polyfill, I've wasted a lot of time with that, modifying the kuromoji.js source code is necessary to solve the issues.
And with the last commit of the kuromoji.js project in 2018 and the author Takuya Asano's last activity on github in 2022, it's to be expected that we won't be able to get any help from him, including merge Pull Request.
The only solution was to fork this repo and then commit, publish, and luckily when I was about to start solving it myself, I was pleasantly surprised at NPM to find someone who had done everything I needed not too long ago, namely @sglkc/kuromoji, a fork of kuromoji.js.
Transitioning from XMLHttpRequest to the Fetch API.
This solves all the key issues, and now we can easily package it up with the build tool and run it in the browser and Service Worker without any errors, and @sglkc/kuromoji doesn't have any changes to the kuromoji.js API.
For processing Japanese text, there is a very nice library WanaKana that handles [romoji, hiragana, katakana] interconversions, as well as determining which of [kanji, romoji, hiragana, katakana] a Unicode character is.
Note that this is not as simple as you might think, and I recommend using WanaKana directly to bypass the complexity behind this, and only use the regex if the results don't meet your needs.
I accomplished something similar by extracting the kanji pronunciations from the Japanese text in the following form.
typescript
// It's not just kanji, such as "市ヶ谷" (イチガヤ), "我々" (ワレワレ).exporttypeKanjiToken= {original:stringreading:stringstart:number// Indexes start from 0end:number}
// It's not just kanji, such as "市ヶ谷" (イチガヤ), "我々" (ワレワレ).exporttypeKanjiToken= {original:stringreading:stringstart:number// Indexes start from 0end:number}
Nginx Proxy Manager是由jc21开发的一款使用Web管理Nginx反向代理的工具,其开发理念是"It had to be so easy that a monkey could do it",相比较传统的Nginx反向代理配置,真的简单太多,普通的反向代理我们只要动动鼠标就ok了,SSL证书的申请也很简单,还会自动为证书请续期,比用Certbot脚本申请还简单!