Skip to content

Commit 4f79015

Browse files
committed
chore: modernize deno deps and jsr publish
1 parent 2dbc762 commit 4f79015

10 files changed

Lines changed: 383 additions & 499 deletions

File tree

.github/workflows/publish-jsr.yml

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
name: Publish to JSR
2+
3+
on:
4+
push:
5+
tags:
6+
- "v*.*.*"
7+
- "*.*.*"
8+
9+
permissions:
10+
contents: read
11+
id-token: write
12+
13+
concurrency:
14+
group: publish-jsr-${{ github.ref }}
15+
cancel-in-progress: false
16+
17+
jobs:
18+
publish:
19+
runs-on: ubuntu-latest
20+
steps:
21+
- name: Checkout
22+
uses: actions/checkout@v4
23+
24+
- name: Setup Deno
25+
uses: denoland/setup-deno@v1
26+
with:
27+
deno-version: v2.x
28+
29+
- name: Verify tag matches deno.json version
30+
shell: bash
31+
run: |
32+
set -euo pipefail
33+
tag="${GITHUB_REF_NAME}"
34+
tag="${tag#v}"
35+
version="$(deno eval --quiet --allow-read 'console.log(JSON.parse(Deno.readTextFileSync(\"deno.json\")).version)')"
36+
37+
if [[ "${tag}" != "${version}" ]]; then
38+
echo "Tag (${GITHUB_REF_NAME}) does not match deno.json version (${version})."
39+
exit 1
40+
fi
41+
42+
- name: Format / Lint / Test
43+
run: |
44+
deno fmt --check
45+
deno lint
46+
deno task test
47+
48+
- name: Publish
49+
run: |
50+
# Tokenless publishing requires linking the JSR package to this GitHub repository
51+
# in the package settings on jsr.io, and OIDC enabled via `id-token: write`.
52+
deno publish

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
node_modules/
2+
coverage/

.vscode/settings.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
2-
"deno.enable": true,
3-
"deno.unstable": true
4-
}
2+
"deno.enable": true,
3+
"deno.unstable": true
4+
}

AGENTS.md

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# Repository Guidelines
2+
3+
## Project Structure & Module Organization
4+
5+
- `mod.ts`: public entrypoint; re-exports the library API.
6+
- `src/`: implementation (currently `src/dhash.ts`).
7+
- `tests/`: Deno tests (`*.test.ts`) and image fixtures used by the tests.
8+
- `deno.json`: package metadata, import map, and tasks.
9+
10+
Keep public exports flowing through `mod.ts`. If you add a new public
11+
function/type, export it from `mod.ts` and add/adjust tests under `tests/`.
12+
13+
## Build, Test, and Development Commands
14+
15+
- `deno task test`: runs the full test suite with the required permissions
16+
(`--allow-read --allow-ffi --allow-env`).
17+
- `deno test`: useful for quick runs; mirror the permissions from
18+
`deno task test` if tests fail due to denied access.
19+
- `deno fmt`: format the repo (preferred before committing).
20+
- `deno lint`: run Deno’s linter on TypeScript sources.
21+
- `deno check mod.ts`: type-check the public surface area.
22+
23+
## Coding Style & Naming Conventions
24+
25+
- TypeScript for Deno; follow `deno fmt` output (2-space indent, trailing commas
26+
where applicable).
27+
- Prefer `@std/*` imports via `deno.json` import mappings (avoid ad-hoc path
28+
utilities).
29+
- Naming:
30+
- exported functions: `camelCase` (e.g. `toAscii`, `compare`).
31+
- test files: `*.test.ts`.
32+
33+
## Testing Guidelines
34+
35+
- Use `Deno.test(...)` with `@std/assert`-style assertions (follow existing
36+
patterns in `tests/dhash.test.ts`).
37+
- Optional coverage: `deno test --coverage=coverage` then
38+
`deno coverage coverage` (output is ignored via `.gitignore`).
39+
- If you change hashing behavior, update expected hashes and/or fixtures in
40+
`tests/` intentionally (include rationale in the PR).
41+
42+
## Commit & Pull Request Guidelines
43+
44+
- Commit messages follow Conventional Commits in this repo: `feat: ...`,
45+
`fix: ...`, `chore: ...`, optionally scoped like `fix(dhash): ...`.
46+
- PRs should include:
47+
- what changed and why (short, concrete),
48+
- how to verify (e.g. `deno task test`),
49+
- notes on permission changes or dependency changes (especially
50+
`npm:sharp@...`) and any `deno.lock` updates.
51+
52+
## Publishing (JSR)
53+
54+
- Bump `version` in `deno.json`.
55+
- Validate locally: `deno fmt`, `deno lint`, `deno task test`.
56+
- Preview package contents: `deno publish --dry-run`.
57+
- Publish: `deno publish` (auth via token/login).
58+
- CI publish: push a semver tag matching `deno.json`’s version (e.g. `v0.2.0`).
59+
GitHub Actions will run checks then publish via JSR’s tokenless GitHub Actions
60+
flow (OIDC). This requires linking the package to this GitHub repo in the JSR
61+
package settings.

