├── .gitattributes
├── .gitignore
├── example
├── index.js
├── examples
│ ├── preact.js
│ ├── golang.go
│ ├── vue.js
│ ├── python.py
│ └── next.js
└── App.vue
├── test
└── index.test.js
├── .editorconfig
├── circle.yml
├── LICENSE
├── src
└── index.js
├── package.json
└── README.md
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .DS_Store
3 | *.log
4 |
5 | /dist
6 | /dist-example
7 |
--------------------------------------------------------------------------------
/example/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './App.vue'
3 |
4 | new Vue({
5 | el: '#app',
6 | render: h => h(App)
7 | })
8 |
--------------------------------------------------------------------------------
/test/index.test.js:
--------------------------------------------------------------------------------
1 | import hanabi from '../src'
2 |
3 | test('main', () => {
4 | const out = hanabi(`co`)
5 | expect(out).toBe('co')
6 | })
7 |
--------------------------------------------------------------------------------
/example/examples/preact.js:
--------------------------------------------------------------------------------
1 | import { h, render } from 'preact';
2 |
3 | render((
4 |
5 | Hello, world!
6 |
7 |
8 | ), document.body);
9 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = space
5 | indent_size = 2
6 | end_of_line = lf
7 | charset = utf-8
8 | trim_trailing_whitespace = true
9 | insert_final_newline = true
10 |
11 | [*.md]
12 | trim_trailing_whitespace = false
--------------------------------------------------------------------------------
/circle.yml:
--------------------------------------------------------------------------------
1 | machine:
2 | node:
3 | version: 7
4 | environment:
5 | PATH: "${PATH}:${HOME}/${CIRCLE_PROJECT_REPONAME}/node_modules/.bin"
6 |
7 | dependencies:
8 | override:
9 | - yarn
10 | cache_directories:
11 | - ~/.cache/yarn
12 |
13 | test:
14 | override:
15 | - yarn test
16 |
--------------------------------------------------------------------------------
/example/examples/golang.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | // fib returns a function that returns
6 | // successive Fibonacci numbers.
7 | func fib() func() int {
8 | a, b := 0, 1
9 | return func() int {
10 | a, b = b, a+b
11 | return a
12 | }
13 | }
14 |
15 | func main() {
16 | f := fib()
17 | // Function calls are evaluated left-to-right.
18 | fmt.Println(f(), f(), f(), f(), f())
19 | }
20 |
--------------------------------------------------------------------------------
/example/examples/vue.js:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
25 |
26 |
32 |
--------------------------------------------------------------------------------
/example/examples/python.py:
--------------------------------------------------------------------------------
1 | from bottle import route, install, template
2 | from bottle_sqlite import SQLitePlugin
3 |
4 | install(SQLitePlugin(dbfile='/tmp/test.db'))
5 |
6 | @route('/show/')
7 | def show(db, post_id):
8 | c = db.execute('SELECT title, content FROM posts WHERE id = ?', (post_id,))
9 | row = c.fetchone()
10 | return template('show_post', title=row['title'], text=row['content'])
11 |
12 | @route('/contact')
13 | def contact_page():
14 | ''' This callback does not need a db connection. Because the 'db'
15 | keyword argument is missing, the sqlite plugin ignores this callback
16 | completely. '''
17 | return template('contact')
18 |
--------------------------------------------------------------------------------
/example/examples/next.js:
--------------------------------------------------------------------------------
1 | const { createServer } = require('http')
2 | const { parse } = require('url')
3 | const next = require('next')
4 |
5 | const dev = process.env.NODE_ENV !== 'production'
6 | const app = next({ dev })
7 | const handle = app.getRequestHandler()
8 |
9 | app.prepare().then(() => {
10 | createServer((req, res) => {
11 | const parsedUrl = parse(req.url, true)
12 | const { pathname, query } = parsedUrl
13 |
14 | if (pathname === '/a') {
15 | app.render(req, res, '/b', query)
16 | } else if (pathname === '/b') {
17 | app.render(req, res, '/a', query)
18 | } else {
19 | handle(req, res, parsedUrl)
20 | }
21 | })
22 | .listen(3000, (err) => {
23 | if (err) throw err
24 | console.log('> Ready on http://localhost:3000')
25 | })
26 | })
27 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) egoist <0x142857@gmail.com> (https://egoistian.com)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import jsCommentRe from 'comment-regex'
2 |
3 | const defaultColors = ['23AC69', '91C132', 'F19726', 'E8552D', '1AAB8E', 'E1147F', '2980C1', '1BA1E6', '9FA0A0', 'F19726', 'E30B20', 'E30B20', 'A3338B']
4 |
5 | export default function (input, {
6 | colors = defaultColors
7 | } = {}) {
8 | let index = 0
9 | const cache = {}
10 | const wordRe = /[\u4E00-\u9FFF\u3400-\u4dbf\uf900-\ufaff\u3040-\u309f\uac00-\ud7af\u0400-\u04FF]+|\w+/
11 | const leftAngleRe = /
12 |
13 | const re = new RegExp(`(${wordRe.source}|${leftAngleRe.source})|(${jsCommentRe().source})`, 'gmi')
14 | return input
15 | .replace(re, (m, word, cm) => {
16 | if (cm) {
17 | return toComment(cm)
18 | }
19 |
20 | if (word === '<') {
21 | return '<'
22 | }
23 | let color
24 | if (cache[word]) {
25 | color = cache[word]
26 | } else {
27 | color = colors[index]
28 | cache[word] = color
29 | }
30 |
31 | const out = `${word}`
32 | index = ++index % colors.length
33 | return out
34 | })
35 | }
36 |
37 | function toComment(cm) {
38 | return `${cm}`
39 | }
40 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "hanabi",
3 | "productionName": "Hanabi: Highlight any code, in a colorful way",
4 | "version": "0.4.0",
5 | "description": "Highlight any code, in a colorful way.",
6 | "repository": {
7 | "url": "egoist/hanabi",
8 | "type": "git"
9 | },
10 | "main": "dist/hanabi.js",
11 | "files": [
12 | "dist"
13 | ],
14 | "scripts": {
15 | "test": "jest && npm run lint && npm run build",
16 | "lint": "xo",
17 | "build": "bili --format umd --module-name hanabi --compress",
18 | "example": "vbuild example/index.js -d",
19 | "build:example": "vbuild example/index.js --dist dist-example",
20 | "deploy": "npm run build:example && gh-pages -d dist-example"
21 | },
22 | "author": "egoist <0x142857@gmail.com>",
23 | "license": "MIT",
24 | "jest": {
25 | "testEnvironment": "node"
26 | },
27 | "babel": {
28 | "babelrc": false,
29 | "env": {
30 | "test": {
31 | "presets": [
32 | "es2015"
33 | ]
34 | }
35 | }
36 | },
37 | "devDependencies": {
38 | "babel-preset-es2015": "^6.24.0",
39 | "bili": "^0.14.0",
40 | "gh-pages": "^0.12.0",
41 | "jest-cli": "^19.0.2",
42 | "raw-loader": "^0.5.1",
43 | "vbuild": "^6.24.3",
44 | "xo": "^0.17.1"
45 | },
46 | "xo": {
47 | "space": 2,
48 | "semicolon": false,
49 | "envs": [
50 | "jest"
51 | ],
52 | "ignores": [
53 | "example/**"
54 | ]
55 | },
56 | "dependencies": {
57 | "comment-regex": "^1.0.0"
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # hanabi
2 |
3 | [](https://npmjs.com/package/hanabi) [](https://npmjs.com/package/hanabi) [](https://circleci.com/gh/egoist/hanabi) [](https://github.com/egoist/donate)
4 |
5 | How does it look like? Hmmm:
6 |
7 |
8 |
9 | ## Install
10 |
11 | ```bash
12 | yarn add hanabi
13 | ```
14 |
15 | CDN: https://unpkg.com/hanabi/dist/
16 |
17 | ## Usage
18 |
19 | ```js
20 | const hanabi = require("hanabi");
21 |
22 | hanabi(code);
23 | ```
24 |
25 | Demo: https://hanabi.egoist.dev/
26 |
27 | ## Contributing
28 |
29 | 1. Fork it!
30 | 2. Create your feature branch: `git checkout -b my-new-feature`
31 | 3. Commit your changes: `git commit -am 'Add some feature'`
32 | 4. Push to the branch: `git push origin my-new-feature`
33 | 5. Submit a pull request :D
34 |
35 | ## Author
36 |
37 | **hanabi** © [egoist](https://github.com/egoist), Released under the [MIT](./LICENSE) License.
38 | Authored and maintained by egoist with help from contributors ([list](https://github.com/egoist/hanabi/contributors)).
39 |
40 | > [egoist.dev](https://egoist.dev) · GitHub [@egoist](https://github.com/egoist) · Twitter [@\localhost_5173](https://twitter.com/localhost_5173)
41 |
--------------------------------------------------------------------------------
/example/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 |
12 |
13 |
14 |
15 |
59 |
60 |
66 |
--------------------------------------------------------------------------------