penrose 0.2.45 → 0.3.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/.envrc +47 -0
- package/.github/workflows/ci.yaml +29 -0
- package/.pre-commit-config.yaml +22 -0
- package/Makefile +38 -0
- package/README.md +1 -1
- package/devenv.lock +123 -0
- package/devenv.nix +39 -0
- package/devenv.yaml +4 -0
- package/lib/__tests__/penrose.test.js +0 -50
- package/lib/penrose.js +7 -296
- package/package.json +15 -20
- package/.circleci/config.yml +0 -17
package/.envrc
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
version_gte() {
|
|
4
|
+
local cmd="$1"
|
|
5
|
+
local required_version="$2"
|
|
6
|
+
local installed_version=$($cmd | grep -oE "[0-9]+(\.[0-9]+)+" | head -n 1)
|
|
7
|
+
|
|
8
|
+
if [ -z "$installed_version" ]; then
|
|
9
|
+
return 1
|
|
10
|
+
fi
|
|
11
|
+
|
|
12
|
+
IFS="."
|
|
13
|
+
set -- $installed_version
|
|
14
|
+
local installed_parts="$@"
|
|
15
|
+
set -- $required_version
|
|
16
|
+
local required_parts="$@"
|
|
17
|
+
unset IFS
|
|
18
|
+
|
|
19
|
+
local i=1
|
|
20
|
+
for required_part in $required_parts; do
|
|
21
|
+
installed_part=$(echo "$installed_parts" | cut -d " " -f $i)
|
|
22
|
+
if [ "${installed_part:-0}" -lt "$required_part" ]; then
|
|
23
|
+
return 1
|
|
24
|
+
elif [ "${installed_part:-0}" -gt "$required_part" ]; then
|
|
25
|
+
return 0
|
|
26
|
+
fi
|
|
27
|
+
i=$((i + 1))
|
|
28
|
+
done
|
|
29
|
+
|
|
30
|
+
return 0
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if type nix-shell >/dev/null 2>&1; then
|
|
34
|
+
if ! has devenv; then
|
|
35
|
+
# Install devenv v1.x. Hash from https://www.nixhub.io/packages/devenv
|
|
36
|
+
if version_gte "nix --version" "2.30.0"; then
|
|
37
|
+
nix profile add github:NixOS/nixpkgs/80d901ec0377e19ac3f7bb8c035201e2e098cc97#devenv
|
|
38
|
+
else
|
|
39
|
+
nix profile install github:NixOS/nixpkgs/80d901ec0377e19ac3f7bb8c035201e2e098cc97#devenv
|
|
40
|
+
fi
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
eval "$(devenv direnvrc)"
|
|
44
|
+
use devenv
|
|
45
|
+
else
|
|
46
|
+
echo "nix-shell is not available. Install Nix: https://nixos.org/download"
|
|
47
|
+
fi
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [master]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
test:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
steps:
|
|
12
|
+
- uses: actions/checkout@v4
|
|
13
|
+
|
|
14
|
+
- name: Install system dependencies
|
|
15
|
+
run: |
|
|
16
|
+
sudo apt-get update -qq
|
|
17
|
+
sudo apt-get install -y -qq graphicsmagick
|
|
18
|
+
|
|
19
|
+
- name: Install Node
|
|
20
|
+
uses: actions/setup-node@v4
|
|
21
|
+
with:
|
|
22
|
+
node-version: 24.15.0
|
|
23
|
+
cache: npm
|
|
24
|
+
|
|
25
|
+
- name: Install Node dependencies
|
|
26
|
+
run: npm ci
|
|
27
|
+
|
|
28
|
+
- name: Run Node tests
|
|
29
|
+
run: npm test
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
default_language_version:
|
|
2
|
+
node: 24.15.0
|
|
3
|
+
|
|
4
|
+
default_stages: [pre-commit]
|
|
5
|
+
|
|
6
|
+
fail_fast: true
|
|
7
|
+
|
|
8
|
+
repos:
|
|
9
|
+
- repo: local
|
|
10
|
+
hooks:
|
|
11
|
+
- id: nixfmt
|
|
12
|
+
name: nixfmt
|
|
13
|
+
entry: nixfmt
|
|
14
|
+
language: system
|
|
15
|
+
files: \.nix$
|
|
16
|
+
|
|
17
|
+
- id: format-js
|
|
18
|
+
name: Format JS
|
|
19
|
+
language: system
|
|
20
|
+
entry: npx prettier --parser babel --write
|
|
21
|
+
files: ^(lib)/.*\.(js|jsx|cjs|mjs)$
|
|
22
|
+
pass_filenames: true
|
package/Makefile
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
ifneq ($(shell which tput),)
|
|
2
|
+
ifneq ($(TERM),)
|
|
3
|
+
RED := $(shell tput setaf 1)
|
|
4
|
+
GREEN := $(shell tput setaf 2)
|
|
5
|
+
YELLOW := $(shell tput setaf 3)
|
|
6
|
+
CYAN := $(shell tput setaf 6)
|
|
7
|
+
RESET := $(shell tput sgr0)
|
|
8
|
+
endif
|
|
9
|
+
endif
|
|
10
|
+
|
|
11
|
+
format:
|
|
12
|
+
@echo "Formatting code..."
|
|
13
|
+
pre-commit run format-js --all-files
|
|
14
|
+
|
|
15
|
+
bump-version:
|
|
16
|
+
@BUMP=$(word 2,$(MAKECMDGOALS)); \
|
|
17
|
+
VALID_BUMP="major minor patch premajor preminor prepatch prerelease"; \
|
|
18
|
+
if [ -z "$$BUMP" ]; then \
|
|
19
|
+
echo "$(RED)Error: Bump is required.$(RESET)"; \
|
|
20
|
+
echo "Usage: make bump-version [major|minor|patch|premajor|preminor|prepatch|prerelease]"; \
|
|
21
|
+
exit 1; \
|
|
22
|
+
fi; \
|
|
23
|
+
if ! echo "$$VALID_BUMP" | grep -qw "$$BUMP"; then \
|
|
24
|
+
echo "$(RED)Error: Invalid bump '$$BUMP'.$(RESET)"; \
|
|
25
|
+
echo "Must be one of: $(CYAN)$$VALID_BUMP$(RESET)"; \
|
|
26
|
+
exit 1; \
|
|
27
|
+
fi; \
|
|
28
|
+
npm version $$BUMP;
|
|
29
|
+
|
|
30
|
+
create-release:
|
|
31
|
+
@VERSION=$$(npm pkg get version --browser=false | tr -d '"'); \
|
|
32
|
+
gh release create $$VERSION;
|
|
33
|
+
|
|
34
|
+
# Prevent make from treating arguments to bump-version as targets
|
|
35
|
+
ifeq (bump-version,$(firstword $(MAKECMDGOALS)))
|
|
36
|
+
%:
|
|
37
|
+
@:
|
|
38
|
+
endif
|
package/README.md
CHANGED
package/devenv.lock
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
{
|
|
2
|
+
"nodes": {
|
|
3
|
+
"devenv": {
|
|
4
|
+
"locked": {
|
|
5
|
+
"dir": "src/modules",
|
|
6
|
+
"lastModified": 1770833792,
|
|
7
|
+
"owner": "cachix",
|
|
8
|
+
"repo": "devenv",
|
|
9
|
+
"rev": "1e5f2d43973d3f4a6e7bf3e13fd39e0c4d9af3de",
|
|
10
|
+
"type": "github"
|
|
11
|
+
},
|
|
12
|
+
"original": {
|
|
13
|
+
"dir": "src/modules",
|
|
14
|
+
"owner": "cachix",
|
|
15
|
+
"repo": "devenv",
|
|
16
|
+
"type": "github"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"flake-compat": {
|
|
20
|
+
"flake": false,
|
|
21
|
+
"locked": {
|
|
22
|
+
"lastModified": 1767039857,
|
|
23
|
+
"owner": "NixOS",
|
|
24
|
+
"repo": "flake-compat",
|
|
25
|
+
"rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab",
|
|
26
|
+
"type": "github"
|
|
27
|
+
},
|
|
28
|
+
"original": {
|
|
29
|
+
"owner": "NixOS",
|
|
30
|
+
"repo": "flake-compat",
|
|
31
|
+
"type": "github"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"git-hooks": {
|
|
35
|
+
"inputs": {
|
|
36
|
+
"flake-compat": "flake-compat",
|
|
37
|
+
"gitignore": "gitignore",
|
|
38
|
+
"nixpkgs": [
|
|
39
|
+
"nixpkgs"
|
|
40
|
+
]
|
|
41
|
+
},
|
|
42
|
+
"locked": {
|
|
43
|
+
"lastModified": 1770726378,
|
|
44
|
+
"owner": "cachix",
|
|
45
|
+
"repo": "git-hooks.nix",
|
|
46
|
+
"rev": "5eaaedde414f6eb1aea8b8525c466dc37bba95ae",
|
|
47
|
+
"type": "github"
|
|
48
|
+
},
|
|
49
|
+
"original": {
|
|
50
|
+
"owner": "cachix",
|
|
51
|
+
"repo": "git-hooks.nix",
|
|
52
|
+
"type": "github"
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
"gitignore": {
|
|
56
|
+
"inputs": {
|
|
57
|
+
"nixpkgs": [
|
|
58
|
+
"git-hooks",
|
|
59
|
+
"nixpkgs"
|
|
60
|
+
]
|
|
61
|
+
},
|
|
62
|
+
"locked": {
|
|
63
|
+
"lastModified": 1762808025,
|
|
64
|
+
"owner": "hercules-ci",
|
|
65
|
+
"repo": "gitignore.nix",
|
|
66
|
+
"rev": "cb5e3fdca1de58ccbc3ef53de65bd372b48f567c",
|
|
67
|
+
"type": "github"
|
|
68
|
+
},
|
|
69
|
+
"original": {
|
|
70
|
+
"owner": "hercules-ci",
|
|
71
|
+
"repo": "gitignore.nix",
|
|
72
|
+
"type": "github"
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
"nixpkgs": {
|
|
76
|
+
"inputs": {
|
|
77
|
+
"nixpkgs-src": "nixpkgs-src"
|
|
78
|
+
},
|
|
79
|
+
"locked": {
|
|
80
|
+
"lastModified": 1770434727,
|
|
81
|
+
"owner": "cachix",
|
|
82
|
+
"repo": "devenv-nixpkgs",
|
|
83
|
+
"rev": "8430f16a39c27bdeef236f1eeb56f0b51b33d348",
|
|
84
|
+
"type": "github"
|
|
85
|
+
},
|
|
86
|
+
"original": {
|
|
87
|
+
"owner": "cachix",
|
|
88
|
+
"ref": "rolling",
|
|
89
|
+
"repo": "devenv-nixpkgs",
|
|
90
|
+
"type": "github"
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
"nixpkgs-src": {
|
|
94
|
+
"flake": false,
|
|
95
|
+
"locked": {
|
|
96
|
+
"lastModified": 1769922788,
|
|
97
|
+
"narHash": "sha256-H3AfG4ObMDTkTJYkd8cz1/RbY9LatN5Mk4UF48VuSXc=",
|
|
98
|
+
"owner": "NixOS",
|
|
99
|
+
"repo": "nixpkgs",
|
|
100
|
+
"rev": "207d15f1a6603226e1e223dc79ac29c7846da32e",
|
|
101
|
+
"type": "github"
|
|
102
|
+
},
|
|
103
|
+
"original": {
|
|
104
|
+
"owner": "NixOS",
|
|
105
|
+
"ref": "nixpkgs-unstable",
|
|
106
|
+
"repo": "nixpkgs",
|
|
107
|
+
"type": "github"
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
"root": {
|
|
111
|
+
"inputs": {
|
|
112
|
+
"devenv": "devenv",
|
|
113
|
+
"git-hooks": "git-hooks",
|
|
114
|
+
"nixpkgs": "nixpkgs",
|
|
115
|
+
"pre-commit-hooks": [
|
|
116
|
+
"git-hooks"
|
|
117
|
+
]
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
"root": "root",
|
|
122
|
+
"version": 7
|
|
123
|
+
}
|
package/devenv.nix
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
pkgs,
|
|
3
|
+
lib,
|
|
4
|
+
config,
|
|
5
|
+
inputs,
|
|
6
|
+
...
|
|
7
|
+
}:
|
|
8
|
+
{
|
|
9
|
+
env.DEVENV_TASKS_QUIET = 1;
|
|
10
|
+
|
|
11
|
+
packages = with pkgs; [
|
|
12
|
+
graphicsmagick
|
|
13
|
+
nixfmt
|
|
14
|
+
pre-commit
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
languages = {
|
|
18
|
+
javascript = {
|
|
19
|
+
enable = true;
|
|
20
|
+
package = pkgs.nodejs_24;
|
|
21
|
+
npm = {
|
|
22
|
+
enable = true;
|
|
23
|
+
install = {
|
|
24
|
+
enable = true;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
dotenv = {
|
|
31
|
+
disableHint = true;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
enterShell = ''
|
|
35
|
+
if [ -d ".git" ]; then
|
|
36
|
+
pre-commit install --overwrite > /dev/null 2>&1
|
|
37
|
+
fi
|
|
38
|
+
'';
|
|
39
|
+
}
|
package/devenv.yaml
ADDED
|
@@ -217,54 +217,4 @@ describe('Penrose', () => {
|
|
|
217
217
|
await fs.remove(path.join(dir, 'data/files/styles'));
|
|
218
218
|
});
|
|
219
219
|
});
|
|
220
|
-
|
|
221
|
-
describe('createMathFile', () => {
|
|
222
|
-
test('Should create math files', async () => {
|
|
223
|
-
await fs.remove(path.join(dir, 'data/files/math'));
|
|
224
|
-
|
|
225
|
-
const math = [
|
|
226
|
-
{
|
|
227
|
-
data: 'E = mc^2',
|
|
228
|
-
format: 'tex'
|
|
229
|
-
}
|
|
230
|
-
];
|
|
231
|
-
|
|
232
|
-
const tasks = [];
|
|
233
|
-
const expected = [];
|
|
234
|
-
|
|
235
|
-
_.forEach(math, function (value) {
|
|
236
|
-
const outputFormat = 'svg';
|
|
237
|
-
const task = {
|
|
238
|
-
input: value.data,
|
|
239
|
-
inputFormat: value.format,
|
|
240
|
-
outputFormat: outputFormat
|
|
241
|
-
};
|
|
242
|
-
const filename = penrose.getMathFilename(task);
|
|
243
|
-
task.output = penrose.getMathPath(outputFormat, filename);
|
|
244
|
-
|
|
245
|
-
tasks.push(task);
|
|
246
|
-
|
|
247
|
-
expected.push(
|
|
248
|
-
path.join(config.schemes.public.path, 'math/svg', filename)
|
|
249
|
-
);
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
await Promise.mapSeries(tasks, function (task) {
|
|
253
|
-
return penrose.createMathFile(task);
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
const actual = await multiGlob(
|
|
257
|
-
_.map(config.schemes, function (scheme) {
|
|
258
|
-
return scheme.path + 'math/**/*';
|
|
259
|
-
}),
|
|
260
|
-
{
|
|
261
|
-
nodir: true
|
|
262
|
-
}
|
|
263
|
-
);
|
|
264
|
-
|
|
265
|
-
expect(actual).toEqual(expected);
|
|
266
|
-
|
|
267
|
-
await fs.remove(path.join(dir, 'data/files/math'));
|
|
268
|
-
});
|
|
269
|
-
});
|
|
270
220
|
});
|
package/lib/penrose.js
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
const _ = require('lodash');
|
|
2
|
-
const canonStringify = require('canonical-json/index2');
|
|
3
2
|
const chalk = require('chalk');
|
|
4
|
-
const cheerio = require('cheerio');
|
|
5
|
-
const crypto = require('crypto');
|
|
6
3
|
const fs = require('fs-extra');
|
|
7
|
-
const mathjax = require('mathjax-node/lib/mj-single.js');
|
|
8
4
|
const path = require('path');
|
|
9
|
-
const pkg = require('../package.json');
|
|
10
5
|
const Promise = require('bluebird');
|
|
11
6
|
const replaceExt = require('replace-ext');
|
|
12
7
|
const sharp = require('sharp');
|
|
@@ -20,10 +15,6 @@ const JPEG = 'jpeg';
|
|
|
20
15
|
const PNG = 'png';
|
|
21
16
|
const SVG = 'svg';
|
|
22
17
|
const WEBP = 'webp';
|
|
23
|
-
const TEX = 'tex';
|
|
24
|
-
const INLINE_TEX = 'inline-tex';
|
|
25
|
-
const ASCIIMATH = 'asciimath';
|
|
26
|
-
const MATHML = 'mathml';
|
|
27
18
|
const RESIZE = 'resize';
|
|
28
19
|
|
|
29
20
|
const EXTNAME_FORMAT_MAP = {
|
|
@@ -39,13 +30,6 @@ const FORMAT_EXTNAME_MAP = {
|
|
|
39
30
|
[WEBP]: 'webp'
|
|
40
31
|
};
|
|
41
32
|
|
|
42
|
-
const MATHJAX_FORMAT_MAP = {
|
|
43
|
-
[TEX]: 'TeX',
|
|
44
|
-
[INLINE_TEX]: 'inline-TeX',
|
|
45
|
-
[ASCIIMATH]: 'AsciiMath',
|
|
46
|
-
[MATHML]: 'MathML'
|
|
47
|
-
};
|
|
48
|
-
|
|
49
33
|
const JPEG_OPTIONS = [
|
|
50
34
|
'quality',
|
|
51
35
|
'progressive',
|
|
@@ -89,57 +73,6 @@ const RESIZE_OPTIONS = [
|
|
|
89
73
|
|
|
90
74
|
Promise.promisifyAll(fs);
|
|
91
75
|
|
|
92
|
-
/**
|
|
93
|
-
*
|
|
94
|
-
* @param {string} value
|
|
95
|
-
* @param {number} ex
|
|
96
|
-
* @returns {number}
|
|
97
|
-
*/
|
|
98
|
-
function exToPx(value, ex) {
|
|
99
|
-
const match = value.match(/^(.+)ex$/i);
|
|
100
|
-
|
|
101
|
-
if (match) {
|
|
102
|
-
return Number(match[1]) * ex;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
return Number(value);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
*
|
|
110
|
-
* @param {Object} args
|
|
111
|
-
* @returns {Promise}
|
|
112
|
-
*/
|
|
113
|
-
function typesetMath(args) {
|
|
114
|
-
const format = MATHJAX_FORMAT_MAP[args.inputFormat];
|
|
115
|
-
|
|
116
|
-
if (_.isUndefined(format)) {
|
|
117
|
-
throw new Error('Input format `' + args.inputFormat + '` is not supported');
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
if (!~[SVG].indexOf(args.outputFormat)) {
|
|
121
|
-
throw new Error(
|
|
122
|
-
'Output format `' + args.outputFormat + '` is not supported'
|
|
123
|
-
);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
return new Promise((resolve, reject) => {
|
|
127
|
-
const config = _.assign(_.pick(args, ['ex', 'width']), {
|
|
128
|
-
math: args.input,
|
|
129
|
-
format: format,
|
|
130
|
-
svg: true
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
mathjax.typeset(config, (result) => {
|
|
134
|
-
if (result.errors) {
|
|
135
|
-
reject(result.errors);
|
|
136
|
-
} else {
|
|
137
|
-
resolve(result);
|
|
138
|
-
}
|
|
139
|
-
});
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
|
|
143
76
|
/**
|
|
144
77
|
*
|
|
145
78
|
* @param {Object} config
|
|
@@ -147,30 +80,8 @@ function typesetMath(args) {
|
|
|
147
80
|
*/
|
|
148
81
|
function Penrose(config) {
|
|
149
82
|
this.config = {
|
|
150
|
-
...config
|
|
151
|
-
math: {
|
|
152
|
-
displayErrors: false,
|
|
153
|
-
displayMessages: false,
|
|
154
|
-
undefinedCharError: false,
|
|
155
|
-
MathJax: {
|
|
156
|
-
SVG: {
|
|
157
|
-
font: 'TeX'
|
|
158
|
-
}
|
|
159
|
-
},
|
|
160
|
-
ex: 6, // ex-size in pixels
|
|
161
|
-
width: 100, // Width of container (in ex) for linebreaking and tags
|
|
162
|
-
...config.math
|
|
163
|
-
}
|
|
83
|
+
...config
|
|
164
84
|
};
|
|
165
|
-
|
|
166
|
-
mathjax.config(
|
|
167
|
-
_.pick(this.config.math, [
|
|
168
|
-
'displayErrors',
|
|
169
|
-
'displayMessages',
|
|
170
|
-
'undefinedCharError',
|
|
171
|
-
'MathJax'
|
|
172
|
-
])
|
|
173
|
-
);
|
|
174
85
|
}
|
|
175
86
|
|
|
176
87
|
Penrose.prototype = {
|
|
@@ -234,140 +145,7 @@ Penrose.prototype = {
|
|
|
234
145
|
return transformer.toFile(distPath).then(() => distPath);
|
|
235
146
|
});
|
|
236
147
|
},
|
|
237
|
-
/**
|
|
238
|
-
*
|
|
239
|
-
* @param {Object} args
|
|
240
|
-
* @returns {Promise}
|
|
241
|
-
*/
|
|
242
|
-
createMath: function (args) {
|
|
243
|
-
console.log('Typesetting math', chalk.cyan(args.input));
|
|
244
|
-
|
|
245
|
-
const config = _.assign(
|
|
246
|
-
_.pick(this.config.math, ['ex', 'width']),
|
|
247
|
-
_.pick(args, ['input', 'inputFormat', 'outputFormat', 'ex', 'width'])
|
|
248
|
-
);
|
|
249
|
-
|
|
250
|
-
if (SVG === config.outputFormat) {
|
|
251
|
-
return typesetMath(config).then((result) => {
|
|
252
|
-
const $svg = cheerio.load(result.svg)('svg');
|
|
253
|
-
const width = Math.ceil(exToPx($svg.attr('width'), config.ex));
|
|
254
|
-
const height = Math.ceil(exToPx($svg.attr('height'), config.ex));
|
|
255
|
-
|
|
256
|
-
return Promise.resolve({
|
|
257
|
-
data: result.svg,
|
|
258
|
-
width: width,
|
|
259
|
-
height: height
|
|
260
|
-
});
|
|
261
|
-
});
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
throw new Error(
|
|
265
|
-
'Output format `' + config.outputFormat + '` is not supported'
|
|
266
|
-
);
|
|
267
|
-
},
|
|
268
|
-
/**
|
|
269
|
-
*
|
|
270
|
-
* @param {Object} args
|
|
271
|
-
* @returns {Promise}
|
|
272
|
-
*/
|
|
273
|
-
createMathDataURIBase64: function (args) {
|
|
274
|
-
console.log('Typesetting math', chalk.cyan(args.input));
|
|
275
|
-
|
|
276
|
-
const config = _.assign(
|
|
277
|
-
_.pick(this.config.math, ['ex', 'width']),
|
|
278
|
-
_.pick(args, ['input', 'inputFormat', 'outputFormat', 'ex', 'width'])
|
|
279
|
-
);
|
|
280
|
-
|
|
281
|
-
if (SVG === config.outputFormat) {
|
|
282
|
-
return typesetMath(config).then((result) => {
|
|
283
|
-
const buffer = Buffer.from(result.svg, 'utf-8');
|
|
284
148
|
|
|
285
|
-
return Promise.resolve(
|
|
286
|
-
'data:image/svg+xml;base64,' + buffer.toString('base64')
|
|
287
|
-
);
|
|
288
|
-
});
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
if (PNG === config.outputFormat) {
|
|
292
|
-
config.outputFormat = SVG;
|
|
293
|
-
|
|
294
|
-
return typesetMath(config)
|
|
295
|
-
.then((result) => {
|
|
296
|
-
const buffer = Buffer.from(result.svg, 'utf-8');
|
|
297
|
-
const $svg = cheerio.load(result.svg)('svg');
|
|
298
|
-
const width = Math.ceil(exToPx($svg.attr('width'), config.ex));
|
|
299
|
-
const height = Math.ceil(exToPx($svg.attr('height'), config.ex));
|
|
300
|
-
const resize = {
|
|
301
|
-
width: width,
|
|
302
|
-
height: height
|
|
303
|
-
};
|
|
304
|
-
|
|
305
|
-
return sharp(buffer).resize(resize).toBuffer();
|
|
306
|
-
})
|
|
307
|
-
.then((buffer) =>
|
|
308
|
-
Promise.resolve('data:image/png;base64,' + buffer.toString('base64'))
|
|
309
|
-
);
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
throw new Error(
|
|
313
|
-
'Output format `' + config.outputFormat + '` is not supported'
|
|
314
|
-
);
|
|
315
|
-
},
|
|
316
|
-
/**
|
|
317
|
-
*
|
|
318
|
-
* @param {Object} args
|
|
319
|
-
* @returns {Promise}
|
|
320
|
-
*/
|
|
321
|
-
createMathFile: function (args) {
|
|
322
|
-
console.log('Typesetting math', chalk.cyan(args.input));
|
|
323
|
-
|
|
324
|
-
const config = _.assign(
|
|
325
|
-
_.pick(this.config.math, ['ex', 'width']),
|
|
326
|
-
_.pick(args, [
|
|
327
|
-
'input',
|
|
328
|
-
'inputFormat',
|
|
329
|
-
'output',
|
|
330
|
-
'outputFormat',
|
|
331
|
-
'ex',
|
|
332
|
-
'width'
|
|
333
|
-
])
|
|
334
|
-
);
|
|
335
|
-
const outputResolved = this.resolvePath(config.output);
|
|
336
|
-
|
|
337
|
-
if (SVG === config.outputFormat) {
|
|
338
|
-
return fs
|
|
339
|
-
.mkdirp(path.dirname(outputResolved))
|
|
340
|
-
.then(() => typesetMath(config))
|
|
341
|
-
.then((result) =>
|
|
342
|
-
fs.writeFileAsync(outputResolved, result.svg, 'utf-8')
|
|
343
|
-
);
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
if (PNG === config.outputFormat) {
|
|
347
|
-
config.outputFormat = SVG;
|
|
348
|
-
|
|
349
|
-
return fs
|
|
350
|
-
.mkdirp(path.dirname(outputResolved))
|
|
351
|
-
.then(() => typesetMath(config))
|
|
352
|
-
.then((result) => {
|
|
353
|
-
const buffer = Buffer.from(result.svg, 'utf-8');
|
|
354
|
-
const $svg = cheerio.load(result.svg)('svg');
|
|
355
|
-
const width = Math.ceil(exToPx($svg.attr('width'), config.ex));
|
|
356
|
-
const height = Math.ceil(exToPx($svg.attr('height'), config.ex));
|
|
357
|
-
const resize = {
|
|
358
|
-
width: width,
|
|
359
|
-
height: height
|
|
360
|
-
};
|
|
361
|
-
|
|
362
|
-
return sharp(buffer).resize(resize).toBuffer();
|
|
363
|
-
})
|
|
364
|
-
.then((buffer) => fs.writeFileAsync(outputResolved, buffer));
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
throw new Error(
|
|
368
|
-
'Output format `' + config.outputFormat + '` is not supported'
|
|
369
|
-
);
|
|
370
|
-
},
|
|
371
149
|
/**
|
|
372
150
|
*
|
|
373
151
|
* @param {string} uri
|
|
@@ -382,6 +160,7 @@ Penrose.prototype = {
|
|
|
382
160
|
|
|
383
161
|
return uri.substring(0, index);
|
|
384
162
|
},
|
|
163
|
+
|
|
385
164
|
/**
|
|
386
165
|
*
|
|
387
166
|
* @param {string} uri
|
|
@@ -391,6 +170,7 @@ Penrose.prototype = {
|
|
|
391
170
|
setScheme: function (uri, scheme) {
|
|
392
171
|
return scheme + '://' + this.getTarget(uri);
|
|
393
172
|
},
|
|
173
|
+
|
|
394
174
|
/**
|
|
395
175
|
*
|
|
396
176
|
* @param {string} uri
|
|
@@ -405,6 +185,7 @@ Penrose.prototype = {
|
|
|
405
185
|
|
|
406
186
|
return uri.substring(index + 3);
|
|
407
187
|
},
|
|
188
|
+
|
|
408
189
|
/**
|
|
409
190
|
* Returns absolute URL.
|
|
410
191
|
*
|
|
@@ -420,6 +201,7 @@ Penrose.prototype = {
|
|
|
420
201
|
|
|
421
202
|
return uri;
|
|
422
203
|
},
|
|
204
|
+
|
|
423
205
|
/**
|
|
424
206
|
*
|
|
425
207
|
* @param {string} uri
|
|
@@ -443,6 +225,7 @@ Penrose.prototype = {
|
|
|
443
225
|
|
|
444
226
|
return schemePath + target;
|
|
445
227
|
},
|
|
228
|
+
|
|
446
229
|
/**
|
|
447
230
|
*
|
|
448
231
|
* @param {string} styleName
|
|
@@ -467,6 +250,7 @@ Penrose.prototype = {
|
|
|
467
250
|
|
|
468
251
|
return scheme + '://styles/' + styleName + '/' + target;
|
|
469
252
|
},
|
|
253
|
+
|
|
470
254
|
/**
|
|
471
255
|
* Returns absolute URL to derivative image.
|
|
472
256
|
*
|
|
@@ -483,75 +267,6 @@ Penrose.prototype = {
|
|
|
483
267
|
return '/' + this.resolvePath(uri);
|
|
484
268
|
}
|
|
485
269
|
|
|
486
|
-
throw new Error('Scheme `' + scheme + '` not supported');
|
|
487
|
-
},
|
|
488
|
-
/**
|
|
489
|
-
*
|
|
490
|
-
* @param {Object} args
|
|
491
|
-
* @returns {string}
|
|
492
|
-
*/
|
|
493
|
-
getMathDigest: function (args) {
|
|
494
|
-
const config = _.assign(
|
|
495
|
-
_.pick(this.config.math, ['ex', 'width']),
|
|
496
|
-
_.pick(args, ['ex', 'width'])
|
|
497
|
-
);
|
|
498
|
-
|
|
499
|
-
const data =
|
|
500
|
-
pkg.version + ';' + canonStringify(config) + ';' + args.input.trim();
|
|
501
|
-
|
|
502
|
-
return crypto.createHash('md5').update(data).digest('hex');
|
|
503
|
-
},
|
|
504
|
-
/**
|
|
505
|
-
*
|
|
506
|
-
* @param {Object} args
|
|
507
|
-
* @returns {string}
|
|
508
|
-
*/
|
|
509
|
-
getMathFilename: function (args) {
|
|
510
|
-
let ext;
|
|
511
|
-
|
|
512
|
-
if (SVG === args.outputFormat) {
|
|
513
|
-
ext = '.svg';
|
|
514
|
-
} else if (PNG === args.outputFormat) {
|
|
515
|
-
ext = '.png';
|
|
516
|
-
} else {
|
|
517
|
-
throw new Error('Format `' + args.outputFormat + '` is not supported');
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
return this.getMathDigest(args) + ext;
|
|
521
|
-
},
|
|
522
|
-
/**
|
|
523
|
-
*
|
|
524
|
-
* @param {string} outputFormat
|
|
525
|
-
* @param {string} uri
|
|
526
|
-
* @returns {string}
|
|
527
|
-
*/
|
|
528
|
-
getMathPath: function (outputFormat, uri) {
|
|
529
|
-
let scheme = this.getScheme(uri);
|
|
530
|
-
let target;
|
|
531
|
-
|
|
532
|
-
if (_.isUndefined(scheme)) {
|
|
533
|
-
scheme = PUBLIC;
|
|
534
|
-
target = uri;
|
|
535
|
-
} else {
|
|
536
|
-
target = this.getTarget(uri);
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
return scheme + '://math/' + outputFormat + '/' + target;
|
|
540
|
-
},
|
|
541
|
-
/**
|
|
542
|
-
*
|
|
543
|
-
* @param {string} outputFormat
|
|
544
|
-
* @param {string} path
|
|
545
|
-
* @returns {string}
|
|
546
|
-
*/
|
|
547
|
-
getMathURL: function (outputFormat, path) {
|
|
548
|
-
const uri = this.getMathPath(outputFormat, path);
|
|
549
|
-
const scheme = this.getScheme(uri);
|
|
550
|
-
|
|
551
|
-
if (PUBLIC === scheme || TEMPORARY === scheme) {
|
|
552
|
-
return '/' + this.resolvePath(uri);
|
|
553
|
-
}
|
|
554
|
-
|
|
555
270
|
throw new Error('Scheme `' + scheme + '` not supported');
|
|
556
271
|
}
|
|
557
272
|
};
|
|
@@ -561,10 +276,6 @@ module.exports = {
|
|
|
561
276
|
PNG,
|
|
562
277
|
SVG,
|
|
563
278
|
WEBP,
|
|
564
|
-
TEX,
|
|
565
|
-
INLINE_TEX,
|
|
566
|
-
ASCIIMATH,
|
|
567
|
-
MATHML,
|
|
568
279
|
RESIZE,
|
|
569
280
|
PUBLIC,
|
|
570
281
|
TEMPORARY,
|
package/package.json
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "penrose",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Build derivative images",
|
|
5
5
|
"main": "lib/penrose.js",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
|
-
"url": "git://github.com/netbek/penrose"
|
|
8
|
+
"url": "git://github.com/netbek/penrose.git"
|
|
9
9
|
},
|
|
10
10
|
"scripts": {
|
|
11
|
-
"format-js": "prettier --parser babel --write \"lib/**/*.js\"",
|
|
12
11
|
"test": "vitest run"
|
|
13
12
|
},
|
|
14
13
|
"author": {
|
|
@@ -21,34 +20,30 @@
|
|
|
21
20
|
"url": "https://github.com/netbek/penrose/issues"
|
|
22
21
|
},
|
|
23
22
|
"dependencies": {
|
|
24
|
-
"@babel/core": "7.
|
|
23
|
+
"@babel/core": "7.29.0",
|
|
25
24
|
"babel-eslint": "10.1.0",
|
|
26
25
|
"babel-loader": "8.4.1",
|
|
27
26
|
"babel-plugin-lodash": "3.3.4",
|
|
28
27
|
"babel-plugin-transform-class-properties": "6.24.1",
|
|
29
28
|
"bluebird": "3.7.2",
|
|
30
|
-
"canonical-json": "0.0.4",
|
|
31
29
|
"chalk": "4.1.2",
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"glob-promise": "4.2.2",
|
|
36
|
-
"lodash": "4.17.21",
|
|
30
|
+
"fs-extra": "11.3.5",
|
|
31
|
+
"glob-promise": "6.0.7",
|
|
32
|
+
"lodash": "4.18.1",
|
|
37
33
|
"lodash-webpack-plugin": "0.11.6",
|
|
38
|
-
"mathjax": "2.7.9",
|
|
39
|
-
"mathjax-node": "0.5.2",
|
|
40
34
|
"phantomjs-prebuilt": "2.1.16",
|
|
41
|
-
"prettier": "3.
|
|
35
|
+
"prettier": "3.8.3",
|
|
42
36
|
"replace-ext": "2.0.0",
|
|
43
|
-
"sharp": "0.
|
|
37
|
+
"sharp": "0.34.5"
|
|
44
38
|
},
|
|
45
39
|
"devDependencies": {
|
|
46
|
-
"@typescript-eslint/eslint-plugin": "
|
|
47
|
-
"@typescript-eslint/parser": "
|
|
40
|
+
"@typescript-eslint/eslint-plugin": "8.59.2",
|
|
41
|
+
"@typescript-eslint/parser": "8.59.2",
|
|
48
42
|
"eslint": "8.57.1",
|
|
49
|
-
"eslint-config-prettier": "9.1.
|
|
50
|
-
"eslint-plugin-prettier": "5.
|
|
51
|
-
"
|
|
52
|
-
"
|
|
43
|
+
"eslint-config-prettier": "9.1.2",
|
|
44
|
+
"eslint-plugin-prettier": "5.5.5",
|
|
45
|
+
"npm-check-updates": "22.1.1",
|
|
46
|
+
"typescript": "6.0.3",
|
|
47
|
+
"vitest": "3.2.4"
|
|
53
48
|
}
|
|
54
49
|
}
|
package/.circleci/config.yml
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
version: 2
|
|
2
|
-
jobs:
|
|
3
|
-
build:
|
|
4
|
-
docker:
|
|
5
|
-
- image: cimg/node:20.10.0-browsers
|
|
6
|
-
steps:
|
|
7
|
-
- checkout
|
|
8
|
-
- run:
|
|
9
|
-
name: Install dependencies
|
|
10
|
-
command: |
|
|
11
|
-
sudo npm install -g bower grunt-cli gulp-cli
|
|
12
|
-
sudo apt-get update -qq
|
|
13
|
-
sudo apt-get install -y -qq graphicsmagick
|
|
14
|
-
npm ci
|
|
15
|
-
- run:
|
|
16
|
-
name: Run tests
|
|
17
|
-
command: npm test
|