README.md

Lines changed: 27 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,23 @@
1-
# dhash
1+
# dhash
2+
23
_A `dhash` implementation for Deno._
34

4-
A fast algorithm that allows checking if two images are "kind of" the same (the same source image, slightly modified). Examples:
5+
A fast algorithm that allows checking if two images are "kind of" the same (the
6+
same source image, slightly modified). Examples:
57

6-
- A resized, compressed, slightly cropped, or color-altered image compared with the original
7-
- A watermarked image versus it's source
8+
- A resized, compressed, slightly cropped, or color-altered image compared with
9+
the original
10+
- A watermarked image versus it's source
811
- Meme images (mostly the same template, different text)
912

10-
It does this by computing a `perceptual hash` of each image and then using it to compare similarity.
13+
It does this by computing a `perceptual hash` of each image and then using it to
14+
compare similarity.
1115

1216
```
1317
Perceptual hashing is the use of a fingerprinting algorithm that produces a
1418
snippet or fingerprint of various forms of multimedia.
1519
```
1620

17-
1821
Based on the
1922
["Kind of Like That"](https://www.hackerfactor.com/blog/?/archives/529-Kind-of-Like-That.html)
2023
article by [Dr. Neal Krawetz](https://www.hackerfactor.com/about.php).
@@ -39,34 +42,28 @@ const [hash1, hash2] = await Promise.all([
3942
console.log(compare(hash1, hash2));
4043
```
4144

42-
There are also two functions that you may use to display the fingerprint in a
43-
non-hash form:
45+
Bit convention: this implementation sets bit `1` when the pixel intensity
46+
increases left-to-right (`left < right`). Use `dhash(src, { invert: true })` if
47+
you need the opposite convention to match another implementation.
48+
49+
## API
50+
51+
In addition to `dhash()` and `compare()`:
4452

4553
```ts
46-
/**
47-
* toAscii will return the fingerprint represented as a matrix of
48-
* black/white pixels, represented by default through unicode low density
49-
* and full blocks, ie:
50-
*
51-
* ██░░██████░░░░░░
52-
* ░░██░░░░░░░░░░██
53-
* ██░░░░░░████░░██
54-
* ░░████░░████░░██
55-
* ░░░░░░░░░░░░░░██
56-
* ████████░░░░░░░░
57-
* ░░░░░░██░░░░░░░░
58-
* ░░░░░░░░░░░░░░░░
59-
* /
60-
toAscii(hash: string, chars: [string, string]): string
61-
62-
/**
63-
* save will render the fingerprint as an 8x8px PNG file with black and
64-
* white pixels, at the specified path.
65-
*
66-
* async save(hash: string, file: string): Promise<void>
67-
*/
54+
toAscii(hash: string, chars?: [string, string]): string
55+
raw(hash: string): Promise<Uint8Array> // PNG bytes for the 8x8 fingerprint
56+
save(hash: string, filePath: string): Promise<void> // writes `${filePath}.png`
6857
```
6958

59+
`toAscii()` always renders an 8x8 matrix (64 bits); leading zero bits are
60+
preserved.
61+
62+
## Development
63+
64+
- Run tests: `deno task test` (requires `--allow-read --allow-ffi --allow-env`
65+
because `sharp` uses native bindings and reads fixtures).
66+
7067
## License
7168

7269
MIT © [Claudiu Ceia](https://github.com/ClaudiuCeia)

deno.json

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,22 @@
33
"version": "0.2.0",
44
"license": "MIT",
55
"exports": "./mod.ts",
6+
"nodeModulesDir": "auto",
7+
"publish": {
8+
"exclude": [
9+
".vscode",
10+
"tests",
11+
"coverage",
12+
"node_modules",
13+
"AGENTS.md"
14+
]
15+
},
616
"tasks": {
7-
"test": "deno test --allow-net --allow-read --allow-ffi --allow-env"
17+
"test": "deno test --allow-read --allow-ffi --allow-env"
818
},
919
"imports": {
10-
"@std/path": "jsr:@std/path@^1.0.9"
20+
"@std/assert": "jsr:@std/assert@^1.0.18",
21+
"@std/path": "jsr:@std/path@^1.1.4",
22+
"sharp": "npm:sharp@0.34.5"
1123
}
1224
}

0 commit comments

Comments
 (0)