pompelmi 1.8.0 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/BADGE.md +4 -4
- package/README.md +25 -3
- package/action/scanner.js +56 -0
- package/action.yml +5 -0
- package/package.json +2 -1
- package/types/index.d.ts +82 -0
package/BADGE.md
CHANGED
|
@@ -5,25 +5,25 @@ Add this badge to your repository's `README.md` to show that your file uploads a
|
|
|
5
5
|
## Markdown
|
|
6
6
|
|
|
7
7
|
```markdown
|
|
8
|
-
[](https://github.com/pompelmi/pompelmi)
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
## HTML
|
|
12
12
|
|
|
13
13
|
```html
|
|
14
14
|
<a href="https://github.com/pompelmi/pompelmi">
|
|
15
|
-
<img src="https://img.shields.io/badge/scanned%20by-pompelmi-orange?logo=
|
|
15
|
+
<img src="https://img.shields.io/badge/scanned%20by-pompelmi-orange?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAAXNSR0IArs4c6QAAAQxlWElmTU0AKgAAAAgABwESAAMAAAABAAEAAAEaAAUAAAABAAAAYgEbAAUAAAABAAAAagEoAAMAAAABAAIAAAExAAIAAAA5AAAAcgE7AAIAAAASAAAArIdpAAQAAAABAAAAvgAAAAAAAABgAAAAAQAAAGAAAAABQ2FudmEgZG9jPURBSEdqUE42M19JIHVzZXI9VUFHZVZYTlJxNEkgYnJhbmQ9QkFHZVZib2RxREkAAFRvbW1hc28gQmVydG9jY2hpAAAGkAAABwAAAAQwMjEwkQEABwAAAAQBAgMAoAAABwAAAAQwMTAwoAEAAwAAAAEAAQAAoAIABAAAAAEAAAAOoAMABAAAAAEAAAAOAAAAAOn+IX8AAAAJcEhZcwAADsQAAA7EAZUrDhsAAAZHaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJYTVAgQ29yZSA2LjAuMCI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOmV4aWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vZXhpZi8xLjAvIgogICAgICAgICAgICB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOnRpZmY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vdGlmZi8xLjAvIgogICAgICAgICAgICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iPgogICAgICAgICA8ZXhpZjpDb2xvclNwYWNlPjY1NTM1PC9leGlmOkNvbG9yU3BhY2U+CiAgICAgICAgIDxleGlmOlBpeGVsWERpbWVuc2lvbj4xNTAwPC9leGlmOlBpeGVsWERpbWVuc2lvbj4KICAgICAgICAgPGV4aWY6RXhpZlZlcnNpb24+MDIxMDwvZXhpZjpFeGlmVmVyc2lvbj4KICAgICAgICAgPGV4aWY6Rmxhc2hQaXhWZXJzaW9uPjAxMDA8L2V4aWY6Rmxhc2hQaXhWZXJzaW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFlEaW1lbnNpb24+MTUwMDwvZXhpZjpQaXhlbFlEaW1lbnNpb24+CiAgICAgICAgIDxleGlmOkNvbXBvbmVudHNDb25maWd1cmF0aW9uPgogICAgICAgICAgICA8cmRmOlNlcT4KICAgICAgICAgICAgICAgPHJkZjpsaT4xPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+MjwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPjM8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT4wPC9yZGY6bGk+CiAgICAgICAgICAgIDwvcmRmOlNlcT4KICAgICAgICAgPC9leGlmOkNvbXBvbmVudHNDb25maWd1cmF0aW9uPgogICAgICAgICA8eG1wOkNyZWF0b3JUb29sPkNhbnZhIGRvYz1EQUhHalBONjNfSSB1c2VyPVVBR2VWWE5ScTRJIGJyYW5kPUJBR2VWYm9kcURJPC94bXA6Q3JlYXRvclRvb2w+CiAgICAgICAgIDx0aWZmOlJlc29sdXRpb25Vbml0PjI8L3RpZmY6UmVzb2x1dGlvblVuaXQ+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgICAgIDx0aWZmOlhSZXNvbHV0aW9uPjk2PC90aWZmOlhSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpZUmVzb2x1dGlvbj45NjwvdGlmZjpZUmVzb2x1dGlvbj4KICAgICAgICAgPGRjOnRpdGxlPgogICAgICAgICAgICA8cmRmOkFsdD4KICAgICAgICAgICAgICAgPHJkZjpsaSB4bWw6bGFuZz0ieC1kZWZhdWx0Ij5Qcm9nZXR0byBzZW56YSB0aXRvbG8gLSAxPC9yZGY6bGk+CiAgICAgICAgICAgIDwvcmRmOkFsdD4KICAgICAgICAgPC9kYzp0aXRsZT4KICAgICAgICAgPGRjOmNyZWF0b3I+CiAgICAgICAgICAgIDxyZGY6U2VxPgogICAgICAgICAgICAgICA8cmRmOmxpPlRvbW1hc28gQmVydG9jY2hpPC9yZGY6bGk+CiAgICAgICAgICAgIDwvcmRmOlNlcT4KICAgICAgICAgPC9kYzpjcmVhdG9yPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4Kn4j/DQAAAeFJREFUKBWtUjtrFFEU/u68Z5zs7LLPhEgEG0ljETGFImgnNhKsYiEBLYU0KqiERaxEQbcRK8HCiH/AUrFVEEQQ0YiurvvIRp2d2ZnZeezJzIZZSAxi4S3uOffc73zfOede4H8vImJ/4/zj8t7Tc3MdixaYJ70RcsaL6uKd7m4E3M6g6TgrduBf7TQbF463zQX//rXDOzHJeZvixdrJTC7a89hreqdO62VntlzUZD+MAsd96HDqcuXS7X5KIqROYi8fWgom1nsFcX4SimFoYbeF4P1bXhUH54Mw+BZDbqT4can0HEIh7C4rhdx8xMtwbRv+18/wLROm08dgODz7sVaT08SRYjJB/+Wjm+KHzpWNxiswXQE/sxcYAoHVBjERJHIZs/NOiRMHSfKW4u+7hr9uLXk/XUCSwHEcqNWCVNkHafYIpHwJvKquTZ84GqaKW4nZZuS7Zhj0TbC8AfBirJqBV6+DYi7SJ6GVZuaMbOkZ/XitjRUZu2UNNXFVmVBAn9bANroQBA5CpQyKeyTPhZTVFebZByAbo/bGU6XWl2qvOE2cyo6xYtaPdPaEK04dVGR5kTxbo1+dJvrSCsuf6SWK295xVD/FMQYa+fHWfnB9v+4MDNP8Xp+qru76i1LsP9lNSkO4P3HUKYoAAAAASUVORK5CYII=" alt="Scanned by pompelmi">
|
|
16
16
|
</a>
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
## RST (reStructuredText)
|
|
20
20
|
|
|
21
21
|
```rst
|
|
22
|
-
.. image:: https://img.shields.io/badge/scanned%20by-pompelmi-orange?logo=
|
|
22
|
+
.. image:: https://img.shields.io/badge/scanned%20by-pompelmi-orange?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAAXNSR0IArs4c6QAAAQxlWElmTU0AKgAAAAgABwESAAMAAAABAAEAAAEaAAUAAAABAAAAYgEbAAUAAAABAAAAagEoAAMAAAABAAIAAAExAAIAAAA5AAAAcgE7AAIAAAASAAAArIdpAAQAAAABAAAAvgAAAAAAAABgAAAAAQAAAGAAAAABQ2FudmEgZG9jPURBSEdqUE42M19JIHVzZXI9VUFHZVZYTlJxNEkgYnJhbmQ9QkFHZVZib2RxREkAAFRvbW1hc28gQmVydG9jY2hpAAAGkAAABwAAAAQwMjEwkQEABwAAAAQBAgMAoAAABwAAAAQwMTAwoAEAAwAAAAEAAQAAoAIABAAAAAEAAAAOoAMABAAAAAEAAAAOAAAAAOn+IX8AAAAJcEhZcwAADsQAAA7EAZUrDhsAAAZHaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJYTVAgQ29yZSA2LjAuMCI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOmV4aWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vZXhpZi8xLjAvIgogICAgICAgICAgICB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOnRpZmY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vdGlmZi8xLjAvIgogICAgICAgICAgICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iPgogICAgICAgICA8ZXhpZjpDb2xvclNwYWNlPjY1NTM1PC9leGlmOkNvbG9yU3BhY2U+CiAgICAgICAgIDxleGlmOlBpeGVsWERpbWVuc2lvbj4xNTAwPC9leGlmOlBpeGVsWERpbWVuc2lvbj4KICAgICAgICAgPGV4aWY6RXhpZlZlcnNpb24+MDIxMDwvZXhpZjpFeGlmVmVyc2lvbj4KICAgICAgICAgPGV4aWY6Rmxhc2hQaXhWZXJzaW9uPjAxMDA8L2V4aWY6Rmxhc2hQaXhWZXJzaW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFlEaW1lbnNpb24+MTUwMDwvZXhpZjpQaXhlbFlEaW1lbnNpb24+CiAgICAgICAgIDxleGlmOkNvbXBvbmVudHNDb25maWd1cmF0aW9uPgogICAgICAgICAgICA8cmRmOlNlcT4KICAgICAgICAgICAgICAgPHJkZjpsaT4xPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+MjwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPjM8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT4wPC9yZGY6bGk+CiAgICAgICAgICAgIDwvcmRmOlNlcT4KICAgICAgICAgPC9leGlmOkNvbXBvbmVudHNDb25maWd1cmF0aW9uPgogICAgICAgICA8eG1wOkNyZWF0b3JUb29sPkNhbnZhIGRvYz1EQUhHalBONjNfSSB1c2VyPVVBR2VWWE5ScTRJIGJyYW5kPUJBR2VWYm9kcURJPC94bXA6Q3JlYXRvclRvb2w+CiAgICAgICAgIDx0aWZmOlJlc29sdXRpb25Vbml0PjI8L3RpZmY6UmVzb2x1dGlvblVuaXQ+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgICAgIDx0aWZmOlhSZXNvbHV0aW9uPjk2PC90aWZmOlhSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpZUmVzb2x1dGlvbj45NjwvdGlmZjpZUmVzb2x1dGlvbj4KICAgICAgICAgPGRjOnRpdGxlPgogICAgICAgICAgICA8cmRmOkFsdD4KICAgICAgICAgICAgICAgPHJkZjpsaSB4bWw6bGFuZz0ieC1kZWZhdWx0Ij5Qcm9nZXR0byBzZW56YSB0aXRvbG8gLSAxPC9yZGY6bGk+CiAgICAgICAgICAgIDwvcmRmOkFsdD4KICAgICAgICAgPC9kYzp0aXRsZT4KICAgICAgICAgPGRjOmNyZWF0b3I+CiAgICAgICAgICAgIDxyZGY6U2VxPgogICAgICAgICAgICAgICA8cmRmOmxpPlRvbW1hc28gQmVydG9jY2hpPC9yZGY6bGk+CiAgICAgICAgICAgIDwvcmRmOlNlcT4KICAgICAgICAgPC9kYzpjcmVhdG9yPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4Kn4j/DQAAAeFJREFUKBWtUjtrFFEU/u68Z5zs7LLPhEgEG0ljETGFImgnNhKsYiEBLYU0KqiERaxEQbcRK8HCiH/AUrFVEEQQ0YiurvvIRp2d2ZnZeezJzIZZSAxi4S3uOffc73zfOede4H8vImJ/4/zj8t7Tc3MdixaYJ70RcsaL6uKd7m4E3M6g6TgrduBf7TQbF463zQX//rXDOzHJeZvixdrJTC7a89hreqdO62VntlzUZD+MAsd96HDqcuXS7X5KIqROYi8fWgom1nsFcX4SimFoYbeF4P1bXhUH54Mw+BZDbqT4can0HEIh7C4rhdx8xMtwbRv+18/wLROm08dgODz7sVaT08SRYjJB/+Wjm+KHzpWNxiswXQE/sxcYAoHVBjERJHIZs/NOiRMHSfKW4u+7hr9uLXk/XUCSwHEcqNWCVNkHafYIpHwJvKquTZ84GqaKW4nZZuS7Zhj0TbC8AfBirJqBV6+DYi7SJ6GVZuaMbOkZ/XitjRUZu2UNNXFVmVBAn9bANroQBA5CpQyKeyTPhZTVFebZByAbo/bGU6XWl2qvOE2cyo6xYtaPdPaEK04dVGR5kTxbo1+dJvrSCsuf6SWK295xVD/FMQYa+fHWfnB9v+4MDNP8Xp+qru76i1LsP9lNSkO4P3HUKYoAAAAASUVORK5CYII=
|
|
23
23
|
:target: https://github.com/pompelmi/pompelmi
|
|
24
24
|
:alt: Scanned by pompelmi
|
|
25
25
|
```
|
|
26
26
|
|
|
27
27
|
## Preview
|
|
28
28
|
|
|
29
|
-
[](https://github.com/pompelmi/pompelmi)
|
package/README.md
CHANGED
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
<img src="https://img.shields.io/badge/license-ISC-blue" alt="license">
|
|
16
16
|
<a href="https://github.com/pompelmi/pompelmi/actions/workflows/ci.yml"><img src="https://github.com/pompelmi/pompelmi/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
|
|
17
17
|
<a href="https://github.com/pompelmi/pompelmi/actions/workflows/release.yml"><img src="https://github.com/pompelmi/pompelmi/actions/workflows/release.yml/badge.svg" alt="npm publish"></a>
|
|
18
|
-
<
|
|
18
|
+
<img src="https://img.shields.io/badge/TypeScript-types%20included-3178c6?logo=typescript&logoColor=white" alt="TypeScript types included">
|
|
19
|
+
<a href="https://github.com/pompelmi/pompelmi"><img src="https://img.shields.io/badge/scanned%20by-pompelmi-orange?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAAXNSR0IArs4c6QAAAQxlWElmTU0AKgAAAAgABwESAAMAAAABAAEAAAEaAAUAAAABAAAAYgEbAAUAAAABAAAAagEoAAMAAAABAAIAAAExAAIAAAA5AAAAcgE7AAIAAAASAAAArIdpAAQAAAABAAAAvgAAAAAAAABgAAAAAQAAAGAAAAABQ2FudmEgZG9jPURBSEdqUE42M19JIHVzZXI9VUFHZVZYTlJxNEkgYnJhbmQ9QkFHZVZib2RxREkAAFRvbW1hc28gQmVydG9jY2hpAAAGkAAABwAAAAQwMjEwkQEABwAAAAQBAgMAoAAABwAAAAQwMTAwoAEAAwAAAAEAAQAAoAIABAAAAAEAAAAOoAMABAAAAAEAAAAOAAAAAOn+IX8AAAAJcEhZcwAADsQAAA7EAZUrDhsAAAZHaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJYTVAgQ29yZSA2LjAuMCI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOmV4aWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vZXhpZi8xLjAvIgogICAgICAgICAgICB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOnRpZmY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vdGlmZi8xLjAvIgogICAgICAgICAgICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iPgogICAgICAgICA8ZXhpZjpDb2xvclNwYWNlPjY1NTM1PC9leGlmOkNvbG9yU3BhY2U+CiAgICAgICAgIDxleGlmOlBpeGVsWERpbWVuc2lvbj4xNTAwPC9leGlmOlBpeGVsWERpbWVuc2lvbj4KICAgICAgICAgPGV4aWY6RXhpZlZlcnNpb24+MDIxMDwvZXhpZjpFeGlmVmVyc2lvbj4KICAgICAgICAgPGV4aWY6Rmxhc2hQaXhWZXJzaW9uPjAxMDA8L2V4aWY6Rmxhc2hQaXhWZXJzaW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFlEaW1lbnNpb24+MTUwMDwvZXhpZjpQaXhlbFlEaW1lbnNpb24+CiAgICAgICAgIDxleGlmOkNvbXBvbmVudHNDb25maWd1cmF0aW9uPgogICAgICAgICAgICA8cmRmOlNlcT4KICAgICAgICAgICAgICAgPHJkZjpsaT4xPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+MjwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPjM8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT4wPC9yZGY6bGk+CiAgICAgICAgICAgIDwvcmRmOlNlcT4KICAgICAgICAgPC9leGlmOkNvbXBvbmVudHNDb25maWd1cmF0aW9uPgogICAgICAgICA8eG1wOkNyZWF0b3JUb29sPkNhbnZhIGRvYz1EQUhHalBONjNfSSB1c2VyPVVBR2VWWE5ScTRJIGJyYW5kPUJBR2VWYm9kcURJPC94bXA6Q3JlYXRvclRvb2w+CiAgICAgICAgIDx0aWZmOlJlc29sdXRpb25Vbml0PjI8L3RpZmY6UmVzb2x1dGlvblVuaXQ+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgICAgIDx0aWZmOlhSZXNvbHV0aW9uPjk2PC90aWZmOlhSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpZUmVzb2x1dGlvbj45NjwvdGlmZjpZUmVzb2x1dGlvbj4KICAgICAgICAgPGRjOnRpdGxlPgogICAgICAgICAgICA8cmRmOkFsdD4KICAgICAgICAgICAgICAgPHJkZjpsaSB4bWw6bGFuZz0ieC1kZWZhdWx0Ij5Qcm9nZXR0byBzZW56YSB0aXRvbG8gLSAxPC9yZGY6bGk+CiAgICAgICAgICAgIDwvcmRmOkFsdD4KICAgICAgICAgPC9kYzp0aXRsZT4KICAgICAgICAgPGRjOmNyZWF0b3I+CiAgICAgICAgICAgIDxyZGY6U2VxPgogICAgICAgICAgICAgICA8cmRmOmxpPlRvbW1hc28gQmVydG9jY2hpPC9yZGY6bGk+CiAgICAgICAgICAgIDwvcmRmOlNlcT4KICAgICAgICAgPC9kYzpjcmVhdG9yPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4Kn4j/DQAAAeFJREFUKBWtUjtrFFEU/u68Z5zs7LLPhEgEG0ljETGFImgnNhKsYiEBLYU0KqiERaxEQbcRK8HCiH/AUrFVEEQQ0YiurvvIRp2d2ZnZeezJzIZZSAxi4S3uOffc73zfOede4H8vImJ/4/zj8t7Tc3MdixaYJ70RcsaL6uKd7m4E3M6g6TgrduBf7TQbF463zQX//rXDOzHJeZvixdrJTC7a89hreqdO62VntlzUZD+MAsd96HDqcuXS7X5KIqROYi8fWgom1nsFcX4SimFoYbeF4P1bXhUH54Mw+BZDbqT4can0HEIh7C4rhdx8xMtwbRv+18/wLROm08dgODz7sVaT08SRYjJB/+Wjm+KHzpWNxiswXQE/sxcYAoHVBjERJHIZs/NOiRMHSfKW4u+7hr9uLXk/XUCSwHEcqNWCVNkHafYIpHwJvKquTZ84GqaKW4nZZuS7Zhj0TbC8AfBirJqBV6+DYi7SJ6GVZuaMbOkZ/XitjRUZu2UNNXFVmVBAn9bANroQBA5CpQyKeyTPhZTVFebZByAbo/bGU6XWl2qvOE2cyo6xYtaPdPaEK04dVGR5kTxbo1+dJvrSCsuf6SWK295xVD/FMQYa+fHWfnB9v+4MDNP8Xp+qru76i1LsP9lNSkO4P3HUKYoAAAAASUVORK5CYII=" alt="Scanned by pompelmi"></a>
|
|
19
20
|
</p>
|
|
20
21
|
|
|
21
22
|
---
|
|
@@ -346,7 +347,19 @@ choco install clamav -y
|
|
|
346
347
|
|
|
347
348
|
## Examples
|
|
348
349
|
|
|
349
|
-
The [`examples/`](./examples/) directory contains standalone runnable scripts
|
|
350
|
+
The [`examples/`](./examples/) directory contains standalone runnable scripts and framework-specific starters.
|
|
351
|
+
|
|
352
|
+
### Framework starters
|
|
353
|
+
|
|
354
|
+
| Directory | Description |
|
|
355
|
+
|-----------|-------------|
|
|
356
|
+
| [`examples/express/`](./examples/express/) | Full Express app with multer + pompelmi middleware |
|
|
357
|
+
| [`examples/nextjs/`](./examples/nextjs/) | Next.js API route that scans raw upload bytes |
|
|
358
|
+
| [`examples/nestjs/`](./examples/nestjs/) | NestJS guard wrapping pompelmi for route-level protection |
|
|
359
|
+
|
|
360
|
+
### Standalone scripts
|
|
361
|
+
|
|
362
|
+
Each can be run with `node examples/<name>.js`.
|
|
350
363
|
|
|
351
364
|
| File | Description |
|
|
352
365
|
|------|-------------|
|
|
@@ -370,7 +383,7 @@ The [`examples/`](./examples/) directory contains standalone runnable scripts. E
|
|
|
370
383
|
| `scan-zip.js` | ZIP archive scan (ClamAV recurses automatically) |
|
|
371
384
|
| `install-clamav.js` | Programmatic ClamAV installation |
|
|
372
385
|
| `update-virus-database.js` | Programmatic virus DB update |
|
|
373
|
-
| `typescript-usage.ts` | TypeScript example with
|
|
386
|
+
| `typescript-usage.ts` | TypeScript example with full type declarations |
|
|
374
387
|
|
|
375
388
|
---
|
|
376
389
|
|
|
@@ -412,6 +425,7 @@ Scan any repository for viruses on every push or pull request — ClamAV is bund
|
|
|
412
425
|
|-------|-------------|---------|
|
|
413
426
|
| `path` | Directory or file to scan | `.` (full workspace) |
|
|
414
427
|
| `fail-on-virus` | Fail the workflow step when infected files are found | `true` |
|
|
428
|
+
| `comment-on-pr` | Post a PR comment listing infected files (requires `GITHUB_TOKEN`) | `true` |
|
|
415
429
|
|
|
416
430
|
### Outputs
|
|
417
431
|
|
|
@@ -457,6 +471,14 @@ Please read [CODE_OF_CONDUCT.md](./CODE_OF_CONDUCT.md) before contributing. To r
|
|
|
457
471
|
|
|
458
472
|
---
|
|
459
473
|
|
|
474
|
+
## Coming soon
|
|
475
|
+
|
|
476
|
+
- [ ] AWS S3 integration — scan objects directly from S3 without downloading
|
|
477
|
+
- [ ] Cloudflare Workers support — edge-native scanning via the clamd TCP protocol
|
|
478
|
+
- [ ] NestJS official module — `PompelmiModule.forRoot()` with injectable `PompelmiService`
|
|
479
|
+
|
|
480
|
+
---
|
|
481
|
+
|
|
460
482
|
## License
|
|
461
483
|
|
|
462
484
|
[ISC](./LICENSE) — © pompelmi contributors
|
package/action/scanner.js
CHANGED
|
@@ -6,6 +6,7 @@ const { scan, scanDirectory, Verdict } = require('pompelmi');
|
|
|
6
6
|
|
|
7
7
|
const scanPath = process.argv[2] || '.';
|
|
8
8
|
const failOnVirus = process.argv[3] !== 'false';
|
|
9
|
+
const commentOnPr = process.argv[4] !== 'false';
|
|
9
10
|
|
|
10
11
|
async function writeReport(clean, malicious, errors, outputDir) {
|
|
11
12
|
const total = clean.length + malicious.length + errors.length;
|
|
@@ -67,6 +68,60 @@ function escHtml(s) {
|
|
|
67
68
|
return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
68
69
|
}
|
|
69
70
|
|
|
71
|
+
async function postPrComment(malicious) {
|
|
72
|
+
if (!commentOnPr) return;
|
|
73
|
+
|
|
74
|
+
const token = process.env.GITHUB_TOKEN;
|
|
75
|
+
const eventName = process.env.GITHUB_EVENT_NAME;
|
|
76
|
+
if (!token || eventName !== 'pull_request') return;
|
|
77
|
+
|
|
78
|
+
const eventPath = process.env.GITHUB_EVENT_PATH;
|
|
79
|
+
if (!eventPath || !fs.existsSync(eventPath)) return;
|
|
80
|
+
|
|
81
|
+
let event;
|
|
82
|
+
try { event = JSON.parse(fs.readFileSync(eventPath, 'utf8')); }
|
|
83
|
+
catch { return; }
|
|
84
|
+
|
|
85
|
+
const prNumber = event.pull_request && event.pull_request.number;
|
|
86
|
+
const repo = process.env.GITHUB_REPOSITORY;
|
|
87
|
+
if (!prNumber || !repo) return;
|
|
88
|
+
|
|
89
|
+
const rows = malicious
|
|
90
|
+
.map(f => `| \`${escHtml(f)}\` | Malicious |`)
|
|
91
|
+
.join('\n');
|
|
92
|
+
const body =
|
|
93
|
+
`## ❌ Pompelmi: Virus Detected\n\n` +
|
|
94
|
+
`The following infected file(s) were found during the scan:\n\n` +
|
|
95
|
+
`| File | Verdict |\n|------|--------|\n${rows}\n\n` +
|
|
96
|
+
`> Scanned by [pompelmi](https://pompelmi.app)`;
|
|
97
|
+
|
|
98
|
+
const https = require('https');
|
|
99
|
+
const payload = JSON.stringify({ body });
|
|
100
|
+
|
|
101
|
+
await new Promise((resolve, reject) => {
|
|
102
|
+
const req = https.request({
|
|
103
|
+
hostname: 'api.github.com',
|
|
104
|
+
path: `/repos/${repo}/issues/${prNumber}/comments`,
|
|
105
|
+
method: 'POST',
|
|
106
|
+
headers: {
|
|
107
|
+
'Authorization': `Bearer ${token}`,
|
|
108
|
+
'Content-Type': 'application/json',
|
|
109
|
+
'Content-Length': Buffer.byteLength(payload),
|
|
110
|
+
'User-Agent': 'pompelmi-action',
|
|
111
|
+
'Accept': 'application/vnd.github+json',
|
|
112
|
+
'X-GitHub-Api-Version': '2022-11-28',
|
|
113
|
+
},
|
|
114
|
+
}, (res) => {
|
|
115
|
+
res.resume();
|
|
116
|
+
if (res.statusCode >= 200 && res.statusCode < 300) resolve();
|
|
117
|
+
else reject(new Error(`GitHub API returned HTTP ${res.statusCode}`));
|
|
118
|
+
});
|
|
119
|
+
req.on('error', reject);
|
|
120
|
+
req.write(payload);
|
|
121
|
+
req.end();
|
|
122
|
+
}).catch(err => console.warn(`Could not post PR comment: ${err.message}`));
|
|
123
|
+
}
|
|
124
|
+
|
|
70
125
|
async function uploadArtifact(jsonPath, htmlPath) {
|
|
71
126
|
try {
|
|
72
127
|
const { DefaultArtifactClient } = require('@actions/artifact');
|
|
@@ -152,6 +207,7 @@ async function main() {
|
|
|
152
207
|
if (malicious.length > 0) {
|
|
153
208
|
console.error('\nInfected files:');
|
|
154
209
|
malicious.forEach(f => console.error(` ${f}`));
|
|
210
|
+
await postPrComment(malicious);
|
|
155
211
|
if (failOnVirus) {
|
|
156
212
|
console.error('\n::error::Virus(es) detected — failing workflow.');
|
|
157
213
|
process.exit(1);
|
package/action.yml
CHANGED
|
@@ -14,6 +14,10 @@ inputs:
|
|
|
14
14
|
description: 'Fail the workflow step when infected files are found'
|
|
15
15
|
required: false
|
|
16
16
|
default: 'true'
|
|
17
|
+
comment-on-pr:
|
|
18
|
+
description: 'Post a PR comment listing infected files when a virus is found (requires GITHUB_TOKEN)'
|
|
19
|
+
required: false
|
|
20
|
+
default: 'true'
|
|
17
21
|
|
|
18
22
|
outputs:
|
|
19
23
|
infected-files:
|
|
@@ -27,3 +31,4 @@ runs:
|
|
|
27
31
|
args:
|
|
28
32
|
- ${{ inputs.path }}
|
|
29
33
|
- ${{ inputs.fail-on-virus }}
|
|
34
|
+
- ${{ inputs.comment-on-pr }}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pompelmi",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.9.0",
|
|
4
4
|
"description": "ClamAV for humans — scan any file and get back Clean, Malicious, or ScanError. No daemons. No cloud. No native bindings.",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"author": "pompelmi contributors",
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
],
|
|
33
33
|
"type": "commonjs",
|
|
34
34
|
"main": "./src/index.js",
|
|
35
|
+
"types": "./types/index.d.ts",
|
|
35
36
|
"scripts": {
|
|
36
37
|
"test": "node --test test/unit.test.js && node test/scan.test.js",
|
|
37
38
|
"lint": "eslint src/"
|
package/types/index.d.ts
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { Readable } from 'stream';
|
|
2
|
+
import { IncomingMessage, ServerResponse } from 'http';
|
|
3
|
+
|
|
4
|
+
/** Options passed to any scan function */
|
|
5
|
+
export interface ScanOptions {
|
|
6
|
+
/** clamd hostname — enables TCP mode when set */
|
|
7
|
+
host?: string;
|
|
8
|
+
/** clamd port (default: 3310) */
|
|
9
|
+
port?: number;
|
|
10
|
+
/** Path to a clamd UNIX domain socket (e.g. /run/clamav/clamd.sock) */
|
|
11
|
+
socket?: string;
|
|
12
|
+
/** Socket idle timeout in milliseconds, clamd mode only (default: 15000) */
|
|
13
|
+
timeout?: number;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** Options for the Express/Fastify middleware */
|
|
17
|
+
export interface MiddlewareOptions extends ScanOptions {
|
|
18
|
+
/** multer field name to look for uploaded files (default: 'file') */
|
|
19
|
+
uploadField?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Result returned by scanDirectory */
|
|
23
|
+
export interface DirectoryScanResult {
|
|
24
|
+
/** Absolute paths of files that scanned clean */
|
|
25
|
+
clean: string[];
|
|
26
|
+
/** Absolute paths of infected files */
|
|
27
|
+
malicious: string[];
|
|
28
|
+
/** Absolute paths of files that produced a scan error */
|
|
29
|
+
errors: string[];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Opaque Symbol-based scan verdicts */
|
|
33
|
+
export declare const Verdict: {
|
|
34
|
+
readonly Clean: unique symbol;
|
|
35
|
+
readonly Malicious: unique symbol;
|
|
36
|
+
readonly ScanError: unique symbol;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/** The type of any Verdict symbol */
|
|
40
|
+
export type VerdictValue = typeof Verdict[keyof typeof Verdict];
|
|
41
|
+
|
|
42
|
+
type NextFunction = (err?: unknown) => void;
|
|
43
|
+
type RequestHandler = (
|
|
44
|
+
req: IncomingMessage,
|
|
45
|
+
res: ServerResponse,
|
|
46
|
+
next: NextFunction
|
|
47
|
+
) => void | Promise<void>;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Scan a file at the given path.
|
|
51
|
+
* Resolves to Verdict.Clean, Verdict.Malicious, or Verdict.ScanError.
|
|
52
|
+
* Rejects if the file is not found or clamscan is unavailable.
|
|
53
|
+
*/
|
|
54
|
+
export declare function scan(filePath: string, options?: ScanOptions): Promise<VerdictValue>;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Scan an in-memory Buffer.
|
|
58
|
+
* In TCP/socket mode the buffer is streamed to clamd with no disk I/O.
|
|
59
|
+
*/
|
|
60
|
+
export declare function scanBuffer(buffer: Buffer, options?: ScanOptions): Promise<VerdictValue>;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Scan a Node.js Readable stream.
|
|
64
|
+
* In TCP/socket mode the stream is piped to clamd with no disk I/O.
|
|
65
|
+
*/
|
|
66
|
+
export declare function scanStream(stream: Readable, options?: ScanOptions): Promise<VerdictValue>;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Recursively scan every file under dirPath.
|
|
70
|
+
* Per-file errors are caught and collected without aborting the full scan.
|
|
71
|
+
*/
|
|
72
|
+
export declare function scanDirectory(
|
|
73
|
+
dirPath: string,
|
|
74
|
+
options?: ScanOptions
|
|
75
|
+
): Promise<DirectoryScanResult>;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Express / Fastify middleware that scans multer-uploaded files
|
|
79
|
+
* (req.file / req.files) and responds HTTP 403 on any infection.
|
|
80
|
+
* Call after multer, before your route handler.
|
|
81
|
+
*/
|
|
82
|
+
export declare function middleware(options?: MiddlewareOptions): RequestHandler;
|