Compare commits

..

170 Commits

Author SHA1 Message Date
Ming Di Leom 8849b2bec0
Merge pull request #167 from curbengh/dependabot/github_actions/actions/checkout-5
chore(deps): bump actions/checkout from 4 to 5
2025-08-17 08:40:19 +00:00
dependabot[bot] 499b6db3b4
chore(deps): bump actions/checkout from 4 to 5
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-11 20:04:42 +00:00
MDLeom 1c70f12716
test(jest): disable globalsCleanup 2025-08-04 12:42:09 +00:00
MDLeom a9ca2092a4
style: node:* prefix for native module 2025-08-04 12:21:05 +00:00
Ming Di Leom 463b3a16a9
Merge pull request #164 from curbengh/dependabot/github_actions/codecov/codecov-action-5
chore(deps): bump codecov/codecov-action from 4 to 5
2025-07-20 08:28:13 +00:00
dependabot[bot] 45a4e8d154
chore(deps): bump codecov/codecov-action from 4 to 5
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4 to 5.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v4...v5)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-18 11:56:51 +00:00
Ming Di Leom 45f2e51521
Merge pull request #165 from curbengh/jest-circus
test: workaround for jest-circus module not found
2025-07-18 11:55:35 +00:00
MDLeom 792762cca3
test: workaround for jest-circus module not found
https://github.com/jestjs/jest/issues/15724

also install zstd with --force to ensure the postinstall script
that builds the binary actually runs on linux
2025-07-18 11:52:38 +00:00
Ming Di Leom f5b5c11cbf
Merge pull request #163 from curbengh/zstd-ci
fix zstd unit test
2025-07-17 12:40:39 +00:00
MDLeom d32e929e88
ci: switch to npm for tester workflow
difficulty installing zstd using bun
2025-07-17 12:34:59 +00:00
MDLeom 4460f10933
ci: switch to bun 2025-07-17 12:21:25 +00:00
MDLeom 7f9a1de057
fix(jest): install jest-circus
required in ubuntu+node20
2025-07-17 12:20:49 +00:00
MDLeom 77ea350028
test: install optional deps 2025-07-15 12:01:45 +00:00
MDLeom be6a367355
style: quote 2025-07-15 11:55:37 +00:00
MDLeom dd3039eca2
test: zstd binary is now bundled 2025-07-15 11:53:12 +00:00
MDLeom 66a6050ecb
test(coverage): Node 22
active LTS
2025-07-13 07:01:10 +00:00
MDLeom 368619aecf
chore(deps): bump jest from 29 to 30 2025-07-13 06:57:41 +00:00
MDLeom 9d39180268
chore(deps): bump svgo from 3 to 4 2025-07-13 06:47:31 +00:00
MDLeom 0a88aadea3
chore(deps): bump zstd from 1 to 2 2025-07-13 06:35:13 +00:00
MDLeom 3264135f54
test: node 24
drop 18, EOL on 2025-04-30
2025-07-13 06:26:33 +00:00
MDLeom 1bd42aec37
chore(node): drop Node 18
BREAKING CHANGE
Node 18 EOL 2025-04-30
2025-07-13 06:24:59 +00:00
MDLeom 4bd000bfee
release: 9.0.0 2024-06-22 02:28:47 +00:00
MDLeom 5fb3349dec
chore(npm): add "zstd" keyword
remove generic keywords
2024-06-22 02:26:43 +00:00
MDLeom 80b2325cbf
chore(npm): "repository" is now an object 2024-06-22 02:25:33 +00:00
MDLeom 812ff614fc
ci: use windows bash
variable is not expanded properly in pwsh
2024-06-11 12:37:53 +00:00
MDLeom 702eb2fa0c
ci: ${} not supported in pwsh 2024-06-11 12:22:08 +00:00
MDLeom a2c810cfb5
ci: install zstd binary 2024-06-11 12:06:41 +00:00
MDLeom 30c33c0ad3
docs: install zstd dependency explicitly
using --force --include=optional flags are excessive
This reverts commit e33fd0ed5d &
1b04f7c8f1.
2024-06-11 11:30:02 +00:00
MDLeom 1c9d91b524
docs(license): update year 2024-06-10 06:19:21 +00:00
MDLeom c18f4c8476
docs: differentiate minify and compress
update snyk badge
2024-06-10 06:18:06 +00:00
MDLeom e33fd0ed5d
build(npm): --force flag to install optional deps
of child deps
required by https://github.com/curbengh/hexo-yam#cannot-find-module-mongodb-jszstd-linux-x64-gnu
2024-06-08 08:11:38 +00:00
MDLeom 73db847fd4
docs: reorder sections
removed outdated http-compression section
2024-06-08 08:11:28 +00:00
Ming Di Leom 7639547408
Merge pull request #157 from curbengh/previewServer
feat: previewServer option
2024-06-07 20:06:54 +09:30
Ming Di Leom f7df26377a
Merge pull request #158 from curbengh/zstd
feat: zstd compression
2024-06-07 19:52:50 +09:30
MDLeom 1b04f7c8f1
docs(zstd): --force flag to install optional deps
of child deps
https://stackoverflow.com/a/42400102
2024-06-07 09:04:05 +00:00
MDLeom 18a5d8108b
test: include optional deps
to include zstd binary
2024-06-06 11:45:53 +00:00
MDLeom 7f2033e553
feat: zstd compression
disabled by default due to lack of server support
close #156
2024-06-06 11:14:57 +00:00
MDLeom e9584b2e0b
feat: previewServer option
BREAKING CHANGE
plugin is now disabled by default when running `hexo server`,
unless previewServer is set to false.

Close #154
Inspired by e778c55f37/index.js (L49)
2024-06-05 11:08:12 +00:00
Ming Di Leom e99e110d39
Merge pull request #155 from curbengh/dependabot/github_actions/codecov/codecov-action-4
chore(deps): bump codecov/codecov-action from 3 to 4
2024-06-05 18:46:36 +09:30
MDLeom a5f19dbe79
ci(codecov): add upload token
https://github.com/codecov/codecov-action/releases/tag/v4.0.0
2024-06-05 09:14:12 +00:00
MDLeom c3ed0c68c7
test: node 22
drop 21, EOL on 2024-06-01
2024-06-05 09:04:31 +00:00
MDLeom f92017f688
test: node 22
drop 21, EOL on 2024-06-01
2024-06-04 08:52:45 +00:00
dependabot[bot] 0abd90c78a
chore(deps): bump codecov/codecov-action from 3 to 4
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 3 to 4.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-01 15:46:21 +00:00
Ming Di Leom 426da85620
Merge pull request #150 from curbengh/dependabot/github_actions/actions/cache-4
chore(deps): bump actions/cache from 3 to 4
2024-01-28 21:14:53 +10:30
Ming Di Leom bfb886abac
Merge pull request #149 from curbengh/dependabot/github_actions/github/codeql-action-3
chore(deps): bump github/codeql-action from 2 to 3
2024-01-28 21:12:39 +10:30
Ming Di Leom d99caafe90
Merge pull request #145 from curbengh/dependabot/github_actions/actions/setup-node-4
chore(deps): bump actions/setup-node from 3 to 4
2024-01-28 21:10:18 +10:30
Ming Di Leom 3cc6f5e79e
Merge pull request #151 from curbengh/dependabot/npm_and_yarn/hexo-7.1.0
chore(deps-dev): bump hexo from 6.3.0 to 7.1.0
2024-01-28 21:06:37 +10:30
Ming Di Leom 56af48f632
Merge pull request #152 from curbengh/html-minifier-terser
refactor: switch html-minifier to html-minifier-terser
2024-01-28 21:04:53 +10:30
MDLeom 0bee9ada0e
refactor: switch html-minifier to html-minifier-terser
https://github.com/kangax/html-minifier/issues/1135
2024-01-28 10:26:21 +00:00
dependabot[bot] 1af8c52cdb
chore(deps-dev): bump hexo from 6.3.0 to 7.1.0
Bumps [hexo](https://github.com/hexojs/hexo) from 6.3.0 to 7.1.0.
- [Release notes](https://github.com/hexojs/hexo/releases)
- [Commits](https://github.com/hexojs/hexo/compare/6.3.0...v7.1.0)

---
updated-dependencies:
- dependency-name: hexo
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-19 15:40:47 +00:00
dependabot[bot] 81ceea413d
chore(deps): bump actions/cache from 3 to 4
Bumps [actions/cache](https://github.com/actions/cache) from 3 to 4.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-18 15:37:36 +00:00
dependabot[bot] 8e937ead21
chore(deps): bump github/codeql-action from 2 to 3
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2 to 3.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/v2...v3)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-13 15:52:54 +00:00
MDLeom 7809098034
ci: node 20
active lts
2023-12-12 08:33:33 +00:00
MDLeom dffeb0cfc7
test: node 21 2023-12-12 08:30:27 +00:00
dependabot[bot] bfcd93edb7
chore(deps): bump actions/setup-node from 3 to 4
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 3 to 4.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-24 15:47:02 +00:00
Ming Di Leom 2992e8d8e7
Merge pull request #142 from curbengh/dependabot/github_actions/actions/checkout-4
chore(deps): bump actions/checkout from 3 to 4
2023-10-01 15:20:29 +10:30
dependabot[bot] cf7e8f675c
chore(deps): bump actions/checkout from 3 to 4
Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-01 04:48:01 +00:00
MDLeom 3523b0fd98
chore(node): drop Node 16
BREAKING CHANGE
Node 16 EOL 2023-09-11
2023-10-01 04:46:39 +00:00
Ming Di Leom df3b0513e7
Merge pull request #143 from curbengh/bun
feat(ci): run linux jobs using Bun
2023-10-01 15:09:17 +10:30
MDLeom dbed65ffeb
feat(ci): run linux jobs using Bun 2023-10-01 04:05:08 +00:00
Ming Di Leom c964cfcf80
Merge pull request #140 from curbengh/node-20
chore(node): require node 16+
2023-10-01 14:06:48 +10:30
MDLeom 793bcd81c4
chore(node): require node 16+
- node 14 EOL 2023-04-30
- add node 20
2023-05-06 06:04:21 +00:00
MDLeom f65e7e7a22
docs: remove deprecated lgtm badge 2023-04-28 08:53:38 +00:00
MDLeom d9e6228960
docs: fix build badge
https://github.com/badges/shields/issues/8671
2023-03-06 09:33:04 +00:00
Ming Di Leom 6c6060f28c
Merge pull request #139 from curbengh/8.0
release: 8.0.0
2022-11-13 11:08:42 +10:30
MDLeom 79f4f24f8e
release: 8.0.0 2022-11-13 00:05:34 +00:00
Ming Di Leom b0575e6fdc
Merge pull request #135 from curbengh/dependabot/npm_and_yarn/svgo-3.0.0
chore(deps): bump svgo from 2.8.0 to 3.0.0
2022-11-06 15:55:40 +10:30
MDLeom a6f434ff8d
fix(svg): ignore empty input 2022-11-06 04:50:36 +00:00
MDLeom a6e2ea0879
fix(svg): svgo@3 now throws error
- cleanupIDs -> cleanupIds
- https://github.com/svg/svgo/releases/tag/v3.0.0
2022-11-06 02:58:07 +00:00
dependabot[bot] 9c8a228e09
chore(deps): bump svgo from 2.8.0 to 3.0.0
Bumps [svgo](https://github.com/svg/svgo) from 2.8.0 to 3.0.0.
- [Release notes](https://github.com/svg/svgo/releases)
- [Changelog](https://github.com/svg/svgo/blob/main/CHANGELOG-old.md)
- [Commits](https://github.com/svg/svgo/compare/v2.8.0...v3.0.0)

---
updated-dependencies:
- dependency-name: svgo
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-06 02:58:07 +00:00
Ming Di Leom 4b4d3cb342
Merge pull request #137 from curbengh/node-19
ci(tester): add node 19
2022-11-06 13:26:09 +10:30
MDLeom 8258359f6b
ci(tester): add node 19 2022-11-05 02:02:16 +00:00
Ming Di Leom c6c7d3743a
Merge pull request #134 from curbengh/deps
chore(ga-deps): use latest minor version
2022-10-09 19:53:39 +10:30
MDLeom 777ffabd2b
ci: run snyk & semgrep weekly 2022-10-09 08:00:56 +00:00
MDLeom 5453fc9ee0
chore(deps-dev): bump jest from 28.1.3 to 29.1.2 2022-10-09 07:59:47 +00:00
MDLeom c3b899556a
chore(ga-deps): use latest minor version 2022-10-09 07:58:57 +00:00
Ming Di Leom 866ba28c3c
Merge pull request #133 from curbengh/semgrep-init
ci: semgrep init
2022-10-09 18:09:46 +10:30
MDLeom b54324c154
ci: semgrep init 2022-10-09 07:32:00 +00:00
MDLeom 077055ed0b
release: 7.0.0 2022-05-17 00:59:09 +00:00
MDLeom d54ed360be
chore(node): use Node 16 on codeql 2022-05-17 00:40:28 +00:00
MDLeom 1ae4d77071
chore(dev-deps): bump setup-node from 3.1.1 to 3.2.0 2022-05-17 00:37:59 +00:00
MDLeom 0f73e6ed98
chore(dev-deps): bump codeql-action from 1 to 2 2022-05-17 00:36:57 +00:00
MDLeom 79f15acb79
ci(snyk): run snyk on codeql bump 2022-05-17 00:35:52 +00:00
MDLeom 2ae5520a60
ci(snyk): separate test & monitor 2022-05-13 01:27:05 +00:00
MDLeom ef46c3c6d9
ci(synk): run test & upload to codeql 2022-05-13 01:00:45 +00:00
MDLeom 4648fa32f1
chore(snyk): remove old policy 2022-05-13 00:50:47 +00:00
MDLeom 197836b82b
docs: cleanup previous config changes
- update brotli support status
2022-05-06 06:21:15 +00:00
Ming Di Leom d757c1b5c7
Merge pull request #110 from curbengh/update-deps
chore(node): drop Node 12 & 17, add 18
2022-05-05 14:24:05 +09:30
MDLeom 0623de5252
chore(node): drop Node 12 & 17, add 18
BREAKING CHANGE
2022-05-04 03:17:49 +00:00
MDLeom fbb2c71e87
chore(actions): bump codecov-action from 2.1.0 to 3.1.0 2022-05-04 02:38:28 +00:00
MDLeom b3d09fec7a
chore(actions): bump setup-node from 2.4.1 to 3.1.1 2022-05-04 02:36:40 +00:00
MDLeom 3edbe68008
chore(actions): bump cache from 2.1.6 to 3.0.2 2022-05-04 02:35:32 +00:00
MDLeom 1833ffa76e
chore(actions): bump checkout from 2.3.4 to 3.0.2 2022-05-04 02:35:02 +00:00
MDLeom 63eee78e01
chore(dev-deps): bump standard from 16 to 17 2022-05-04 02:29:34 +00:00
MDLeom 7e81770894
chore(dev-deps): bump jest from 27 to 28 2022-05-04 02:28:59 +00:00
MDLeom 288a4e3232
chore(dev-deps): bump hexo from 5.1.1 to 6.1.0 2022-05-04 02:28:14 +00:00
MDLeom d8e6969352
release: 6.0.0 2021-10-20 09:02:30 +00:00
Ming Di Leom a6018cb7f5
Merge pull request #84 from curbengh/node-17
chore(ci): Node 17
2021-10-20 19:31:01 +10:30
MDLeom 4a271929d5
chore(ci): Node 17 2021-10-20 08:56:46 +00:00
MDLeom 282a905305
chore(ci): drop Node 15
- EOL 2021-06-01
2021-10-16 09:54:49 +00:00
MDLeom 5f9c3d32d9 chore(deps): bump svgo from 2.3.0 to 2.4.0
- tested compatibility
2021-10-16 09:38:02 +00:00
Ming Di Leom 6d633f0593
Merge pull request #82 from curbengh/dependabot/npm_and_yarn/jest-27.2.5
chore(deps-dev): bump jest from 26.6.3 to 27.2.5
2021-10-16 20:06:54 +10:30
Ming Di Leom 0e66fc81cf
Merge pull request #78 from curbengh/dependabot/github_actions/actions/setup-node-2.4.1
chore(deps): bump actions/setup-node from 2.1.5 to 2.4.1
2021-10-16 20:04:45 +10:30
Ming Di Leom 7178b50186
Merge pull request #75 from curbengh/dependabot/github_actions/codecov/codecov-action-2.1.0
chore(deps): bump codecov/codecov-action from 1 to 2.1.0
2021-10-16 20:03:55 +10:30
Ming Di Leom cc53b9054b
Merge pull request #71 from curbengh/dependabot/npm_and_yarn/minify-xml-3.2.0
chore(deps): bump minify-xml from 2.5.0 to 3.2.0
2021-10-16 20:01:41 +10:30
dependabot[bot] 3ce4b69991
chore(deps): bump actions/setup-node from 2.1.5 to 2.4.1
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 2.1.5 to 2.4.1.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v2.1.5...v2.4.1)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-16 09:29:53 +00:00
Ming Di Leom 1f775df118
Merge pull request #58 from curbengh/dependabot/github_actions/actions/cache-2.1.6
chore(deps): bump actions/cache from 2.1.4 to 2.1.6
2021-10-16 19:59:45 +10:30
Ming Di Leom 45ed8c2bac
Merge pull request #54 from curbengh/dependabot/github_actions/actions/checkout-2.3.4
chore(deps): bump actions/checkout from 2 to 2.3.4
2021-10-16 19:59:02 +10:30
MDLeom c0041b0f23
fix(svg): compatibility with svgo 2.4+
- overriding default plugins
- https://github.com/svg/svgo/releases/tag/v2.4.0
2021-10-10 09:19:50 +00:00
dependabot[bot] 88deed06bb
chore(deps-dev): bump jest from 26.6.3 to 27.2.5
Bumps [jest](https://github.com/facebook/jest) from 26.6.3 to 27.2.5.
- [Release notes](https://github.com/facebook/jest/releases)
- [Changelog](https://github.com/facebook/jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/jest/compare/v26.6.3...v27.2.5)

---
updated-dependencies:
- dependency-name: jest
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-08 15:05:13 +00:00
dependabot[bot] ed5d09c803
chore(deps): bump codecov/codecov-action from 1 to 2.1.0
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 1 to 2.1.0.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/master/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v1...v2.1.0)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-09-13 15:02:16 +00:00
dependabot[bot] e4b349202c
chore(deps): bump minify-xml from 2.5.0 to 3.2.0
Bumps [minify-xml](https://github.com/kristian/minify-xml) from 2.5.0 to 3.2.0.
- [Release notes](https://github.com/kristian/minify-xml/releases)
- [Commits](https://github.com/kristian/minify-xml/compare/2.5.0...3.2.0)

---
updated-dependencies:
- dependency-name: minify-xml
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-23 15:04:15 +00:00
dependabot[bot] 460bb9c035
chore(deps): bump actions/cache from 2.1.4 to 2.1.6
Bumps [actions/cache](https://github.com/actions/cache) from 2.1.4 to 2.1.6.
- [Release notes](https://github.com/actions/cache/releases)
- [Commits](https://github.com/actions/cache/compare/v2.1.4...v2.1.6)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-28 05:22:05 +00:00
dependabot[bot] eca9b2b7c9
chore(deps): bump actions/checkout from 2 to 2.3.4
Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 2.3.4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v2...v2.3.4)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-12 05:09:55 +00:00
Ming Di Leom be96f15ceb
Merge pull request #52 from curbengh/node-16
release: 5.0.0
2021-05-02 15:45:10 +09:30
MDLeom fde28cdd9a
release: 5.0.0 2021-04-25 08:51:39 +00:00
MDLeom 7aa2f90e52
chore(ci): add Node 16
- released 2021-04-20
2021-04-25 08:48:55 +00:00
MDLeom b169489ce9
chore(ci): run most tests on Node 14
- active LTS
2021-04-25 08:47:04 +00:00
MDLeom 81fd44e514
chore: drop Node 10
- EOL 2021-04-30
2021-04-25 08:45:39 +00:00
MDLeom 1f95af32b7
docs(v5): syntax change in svg.plugins option 2021-04-25 08:41:23 +00:00
Ming Di Leom 6c21cc6a9b
Merge pull request #51 from curbengh/svgo-2
chore(deps): bump svgo from 1.3.2 to 2.3.0 (BREAKING CHANGE)
2021-04-25 18:04:24 +09:30
MDLeom 3819909c84
chore(deps): bump svgo from 1.3.2 to 2.3.0 (BREAKING CHANGE)
- BREAKING CHANGE: syntax of minify.svg.plugins option
  * https://github.com/svg/svgo/releases/tag/v2.0.0
- svgo optimize() changed from async to sync
2021-04-25 08:25:32 +00:00
Ming Di Leom 4f033711e2
Merge pull request #49 from curbengh/dependabot/npm_and_yarn/clean-css-5.1.2
chore(deps): bump clean-css from 4.2.3 to 5.1.2
2021-04-25 15:53:44 +09:30
Ming Di Leom e05f96f971
Merge pull request #42 from curbengh/dependabot/github_actions/actions/setup-node-v2.1.5
chore(deps): bump actions/setup-node from v2.1.2 to v2.1.5
2021-04-25 15:51:56 +09:30
Ming Di Leom 193cc355be
Merge pull request #37 from curbengh/dependabot/github_actions/actions/cache-v2.1.4
chore(deps): bump actions/cache from v2 to v2.1.4
2021-04-25 15:51:30 +09:30
dependabot[bot] 679858e4e8
chore(deps): bump clean-css from 4.2.3 to 5.1.2
Bumps [clean-css](https://github.com/jakubpawlowicz/clean-css) from 4.2.3 to 5.1.2.
- [Release notes](https://github.com/jakubpawlowicz/clean-css/releases)
- [Changelog](https://github.com/jakubpawlowicz/clean-css/blob/master/History.md)
- [Commits](https://github.com/jakubpawlowicz/clean-css/compare/v4.2.3...v5.1.2)

Signed-off-by: dependabot[bot] <support@github.com>
2021-03-22 06:55:41 +00:00
dependabot[bot] 1c10c9ee5e
chore(deps): bump actions/setup-node from v2.1.2 to v2.1.5
Bumps [actions/setup-node](https://github.com/actions/setup-node) from v2.1.2 to v2.1.5.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v2.1.2...46071b5c7a2e0c34e49c3cb8a0e792e86e18d5ea)

Signed-off-by: dependabot[bot] <support@github.com>
2021-02-23 05:51:48 +00:00
dependabot[bot] e621a7937a
chore(deps): bump actions/cache from v2 to v2.1.4
Bumps [actions/cache](https://github.com/actions/cache) from v2 to v2.1.4.
- [Release notes](https://github.com/actions/cache/releases)
- [Commits](https://github.com/actions/cache/compare/v2...26968a09c0ea4f3e233fdddbafd1166051a095f6)

Signed-off-by: dependabot[bot] <support@github.com>
2021-02-08 06:31:24 +00:00
MDLeom ef57b75638
docs(precompressed): link to caddy guide 2020-11-13 23:04:16 +00:00
MDLeom 5cc13c1ad8 docs(br): GitLab Pages now support pre-compressed br
- https://gitlab.com/gitlab-org/gitlab-pages/-/merge_requests/359
2020-11-12 02:05:51 +00:00
MDLeom 140a005dc7 docs(br): Caddy v2 doesn't server pre-compressed files automatically 2020-11-12 02:05:51 +00:00
MDLeom ea29aa0ad5
Merge pull request #33 from curbengh/node-15
chore(actions): add Node 15
2020-11-07 14:18:47 +10:30
MDLeom bbc464b29e
chore(actions): simpler Node version syntax 2020-11-07 03:43:57 +00:00
MDLeom cef2d0e377
chore(actions): add Node 15 2020-11-07 03:42:45 +00:00
MDLeom 91c4d936e0
Merge pull request #32 from curbengh/dependabot/npm_and_yarn/standard-16.0.1
chore(deps-dev): bump standard from 14.3.4 to 16.0.1
2020-11-07 11:45:40 +10:30
MDLeom 4a16fca23e
Merge pull request #27 from curbengh/dependabot/github_actions/actions/setup-node-v2.1.2
chore(dev-deps): bump actions/setup-node from v2.1.1 to v2.1.2
2020-11-07 11:43:57 +10:30
dependabot[bot] d8805d9a9a
chore(deps-dev): bump standard from 14.3.4 to 16.0.1
Bumps [standard](https://github.com/standard/standard) from 14.3.4 to 16.0.1.
- [Release notes](https://github.com/standard/standard/releases)
- [Changelog](https://github.com/standard/standard/blob/master/CHANGELOG.md)
- [Commits](https://github.com/standard/standard/compare/v14.3.4...v16.0.1)

Signed-off-by: dependabot[bot] <support@github.com>
2020-11-02 07:11:23 +00:00
dependabot[bot] 19424d8ae8
chore(deps): bump actions/setup-node from v2.1.1 to v2.1.2
Bumps [actions/setup-node](https://github.com/actions/setup-node) from v2.1.1 to v2.1.2.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v2.1.1...c6fd00ceb9747fb23ffdf72987450a2664414867)

Signed-off-by: dependabot[bot] <support@github.com>
2020-10-02 06:11:47 +00:00
MDLeom 18e1fd3a78
ci(snyk): requires deps to be installed beforehand 2020-09-09 05:23:11 +00:00
MDLeom bc742f75fb
Merge pull request #26 from curbengh/dependabot/github_actions/actions/setup-node-v2.1.1
chore(deps): bump actions/setup-node from v1 to v2.1.1
2020-09-06 10:07:56 +09:30
dependabot[bot] 11b07ab00f
chore(deps): bump actions/setup-node from v1 to v2.1.1
Bumps [actions/setup-node](https://github.com/actions/setup-node) from v1 to v2.1.1.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v1...321b6ccb03083caa2ad22b27dc4b45335212e824)

Signed-off-by: dependabot[bot] <support@github.com>
2020-09-06 00:05:01 +00:00
MDLeom 0fd2ed31ee
release: 4.2.0 2020-09-06 00:04:28 +00:00
MDLeom ba66c4bc89
chore(dependabot): monitor actions' dep
- https://docs.github.com/en/github/administering-a-repository/configuration-options-for-dependency-updates#package-ecosystem
2020-09-06 00:02:26 +00:00
MDLeom 9ac8969a08
docs: Netlify supports brotli 2020-09-05 14:15:58 +00:00
MDLeom 353ca8ea37
docs: links to xml & json sections 2020-09-05 14:05:10 +00:00
MDLeom fd117bcd58
docs(badge): add codecov 2020-09-05 13:51:51 +00:00
MDLeom c8cc870b4c
docs(badge): add logo 2020-09-05 13:49:02 +00:00
MDLeom 327b36782b
ci(snyk): fix cron syntax
- docs: add actions badge
2020-09-05 12:47:23 +00:00
MDLeom 57db21d2ad
ci: replace travis with actions 2020-09-05 12:43:05 +00:00
MDLeom 51cc9b1d8d
feat: show path that caused the error 2020-09-05 11:58:20 +00:00
MDLeom c57e227efd
fix: set default config 2020-09-05 11:41:22 +00:00
MDLeom 37ba1d9a2b
refactor: destructure 2020-09-05 11:22:36 +00:00
MDLeom ce8c4a145b
refactor(test): set default config in individual test 2020-09-05 11:18:35 +00:00
MDLeom 16cdf467d9
fix(js): compatibility with terser v5
- https://github.com/terser/terser/blob/master/CHANGELOG.md#v500-beta0
2020-09-05 10:56:33 +00:00
MDLeom 3de777904f
chore(deps-dev): update hexo from 25.4.0 to 26.4.2 2020-09-05 10:23:32 +00:00
MDLeom d9817f8a44
chore(deps-dev): update hexo from 4.2.0 to 5.1.1 2020-09-05 10:23:01 +00:00
MDLeom 605c5fd57f
chore(deps): update terser from 4.0.0 to 5.3.0 2020-09-05 10:21:22 +00:00
MDLeom d68c26a2c2
docs: use Shields.io badges
- move david-dm.org to more stable libraries.io
2020-09-05 10:18:51 +00:00
MDLeom 7f60c6959e
chore: replace deprecated greenkeeper with dependabot 2020-09-05 10:10:34 +00:00
MDLeom c2bcaa7d69
Merge pull request #25 from curbengh/minify-xml
feat: utilise better minify-xml
2020-09-03 14:37:16 +09:30
MDLeom 8bbecf676f
feat: utilise better minify-xml
- replace pretty-data
2020-09-02 11:23:20 +00:00
MDLeom 9b94a2c2df
ci(travis): remove Node 13
- EOL 1 June 2020
2020-06-06 07:45:47 +01:00
MDLeom bdb7e94350
test(gz): blns 2020-06-06 07:42:12 +01:00
MDLeom e5ab822c45
test(br): blns 2020-06-06 07:41:37 +01:00
MDLeom c42b9040a6
test(js): throw error on invalid input 2020-05-25 09:36:21 +01:00
MDLeom 9e67d11e8a
test(html): invalid input
- uncovered using blns.json
- https://github.com/minimaxir/big-list-of-naughty-strings
2020-05-25 09:13:15 +01:00
MDLeom e1843f7400
chore(deps-dev): Update jest to 25.4.0 2020-04-24 13:57:26 +01:00
MDLeom b8d48c7f8a
ci(travis): add Node 14 2020-04-24 13:54:24 +01:00
MDLeom c721fa8c02
docs(readme): add lgtm.com badges 2020-02-24 04:11:50 +00:00
curbengh 81ab472fe1
test: utilise toThrow() to catch error
- try...catch would (incorrectly) pass the test, despite having no error
2020-01-09 15:14:25 +00:00
25 changed files with 1500 additions and 401 deletions

10
.github/dependabot.yml vendored Normal file
View File

@ -0,0 +1,10 @@
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "daily"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"

22
.github/workflows/linter.yml vendored Normal file
View File

@ -0,0 +1,22 @@
name: Linter
on: [push, pull_request]
jobs:
linter:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- name: Install Bun
uses: oven-sh/setup-bun@v2
- name: Cache NPM dependencies
uses: actions/cache@v4
with:
path: node_modules
key: ${{ runner.os }}-npm-cache
restore-keys: |
${{ runner.os }}-npm-cache
- name: Install Dependencies
run: bun install
- name: Lint
run: bun run lint

23
.github/workflows/semgrep.yml vendored Normal file
View File

@ -0,0 +1,23 @@
name: Semgrep
on:
pull_request: {}
push:
branches:
- master
paths:
- .github/workflows/semgrep.yml
schedule:
# Weekly
- cron: "0 0 * * 0"
jobs:
semgrep:
name: Scan
runs-on: ubuntu-latest
env:
SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }}
container:
image: returntocorp/semgrep
if: (github.actor != 'dependabot[bot]')
steps:
- uses: actions/checkout@v5
- run: semgrep ci

37
.github/workflows/snyk.yml vendored Normal file
View File

@ -0,0 +1,37 @@
name: Snyk
on:
schedule:
# Weekly
- cron: "0 0 * * 0"
pull_request:
branches:
- "dependabot/github_actions/github/codeql-action**"
jobs:
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- name: Install Bun
uses: oven-sh/setup-bun@v2
- name: Install Dependencies
run: bun install
- name: Run Snyk to check for vulnerabilities
uses: snyk/actions/node@master
continue-on-error: true # To make sure that SARIF upload gets called
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
with:
command: test
args: --sarif-file-output=snyk.sarif
- name: Upload result to GitHub Code Scanning
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: snyk.sarif
- name: Monitor for vulnerabilities
uses: snyk/actions/node@master
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
with:
command: monitor

52
.github/workflows/tester.yml vendored Normal file
View File

@ -0,0 +1,52 @@
name: Tester
on: [push, pull_request]
jobs:
tester:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: ["20", "22", "24"]
fail-fast: false
steps:
- uses: actions/checkout@v5
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- name: Cache NPM dependencies
uses: actions/cache@v4
with:
path: node_modules
key: ${{ runner.os }}-npm-cache
restore-keys: ${{ runner.os }}-npm-cache
- name: Determine unrs-resolver binary version
shell: bash
run: |
case "$RUNNER_OS" in
"Linux")
echo "PLATFORM=linux-x64-gnu" >> "$GITHUB_ENV" ;;
"Windows")
echo "PLATFORM=win32-x64-msvc" >> "$GITHUB_ENV" ;;
"macOS")
echo "PLATFORM=darwin-arm64" >> "$GITHUB_ENV" ;;
esac
- name: Install Dependencies
shell: bash
run: |
npm install
npm install --include=optional --force @mongodb-js/zstd
npm install "@unrs/resolver-binding-$PLATFORM"
- name: Test
run: npm run test
env:
CI: true
- name: Upload coverage report to Codecov
if: matrix.os == 'ubuntu-latest' && matrix.node-version == '22'
uses: codecov/codecov-action@v5
with:
fail_ci_if_error: true
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

1
.gitignore vendored
View File

@ -4,3 +4,4 @@ package-lock.json
tmp/
*.log
coverage/
bun.lockb

1
.npmrc
View File

@ -1,2 +1 @@
package-lock=false
optional=false

6
.snyk
View File

@ -2,8 +2,4 @@
version: v1.12.0
# ignores vulnerabilities until expiry date; change duration by modifying expiry date
ignore:
SNYK-JS-LODASH-450202:
- '*':
reason: Patch/update unavailable. Introduced through Snyk.
expires: '2019-12-31T00:00:00.000Z'
patch: {}
patch:

View File

@ -1,25 +0,0 @@
dist: bionic
language: node_js
node_js:
- "10"
- "12"
- "13"
cache:
npm: true
script:
- npm run lint
- npm run test
after_script:
- if ([[ $TRAVIS_EVENT_TYPE == "push" ]] || [[ $TRAVIS_EVENT_TYPE == "cron" ]]) && [[ $TRAVIS_BRANCH == "master" ]] && [[ $TRAVIS_NODE_VERSION == "12" ]]; then
npm install snyk;
snyk auth $SNYK_TOKEN;
snyk test;
snyk protect;
snyk monitor;
fi
- npm install codecov
- codecov

View File

@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2018-2019 curbengh, 2016-2018 rozbo
Copyright (c) 2018-2024 curbengh, 2016-2018 rozbo
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

229
README.md
View File

@ -1,46 +1,32 @@
# hexo-yam
[![npm version](https://badge.fury.io/js/hexo-yam.svg)](https://www.npmjs.com/package/hexo-yam)
[![Build Status](https://travis-ci.com/curbengh/hexo-yam.svg?branch=master)](https://travis-ci.com/curbengh/hexo-yam)
[![codecov](https://codecov.io/gh/curbengh/hexo-yam/branch/master/graph/badge.svg)](https://codecov.io/gh/curbengh/hexo-yam)
[![NPM Dependencies](https://david-dm.org/curbengh/hexo-yam.svg)](https://david-dm.org/curbengh/hexo-yam)
[![Known Vulnerabilities](https://snyk.io/test/npm/hexo-yam/badge.svg)](https://snyk.io/test/npm/hexo-yam)
[![Greenkeeper badge](https://badges.greenkeeper.io/curbengh/hexo-yam.svg)](https://greenkeeper.io/)
Yet Another Minifier for Hexo. Minify and compress HTML, JS, CSS, SVG, XML and JSON. [Other files](https://github.com/curbengh/hexo-yam/blob/ba77db0094a7c07ea9f70f010bfc15541d4105ca/index.js#L64) are also compressed. Support gzip and [brotli](https://en.wikipedia.org/wiki/Brotli) [compressions](https://en.wikipedia.org/wiki/HTTP_compression).
[![npm version](https://img.shields.io/npm/v/hexo-yam?logo=npm)](https://www.npmjs.com/package/hexo-yam)
[![Build Status](https://img.shields.io/github/actions/workflow/status/curbengh/hexo-yam/tester.yml?branch=master&logo=github)](https://github.com/curbengh/hexo-yam/actions?query=workflow%3ATester)
[![codecov](https://img.shields.io/codecov/c/gh/curbengh/hexo-yam?logo=codecov)](https://codecov.io/gh/curbengh/hexo-yam)
[![NPM Dependencies](https://img.shields.io/librariesio/release/npm/hexo-yam)](https://libraries.io/npm/hexo-yam)
[![Known Vulnerabilities](https://snyk.io/test/github/curbengh/hexo-yam/badge.svg)](https://snyk.io/test/github/curbengh/hexo-yam)
Yet Another Minifier for Hexo. Minify HTML, JS, CSS, SVG, XML and JSON. Compress static [web assets](https://github.com/curbengh/hexo-yam/blob/ba77db0094a7c07ea9f70f010bfc15541d4105ca/index.js#L64) using gzip, brotli and zstd.
## Table of contents
- [Version 4](#version-4)
- [Installation](#installation)
- [Options](#options)
- [HTML](#html)
- [CSS](#css)
- [JS](#js)
- [SVG](#svg)
- [Gzip](#gzip)
- [Brotli](#brotli)
- [XML](#xml)
- [JSON](#json)
- [Gzip](#gzip)
- [Brotli](#brotli)
- [Zstd](#zstd)
- [Globbing](#globbing)
- [HTTP Compression](#http-compression)
## Version 4
In v4, `logger:` option has been renamed to `verbose:`
Migrate:
``` diff
minify:
html:
- logger: true
+ verbose: true
```
## Installation
```bash
$ npm install hexo-yam --save
$ npm install --save hexo-yam
```
## Options
@ -48,21 +34,27 @@ $ npm install hexo-yam --save
```yaml
minify:
enable: true
previewServer: true
html:
css:
js:
svg:
gzip:
brotli:
xml:
json:
```
- **enable** - Enable the plugin. Defaults to `true`.
- **previewServer** - Disable the plugin when running `hexo server`. Defaults to `true`.
- **html** - See [HTML](#html) section
- **css** - See [CSS](#css) section
- **js** - See [JS](#js) section
- **svg** - See [SVG](#svg) section
- **gzip** - See [Gzip](#gzip) section
- **brotli** - See [Brotli](#brotli) section
- **xml** - See [XML](#xml) section
- **json** - See [JSON](#json) section
## HTML
@ -72,6 +64,7 @@ minify:
enable: true
exclude:
```
- **enable** - Enable the plugin. Defaults to `true`.
- **priority** - Plugin's priority. Defaults to `10`. Set lower value to set higher priority and vice versa.
- **verbose** - Verbose output. Defaults to `false`.
@ -87,8 +80,9 @@ minify:
css:
enable: true
exclude:
- '*.min.css'
- "*.min.css"
```
- **enable** - Enable the plugin. Defaults to `true`.
- **priority** - Plugin's priority. Defaults to `10`.
- **verbose** - Verbose output. Defaults to `false`.
@ -105,8 +99,9 @@ minify:
js:
enable: true
exclude:
- '*.min.js'
- "*.min.js"
```
- **enable** - Enable the plugin. Defaults to `true`.
- **priority** - Plugin's priority. Defaults to `10`.
- **verbose** - Verbose output. Defaults to `false`.
@ -126,19 +121,70 @@ minify:
svg:
enable: true
include:
- '*.svg'
- '!*.min.svg'
- "*.svg"
- "!*.min.svg"
```
- **enable** - Enable the plugin. Defaults to `true`.
- **priority** - Plugin's priority. Defaults to `10`.
- **verbose** - Verbose output. Defaults to `false`.
- **include** - Include files. Support [wildcard](http://www.globtester.com/) pattern(s) in a string or array.
- Exclude `*.min.svg` by default.
- **plugins** - Plugin options.
- Example: to retain comments, `plugins: [{removeComments: false}]`.
- Examples:
```yaml
plugins:
# Retain comments
removeComments: false
# Do not remove unused ID attributes
cleanupIds: false
```
- For more options, see [svgo](https://github.com/svg/svgo).
- **globOptions** - See [globbing](#globbing) section.
## XML
Remove whitespaces in xml.
```yaml
minify:
xml:
enable: false
include:
- "*.xml"
- "!*.min.xml"
```
- **enable** - Enable the plugin. Defaults to `false`.
- **priority** - Plugin's priority. Defaults to `10`.
- **verbose** - Verbose output. Defaults to `false`.
- **include** - Include files. Support [wildcard](http://www.globtester.com/) pattern(s) in a string or array.
- Exclude `*.min.xml` by default.
- **removeComments** - Remove [comments](https://developer.mozilla.org/en-US/docs/Web/XML/XML_introduction) in xml. Defaults to `true`.
- **globOptions** - See [globbing](#globbing) section.
For more options, see [minify-xml](https://github.com/kristian/minify-xml#options).
## JSON
Remove whitespaces in json.
```yaml
minify:
json:
enable: false
include:
- "*.json"
- "!*.min.json"
```
- **enable** - Enable the plugin. Defaults to `false`.
- **priority** - Plugin's priority. Defaults to `10`.
- **verbose** - Verbose output. Defaults to `false`.
- **include** - Include files. Support [wildcard](http://www.globtester.com/) pattern(s) in a string or array.
- Exclude `*.min.json` by default.
- **globOptions** - See [globbing](#globbing) section.
## Gzip
```yaml
@ -146,18 +192,19 @@ minify:
gzip:
enable: true
include:
- '*.html'
- '*.css'
- '*.js'
- '*.txt'
- '*.ttf'
- '*.atom'
- '*.stl'
- '*.xml'
- '*.svg'
- '*.eot'
- '*.json'
- "*.html"
- "*.css"
- "*.js"
- "*.txt"
- "*.ttf"
- "*.atom"
- "*.stl"
- "*.xml"
- "*.svg"
- "*.eot"
- "*.json"
```
- **enable** - Enable the plugin. Defaults to `true`.
- **priority** - Plugin's priority. Defaults to `10`.
- **verbose** - Verbose output. Defaults to `false`.
@ -174,18 +221,19 @@ minify:
brotli:
enable: true
include:
- '*.html'
- '*.css'
- '*.js'
- '*.txt'
- '*.ttf'
- '*.atom'
- '*.stl'
- '*.xml'
- '*.svg'
- '*.eot'
- '*.json'
- "*.html"
- "*.css"
- "*.js"
- "*.txt"
- "*.ttf"
- "*.atom"
- "*.stl"
- "*.xml"
- "*.svg"
- "*.eot"
- "*.json"
```
- **enable** - Enable the plugin. Defaults to `true`.
- **priority** - Plugin's priority. Defaults to `10`.
- **verbose** - Verbose output. Defaults to `false`.
@ -193,44 +241,32 @@ minify:
- **globOptions** - See [globbing](#globbing) section.
- **level** - Compression level. Range `1-11`. Defaults to `11`, or the value of [`zlib.constants.BROTLI_MAX_QUALITY`](https://nodejs.org/docs/latest-v12.x/api/zlib.html#zlib_brotli_constants)
## XML
Remove whitespaces in xml.
## Zstd
```yaml
minify:
xml:
zstd:
enable: false
include:
- '*.xml'
- '!*.min.xml'
- "*.html"
- "*.css"
- "*.js"
- "*.txt"
- "*.ttf"
- "*.atom"
- "*.stl"
- "*.xml"
- "*.svg"
- "*.eot"
- "*.json"
```
- **enable** - Enable the plugin. Defaults to `false`.
- **priority** - Plugin's priority. Defaults to `10`.
- **verbose** - Verbose output. Defaults to `false`.
- **include** - Include files. Support [wildcard](http://www.globtester.com/) pattern(s) in a string or array.
- Exclude `*.min.xml` by default.
- **removeComments** - Remove [comments](https://developer.mozilla.org/en-US/docs/Web/XML/XML_introduction) in xml. Defaults to `true`.
- **globOptions** - See [globbing](#globbing) section.
## JSON
Remove whitespaces in json.
``` yaml
minify:
json:
enable: false
include:
- '*.json'
- '!*.min.json'
```
- **enable** - Enable the plugin. Defaults to `false`.
- **priority** - Plugin's priority. Defaults to `10`.
- **verbose** - Verbose output. Defaults to `false`.
- **include** - Include files. Support [wildcard](http://www.globtester.com/) pattern(s) in a string or array.
- Exclude `*.min.json` by default.
- **globOptions** - See [globbing](#globbing) section.
- **level** - Compression level. Range `1-22`. Defaults to `3`, or the value of [`DEFAULT_LEVEL`](https://github.com/mongodb-js/zstd/blob/a3a08c61c9045411c8275e248498dbc583457fb5/src/lib.rs#L9)
## Globbing
@ -242,49 +278,30 @@ Use "globOptions" to customise how glob patterns match files. Refer to [micromat
```yml
exclude:
- '*foo.html' # basename is enabled
- '**/bar/*/*.html' # basename is automatically disabled
- '*baz.css' # basename is enabled
- "*foo.html" # basename is enabled
- "**/bar/*/*.html" # basename is automatically disabled
- "*baz.css" # basename is enabled
globOptions:
basename: true # default
```
- This behaviour doesn't apply to pattern that starts with `!` (negation).
- This limitation only applies to `include:` option used in svg, gzip and brotli.
- This means the following options would *not* work,
- This means the following options would _not_ work,
```yml
include:
- '!foo.svg'
- '!**/bar/*/*.svg'
- "!foo.svg"
- "!**/bar/*/*.svg"
globOptions:
basename: true
```
- basename will stay disabled, if explicitly disabled in "globOptions".
## HTTP Compression
While most modern web browsers [support Brotli](https://www.caniuse.com/#feat=brotli), you also need to consider whether the web/app server, hosting platform, reverse proxy or CDN (whichever relevant to you) support it.
As of May 2019, GitHub Pages, GitLab Pages and Netlify *do not* support brotli yet. You can generate `.br` files, but they won't serve those files.
Name | Status (May 8, 2019)
--- | ---
GitHub Pages | [In consideration](https://github.community/t5/GitHub-Pages/Support-for-pre-compressed-assets-and-brotli-compression/m-p/22055)
GitLab Pages | [In progress](https://gitlab.com/gitlab-org/gitlab-pages/merge_requests/120)
Netlify | [In consideration](https://postimg.cc/qgxn0261)
Hexo Server | [In progress](https://github.com/hexojs/hexo-server/pull/100)
If you have access to the web server config, you should disable on-the-fly compression for static files (that are already compressed by this plugin),
- [nginx](https://github.com/google/ngx_brotli): Make sure both filter and static modules are enabled. This way pre-compressed `.br` files will be served while dynamic content can be compressed on-the-fly. Protip: `brotli_types text/plain text/css application/javascript application/json image/svg+xml application/xml+rss;` to prevent compressing media files (which are already compressed anyway).
- [Apache](https://httpd.apache.org/docs/2.4/en/mod/mod_brotli.html): See 'Serving pre-compressed content' section of [mod_brotli](https://httpd.apache.org/docs/2.4/en/mod/mod_brotli.html).
- [Caddy](https://caddyserver.com/features): [0.9.4+](https://caddyserver.com/blog/caddy-0_9_4-released) by default support pre-compressed `.gz` `.br` files and on-the-fly gzip compress dynamic files.
- [express](https://github.com/expressjs/express)/[connect](https://github.com/senchalabs/connect): Use [pre-compressed-assets](https://github.com/domadams/pre-compressed-assets). You still can continue to use [compression](https://github.com/expressjs/compression)/[shrink-ray-current](https://github.com/Alorel/shrink-ray) for dynamic files.
## Credits
All credits go to the following work:
- [hexo-neat](https://github.com/rozbo/hexo-neat) by rozbo
- gzip feature is inspired by [hexo-generator-optimize](https://github.com/JackyRen/hexo-generator-optimize)

5
bunfig.toml Normal file
View File

@ -0,0 +1,5 @@
[install]
optional = false
[install.lockfile]
save = false

View File

@ -1,8 +1,12 @@
/* global hexo */
'use strict'
const minifyDefault = { enable: true }
const htmlDefault = {
hexo.config.minify = Object.assign({
enable: true,
previewServer: true
}, hexo.config.minify)
hexo.config.minify.html = Object.assign({
enable: true,
priority: 10,
verbose: false,
@ -18,16 +22,18 @@ const htmlDefault = {
minifyJS: true,
minifyCSS: true,
globOptions: { basename: true }
}
const cssDefault = {
}, hexo.config.minify.html)
hexo.config.minify.css = Object.assign({
enable: true,
priority: 10,
verbose: false,
exclude: ['*.min.css'],
level: 2,
globOptions: { basename: true }
}
const jsDefault = {
}, hexo.config.minify.css)
hexo.config.minify.js = Object.assign({
enable: true,
priority: 10,
verbose: false,
@ -36,56 +42,59 @@ const jsDefault = {
mangle: true,
output: {},
globOptions: { basename: true }
}
const svgDefault = {
}, hexo.config.minify.js)
hexo.config.minify.svg = Object.assign({
enable: true,
priority: 10,
verbose: false,
include: ['*.svg', '!*.min.svg'],
plugins: [],
plugins: {},
globOptions: { basename: true }
}
const gzipDefault = {
}, hexo.config.minify.svg)
hexo.config.minify.gzip = Object.assign({
enable: true,
priority: 10,
verbose: false,
include: ['*.html', '*.css', '*.js', '*.txt', '*.ttf', '*.atom', '*.stl', '*.xml', '*.svg', '*.eot', '*.json'],
globOptions: { basename: true }
}
const brotliDefault = {
}, hexo.config.minify.gzip)
hexo.config.minify.brotli = Object.assign({
enable: true,
priority: 10,
verbose: false,
include: ['*.html', '*.css', '*.js', '*.txt', '*.ttf', '*.atom', '*.stl', '*.xml', '*.svg', '*.eot', '*.json'],
globOptions: { basename: true }
}
const xmlDefault = {
}, hexo.config.minify.brotli)
hexo.config.minify.zstd = Object.assign({
enable: false,
priority: 10,
verbose: false,
include: ['*.html', '*.css', '*.js', '*.txt', '*.ttf', '*.atom', '*.stl', '*.xml', '*.svg', '*.eot', '*.json'],
globOptions: { basename: true }
}, hexo.config.minify.zstd)
hexo.config.minify.xml = Object.assign({
enable: false,
priority: 10,
verbose: false,
include: ['*.xml', '!*.min.xml'],
removeComments: true,
globOptions: { basename: true }
}
const jsonDefault = {
}, hexo.config.minify.xml)
hexo.config.minify.json = Object.assign({
enable: false,
priority: 10,
verbose: false,
include: ['*.json', '!*.min.json'],
globOptions: { basename: true }
}
}, hexo.config.minify.json)
hexo.config.minify = Object.assign(minifyDefault, hexo.config.minify)
hexo.config.minify.html = Object.assign(htmlDefault, hexo.config.minify.html)
hexo.config.minify.css = Object.assign(cssDefault, hexo.config.minify.css)
hexo.config.minify.js = Object.assign(jsDefault, hexo.config.minify.js)
hexo.config.minify.svg = Object.assign(svgDefault, hexo.config.minify.svg)
hexo.config.minify.gzip = Object.assign(gzipDefault, hexo.config.minify.gzip)
hexo.config.minify.brotli = Object.assign(brotliDefault, hexo.config.minify.brotli)
hexo.config.minify.xml = Object.assign(xmlDefault, hexo.config.minify.xml)
hexo.config.minify.json = Object.assign(jsonDefault, hexo.config.minify.json)
if (hexo.config.minify.enable === true) {
if (hexo.config.minify.enable === true && !(hexo.config.minify.previewServer === true && ['s', 'server'].includes(hexo.env.cmd))) {
const filter = require('./lib/filter')
hexo.extend.filter.register('after_render:html', filter.minifyHtml, hexo.config.minify.html.priority)
hexo.extend.filter.register('after_render:css', filter.minifyCss, hexo.config.minify.css.priority)
@ -93,18 +102,7 @@ if (hexo.config.minify.enable === true) {
hexo.extend.filter.register('after_generate', filter.minifySvg, hexo.config.minify.svg.priority)
hexo.extend.filter.register('after_generate', filter.gzipFn, hexo.config.minify.gzip.priority)
hexo.extend.filter.register('after_generate', filter.brotliFn, hexo.config.minify.brotli.priority)
hexo.extend.filter.register('after_generate', filter.zstdFn, hexo.config.minify.zstd.priority)
hexo.extend.filter.register('after_generate', filter.minifyXml, hexo.config.minify.xml.priority)
hexo.extend.filter.register('after_generate', filter.minifyJson, hexo.config.minify.json.priority)
}
module.exports = {
minifyDefault,
htmlDefault,
cssDefault,
jsDefault,
svgDefault,
gzipDefault,
brotliDefault,
xmlDefault,
jsonDefault
}

View File

@ -1,14 +1,16 @@
'use strict'
const Htmlminifier = require('html-minifier').minify
const { minify: htmlMinify } = require('html-minifier-terser')
const CleanCSS = require('clean-css')
const Terser = require('terser')
const Svgo = require('svgo')
const zlib = require('zlib')
const { promisify } = require('util')
const { minify: terserMinify } = require('terser')
const { optimize: svgOptimize } = require('svgo')
const zlib = require('node:zlib')
const { promisify } = require('node:util')
const gzip = promisify(zlib.gzip)
const br = promisify(zlib.brotliCompress)
const { minify: compressXml } = require('minify-xml')
const micromatch = require('micromatch')
const { compress: zstd } = require('@mongodb-js/zstd')
const isMatch = (path = '', patterns = [], options = {}) => {
if (path && patterns) {
@ -58,7 +60,7 @@ function logFn (original, minified, path, ext) {
log.log(`${ext}: ${path} [${saved}% saved]`)
}
function minifyHtml (str, data) {
async function minifyHtml (str, data) {
const hexo = this
const options = hexo.config.minify.html
if (options.enable === false || !str) return
@ -69,10 +71,14 @@ function minifyHtml (str, data) {
// Return if a path matches exclusion pattern
if (isMatch(path, exclude, globOptions)) return str
const result = Htmlminifier(str, options)
try {
const result = await htmlMinify(str, options)
if (verbose) logFn.call(this, str, result, path, 'html')
return result
} catch (err) {
throw new Error(`Path: ${path}\n${err}`)
}
}
async function minifyCss (str, data) {
@ -90,11 +96,11 @@ async function minifyCss (str, data) {
if (verbose) logFn.call(this, str, styles, path, 'css')
return styles
} catch (err) {
throw new Error(err)
throw new Error(`Path: ${path}\n${err}`)
}
}
function minifyJs (str, data) {
async function minifyJs (str, data) {
const hexo = this
const options = hexo.config.minify.js
if (options.enable === false || !str) return
@ -114,11 +120,13 @@ function minifyJs (str, data) {
delete jsOptions.exclude
delete jsOptions.globOptions
const { code, error } = Terser.minify(str, jsOptions)
if (error) throw new Error(error)
try {
const { code } = await terserMinify(str, jsOptions)
if (verbose) logFn.call(this, str, code, path, 'js')
return code
} catch (err) {
throw new Error(`Path: ${path}\n${err}`)
}
}
function minifySvg () {
@ -129,6 +137,14 @@ function minifySvg () {
const { route } = hexo
const routeList = route.list()
const { globOptions, include, verbose } = options
// const plugins = Array.isArray(options.plugins) ? extendDefaultPlugins(options.plugins) : extendDefaultPlugins([])
const pluginCfg = Object.prototype.toString.call(options.plugins) === '[object Object]' ? { ...options.plugins } : {}
const plugins = [{
name: 'preset-default',
params: {
overrides: pluginCfg
}
}]
return Promise.all((match(routeList, include, globOptions)).map((path) => {
return new Promise((resolve, reject) => {
@ -138,11 +154,11 @@ function minifySvg () {
assetPath.on('end', async () => {
if (assetTxt.length) {
try {
const { data } = await new Svgo(options).optimize(assetTxt)
const { data } = svgOptimize(assetTxt, { ...options, plugins })
if (verbose) logFn.call(this, assetTxt, data, path, 'svg')
resolve(route.set(path, data))
} catch (err) {
reject(new Error(err))
reject(new Error(`Path: ${path}\n${err}`))
}
}
resolve()
@ -174,7 +190,7 @@ function gzipFn () {
if (verbose) logFn.call(this, assetTxt, result, path, 'gzip')
resolve(route.set(path + '.gz', result))
} catch (err) {
reject(new Error(err))
reject(new Error(`Path: ${path}\n${err}`))
}
}
resolve()
@ -206,7 +222,40 @@ function brotliFn () {
if (verbose) logFn.call(this, assetTxt, result, path, 'brotli')
resolve(route.set(path + '.br', result))
} catch (err) {
reject(new Error(err))
reject(new Error(`Path: ${path}\n${err}`))
}
}
resolve()
})
})
}))
}
function zstdFn () {
const hexo = this
const options = hexo.config.minify.zstd
if (options.enable === false) return
const { route } = hexo
const routeList = route.list()
const { globOptions, include, verbose } = options
let { level } = options
if (typeof level !== 'number') level = undefined
return Promise.all((match(routeList, include, globOptions)).map((path) => {
return new Promise((resolve, reject) => {
const assetPath = route.get(path)
let assetTxt = ''
assetPath.on('data', (chunk) => (assetTxt += chunk))
assetPath.on('end', async () => {
if (assetTxt.length) {
try {
const input = Buffer.from(assetTxt, 'utf-8')
const result = await zstd(input, level)
if (verbose) logFn.call(this, assetTxt, result, path, 'zstd')
resolve(route.set(path + '.zst', result))
} catch (err) {
reject(new Error(`Path: ${path}\n${err}`))
}
}
resolve()
@ -222,7 +271,7 @@ function minifyXml () {
const { route } = hexo
const routeList = route.list()
const { globOptions, include, removeComments, verbose } = options
const { globOptions, include, verbose } = options
return Promise.all((match(routeList, include, globOptions)).map((path) => {
return new Promise((resolve, reject) => {
@ -232,19 +281,11 @@ function minifyXml () {
assetPath.on('end', () => {
if (assetTxt.length) {
try {
/* !
* Regex patterns are adapted from pretty-data 0.50.0
* Licensed MIT (c) 2012-2017 Vadim Kiryukhin ( vkiryukhin @ gmail.com )
* https://github.com/vkiryukhin/pretty-data
*/
const text = removeComments
? assetTxt.replace(/<![ \r\n\t]*(--([^-]|[\r\n]|-[^-])*--[ \r\n\t]*)>/g, '')
: assetTxt
const result = text.replace(/>\s{0,}</g, '><')
const result = compressXml(assetTxt, { ...options })
if (verbose) logFn.call(this, assetTxt, result, path, 'xml')
resolve(route.set(path, result))
} catch (err) {
reject(new Error(err))
reject(new Error(`Path: ${path}\n${err}`))
}
}
resolve()
@ -274,7 +315,7 @@ function minifyJson () {
if (verbose) logFn.call(this, assetTxt, result, path, 'json')
resolve(route.set(path, result))
} catch (err) {
reject(new Error(err))
reject(new Error(`Path: ${path}\n${err}`))
}
}
resolve()
@ -290,6 +331,7 @@ module.exports = {
minifySvg,
gzipFn,
brotliFn,
zstdFn,
minifyXml,
minifyJson
}

View File

@ -1,7 +1,7 @@
{
"name": "hexo-yam",
"description": "Yet Another Minifier. Minify and compress html, js, css, svg, xml and json",
"version": "4.1.0",
"version": "9.0.0",
"readme": "README.md",
"main": "index.js",
"directories": {
@ -16,35 +16,35 @@
"test": "jest"
},
"engines": {
"node": ">= 10.18.0"
"node": ">= 20.9.0"
},
"author": "curben",
"license": "MIT",
"homepage": "https://github.com/curbengh/hexo-yam",
"repository": "curbengh/hexo-yam",
"repository": {
"type": "git",
"url": "git+https://github.com/curbengh/hexo-yam.git"
},
"dependencies": {
"clean-css": "^4.2.1",
"html-minifier": "^4.0.0",
"clean-css": "^5.1.2",
"html-minifier-terser": "^7.2.0",
"micromatch": "^4.0.2",
"svgo": "^1.2.2",
"terser": "^4.0.0"
"minify-xml": "^3.2.0",
"svgo": "^4.0.0",
"terser": "^5.3.0",
"@mongodb-js/zstd": "^2.0.1"
},
"devDependencies": {
"hexo": "^4.2.0",
"jest": "^24.9.0",
"standard": "^14.3.1"
"hexo": "^7.1.0",
"jest": "^30.0.4",
"standard": "^17.0.0"
},
"keywords": [
"html",
"js",
"css",
"svg",
"xml",
"json",
"minify",
"compress",
"gzip",
"brotli",
"zstd",
"hexo-yam",
"hexo"
],
@ -52,25 +52,9 @@
"clearMocks": true,
"collectCoverage": true,
"coverageDirectory": "./coverage/",
"testEnvironment": "node"
},
"greenkeeper": {
"commitMessages": {
"initialBadge": "docs(readme): Add Greenkeeper badge",
"initialDependencies": "chore(deps): Update dependencies to enable Greenkeeper",
"initialBranches": "chore: Whitelist greenkeeper branches",
"dependencyUpdate": "chore(deps): Update ${dependency} from ${oldVersion} to ${version}",
"devDependencyUpdate": "chore(deps-dev): Update ${dependency} from ${oldVersion} to ${version}",
"dependencyPin": "chore(deps): Pin ${dependency} to ${oldVersion}",
"devDependencyPin": "chore(deps-dev): Pin ${dependency} to ${oldVersion}"
},
"prTitles": {
"initialPR": "chore(deps): Update dependencies to enable Greenkeeper",
"initialPrBadge": "docs(readme): Add Greenkeeper badge",
"initialPrBadgeOnly": "docs(readme): Add Greenkeeper badge",
"initialSubgroupPR": "chore(deps): Update dependencies for ${group}",
"basicPR": "chore: Update ${dependency} from ${oldVersion} to ${version}",
"groupPR": "chore: Update ${dependency} in ${group} from ${oldVersion} to ${version}"
"testEnvironment": "node",
"testEnvironmentOptions": {
"globalsCleanup": "off"
}
}
}

View File

@ -2,20 +2,26 @@
'use strict'
const Hexo = require('hexo')
const hexo = new Hexo(__dirname)
global.hexo = hexo
const { brotliDefault } = require('../index')
const b = require('../lib/filter').brotliFn.bind(hexo)
const zlib = require('zlib')
const { promisify } = require('util')
const zlib = require('node:zlib')
const { promisify } = require('node:util')
const brotli = promisify(zlib.brotliCompress)
const unbrotli = promisify(zlib.brotliDecompress)
describe('brotli', () => {
const hexo = new Hexo(__dirname)
const b = require('../lib/filter').brotliFn.bind(hexo)
const path = 'foo.txt'
const input = 'Lorem ipsum dolor sit amet consectetur adipiscing elit fusce'
describe('brotli', () => {
beforeEach(() => {
hexo.config.minify.brotli = Object.assign({}, brotliDefault)
hexo.config.minify = {
brotli: {
enable: true,
verbose: false,
include: ['*.html', '*.css', '*.js', '*.txt', '*.ttf', '*.atom', '*.stl', '*.xml', '*.svg', '*.eot', '*.json'],
globOptions: { basename: true }
}
}
hexo.route.set(path, input)
})
@ -227,4 +233,26 @@ describe('brotli', () => {
expect(routeList).toEqual(expect.arrayContaining(expected))
})
test('blns', async () => {
const blns = require('./fixtures/blns.json')
for (const nStr of blns) {
hexo.route.remove(path)
hexo.route.set(path, nStr)
await b()
const output = hexo.route.get(path.concat('.br'))
const buf = []
output.on('data', (chunk) => (buf.push(chunk)))
output.on('end', async () => {
const result = Buffer.concat(buf)
const resultUnbr = await unbrotli(result)
expect(resultUnbr.toString()).toBe(nStr)
})
}
})
})

View File

@ -2,17 +2,24 @@
'use strict'
const Hexo = require('hexo')
const hexo = new Hexo(__dirname)
global.hexo = hexo
const { cssDefault } = require('../index')
const c = require('../lib/filter').minifyCss.bind(hexo)
const CleanCSS = require('clean-css')
describe('css', () => {
const hexo = new Hexo(__dirname)
const c = require('../lib/filter').minifyCss.bind(hexo)
const input = 'foo { bar: baz; } foo { aaa: bbb; }'
const path = 'foo.css'
describe('css', () => {
beforeEach(() => {
hexo.config.minify.css = Object.assign({}, cssDefault)
hexo.config.minify = {
css: {
enable: true,
verbose: false,
exclude: ['*.min.css'],
level: 2,
globOptions: { basename: true }
}
}
})
test('default', async () => {
@ -65,20 +72,15 @@ describe('css', () => {
}
hexo.config.minify.css = customOpt
let result, expected
try {
await c(input, { path })
} catch (err) {
result = err.message
}
let expected
try {
await new CleanCSS(customOpt).minify(input)
} catch (err) {
expected = err.message
expected = err
}
expect(result).toContain(expected)
expect(expected).toBeDefined()
await expect(c(input, { path })).rejects.toThrow(`Path: ${path}\n${expected}`)
})
test('exclude - *.min.css', async () => {

516
test/fixtures/blns.json vendored Normal file
View File

@ -0,0 +1,516 @@
[
"undefined",
"undef",
"null",
"NULL",
"(null)",
"nil",
"NIL",
"true",
"false",
"True",
"False",
"TRUE",
"FALSE",
"None",
"hasOwnProperty",
"then",
"\\",
"\\\\",
"0",
"1",
"1.00",
"$1.00",
"1/2",
"1E2",
"1E02",
"1E+02",
"-1",
"-1.00",
"-$1.00",
"-1/2",
"-1E2",
"-1E02",
"-1E+02",
"1/0",
"0/0",
"-2147483648/-1",
"-9223372036854775808/-1",
"-0",
"-0.0",
"+0",
"+0.0",
"0.00",
"0..0",
".",
"0.0.0",
"0,00",
"0,,0",
",",
"0,0,0",
"0.0/0",
"1.0/0.0",
"0.0/0.0",
"1,0/0,0",
"0,0/0,0",
"--1",
"-",
"-.",
"-,",
"999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999",
"NaN",
"Infinity",
"-Infinity",
"INF",
"1#INF",
"-1#IND",
"1#QNAN",
"1#SNAN",
"1#IND",
"0x0",
"0xffffffff",
"0xffffffffffffffff",
"0xabad1dea",
"123456789012345678901234567890123456789",
"1,000.00",
"1 000.00",
"1'000.00",
"1,000,000.00",
"1 000 000.00",
"1'000'000.00",
"1.000,00",
"1 000,00",
"1'000,00",
"1.000.000,00",
"1 000 000,00",
"1'000'000,00",
"01000",
"08",
"09",
"2.2250738585072011e-308",
",./;'[]\\-=",
"<>?:\"{}|_+",
"!@#$%^&*()`~",
"\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\u000e\u000f\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f",
"ᅡタᅡチᅡツᅡテᅡトᅡニᅡヌᅡネᅡノᅡハᅡヒᅡフᅡヘᅡホᅡマᅡミᅡムᅡメᅡモᅡヤᅡユᅡヨᅡラᅡリᅡルᅡレᅡロᅡワᅡンᅡ゙ᅡ゚",
"\t\u000b\f ᅡナ £レタ¬タツ¬タテ¬タツ¬タテ¬タト¬タナ¬タニ¬タヌ¬タネ¬タノ¬タハ¬タヒ¬タᄄ¬タᄅ¬タᆵ¬チ゚ ̄タタ",
"ᅡᆳ￘タ￘チ￘ツ￘テ￘ト￘ナ￘ワᅴンᅵマ£ᅠホ¬タヒ¬タフ¬タヘ¬タホ¬タマ¬タᆰ¬タᆱ¬タᆲ¬タᆳ¬タᆴ¬チᅠ¬チᄀ¬チᄁ¬チᆪ¬チᄂ¬チᆭ¬チᄃ¬チᄄ¬チᄅ¬チᆰ¬チᆱ¬チᆲ¬チᆳ¬チᆴ¬チᆵ￯ᄏ﾿￯﾿ᄍ￯﾿ᄎ￯﾿ᄏ￰ムツᄑ￰ロᄇᅠ￰ロᄇᄀ￰ロᄇᄁ￰ロᄇᆪ￰ンナᄈ￰ンナᄡ￰ンナᄉ￰ンナᄊ￰ンナᄋ￰ンナᄌ￰ンナᄍ￰ンナᄎ￳ᅠタチ￳ᅠタᅠ￳ᅠタᄀ￳ᅠタᄁ￳ᅠタᆪ￳ᅠタᄂ￳ᅠタᆬ￳ᅠタᆭ￳ᅠタᄃ￳ᅠタᄄ￳ᅠタᄅ￳ᅠタᆰ￳ᅠタᆱ￳ᅠタᆲ￳ᅠタᆳ￳ᅠタᆴ￳ᅠタᆵ￳ᅠタᄚ￳ᅠタᄆ￳ᅠタᄇ￳ᅠタᄈ￳ᅠタᄡ￳ᅠタᄉ￳ᅠタᄊ￳ᅠタᄋ￳ᅠタᄌ￳ᅠタᄍ￳ᅠタᄎ￳ᅠタᄏ￳ᅠタᄐ￳ᅠタᄑ￳ᅠタᄒ￳ᅠタ﾿￳ᅠチタ￳ᅠチチ￳ᅠチツ￳ᅠチテ￳ᅠチト￳ᅠチナ￳ᅠチニ￳ᅠチヌ￳ᅠチネ￳ᅠチノ￳ᅠチハ￳ᅠチヒ￳ᅠチフ￳ᅠチヘ￳ᅠチホ￳ᅠチマ￳ᅠチミ￳ᅠチム￳ᅠチメ￳ᅠチモ￳ᅠチヤ￳ᅠチユ￳ᅠチヨ￳ᅠチラ￳ᅠチリ￳ᅠチル￳ᅠチレ￳ᅠチロ￳ᅠチワ￳ᅠチン￳ᅠヂ￳ᅠチ゚￳ᅠチᅠ￳ᅠチᄀ￳ᅠチᄁ￳ᅠチᆪ￳ᅠチᄂ￳ᅠチᆬ￳ᅠチᆭ￳ᅠチᄃ￳ᅠチᄄ￳ᅠチᄅ￳ᅠチᆰ￳ᅠチᆱ￳ᅠチᆲ￳ᅠチᆳ￳ᅠチᆴ￳ᅠチᆵ￳ᅠチᄚ￳ᅠチᄆ￳ᅠチᄇ￳ᅠチᄈ￳ᅠチᄡ￳ᅠチᄉ￳ᅠチᄊ￳ᅠチᄋ￳ᅠチᄌ￳ᅠチᄍ￳ᅠチᄎ￳ᅠチᄏ￳ᅠチᄐ￳ᅠチᄑ￳ᅠチᄒ￳ᅠチ﾿",
"￯ᄏ﾿",
"￯﾿ᄒ",
"ᅫᄅ¬ノネᅢᄃ¬ネレ¬ネᆱᅨワᅡᄉ¬ノᄂ¬ノᆬᅢᄋ",
"ᅢᆬᅢ゚¬ネツᅥメᅡ례ル¬ネニᅨレᅡᆲ¬タᆭᅢᆭ",
"ᅤモ¬ネムᅡᄡᅡᆴ¬タᅠᅡᆬᅡ뗴ニᅢ죄タ¬タワ¬タリ",
"ᅡᄀ¬ト깏ᅡᄁ¬ネ゙ᅡ다ᄊ¬タ깕ᅡᄎ¬タモ¬ノᅠ",
"ᅡ졔ロᅢヌ¬ラハᅣ몌ワᅢツᅡᆵᅨリᅡ﾿",
"ᅢナᅢヘᅢホᅢマᅨンᅢモᅢヤ￯ᆪ﾿ᅢメᅢレᅢニ¬リテ",
"ᅤメ¬ダᅡᄡ¬タᄚᅨヌᅢチᅡ뗴ニᅢリ¬ネマ¬タン¬タル",
"`¬チト¬ツᆲ¬タᄍ¬タᄎ￯ᆲチ￯ᆲツ¬タ가ᄚᅡᄋ¬タレ¬タヤᅡᄆ",
"¬ナロ¬ナワ¬ナン¬ナ゙",
"￐チ￐ツ￐テ￐ト￐ナ￐ニ￐ヌ￐ネ￐ノ￐ハ￐ヒ￐フ￐ヘ￐ホ￐マ￐ミ￐ム￐メ￐モ￐ヤ￐ユ￐ヨ￐ラ￐リ￐ル￐レ￐ロ￐ワ￐ン￐゙￐゚￐ᅠ￐ᄀ￐ᄁ￐ᆪ￐ᄂ￐ᆬ￐ᆭ￐ᄃ￐ᄄ￐ᄅ￐ᆰ￐ᆱ￐ᆲ￐ᆳ￐ᆴ￐ᆵ￐ᄚ￐ᄆ￐ᄇ￐ᄈ￐ᄡ￐ᄉ￐ᄊ￐ᄋ￐ᄌ￐ᄍ￐ᄎ￐ᄏ￐ᄐ￐ᄑ￐ᄒ￐﾿￑タ￑チ￑ツ￑テ￑ト￑ナ￑ニ￑ヌ￑ネ￑ノ￑ハ￑ヒ￑フ￑ヘ￑ホ￑マ",
"￙ᅠ￙ᄀ￙ᄁ￙ᆪ￙ᄂ￙ᆬ￙ᆭ￙ᄃ￙ᄄ￙ᄅ",
"¬チᄚ¬チᄡ¬チᄉ",
"¬ツタ¬ツチ¬ツツ",
"¬チᄚ¬チᄡ¬チᄉ¬ツタ¬ツチ¬ツツ",
"¢ᄌヤ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍヌ ¢ᄌヤ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍヌ ¢ᄌヤ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍノ¢ᄍヌ¢ᄍヌ¢ᄍヌ¢ᄍヌ",
"'",
"\"",
"''",
"\"\"",
"'\"'",
"\"''''\"'\"",
"\"'\"'\"''''\"",
"<foo val=¬タワbar¬タン />",
"<foo val=¬タワbar¬タン />",
"<foo val=¬タンbar¬タワ />",
"<foo val=`bar' />",
"￧ヤᄚ¦ᄌᆳ ̄チユ ̄ツモ ̄チᆱ ̄チツ ̄チメ ̄チᆭ¦ᄌヒ ̄チユ ̄チト",
" ̄テム ̄テᄐ ̄テニ ̄ツᆪ ̄テᄐ ̄チᄌ│ᄀフ ̄チヒ ̄チᆰ ̄チト ̄チヒ",
"¥メフ│ᆪᄑ₩ᄐᄁ│ᆰ゙",
"←テᄄ│ミᄑ₩ᅠᄐ",
"↓ツᆲ■レフ↑ᄈᄐ■ユル↓ロミ ↓ヨᄡ■ユル↓ラᄚ↑ᄉᆲ↓ニフ",
"↓ᄚᆭ↓ᄚᄄ→ᆬᄐ ■テタ↑ᄈᅠ ↓リᄄ ■ホᄇ↓ヒワ→ᄃᄄ↑ᄈᄐ ↓ムロ→ヒᄂ→ᆭᆲ →リᅠ→ᄚᄅ↑ᄚチ■ユリ",
"￧ᄂᄒ₩ワテ￧ᄃム¥ᆳᄌ←ルᄁ│ᆰ゙¥ᆳᄌ￧ᅠヤ￧ᄅᄊ₩ノタ",
"↓レᄌ→゙タ→ᄚヤ■ニᅠ→ᆬᄡ",
"￰ᅠワホ￰ᅠワᄆ￰ᅠンᄍ￰ᅠᄆモ￰ᅠᄆᄌ￰ᅠᄇヨ￰ᅠᄈマ",
"￰ミミワ ￰ミミヤ￰ミミヌ￰ミミン￰ミミタ￰ミミᄀ￰ミミヌ￰ミミモ ￰ミミル￰ミミハ￰ミミᄀ￰ミミン￰ミミモ/￰ミミン￰ミミヌ￰ミミラ￰ミミハ￰ミミᄂ￰ミミヤ ￰ミミメ￰ミミヒ￰ミミラ ￰ミミメ￰ミミフ ￰ミミワ ￰ミミᄀ￰ミミタ￰ミミヨ￰ミミヌ￰ミミᄂ￰ミミモ￰ミミン ￰ミミᄆ￰ミムツ ￰ミムト ￰ミミヤ￰ミミヌ￰ミミン￰ミミタ￰ミミᄀ￰ミミヌ￰ミミモ ￰ミミマ￰ミミニ￰ミミナ￰ミミᄂ￰ミミニ￰ミミレ￰ミミハ￰ミミᄀ￰ミミン￰ミミニ￰ミミモ￰ミミニ",
"ᄀᄄ ̄テン ̄チツA←ᄋラᅤメᅢᄅ￯ᄐᄁ←タヘᅢワᅢ゚ᅡᆰᅣナᅢᄆ¦ᄌツ ̄ミタタタ",
"￈ᄎ",
"￈ᄒ",
" ̄テᄑ¢ᄐᄐ¢ᄎネ￙トᅪワ¢ᄎネ¢ᄐᄑ￯ᄒノ  ̄テᄑ¢ᄐᄐ¢ᄎネ￙トᅪワ¢ᄎネ¢ᄐᄑ￯ᄒノ",
"(￯ᄑᄀ¬ラユ ¬ネタ ¬ラユ￯ᄑᄀ)",
"￯ᄑタ￯ᄑᄄ(ᅡᄡ¬ネタ￯ᄑタ¬ネᄅ",
"__￯ᄒロ(,_,*)",
" ̄テᄏ(￯﾿ᆪ¬ネタ￯﾿ᆪ) ̄テᄏ:*:",
"￯ᄒ゚￯ᄑᆬ¬ワ﾿ ̄テᄒ¬ユᄇ(￯ᄑᄀ¬ラユ¬タ﾿¬ラユ￯ᄑᄀ)¬ユᄆ¬ワ﾿￯ᄑᆬ￯ᄒ゚",
", ̄タツ ̄テᄏ:*: ̄テᄏ ̄ツワ¬タル( ¬リᄏ ᅬノ ¬リᄏ ) ̄タツ ̄テᄏ:*: ̄テᄏ ̄ツワ¬タル",
"(¬ユᆵᅡᄚ¬ヨ가ᄚ￯ᄐノ¬ユᆵ￯ᄌᄉ ¬ヤᄏ¬ヤチ¬ヤᄏ)",
"(￯ᄒノ¢ᄇᆬ￧ロハ¢ᄇᆬ￯ᄐノ￯ᄒノ￯ᄏ﾿ ¬ヤᄏ¬ヤチ¬ヤᄏ",
"¬ヤᆲ¬ヤタ¬ヤᆲ ̄テホ( ᅡᄎ _ ᅡᄎ ̄テホ)",
"( ᅪ가ᄚ ᅪワᅧヨ ᅪ가ᄚ)",
"ᅡᆵ\\_( ̄テト)_/ᅡᆵ",
"￰゚リヘ",
"￰゚ムᄅ￰゚マᄑ",
"￰゚ムᄄ¬タヘ￰゚ᆭᄚ ￰゚ムᄄ￰゚マ﾿¬タヘ￰゚ᆭᄚ ￰゚ムᄄ¬タヘ￰゚ᆭᄆ ￰゚ムᄄ￰゚マ﾿¬タヘ￰゚ᆭᄆ ￰゚ᆭᄍ￰゚マ﾿¬タヘ¬ルツ￯ᄌマ",
"￰゚ムᄒ ￰゚ルヌ ￰゚メチ ￰゚ルナ ￰゚ルニ ￰゚ルヒ ￰゚ルホ ￰゚ルヘ",
"￰゚ミᄉ ￰゚ルネ ￰゚ルノ ￰゚ルハ",
"¬ンᄂ￯ᄌマ ￰゚メヤ ￰゚メフ ￰゚メユ ￰゚メ゙ ￰゚メモ ￰゚メラ ￰゚メヨ ￰゚メリ ￰゚メン ￰゚メ゚ ￰゚メワ ￰゚メロ ￰゚メレ ￰゚メル",
"¬ワヒ￰゚マ﾿ ￰゚メᆰ￰゚マ﾿ ￰゚ムミ￰゚マ﾿ ￰゚ルフ￰゚マ﾿ ￰゚ムマ￰゚マ﾿ ￰゚ルマ￰゚マ﾿",
"￰゚ムᄄ¬タヘ￰゚ムᄅ¬タヘ￰゚ムᆭ ￰゚ムᄄ¬タヘ￰゚ムᄅ¬タヘ￰゚ムᄃ¬タヘ￰゚ムᆭ ￰゚ムᄄ¬タヘ￰゚ムᄄ¬タヘ￰゚ムᆭ ￰゚ムᄅ¬タヘ￰゚ムᄅ¬タヘ￰゚ムᄃ ￰゚ムᄄ¬タヘ￰゚ムᆭ ￰゚ムᄄ¬タヘ￰゚ムᄃ¬タヘ￰゚ムᆭ ￰゚ムᄅ¬タヘ￰゚ムᆭ ￰゚ムᄅ¬タヘ￰゚ムᄃ¬タヘ￰゚ムᆭ",
"￰゚レᄒ ￰゚ニメ ￰゚ニモ ￰゚ニユ ￰゚ニヨ ￰゚ニラ ￰゚ニル ￰゚マᄃ",
"0￯ᄌマ¬テᆪ 1￯ᄌマ¬テᆪ 2￯ᄌマ¬テᆪ 3￯ᄌマ¬テᆪ 4￯ᄌマ¬テᆪ 5￯ᄌマ¬テᆪ 6￯ᄌマ¬テᆪ 7￯ᄌマ¬テᆪ 8￯ᄌマ¬テᆪ 9￯ᄌマ¬テᆪ ￰゚ヤ゚",
"￰゚ヌᄎ￰゚ヌᄌ￰゚ヌᄋ￰゚ヌᄎ￰゚ヌᄌ ￰゚ヌᆭ￰゚ヌᆱ￰゚ヌᆭ￰゚ヌᄇ￰゚ヌᄌ",
"￰゚ヌᄎ￰゚ヌᄌ￰゚ヌᄋ￰゚ヌᄎ￰゚ヌᄌ￰゚ヌᆭ￰゚ヌᆱ￰゚ヌᆭ￰゚ヌᄇ",
"￰゚ヌᄎ￰゚ヌᄌ￰゚ヌᄋ￰゚ヌᄎ￰゚ヌᄌ￰゚ヌᆭ",
"￯ᄐム￯ᄐメ￯ᄐモ",
"￙ᄀ￙ᄁ￙ᆪ",
"￘ᆱ￙ナ ￙ニ￙チ￘ᄈ ￘ᄈ￙ツ￘ᄋ￘ᆰ ￙ネ￘ᄄ￘ᄃ￙ト￘ᆰ￘ᆳ￘ᆵ￙ハ￘ᆵ￘フ, ￘ᆲ￘ᄇ￙ハ￘ᄆ￘ᆰ￙ハ ￘ᄄ￘ᄃ￘ᄈ￘ᆰ￘ᆴ￘ᆵ￘ᄃ￙ナ ￘ᆪ￙ニ ￘ᆵ￙ニ￙ネ. ￘ᆬ￘ᄚ ￙ヌ￙ニ￘ᄃ￘゚ ￘ᄃ￙ト￘ᄈ￘ᆰ￘ᄃ￘ᄆ ￙ネ￘ᆰ￙ニ￘ᄉ￙ハ￘ᄄ ￙テ￘ᄃ￙ニ. ￘ᆪ￙ヌ￙ム￙ト ￘ᄃ￙ハ￘ᄋ￘ᄃ￙ト￙ハ￘ᄃ￘フ ￘ᄄ￘ᄆ￙ハ￘ᄋ￘ᄃ￙ニ￙ハ￘ᄃ-￙チ￘ᄆ￙ニ￘ᄈ￘ᄃ ￙ツ￘ᆵ ￘ᆪ￘ᆴ￘ᄚ. ￘ᄈ￙ト￙ハ￙ナ￘ᄃ￙ニ￘フ ￘ᆬ￘ᆰ￙チ￘ᄃ￙ツ￙ハ￘ᄅ ￘ᄄ￙ハ￙ニ ￙ナ￘ᄃ, ￙ハ￘ᄚ￙テ￘ᄆ ￘ᄃ￙ト￘ᆳ￘ᆵ￙ネ￘ᆵ ￘ᆪ￙ハ ￘ᄄ￘ᄍ￘ᆵ, ￙ナ￘ᄍ￘ᄃ￙ナ￙ト￘ᄅ ￘ᄄ￙ネ￙ト￙ニ￘ᆵ￘ᄃ￘フ ￘ᄃ￙ト￘ᆬ￘ᄋ￙ト￘ᄃ￙ツ ￘ᄍ￙ト ￘ᆬ￙ハ￙ネ.",
"ᅲムᅱᄚᅱ튜뛰슈ミᅲ뤼ᄡᅲチᅲルᅲᆰ, ᅲムᅱ쥐튜뛰쥬ミ ᅲミᅱ뮤ワᅱ쮸ヤᅱᄡᅲルᅲン, ᅲミᅱ슑 ᅲヤᅱ유뤼쥐튜チᅲ゙ᅱ유ルᅱᄡᅲン, ᅲユᅱᄚᅲミᅱ슑 ᅲヤᅱ쥬ミᅱ쥬뛰쓙",
"ᅲヤᅱ쥬ルᅱᄚᅲᆰᅱ쥬ヤtest￘ᄃ￙ト￘ᄉ￙チ￘ᆳ￘ᄃ￘ᆰ ￘ᄃ￙ト￘ᆰ￙ム￘ᆳ￙ネ￙ト",
"￯ᄋᄑ",
"￯ᄋᄎ",
"￙ナ￙マ￙ニ￙ホ￘ᄃ￙ツ￙ホ￘ᄡ￙ホ￘ᄅ￙マ ￘ᄈ￙マ￘ᄄ￙マ￙ト￙ミ ￘ᄃ￙ミ￘ᄈ￙メ￘ᆰ￙ミ￘ᆴ￙メ￘ᆵ￙ホ￘ᄃ￙ナ￙ミ ￘ᄃ￙ト￙ト￙マ￙ム￘ᄎ￙ホ￘ᄅ￙ミ ￙チ￙ミ￙ハ ￘ᄃ￙ト￙ニ￙マ￙ム￘ᄌ￙マ￙ナ￙ミ ￘ᄃ￙ト￙メ￙ツ￙ホ￘ᄃ￘ᆭ￙ミ￙ナ￙ホ￘ᄅ￙ミ ￙ネ￙ホ￙チ￙ミ￙ハ￙ナ ￙ハ￙ホ￘ᆴ￙マ￘ᄉ￙ホ￙ム ￘ᄃ￙ト￘ᆰ￙ホ￙ム￘ᄋ￙メ￘ᄄ￙ミ￙ハ￙ツ￙ホ￘ᄃ￘ᆰ￙マ ￘ᄃ￙ト￙メ￘ᆳ￘ᄃ￘ᄈ￙マ￙ネ￘ᄄ￙ミ￙ハ￙ホ￙ム￘ᄅ￙マ￘フ ",
"£レロ£レト£レモ£レミ£レヒ£レメ£レト£レタ£レム£レト£レツ£レム£レマ£レナ£レワ¬タᆰ¬タᆰ¬タᆰ",
"¬タᆰ¬タᆰ£レロ£レタ£レタ£レタ£レタ£レタ£レタ£レタ£レタ£レタ£レタ£レタ£レタ£レタ£レタ£レタ£レタ£レタ£レワ¬タᆰ",
"¬タᆰ¬タᆰtest¬タᆰ",
"¬タᆱtest¬タᆱ",
"¬タᄅtest¬タᄅ",
"test¬チtest¬タᆱ",
"¬チᆭtest¬チᄃ",
"£ᄍᄚᅩ초초ユoᅪ゙ ᅩᄋiᅩ볿ᅪヌᅩᆰᅪルnᅩンᅩラᅪユvᅩ゚ᅩワᅩリᅩᆭᅪ゚oᅩ쏘ルᅩᄚᅩkᅢ똬レᅩᆴᅩ촑ᅩ쪼모ᄂ ᅩヨtᅩンᅪユᅩ뽃ᅩ콝ᅪ゙hᅩ톼モᅩ볺ᅩ뽀リᅩᄇeᅪヌᅩᆪᅩᄚᅩᆭᅩᆲᅪホ ᅩ꼬토코모リhᅪレᅪホᅪルᅩワᅩᆪᅩ봐ナiᅩᆭᅩ볷ᅩᄚᅩᄂvᅩ콰ヘeᅩ촔ᅩ뽉ᅩᄚ-mᅩᄁiᅪナnᅩヨᅩ초゙ᅩ봂ᅩᄚdᅩ소토゚ᅪルᅩ로토リᅩᄈ ᅩ゙ᅩᆬᅩ모뽌rᅩロᅩラᅩリeᅪルpᅪrᅩ토゙ᅩ콠ᅩラeᅩ초ᅩᆪᅪ゚sᅩリᅪヌᅩ뽜ヘᅩンᅪノeᅪノᅩᆬᅩᆵᅩ゙ᅩ봐レᅩᆲᅪワᅦ쫇ᅪホᅪホᅩ゚ᅩヨᅪヌᅩᄂtᅪヘᅩᆲᅩ놔モᅩ톬ᅪリᅪナiᅩᆰᅩᄆnᅪgᅩᄡᅪノ ᅪマᅪノᅪナcᅩᆲᅩ゚hᅪᄀaᅩᆱᅩ콢ᅪリoᅩᆱᅩ゚ᅩヨᅪヘᅩルᅩンᅪノsᅩラᅩᆭᅩᄇ.ᅩ또쫘ネᅩᆪ",
"ᅩ과モᅩ゙ᅪナIᅩラᅩリᅩᆭᅪンnᅪヌᅪヌᅪルvᅩᆴᅩᆱokᅩ볾ᅩルᅪネiᅩヨᅪルᅩᆳᅩ쪼ᅩ゙nᅩ고콡ᅩᆪᅩᄎgᅩ봐ネᅪルᅩᆳᅪルᅩᆲᅪホ ᅩᄚtᅪヤᅩᆭhᅩ゙ᅩᄇeᅩ꼬ᄂ ᅪヘᅩᆲᅩ봐ヨfᅩᄡᅩリᅪユᅩᆪᅢ똬ヨ£ᄎ쫁ᅩᄅlᅪヨᅪヤᅪレiᅪモᅪレᅩᆭᅪnᅪヨᅪヘᅩラᅪモᅩ뽍gᅪヘ ᅩᄄoᅪレᅩᆰᅪᄀfᅩリᅩᆪᅩᆲ ᅩヨᅩリᅪヨᅩ゚ᅪルᅩᆴcᅭノᅪヤᅩᆱᅪヨᅪモᅪヌᅪヨᅪナhᅩ소녻ᅪレᅪヤᅢ고ラᅩ톼ユᅪナoᅩ톣ᅩᆬsᅩ뫄ネᅩ초ヨᅩᆭᅩ콰ᄁ.ᅩロᅩヨᅩ゙ᅩᅠᅩᆱᅩᄚ",
"ᅩラᅩ촤ヨᅩ쫊ᅪモ£ᄍᆴᅩ놔ヘᅩᆬᅪヌᅪネhᅩ보チeᅪマᅪモᅩ토ラᅩルᅩ톣ᅪヤ ᅪヌᅩワᅩ모ᅪモᅪヘᅪナNᅪユᅪeᅩラᅩᄆzᅩリᅩンᅩワᅩ촤ルpᅩ노초쫘ヘᅩᆵᅪレeᅩᅩ코ᅪワrᅩ또놔ヘᅩ초ヨᅪヤᅩヨᅩヨdᅩᅩ゚ᅩᆳᅩᆲᅩンᅪ゚iᅩᆭᅪヨᅩ롸モᅪヤᅩᄂaᅩᅩラᅩᆲᅪノᅩルnᅪレᅪワ ᅩ코゙ᅩᄚᅪレᅪナhᅩ솨ノiᅩ뽀゙vᅩ꽈ヌ£ᄌルᅪホᅪ゚-ᅭノᅩᆳᅩ로톼ヤmᅩ놄ᅩᆱiᅪユᅪヌᅩンᅩᆭnᅩラᅪル£ᄌヘᅩ゚ ᅩᆵᅩ봐ユᅪ゙ᅦᆱᅩ゚ᅩᆵᅩᄚᅩ봐ルᅩ코ンf ᅩᆰᅩᄚᅩᄚᅩラᅩヨᅩᆳᅩリᅪリcᅩᆭᅪヘᅩ보゙ᅪヘᅩ로ル£ᄌᆬᅪレaᅩᆴᅪホᅩ゚ᅩルᅪワᅥ고로쫘ホsᅩᄂ.ᅩンᅩン ᅭノZᅩ고ヨᅩワᅪヨᅩᄚᅩᆪᅪノᅩワaᅪヨᅩᄚᅪルᅩᆲᅪᄀlᅩ볾ᅩ뽜ヘᅩᄅgᅩ고゚ᅩ토뫄レᅩ゙ᅩᆲᅪナoᅩラᅪワ.ᅩ゚",
"ᅩᆭHᅩᆲᅩ노ラᅩ놔ンeᅪワ ᅩワᅩᆬᅩンᅩ콰ヘᅩ゚ᅩチwᅩユhᅩヨᅩᆵᅪモoᅩンᅪルᅩヨᅪホᅩ몵 ᅭノᅩ초ルᅩ゙ᅩ゚ᅪネWᅩ오톬aᅩ촑ᅪヘᅣᆵᅪネᅪユᅩᆳᅪルᅩᆵᅩワtᅩ쏘톭sᅩリᅪルᅪヨᅩユ ᅩᅩᆱᅩBᅩ콰ヘᅪルᅪノᅩ뽜ナeᅩᄉhᅩ솗ᅪヌᅩᆱᅪルiᅩ쫘モᅩ뽀뽍ᅪホᅩᆱᅩユnᅪ゚dᅩᄡᅩᆰᅩワᅩヨ ᅩᄚᅪノᅩ롸ヌᅪルᅩ봐゙ᅪナTᅪヨᅩ톼モᅩᆰᅪᄁhᅪマᅪモᅩᆴᅩᄏeᅩᆲᅩンᅩ゚ᅪナ ᅩ노쪼ンWᅪルᅩ゙ᅩンᅪヤᅪヌᅪンᅪナaᅪマᅪモᅪヤᅩ쪼톣lᅩᄡᅪヤᅩᄚᅩ노゚ᅪヤ£ᄌ폶.ᅪユ",
"Zᅩᆴᅩ゙ᅩᅪルᅪヤᅪナ£ᄌタᅩラᅩ゙ᅪネᅩ코ラ£ᄌ쏴ルᅪホᅩᆵᅩ쪼゙ᅪモGᅩᄏOᅩᆳᅩラᅩᆴ",
"ᅨル￉ミnb£ᄡノl￉ミ ￉ミuᅥテ￉ミ￉ᆵ ᅦン￉ᄍolop ᅧヌᅦン ᅦン￉ᄍoq￉ミl ᅧヌn ᅧヌunp£ᄡノp£ᄡノ￉ヤu£ᄡノ ￉ᄍod￉ᆵᅦンᅧヌ po￉ᆵsn£ᄡノᅦン op pᅦンs 'ᅧヌ£ᄡノlᅦン ᅥテu£ᄡノ￉ヤs£ᄡノd£ᄡノp￉ミ ￉ᄍnᅧヌᅦンᅧヌ￉ヤᅦンsuo￉ヤ 'ᅧヌᅦン￉ᆵ￉ミ ᅧヌ£ᄡノs ￉ᄍolop ￉ᆵnsd£ᄡノ ￉ᆵᅦン￉ᄍoᅨᆬ",
"00ᅨルᅥヨ$-",
"￯ᄐᄡ￯ᄑネ￯ᄑナ ￯ᄑム￯ᄑユ￯ᄑノ￯ᄑテ￯ᄑヒ ￯ᄑツ￯ᄑメ￯ᄑマ￯ᄑラ￯ᄑホ ￯ᄑニ￯ᄑマ￯ᄑリ ￯ᄑハ￯ᄑユ￯ᄑヘ￯ᄑミ￯ᄑモ ￯ᄑマ￯ᄑヨ￯ᄑナ￯ᄑメ ￯ᄑヤ￯ᄑネ￯ᄑナ ￯ᄑフ￯ᄑチ￯ᄑレ￯ᄑル ￯ᄑト￯ᄑマ￯ᄑヌ",
"￰ンミモ￰ンミᄀ￰ンミ゙ ￰ンミᆰ￰ンミᆴ￰ンミᄁ￰ンミワ￰ンミᄂ ￰ンミロ￰ンミᆱ￰ンミᄄ￰ンミᄚ￰ンミᄃ ￰ンミ゚￰ンミᄄ￰ンミᄆ ￰ンミᆪ￰ンミᆴ￰ンミᆭ￰ンミᄅ￰ンミᆲ ￰ンミᄄ￰ンミᆵ￰ンミ゙￰ンミᆱ ￰ンミᆳ￰ンミᄀ￰ンミ゙ ￰ンミᆬ￰ンミレ￰ンミᄈ￰ンミᄇ ￰ンミン￰ンミᄄ￰ンミᅠ",
"￰ンユ﾿￰ンヨヘ￰ンヨハ ￰ンヨヨ￰ンヨレ￰ンヨホ￰ンヨネ￰ンヨミ ￰ンヨヌ￰ンヨラ￰ンヨヤ￰ンヨワ￰ンヨモ ￰ンヨヒ￰ンヨヤ￰ンヨン ￰ンヨマ￰ンヨレ￰ンヨメ￰ンヨユ￰ンヨリ ￰ンヨヤ￰ンヨロ￰ンヨハ￰ンヨラ ￰ンヨル￰ンヨヘ￰ンヨハ ￰ンヨム￰ンヨニ￰ンヨ゚￰ンヨ゙ ￰ンヨノ￰ンヨヤ￰ンヨフ",
"￰ンムᄏ￰ンメノ￰ンメニ ￰ンメメ￰ンメヨ￰ンメハ￰ンメト￰ンメフ ￰ンメテ￰ンメモ￰ンメミ￰ンメリ￰ンメマ ￰ンメヌ￰ンメミ￰ンメル ￰ンメヒ￰ンメヨ￰ンメホ￰ンメム￰ンメヤ ￰ンメミ￰ンメラ￰ンメニ￰ンメモ ￰ンメユ￰ンメノ￰ンメニ ￰ンメヘ￰ンメツ￰ンメロ￰ンメレ ￰ンメナ￰ンメミ￰ンメネ",
"￰ンモᆪ￰ンモᄆ￰ンモᆴ ￰ンモᄎ￰ンモᄒ￰ンモᄇ￰ンモᆲ￰ンモᄡ ￰ンモᆱ￰ンモᄏ￰ンモᄌ￰ンヤタ￰ンモᄋ ￰ンモᆵ￰ンモᄌ￰ンヤチ ￰ンモᄈ￰ンモᄒ￰ンモᄊ￰ンモᄍ￰ンモᄐ ￰ンモᄌ￰ンモ﾿￰ンモᆴ￰ンモᄏ ￰ンモᄑ￰ンモᄆ￰ンモᆴ ￰ンモᄉ￰ンモᆰ￰ンヤテ￰ンヤツ ￰ンモᆳ￰ンモᄌ￰ンモᄚ",
"￰ンユヒ￰ンユル￰ンユヨ ￰ンユᄁ￰ンユᆭ￰ンユレ￰ンユヤ￰ンユワ ￰ンユモ￰ンユᆪ￰ンユᅠ￰ンユᄄ￰ンユ゚ ￰ンユラ￰ンユᅠ￰ンユᄅ ￰ンユロ￰ンユᆭ￰ンユ゙￰ンユᄀ￰ンユᄂ ￰ンユᅠ￰ンユᄃ￰ンユヨ￰ンユᆪ ￰ンユᆬ￰ンユル￰ンユヨ ￰ンユン￰ンユメ￰ンユᆱ￰ンユᆰ ￰ンユユ￰ンユᅠ￰ンユリ",
"￰ンレテ￰ンレム￰ンレホ ￰ンレレ￰ンレ゙￰ンレメ￰ンレフ￰ンレヤ ￰ンレヒ￰ンレロ￰ンレリ￰ンレᅠ￰ンレラ ￰ンレマ￰ンレリ￰ンレᄀ ￰ンレモ￰ンレ゙￰ンレヨ￰ンレル￰ンレワ ￰ンレリ￰ンレ゚￰ンレホ￰ンレロ ￰ンレン￰ンレム￰ンレホ ￰ンレユ￰ンレハ￰ンレᆪ￰ンレᄁ ￰ンレヘ￰ンレリ￰ンレミ",
"¬メᆵ¬メᆪ¬メᅠ ¬メᆲ¬メᄚ¬メᄂ¬メ゙¬メᆭ ¬メン¬メᆳ¬メᆰ¬メᄇ¬メᄅ ¬メᄀ¬メᆰ¬メᄈ ¬メᆬ¬メᄚ¬メᄄ¬メᆱ¬メᆴ ¬メᆰ¬メᄆ¬メᅠ¬メᆳ ¬メᆵ¬メᆪ¬メᅠ ¬メᄃ¬メワ¬メᄉ¬メᄡ ¬メ゚¬メᆰ¬メᄁ",
"<script>alert(123)</script>",
"&lt;script&gt;alert(&#39;123&#39;);&lt;/script&gt;",
"<img src=x onerror=alert(123) />",
"<svg><script>123<1>alert(123)</script>",
"\"><script>alert(123)</script>",
"'><script>alert(123)</script>",
"><script>alert(123)</script>",
"</script><script>alert(123)</script>",
"< / script >< script >alert(123)< / script >",
" onfocus=JaVaSCript:alert(123) autofocus",
"\" onfocus=JaVaSCript:alert(123) autofocus",
"' onfocus=JaVaSCript:alert(123) autofocus",
"￯ᄐワscript￯ᄐ゙alert(123)￯ᄐワ/script￯ᄐ゙",
"<sc<script>ript>alert(123)</sc</script>ript>",
"--><script>alert(123)</script>",
"\";alert(123);t=\"",
"';alert(123);t='",
"JavaSCript:alert(123)",
";alert(123);",
"src=JaVaSCript:prompt(132)",
"\"><script>alert(123);</script x=\"",
"'><script>alert(123);</script x='",
"><script>alert(123);</script x=",
"\" autofocus onkeyup=\"javascript:alert(123)",
"' autofocus onkeyup='javascript:alert(123)",
"<script\\x20type=\"text/javascript\">javascript:alert(1);</script>",
"<script\\x3Etype=\"text/javascript\">javascript:alert(1);</script>",
"<script\\x0Dtype=\"text/javascript\">javascript:alert(1);</script>",
"<script\\x09type=\"text/javascript\">javascript:alert(1);</script>",
"<script\\x0Ctype=\"text/javascript\">javascript:alert(1);</script>",
"<script\\x2Ftype=\"text/javascript\">javascript:alert(1);</script>",
"<script\\x0Atype=\"text/javascript\">javascript:alert(1);</script>",
"'`\"><\\x3Cscript>javascript:alert(1)</script>",
"'`\"><\\x00script>javascript:alert(1)</script>",
"ABC<div style=\"x\\x3Aexpression(javascript:alert(1)\">DEF",
"ABC<div style=\"x:expression\\x5C(javascript:alert(1)\">DEF",
"ABC<div style=\"x:expression\\x00(javascript:alert(1)\">DEF",
"ABC<div style=\"x:exp\\x00ression(javascript:alert(1)\">DEF",
"ABC<div style=\"x:exp\\x5Cression(javascript:alert(1)\">DEF",
"ABC<div style=\"x:\\x0Aexpression(javascript:alert(1)\">DEF",
"ABC<div style=\"x:\\x09expression(javascript:alert(1)\">DEF",
"ABC<div style=\"x:\\xE3\\x80\\x80expression(javascript:alert(1)\">DEF",
"ABC<div style=\"x:\\xE2\\x80\\x84expression(javascript:alert(1)\">DEF",
"ABC<div style=\"x:\\xC2\\xA0expression(javascript:alert(1)\">DEF",
"ABC<div style=\"x:\\xE2\\x80\\x80expression(javascript:alert(1)\">DEF",
"ABC<div style=\"x:\\xE2\\x80\\x8Aexpression(javascript:alert(1)\">DEF",
"ABC<div style=\"x:\\x0Dexpression(javascript:alert(1)\">DEF",
"ABC<div style=\"x:\\x0Cexpression(javascript:alert(1)\">DEF",
"ABC<div style=\"x:\\xE2\\x80\\x87expression(javascript:alert(1)\">DEF",
"ABC<div style=\"x:\\xEF\\xBB\\xBFexpression(javascript:alert(1)\">DEF",
"ABC<div style=\"x:\\x20expression(javascript:alert(1)\">DEF",
"ABC<div style=\"x:\\xE2\\x80\\x88expression(javascript:alert(1)\">DEF",
"ABC<div style=\"x:\\x00expression(javascript:alert(1)\">DEF",
"ABC<div style=\"x:\\xE2\\x80\\x8Bexpression(javascript:alert(1)\">DEF",
"ABC<div style=\"x:\\xE2\\x80\\x86expression(javascript:alert(1)\">DEF",
"ABC<div style=\"x:\\xE2\\x80\\x85expression(javascript:alert(1)\">DEF",
"ABC<div style=\"x:\\xE2\\x80\\x82expression(javascript:alert(1)\">DEF",
"ABC<div style=\"x:\\x0Bexpression(javascript:alert(1)\">DEF",
"ABC<div style=\"x:\\xE2\\x80\\x81expression(javascript:alert(1)\">DEF",
"ABC<div style=\"x:\\xE2\\x80\\x83expression(javascript:alert(1)\">DEF",
"ABC<div style=\"x:\\xE2\\x80\\x89expression(javascript:alert(1)\">DEF",
"<a href=\"\\x0Bjavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\x0Fjavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\xC2\\xA0javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\x05javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\xE1\\xA0\\x8Ejavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\x18javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\x11javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\xE2\\x80\\x88javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\xE2\\x80\\x89javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\xE2\\x80\\x80javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\x17javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\x03javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\x0Ejavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\x1Ajavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\x00javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\x10javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\xE2\\x80\\x82javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\x20javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\x13javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\x09javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\xE2\\x80\\x8Ajavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\x14javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\x19javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\xE2\\x80\\xAFjavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\x1Fjavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\xE2\\x80\\x81javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\x1Djavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\xE2\\x80\\x87javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\x07javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\xE1\\x9A\\x80javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\xE2\\x80\\x83javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\x04javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\x01javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\x08javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\xE2\\x80\\x84javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\xE2\\x80\\x86javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\xE3\\x80\\x80javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\x12javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\x0Djavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\x0Ajavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\x0Cjavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\x15javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\xE2\\x80\\xA8javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\x16javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\x02javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\x1Bjavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\x06javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\xE2\\x80\\xA9javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\xE2\\x80\\x85javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\x1Ejavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\xE2\\x81\\x9Fjavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"\\x1Cjavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"javascript\\x00:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"javascript\\x3A:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"javascript\\x09:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"javascript\\x0D:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"<a href=\"javascript\\x0A:javascript:alert(1)\" id=\"fuzzelement1\">test</a>",
"`\"'><img src=xxx:x \\x0Aonerror=javascript:alert(1)>",
"`\"'><img src=xxx:x \\x22onerror=javascript:alert(1)>",
"`\"'><img src=xxx:x \\x0Bonerror=javascript:alert(1)>",
"`\"'><img src=xxx:x \\x0Donerror=javascript:alert(1)>",
"`\"'><img src=xxx:x \\x2Fonerror=javascript:alert(1)>",
"`\"'><img src=xxx:x \\x09onerror=javascript:alert(1)>",
"`\"'><img src=xxx:x \\x0Conerror=javascript:alert(1)>",
"`\"'><img src=xxx:x \\x00onerror=javascript:alert(1)>",
"`\"'><img src=xxx:x \\x27onerror=javascript:alert(1)>",
"`\"'><img src=xxx:x \\x20onerror=javascript:alert(1)>",
"\"`'><script>\\x3Bjavascript:alert(1)</script>",
"\"`'><script>\\x0Djavascript:alert(1)</script>",
"\"`'><script>\\xEF\\xBB\\xBFjavascript:alert(1)</script>",
"\"`'><script>\\xE2\\x80\\x81javascript:alert(1)</script>",
"\"`'><script>\\xE2\\x80\\x84javascript:alert(1)</script>",
"\"`'><script>\\xE3\\x80\\x80javascript:alert(1)</script>",
"\"`'><script>\\x09javascript:alert(1)</script>",
"\"`'><script>\\xE2\\x80\\x89javascript:alert(1)</script>",
"\"`'><script>\\xE2\\x80\\x85javascript:alert(1)</script>",
"\"`'><script>\\xE2\\x80\\x88javascript:alert(1)</script>",
"\"`'><script>\\x00javascript:alert(1)</script>",
"\"`'><script>\\xE2\\x80\\xA8javascript:alert(1)</script>",
"\"`'><script>\\xE2\\x80\\x8Ajavascript:alert(1)</script>",
"\"`'><script>\\xE1\\x9A\\x80javascript:alert(1)</script>",
"\"`'><script>\\x0Cjavascript:alert(1)</script>",
"\"`'><script>\\x2Bjavascript:alert(1)</script>",
"\"`'><script>\\xF0\\x90\\x96\\x9Ajavascript:alert(1)</script>",
"\"`'><script>-javascript:alert(1)</script>",
"\"`'><script>\\x0Ajavascript:alert(1)</script>",
"\"`'><script>\\xE2\\x80\\xAFjavascript:alert(1)</script>",
"\"`'><script>\\x7Ejavascript:alert(1)</script>",
"\"`'><script>\\xE2\\x80\\x87javascript:alert(1)</script>",
"\"`'><script>\\xE2\\x81\\x9Fjavascript:alert(1)</script>",
"\"`'><script>\\xE2\\x80\\xA9javascript:alert(1)</script>",
"\"`'><script>\\xC2\\x85javascript:alert(1)</script>",
"\"`'><script>\\xEF\\xBF\\xAEjavascript:alert(1)</script>",
"\"`'><script>\\xE2\\x80\\x83javascript:alert(1)</script>",
"\"`'><script>\\xE2\\x80\\x8Bjavascript:alert(1)</script>",
"\"`'><script>\\xEF\\xBF\\xBEjavascript:alert(1)</script>",
"\"`'><script>\\xE2\\x80\\x80javascript:alert(1)</script>",
"\"`'><script>\\x21javascript:alert(1)</script>",
"\"`'><script>\\xE2\\x80\\x82javascript:alert(1)</script>",
"\"`'><script>\\xE2\\x80\\x86javascript:alert(1)</script>",
"\"`'><script>\\xE1\\xA0\\x8Ejavascript:alert(1)</script>",
"\"`'><script>\\x0Bjavascript:alert(1)</script>",
"\"`'><script>\\x20javascript:alert(1)</script>",
"\"`'><script>\\xC2\\xA0javascript:alert(1)</script>",
"<img \\x00src=x onerror=\"alert(1)\">",
"<img \\x47src=x onerror=\"javascript:alert(1)\">",
"<img \\x11src=x onerror=\"javascript:alert(1)\">",
"<img \\x12src=x onerror=\"javascript:alert(1)\">",
"<img\\x47src=x onerror=\"javascript:alert(1)\">",
"<img\\x10src=x onerror=\"javascript:alert(1)\">",
"<img\\x13src=x onerror=\"javascript:alert(1)\">",
"<img\\x32src=x onerror=\"javascript:alert(1)\">",
"<img\\x47src=x onerror=\"javascript:alert(1)\">",
"<img\\x11src=x onerror=\"javascript:alert(1)\">",
"<img \\x47src=x onerror=\"javascript:alert(1)\">",
"<img \\x34src=x onerror=\"javascript:alert(1)\">",
"<img \\x39src=x onerror=\"javascript:alert(1)\">",
"<img \\x00src=x onerror=\"javascript:alert(1)\">",
"<img src\\x09=x onerror=\"javascript:alert(1)\">",
"<img src\\x10=x onerror=\"javascript:alert(1)\">",
"<img src\\x13=x onerror=\"javascript:alert(1)\">",
"<img src\\x32=x onerror=\"javascript:alert(1)\">",
"<img src\\x12=x onerror=\"javascript:alert(1)\">",
"<img src\\x11=x onerror=\"javascript:alert(1)\">",
"<img src\\x00=x onerror=\"javascript:alert(1)\">",
"<img src\\x47=x onerror=\"javascript:alert(1)\">",
"<img src=x\\x09onerror=\"javascript:alert(1)\">",
"<img src=x\\x10onerror=\"javascript:alert(1)\">",
"<img src=x\\x11onerror=\"javascript:alert(1)\">",
"<img src=x\\x12onerror=\"javascript:alert(1)\">",
"<img src=x\\x13onerror=\"javascript:alert(1)\">",
"<img[a][b][c]src[d]=x[e]onerror=[f]\"alert(1)\">",
"<img src=x onerror=\\x09\"javascript:alert(1)\">",
"<img src=x onerror=\\x10\"javascript:alert(1)\">",
"<img src=x onerror=\\x11\"javascript:alert(1)\">",
"<img src=x onerror=\\x12\"javascript:alert(1)\">",
"<img src=x onerror=\\x32\"javascript:alert(1)\">",
"<img src=x onerror=\\x00\"javascript:alert(1)\">",
"<a href=java&#1&#2&#3&#4&#5&#6&#7&#8&#11&#12script:javascript:alert(1)>XXX</a>",
"<img src=\"x` `<script>javascript:alert(1)</script>\"` `>",
"<img src onerror /\" '\"= alt=javascript:alert(1)//\">",
"<title onpropertychange=javascript:alert(1)></title><title title=>",
"<a href=http://foo.bar/#x=`y></a><img alt=\"`><img src=x:x onerror=javascript:alert(1)></a>\">",
"<!--[if]><script>javascript:alert(1)</script -->",
"<!--[if<img src=x onerror=javascript:alert(1)//]> -->",
"<script src=\"/\\%(jscript)s\"></script>",
"<script src=\"\\\\%(jscript)s\"></script>",
"<IMG \"\"\"><SCRIPT>alert(\"XSS\")</SCRIPT>\">",
"<IMG SRC=javascript:alert(String.fromCharCode(88,83,83))>",
"<IMG SRC=# onmouseover=\"alert('xxs')\">",
"<IMG SRC= onmouseover=\"alert('xxs')\">",
"<IMG onmouseover=\"alert('xxs')\">",
"<IMG SRC=&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#39;&#88;&#83;&#83;&#39;&#41;>",
"<IMG SRC=&#0000106&#0000097&#0000118&#0000097&#0000115&#0000099&#0000114&#0000105&#0000112&#0000116&#0000058&#0000097&#0000108&#0000101&#0000114&#0000116&#0000040&#0000039&#0000088&#0000083&#0000083&#0000039&#0000041>",
"<IMG SRC=&#x6A&#x61&#x76&#x61&#x73&#x63&#x72&#x69&#x70&#x74&#x3A&#x61&#x6C&#x65&#x72&#x74&#x28&#x27&#x58&#x53&#x53&#x27&#x29>",
"<IMG SRC=\"jav ascript:alert('XSS');\">",
"<IMG SRC=\"jav&#x09;ascript:alert('XSS');\">",
"<IMG SRC=\"jav&#x0A;ascript:alert('XSS');\">",
"<IMG SRC=\"jav&#x0D;ascript:alert('XSS');\">",
"perl -e 'print \"<IMG SRC=java\\0script:alert(\\\"XSS\\\")>\";' > out",
"<IMG SRC=\" &#14; javascript:alert('XSS');\">",
"<SCRIPT/XSS SRC=\"http://ha.ckers.org/xss.js\"></SCRIPT>",
"<BODY onload!#$%&()*~+-_.,:;?@[/|\\]^`=alert(\"XSS\")>",
"<SCRIPT/SRC=\"http://ha.ckers.org/xss.js\"></SCRIPT>",
"<<SCRIPT>alert(\"XSS\");//<</SCRIPT>",
"<SCRIPT SRC=http://ha.ckers.org/xss.js?< B >",
"<SCRIPT SRC=//ha.ckers.org/.j>",
"<IMG SRC=\"javascript:alert('XSS')\"",
"<iframe src=http://ha.ckers.org/scriptlet.html <",
"\\\";alert('XSS');//",
"<u oncopy=alert()> Copy me</u>",
"<i onwheel=alert(1)> Scroll over me </i>",
"<plaintext>",
"http://a/%%30%30",
"</textarea><script>alert(123)</script>",
"1;DROP TABLE users",
"1'; DROP TABLE users-- 1",
"' OR 1=1 -- 1",
"' OR '1'='1",
"'; EXEC sp_MSForEachTable 'DROP TABLE ?'; --",
" ",
"%",
"_",
"-",
"--",
"--version",
"--help",
"$USER",
"/dev/null; touch /tmp/blns.fail ; echo",
"`touch /tmp/blns.fail`",
"$(touch /tmp/blns.fail)",
"@{[system \"touch /tmp/blns.fail\"]}",
"eval(\"puts 'hello world'\")",
"System(\"ls -al /\")",
"`ls -al /`",
"Kernel.exec(\"ls -al /\")",
"Kernel.exit(1)",
"%x('ls -al /')",
"<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><!DOCTYPE foo [ <!ELEMENT foo ANY ><!ENTITY xxe SYSTEM \"file:///etc/passwd\" >]><foo>&xxe;</foo>",
"$HOME",
"$ENV{'HOME'}",
"%d",
"%s%s%s%s%s",
"{0}",
"%*.*s",
"%@",
"%n",
"File:///",
"../../../../../../../../../../../etc/passwd%00",
"../../../../../../../../../../../etc/hosts",
"() { 0; }; touch /tmp/blns.shellshock1.fail;",
"() { _; } >_[$($())] { touch /tmp/blns.shellshock2.fail; }",
"<<< %s(un='%s') = %u",
"+++ATH0",
"CON",
"PRN",
"AUX",
"CLOCK$",
"NUL",
"A:",
"ZZ:",
"COM1",
"LPT1",
"LPT2",
"LPT3",
"COM2",
"COM3",
"COM4",
"DCC SEND STARTKEYLOGGER 0 0 0",
"Scunthorpe General Hospital",
"Penistone Community Church",
"Lightwater Country Park",
"Jimmy Clitheroe",
"Horniman Museum",
"shitake mushrooms",
"RomansInSussex.co.uk",
"http://www.cum.qc.ca/",
"Craig Cockburn, Software Specialist",
"Linda Callahan",
"Dr. Herman I. Libshitz",
"magna cum laude",
"Super Bowl XXX",
"medieval erection of parapets",
"evaluate",
"mocha",
"expression",
"Arsenal canal",
"classic",
"Tyson Gay",
"Dick Van Dyke",
"basement",
"If you're reading this, you've been in a coma for almost 20 years now. We're trying a new technique. We don't know where this message will end up in your dream, but we hope it works. Please wake up, we miss you.",
"Roses are \u001b[0;31mred\u001b[0m, violets are \u001b[0;34mblue. Hope you enjoy terminal hue",
"But now...\u001b[20Cfor my greatest trick...\u001b[8m",
"The quic\b\b\b\b\b\bk brown fo\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007x... [Beeeep]",
"Power￙ト￙マ￙ト￙マ￘ᄉ￙ム￘ᄄ￙マ￙ト￙マ￙ト￘ᄉ￙ム￘ᄄ￙マ￘ᄆ￘ᄆ￙ヒ ¢ᆬᆪ ¢ᆬᆪh ¢ᆬᆪ ¢ᆬᆪ¥ニラ",
"゚マᄈ0゚フネ￯ᄌマ",
"¢ᄚワ¢ᄆヘ¢ᄚ゙¬タフ¢ᄚᄒ",
"ᅳᆵᅳニ￙흐リ",
"{% print 'x' * 64 * 1024**3 %}",
"{{ \"\".__class__.__mro__[2].__subclasses__()[40](\"/etc/passwd\").read() }}"
]

View File

@ -2,20 +2,26 @@
'use strict'
const Hexo = require('hexo')
const hexo = new Hexo(__dirname)
global.hexo = hexo
const { gzipDefault } = require('../index')
const g = require('../lib/filter').gzipFn.bind(hexo)
const zlib = require('zlib')
const { promisify } = require('util')
const zlib = require('node:zlib')
const { promisify } = require('node:util')
const gzip = promisify(zlib.gzip)
const unzip = promisify(zlib.unzip)
describe('gzip', () => {
const hexo = new Hexo(__dirname)
const g = require('../lib/filter').gzipFn.bind(hexo)
const path = 'foo.txt'
const input = 'Lorem ipsum dolor sit amet consectetur adipiscing elit fusce'
describe('gzip', () => {
beforeEach(() => {
hexo.config.minify.gzip = Object.assign({}, gzipDefault)
hexo.config.minify = {
gzip: {
enable: true,
verbose: false,
include: ['*.html', '*.css', '*.js', '*.txt', '*.ttf', '*.atom', '*.stl', '*.xml', '*.svg', '*.eot', '*.json'],
globOptions: { basename: true }
}
}
hexo.route.set(path, input)
})
@ -97,13 +103,10 @@ describe('gzip', () => {
try {
await gzip(input, customOpt)
} catch (err) {
expected = err.message
}
try {
await g()
} catch (err) {
expect(err.message).toContain(expected)
expected = err
}
expect(expected).toBeDefined()
await expect(g()).rejects.toThrow(`Path: ${path}\n${expected}`)
})
test('include - exclude non-text file by default', async () => {
@ -232,4 +235,26 @@ describe('gzip', () => {
expect(routeList).toEqual(expect.arrayContaining(expected))
})
test('blns', async () => {
const blns = require('./fixtures/blns.json')
for (const nStr of blns) {
hexo.route.remove(path)
hexo.route.set(path, nStr)
await g()
const output = hexo.route.get(path.concat('.gz'))
const buf = []
output.on('data', (chunk) => (buf.push(chunk)))
output.on('end', async () => {
const result = Buffer.concat(buf)
const resultUnzip = await unzip(result)
expect(resultUnzip.toString()).toBe(nStr)
})
}
})
})

View File

@ -2,105 +2,131 @@
'use strict'
const Hexo = require('hexo')
const hexo = new Hexo(__dirname)
global.hexo = hexo
const { htmlDefault } = require('../index')
const h = require('../lib/filter').minifyHtml.bind(hexo)
const Htmlminifier = require('html-minifier').minify
const input = '<p id="">foo</p>'
const path = 'index.html'
const expected = Htmlminifier(input, htmlDefault)
const { minify: htmlMinify } = require('html-minifier-terser')
describe('html', () => {
beforeEach(() => {
hexo.config.minify.html = Object.assign({}, htmlDefault)
const hexo = new Hexo(__dirname)
const h = require('../lib/filter').minifyHtml.bind(hexo)
const input = '<p id="">foo</p>'
const path = 'index.html'
const defaultCfg = {
html: {
enable: true,
verbose: false,
exclude: [],
collapseBooleanAttributes: true,
collapseWhitespace: true,
ignoreCustomComments: [/^\s*more/],
removeComments: true,
removeEmptyAttributes: true,
removeScriptTypeAttributes: true,
removeStyleLinkTypeAttributes: true,
minifyJS: true,
minifyCSS: true,
globOptions: { basename: true }
}
}
let expected = ''
beforeAll(async () => {
expected = await htmlMinify(input, defaultCfg.html)
})
test('default', () => {
const result = h(input, { path })
beforeEach(() => {
hexo.config.minify = JSON.parse(JSON.stringify(defaultCfg))
})
test('default', async () => {
const result = await h(input, { path })
expect(result).toBe(expected)
})
test('disable', () => {
test('disable', async () => {
hexo.config.minify.html.enable = false
const result = h(input, { path })
const result = await h(input, { path })
expect(result).toBeUndefined()
})
test('empty file', () => {
const result = h('', { path })
test('empty file', async () => {
const result = await h('', { path })
expect(result).toBeUndefined()
})
test('option', () => {
test('option', async () => {
const customOpt = { removeEmptyAttributes: false }
hexo.config.minify.html = customOpt
const result = h(input, { path })
const expected = Htmlminifier(input, customOpt)
const result = await h(input, { path })
const expected = await htmlMinify(input, customOpt)
expect(result).toBe(input)
expect(result).toBe(expected)
})
test('option - verbose', () => {
test('option - verbose', async () => {
hexo.config.minify.html.verbose = true
hexo.log.log = jest.fn()
h(input, { path })
await h(input, { path })
expect(hexo.log.log.mock.calls[0][0]).toContain(`html: ${path}`)
})
test('exclude', () => {
test('exclude', async () => {
const exclude = '*.min.html'
hexo.config.minify.html.exclude = exclude
const result = h(input, { path: 'foo/bar.min.html' })
const result = await h(input, { path: 'foo/bar.min.html' })
expect(result).toBe(input)
})
test('exclude - slash in pattern', () => {
test('exclude - slash in pattern', async () => {
const exclude = '**/lectus/**/*.html'
hexo.config.minify.html.exclude = exclude
const result = h(input, { path: 'eleifend/lectus/nullam/dapibus/netus.html' })
const result = await h(input, { path: 'eleifend/lectus/nullam/dapibus/netus.html' })
expect(result).toBe(input)
})
test('exclude - basename is true + slash', () => {
test('exclude - basename is true + slash', async () => {
const exclude = ['**/lectus/**/*.html', 'bar.html']
const globOptions = { basename: true }
hexo.config.minify.html.exclude = exclude
hexo.config.minify.html.globOptions = globOptions
const result = h(input, { path: 'foo/bar.html' })
const result = await h(input, { path: 'foo/bar.html' })
expect(result).toBe(input)
})
test('exclude - basename is false + slash', () => {
test('exclude - basename is false + slash', async () => {
const exclude = ['**/lectus/**/*.html', 'bar.html']
const globOptions = { basename: false }
hexo.config.minify.html.exclude = exclude
hexo.config.minify.html.globOptions = globOptions
const result = h(input, { path: 'foo/bar.html' })
const result = await h(input, { path: 'foo/bar.html' })
expect(result).toBe(expected)
})
test('null', () => {
test('null', async () => {
hexo.config.minify.html.exclude = null
hexo.config.minify.html.globOptions = null
const result = h(input, { path: null })
const result = await h(input, { path: null })
expect(result).toBe(expected)
})
test('invalid string', async () => {
const invalid = '<html><>?:"{}|_+</html>'
await expect(h(invalid, { path })).rejects.toThrow('Parse Error: <>?:"{}|_+</html>')
})
})

View File

@ -2,43 +2,57 @@
'use strict'
const Hexo = require('hexo')
const hexo = new Hexo(__dirname)
global.hexo = hexo
const { jsDefault } = require('../index')
const j = require('../lib/filter').minifyJs.bind(hexo)
const Terser = require('terser')
const input = 'var o = { "foo": 1, bar: 3 };'
const path = 'foo.js'
const expected = Terser.minify(input, { mangle: jsDefault.mangle }).code
const { minify: terserMinify } = require('terser')
describe('js', () => {
beforeEach(() => {
hexo.config.minify.js = Object.assign({}, jsDefault)
const hexo = new Hexo(__dirname)
const j = require('../lib/filter').minifyJs.bind(hexo)
const input = 'var o = { "foo": 1, bar: 3 };'
const path = 'foo.js'
let expected = ''
beforeAll(async () => {
const { code } = await terserMinify(input, { mangle: true })
expected = code
})
test('default', () => {
const result = j(input, { path })
beforeEach(async () => {
hexo.config.minify = {
js: {
enable: true,
verbose: false,
exclude: ['*.min.js'],
compress: {},
mangle: true,
output: {},
globOptions: { basename: true }
}
}
})
test('default', async () => {
const result = await j(input, { path })
expect(result).toBeDefined()
expect(expected).toBeDefined()
expect(result).toBe(expected)
})
test('disable', () => {
test('disable', async () => {
hexo.config.minify.js.enable = false
const result = j(input, { path })
const result = await j(input, { path })
expect(result).toBeUndefined()
})
test('empty file', () => {
const result = j('', { path })
test('empty file', async () => {
const result = await j('', { path })
expect(result).toBeUndefined()
})
test('option', () => {
test('option', async () => {
const customOpt = {
mangle: {
properties: true
@ -46,21 +60,21 @@ describe('js', () => {
}
hexo.config.minify.js = customOpt
const result = j(input, { path })
const expected = Terser.minify(input, customOpt).code
const result = await j(input, { path })
const { code: expected } = await terserMinify(input, customOpt)
expect(result).toBe(expected)
})
test('option - verbose', () => {
test('option - verbose', async () => {
hexo.config.minify.js.verbose = true
hexo.log.log = jest.fn()
j(input, { path })
await j(input, { path })
expect(hexo.log.log.mock.calls[0][0]).toContain(`js: ${path}`)
})
test('option - invalid', () => {
test('option - invalid', async () => {
const customOpt = {
mangle: {
foo: 'bar'
@ -68,33 +82,42 @@ describe('js', () => {
}
hexo.config.minify.js = customOpt
const { error } = Terser.minify(input, customOpt)
let expected
try {
j(input, { path })
await terserMinify(input, customOpt)
} catch (err) {
expect(err.message).toContain(error.message)
expected = err
}
expect(expected).toBeDefined()
await expect(j(input, { path })).rejects.toThrow(`Path: ${path}\n${expected}`)
})
test('exclude - *.min.js', () => {
const result = j(input, { path: 'foo/bar.min.js' })
test('exclude - *.min.js', async () => {
const result = await j(input, { path: 'foo/bar.min.js' })
expect(result).toBe(input)
})
test('exclude - basename', () => {
test('exclude - basename', async () => {
const exclude = '*baz.js'
hexo.config.minify.js.exclude = exclude
const result = j(input, { path: 'foo/barbaz.js' })
const result = await j(input, { path: 'foo/barbaz.js' })
expect(result).toBe(input)
})
test('exclude - slash in pattern', () => {
test('exclude - slash in pattern', async () => {
const exclude = '**/lectus/**/*.js'
hexo.config.minify.js.exclude = exclude
const result = j(input, { path: 'eleifend/lectus/nullam/dapibus/netus.js' })
const result = await j(input, { path: 'eleifend/lectus/nullam/dapibus/netus.js' })
expect(result).toBe(input)
})
test('invalid string', async () => {
const invalid = 'console.log("\\");'
await expect(j(invalid, { path })).rejects.toThrow(`Path: ${path}\nSyntaxError`)
})
})

View File

@ -2,17 +2,23 @@
'use strict'
const Hexo = require('hexo')
describe('xml', () => {
const hexo = new Hexo(__dirname)
global.hexo = hexo
const { jsonDefault } = require('../index')
const jsonFn = require('../lib/filter').minifyJson.bind(hexo)
const path = 'foo.json'
const input = '{\n\t"vitae": "hendrerit",\n\t"tristique": [\n\t\t"primis",\n\t\t"quam"\n\t]\n}'
const expected = '{"vitae":"hendrerit","tristique":["primis","quam"]}'
describe('xml', () => {
beforeEach(() => {
hexo.config.minify.json = Object.assign({}, jsonDefault)
hexo.config.minify = {
json: {
enable: false,
verbose: false,
include: ['*.json', '!*.min.json'],
globOptions: { basename: true }
}
}
// plugin is disabled by default
hexo.config.minify.json.enable = true
hexo.route.set(path, input)
@ -51,11 +57,7 @@ describe('xml', () => {
test('invalid input', async () => {
hexo.route.set(path, 'foo')
try {
await jsonFn()
} catch (err) {
expect(err.message).toContain('SyntaxError')
}
await expect(jsonFn()).rejects.toThrow(`Path: ${path}\nSyntaxError`)
})
test('empty file', async () => {

View File

@ -2,17 +2,37 @@
'use strict'
const Hexo = require('hexo')
const hexo = new Hexo(__dirname)
global.hexo = hexo
const { svgDefault } = require('../index')
const s = require('../lib/filter').minifySvg.bind(hexo)
const Svgo = require('svgo')
const input = '<svg><rect x="1" y="2" width="3" height="4" id="a"/></svg>'
const path = 'foo.svg'
const { optimize: svgOptimize } = require('svgo')
describe('svg', () => {
const hexo = new Hexo(__dirname)
const s = require('../lib/filter').minifySvg.bind(hexo)
const input = '<svg><rect x="1" y="2" width="3" height="4" id="a"/></svg>'
const path = 'foo.svg'
// svgo's plugins option
let plugins = [{
name: 'preset-default',
params: {
overrides: {}
}
}]
beforeEach(() => {
hexo.config.minify.svg = Object.assign({}, svgDefault)
hexo.config.minify = {
svg: {
enable: true,
verbose: false,
include: ['*.svg', '!*.min.svg'],
plugins: {},
globOptions: { basename: true }
}
}
plugins = [{
name: 'preset-default',
params: {
overrides: {}
}
}]
hexo.route.set(path, input)
})
@ -23,7 +43,7 @@ describe('svg', () => {
test('default', async () => {
await s()
const { data } = await new Svgo(hexo.config.minify.svg).optimize(input)
const { data } = svgOptimize(input, { plugins })
const output = hexo.route.get(path)
let result = ''
@ -50,10 +70,18 @@ describe('svg', () => {
})
test('option', async () => {
const customOpt = [{ cleanupIDs: false }]
const customOpt = {
cleanupIds: false
}
hexo.config.minify.svg.plugins = customOpt
plugins = [{
name: 'preset-default',
params: {
overrides: customOpt
}
}]
await s()
const { data } = await new Svgo(hexo.config.minify.svg).optimize(input)
const { data } = svgOptimize(input, { plugins })
const output = hexo.route.get(path)
let result = ''
@ -72,20 +100,31 @@ describe('svg', () => {
expect(hexo.log.log.mock.calls[0][0]).toContain(`svg: ${path}`)
})
test('option - plugins - invalid', async () => {
hexo.config.minify.svg.plugins = 'invalid'
await s()
const { data } = svgOptimize(input, { plugins })
const output = hexo.route.get(path)
let result = ''
output.on('data', (chunk) => (result += chunk))
output.on('end', () => {
expect(result).toBe(data)
})
})
test('invalid svg', async () => {
const input = '{}'
hexo.route.set(path, input)
let expected
try {
await new Svgo(hexo.config.minify.svg).optimize(input)
svgOptimize(input, { plugins })
} catch (err) {
expected = err
}
try {
await s()
} catch (err) {
expect(err.message).toContain(expected)
}
expect(expected).toBeDefined()
await expect(s()).rejects.toThrow(`Path: ${path}\n${expected}`)
})
test('include - exclude *.min.svg by default', async () => {
@ -106,7 +145,7 @@ describe('svg', () => {
const path = 'foo/bar.svg'
hexo.route.set(path, input)
await s()
const { data } = await new Svgo(hexo.config.minify.svg).optimize(input)
const { data } = svgOptimize(input, { plugins })
const output = hexo.route.get(path)
let result = ''
@ -121,7 +160,7 @@ describe('svg', () => {
const path = 'eleifend/lectus/nullam/dapibus/netus.svg'
hexo.route.set(path, input)
await s()
const { data } = await new Svgo(hexo.config.minify.svg).optimize(input)
const { data } = svgOptimize(input, { plugins })
const output = hexo.route.get(path)
let result = ''
@ -149,7 +188,7 @@ describe('svg', () => {
hexo.route.set(inpath, input)
})
await s()
const { data } = await new Svgo(hexo.config.minify.svg).optimize(input)
const { data } = svgOptimize(input, { plugins })
const minPaths = paths.slice(0, 2)
const unminPaths = paths.slice(2)
@ -193,7 +232,7 @@ describe('svg', () => {
hexo.route.set(inpath, input)
})
await s()
const { data } = await new Svgo(hexo.config.minify.svg).optimize(input)
const { data } = svgOptimize(input, { plugins })
paths.forEach((inpath) => {
const output = hexo.route.get(inpath)

View File

@ -2,17 +2,24 @@
'use strict'
const Hexo = require('hexo')
describe('xml', () => {
const hexo = new Hexo(__dirname)
global.hexo = hexo
const { xmlDefault } = require('../index')
const x = require('../lib/filter').minifyXml.bind(hexo)
const path = 'foo.xml'
const input = '<?xml version="1.0" encoding="utf-8"?>\n<feed xmlns="http://www.w3.org/2005/Atom">\n <!-- foo bar -->\n <title>foo</title>\n</feed>'
const expected = '<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title>foo</title></feed>'
describe('xml', () => {
beforeEach(() => {
hexo.config.minify.xml = Object.assign({}, xmlDefault)
hexo.config.minify = {
xml: {
enable: false,
verbose: false,
include: ['*.xml', '!*.min.xml'],
removeComments: true,
globOptions: { basename: true }
}
}
// plugin is disabled by default
hexo.config.minify.xml.enable = true
hexo.route.set(path, input)
@ -189,4 +196,18 @@ describe('xml', () => {
const result = await x()
expect(result.length).toBe(0)
})
test('avoid processing CDATA', async () => {
const input = '<foo><![CDATA[<p>lorem</p>\n<p>ipsum</p>]]></foo>'
hexo.route.set(path, input)
await x()
const output = hexo.route.get(path)
let result = ''
output.on('data', (chunk) => (result += chunk))
output.on('end', () => {
expect(result).toBe(input)
})
})
})

256
test/zstd.test.js Normal file
View File

@ -0,0 +1,256 @@
/* eslint-env jest */
'use strict'
const Hexo = require('hexo')
const { compress: zstd, decompress: unzstd } = require('@mongodb-js/zstd')
describe('zstd', () => {
const hexo = new Hexo(__dirname)
const z = require('../lib/filter').zstdFn.bind(hexo)
const path = 'foo.txt'
const input = 'Lorem ipsum dolor sit amet consectetur adipiscing elit fusce'
const inputBuf = Buffer.from(input, 'utf8')
beforeEach(() => {
hexo.config.minify = {
zstd: {
enable: true,
verbose: false,
include: ['*.html', '*.css', '*.js', '*.txt', '*.ttf', '*.atom', '*.stl', '*.xml', '*.svg', '*.eot', '*.json'],
globOptions: { basename: true }
}
}
hexo.route.set(path, input)
})
afterEach(() => {
const routeList = hexo.route.list()
routeList.forEach((path) => hexo.route.remove(path))
})
test('default', async () => {
await z()
const output = hexo.route.get(path.concat('.zst'))
const buf = []
output.on('data', (chunk) => (buf.push(chunk)))
output.on('end', async () => {
const result = Buffer.concat(buf)
const expected = await zstd(inputBuf)
const resultUnzst = await unzstd(result)
const expectedUnzst = await unzstd(expected)
expect(result.equals(expected)).toBe(true)
expect(resultUnzst.toString()).toBe(input)
expect(expectedUnzst.toString()).toBe(input)
})
})
test('disable', async () => {
hexo.config.minify.zstd.enable = false
const result = await z()
expect(result).toBeUndefined()
})
test('empty file', async () => {
hexo.route.set(path, '')
const routeList = hexo.route.list()
expect(routeList).not.toContain(path.concat('.zst'))
const result = await z()
expect(result).toBeDefined()
expect(result[0]).toBeUndefined()
})
test('option', async () => {
const level = 1
hexo.config.minify.zstd.level = level
await z()
const output = hexo.route.get(path.concat('.zst'))
const buf = []
output.on('data', (chunk) => (buf.push(chunk)))
output.on('end', async () => {
const result = Buffer.concat(buf)
const expected = await zstd(inputBuf, level)
expect(result.equals(expected)).toBe(true)
})
})
test('option - verbose', async () => {
hexo.config.minify.zstd.verbose = true
hexo.log.log = jest.fn()
await z()
expect(hexo.log.log.mock.calls[0][0]).toContain(`zstd: ${path}`)
})
test('option - level is string', async () => {
const level = 'foo'
hexo.config.minify.zstd.level = level
await z()
const output = hexo.route.get(path.concat('.zst'))
const buf = []
output.on('data', (chunk) => (buf.push(chunk)))
output.on('end', async () => {
const result = Buffer.concat(buf)
const expected = await zstd(inputBuf, undefined)
expect(result.equals(expected)).toBe(true)
})
})
test('include - exclude non-text file by default', async () => {
const path = 'foo.jpg'
hexo.route.set(path, input)
await z()
const result = hexo.route.get(path.concat('.zst'))
expect(result).toBeUndefined()
})
test('include - basename', async () => {
hexo.config.minify.zstd.include = 'bar.txt'
const path = 'foo/bar.txt'
hexo.route.set(path, input)
await z()
const result = hexo.route.get(path.concat('.zst'))
expect(result).toBeDefined()
})
test('include - slash in pattern', async () => {
hexo.config.minify.zstd.include = '**/lectus/**/*.txt'
const path = 'eleifend/lectus/nullam/dapibus/netus.txt'
hexo.route.set(path, input)
await z()
const result = hexo.route.get(path.concat('.zst'))
expect(result).toBeDefined()
})
test('include - basename + slash + basename enabled', async () => {
hexo.route.remove(path)
const paths = [
'lorem/ipsum/dolor.html',
'gravida/sociis/erat/ante.css',
'aptent/elementum.js',
'felis/blandit/cursus.svg'
]
hexo.config.minify.zstd.include = [
'*.html',
'**/sociis/**/*.css'
]
paths.forEach((inpath) => {
hexo.route.set(inpath, input)
})
await z()
const routeList = hexo.route.list()
const expected = [
'lorem/ipsum/dolor.html.zst',
'gravida/sociis/erat/ante.css.zst'
]
const notExpected = [
'aptent/elementum.js.zst',
'felis/blandit/cursus.svg.zst'
]
expect(routeList).toEqual(expect.arrayContaining(expected))
expect(routeList).toEqual(expect.not.arrayContaining(notExpected))
})
test('include - basename + slash + basename disabled', async () => {
hexo.route.remove(path)
const paths = [
'lorem/ipsum/dolor.html',
'gravida/sociis/erat/ante.css',
'aptent/elementum.js',
'felis/blandit/cursus.svg'
]
hexo.config.minify.zstd.include = [
'*.html',
'**/sociis/**/*.css'
]
hexo.config.minify.zstd.globOptions = {
basename: false
}
paths.forEach((inpath) => {
hexo.route.set(inpath, input)
})
await z()
const routeList = hexo.route.list()
const expected = [
'gravida/sociis/erat/ante.css.zst'
]
const notExpected = [
'lorem/ipsum/dolor.html.zst',
'aptent/elementum.js.zst',
'felis/blandit/cursus.svg.zst'
]
expect(routeList).toEqual(expect.arrayContaining(expected))
expect(routeList).toEqual(expect.not.arrayContaining(notExpected))
})
test('include - reverse pattern + basename disabled', async () => {
hexo.route.remove(path)
const paths = [
'lorem/ipsum/dolor.html',
'gravida/sociis/erat/ante.css',
'aptent/elementum.js',
'felis/blandit/cursus.svg'
]
hexo.config.minify.zstd.include = [
'!dolor.html'
]
hexo.config.minify.zstd.globOptions = {
basename: false
}
paths.forEach((inpath) => {
hexo.route.set(inpath, input)
})
await z()
const routeList = hexo.route.list()
const expected = paths.map((path) => path.concat('.zst'))
expect(routeList).toEqual(expect.arrayContaining(expected))
})
test('blns', async () => {
const blns = require('./fixtures/blns.json')
for (const nStr of blns) {
hexo.route.remove(path)
hexo.route.set(path, nStr)
await z()
const output = hexo.route.get(path.concat('.zst'))
const buf = []
output.on('data', (chunk) => (buf.push(chunk)))
output.on('end', async () => {
const result = Buffer.concat(buf)
const resultUnzst = await unzstd(result)
expect(resultUnzst.toString()).toBe(nStr)
})
}
})
})