Fix details in scale, add test

This commit is contained in:
Roger Veciana Rovira 2025-06-04 23:10:01 +02:00
parent 39834741d4
commit cdeb211ae2
11 changed files with 489 additions and 20 deletions

View file

@ -16,6 +16,7 @@ This plugin allows you to edit and view recipes written in the Cooklang format.
- Multi language: The titles for the sections (i.e. *ingredients*, *cookware* and so on) will be translated into the recipe language or the one configured in the Obsidian settings
- Scale quantities: The slider in the ingredients part allows multiplying or dividing the amounts
## Searching
Obsidian won't search files that aren't of the extension *.md by default. Since cooklang has the .cook extension, any search will gnore the files, which is really impractical. Fortuntely, there's a workaround:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 MiB

After

Width:  |  Height:  |  Size: 2.2 MiB

405
package-lock.json generated
View file

@ -15,6 +15,7 @@
"@svelte-plugins/tooltips": "^3.0.3",
"@sveltejs/vite-plugin-svelte": "^5.1.0",
"@tsconfig/svelte": "^5.0.4",
"@types/node": "^22.15.29",
"@typescript-eslint/parser": "^8.33.1",
"builtin-modules": "^5.0.0",
"esbuild-svelte": "^0.9.3",
@ -32,7 +33,8 @@
"typescript": "~5.8.3",
"typescript-eslint": "^8.33.0",
"vite": "^6.3.5",
"vite-plugin-static-copy": "^3.0.0"
"vite-plugin-static-copy": "^3.0.0",
"vitest": "^3.2.1"
}
},
"node_modules/@ampproject/remapping": {
@ -1084,6 +1086,15 @@
"integrity": "sha512-BV9NplVgLmSi4mwKzD8BD/NQ8erOY/nUE/GpgWe2ckx+wIQF5RyRirn/QsSSCPeulVpc3RA/iJt6DpfTIZps0Q==",
"dev": true
},
"node_modules/@types/chai": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.2.tgz",
"integrity": "sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==",
"dev": true,
"dependencies": {
"@types/deep-eql": "*"
}
},
"node_modules/@types/codemirror": {
"version": "5.60.8",
"resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-5.60.8.tgz",
@ -1093,6 +1104,12 @@
"@types/tern": "*"
}
},
"node_modules/@types/deep-eql": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz",
"integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==",
"dev": true
},
"node_modules/@types/estree": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz",
@ -1104,6 +1121,15 @@
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
"dev": true
},
"node_modules/@types/node": {
"version": "22.15.29",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.29.tgz",
"integrity": "sha512-LNdjOkUDlU1RZb8e1kOIUpN1qQUlzGkEtbVNo53vbrwDg5om6oduhm4SiUaPW5ASTXhAiP0jInWG8Qx9fVlOeQ==",
"dev": true,
"dependencies": {
"undici-types": "~6.21.0"
}
},
"node_modules/@types/tern": {
"version": "0.23.9",
"resolved": "https://registry.npmjs.org/@types/tern/-/tern-0.23.9.tgz",
@ -1490,6 +1516,113 @@
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@vitest/expect": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.1.tgz",
"integrity": "sha512-FqS/BnDOzV6+IpxrTg5GQRyLOCtcJqkwMwcS8qGCI2IyRVDwPAtutztaf1CjtPHlZlWtl1yUPCd7HM0cNiDOYw==",
"dev": true,
"dependencies": {
"@types/chai": "^5.2.2",
"@vitest/spy": "3.2.1",
"@vitest/utils": "3.2.1",
"chai": "^5.2.0",
"tinyrainbow": "^2.0.0"
},
"funding": {
"url": "https://opencollective.com/vitest"
}
},
"node_modules/@vitest/mocker": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.1.tgz",
"integrity": "sha512-OXxMJnx1lkB+Vl65Re5BrsZEHc90s5NMjD23ZQ9NlU7f7nZiETGoX4NeKZSmsKjseuMq2uOYXdLOeoM0pJU+qw==",
"dev": true,
"dependencies": {
"@vitest/spy": "3.2.1",
"estree-walker": "^3.0.3",
"magic-string": "^0.30.17"
},
"funding": {
"url": "https://opencollective.com/vitest"
},
"peerDependencies": {
"msw": "^2.4.9",
"vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0"
},
"peerDependenciesMeta": {
"msw": {
"optional": true
},
"vite": {
"optional": true
}
}
},
"node_modules/@vitest/pretty-format": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.1.tgz",
"integrity": "sha512-xBh1X2GPlOGBupp6E1RcUQWIxw0w/hRLd3XyBS6H+dMdKTAqHDNsIR2AnJwPA3yYe9DFy3VUKTe3VRTrAiQ01g==",
"dev": true,
"dependencies": {
"tinyrainbow": "^2.0.0"
},
"funding": {
"url": "https://opencollective.com/vitest"
}
},
"node_modules/@vitest/runner": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.1.tgz",
"integrity": "sha512-kygXhNTu/wkMYbwYpS3z/9tBe0O8qpdBuC3dD/AW9sWa0LE/DAZEjnHtWA9sIad7lpD4nFW1yQ+zN7mEKNH3yA==",
"dev": true,
"dependencies": {
"@vitest/utils": "3.2.1",
"pathe": "^2.0.3"
},
"funding": {
"url": "https://opencollective.com/vitest"
}
},
"node_modules/@vitest/snapshot": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.1.tgz",
"integrity": "sha512-5xko/ZpW2Yc65NVK9Gpfg2y4BFvcF+At7yRT5AHUpTg9JvZ4xZoyuRY4ASlmNcBZjMslV08VRLDrBOmUe2YX3g==",
"dev": true,
"dependencies": {
"@vitest/pretty-format": "3.2.1",
"magic-string": "^0.30.17",
"pathe": "^2.0.3"
},
"funding": {
"url": "https://opencollective.com/vitest"
}
},
"node_modules/@vitest/spy": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.1.tgz",
"integrity": "sha512-Nbfib34Z2rfcJGSetMxjDCznn4pCYPZOtQYox2kzebIJcgH75yheIKd5QYSFmR8DIZf2M8fwOm66qSDIfRFFfQ==",
"dev": true,
"dependencies": {
"tinyspy": "^4.0.3"
},
"funding": {
"url": "https://opencollective.com/vitest"
}
},
"node_modules/@vitest/utils": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.1.tgz",
"integrity": "sha512-KkHlGhePEKZSub5ViknBcN5KEF+u7dSUr9NW8QsVICusUojrgrOnnY3DEWWO877ax2Pyopuk2qHmt+gkNKnBVw==",
"dev": true,
"dependencies": {
"@vitest/pretty-format": "3.2.1",
"loupe": "^3.1.3",
"tinyrainbow": "^2.0.0"
},
"funding": {
"url": "https://opencollective.com/vitest"
}
},
"node_modules/acorn": {
"version": "8.14.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
@ -1580,6 +1713,15 @@
"node": ">= 0.4"
}
},
"node_modules/assertion-error": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz",
"integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==",
"dev": true,
"engines": {
"node": ">=12"
}
},
"node_modules/axobject-query": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
@ -1640,6 +1782,15 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/cac": {
"version": "6.7.14",
"resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz",
"integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/callsites": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
@ -1649,6 +1800,22 @@
"node": ">=6"
}
},
"node_modules/chai": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/chai/-/chai-5.2.0.tgz",
"integrity": "sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==",
"dev": true,
"dependencies": {
"assertion-error": "^2.0.1",
"check-error": "^2.1.1",
"deep-eql": "^5.0.1",
"loupe": "^3.1.0",
"pathval": "^2.0.0"
},
"engines": {
"node": ">=12"
}
},
"node_modules/chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
@ -1665,6 +1832,15 @@
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
"node_modules/check-error": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz",
"integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==",
"dev": true,
"engines": {
"node": ">= 16"
}
},
"node_modules/chokidar": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
@ -1772,6 +1948,15 @@
}
}
},
"node_modules/deep-eql": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz",
"integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==",
"dev": true,
"engines": {
"node": ">=6"
}
},
"node_modules/deep-is": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
@ -1787,6 +1972,12 @@
"node": ">=0.10.0"
}
},
"node_modules/es-module-lexer": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz",
"integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==",
"dev": true
},
"node_modules/esbuild": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.5.tgz",
@ -2051,6 +2242,15 @@
"node": ">=4.0"
}
},
"node_modules/estree-walker": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
"integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
"dev": true,
"dependencies": {
"@types/estree": "^1.0.0"
}
},
"node_modules/esutils": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
@ -2060,6 +2260,15 @@
"node": ">=0.10.0"
}
},
"node_modules/expect-type": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.1.tgz",
"integrity": "sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw==",
"dev": true,
"engines": {
"node": ">=12.0.0"
}
},
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
@ -2534,6 +2743,12 @@
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
"dev": true
},
"node_modules/loupe": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.3.tgz",
"integrity": "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==",
"dev": true
},
"node_modules/magic-string": {
"version": "0.30.17",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz",
@ -2758,6 +2973,21 @@
"node": ">=8"
}
},
"node_modules/pathe": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
"integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
"dev": true
},
"node_modules/pathval": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz",
"integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==",
"dev": true,
"engines": {
"node": ">= 14.16"
}
},
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
@ -3084,6 +3314,12 @@
"node": ">=8"
}
},
"node_modules/siginfo": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz",
"integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==",
"dev": true
},
"node_modules/source-map-js": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
@ -3093,6 +3329,18 @@
"node": ">=0.10.0"
}
},
"node_modules/stackback": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz",
"integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==",
"dev": true
},
"node_modules/std-env": {
"version": "3.9.0",
"resolved": "https://registry.npmjs.org/std-env/-/std-env-3.9.0.tgz",
"integrity": "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==",
"dev": true
},
"node_modules/strip-json-comments": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
@ -3272,6 +3520,18 @@
"svelte": "^4.2.7 || ^5.0.0"
}
},
"node_modules/tinybench": {
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz",
"integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==",
"dev": true
},
"node_modules/tinyexec": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz",
"integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==",
"dev": true
},
"node_modules/tinyglobby": {
"version": "0.2.14",
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz",
@ -3288,6 +3548,33 @@
"url": "https://github.com/sponsors/SuperchupuDev"
}
},
"node_modules/tinypool": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.0.tgz",
"integrity": "sha512-7CotroY9a8DKsKprEy/a14aCCm8jYVmR7aFy4fpkZM8sdpNJbKkixuNjgM50yCmip2ezc8z4N7k3oe2+rfRJCQ==",
"dev": true,
"engines": {
"node": "^18.0.0 || >=20.0.0"
}
},
"node_modules/tinyrainbow": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz",
"integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==",
"dev": true,
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/tinyspy": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-4.0.3.tgz",
"integrity": "sha512-t2T/WLB2WRgZ9EpE4jgPJ9w+i66UZfDc8wHh0xrwiRNN+UwH98GIJkTeZqX9rg0i0ptwzqW+uYeIF0T4F8LR7A==",
"dev": true,
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
@ -3403,6 +3690,12 @@
"typescript": ">=4.8.4 <5.9.0"
}
},
"node_modules/undici-types": {
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
"dev": true
},
"node_modules/universalify": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
@ -3501,6 +3794,28 @@
}
}
},
"node_modules/vite-node": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.2.1.tgz",
"integrity": "sha512-V4EyKQPxquurNJPtQJRZo8hKOoKNBRIhxcDbQFPFig0JdoWcUhwRgK8yoCXXrfYVPKS6XwirGHPszLnR8FbjCA==",
"dev": true,
"dependencies": {
"cac": "^6.7.14",
"debug": "^4.4.1",
"es-module-lexer": "^1.7.0",
"pathe": "^2.0.3",
"vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0"
},
"bin": {
"vite-node": "vite-node.mjs"
},
"engines": {
"node": "^18.0.0 || ^20.0.0 || >=22.0.0"
},
"funding": {
"url": "https://opencollective.com/vitest"
}
},
"node_modules/vite-plugin-static-copy": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/vite-plugin-static-copy/-/vite-plugin-static-copy-3.0.0.tgz",
@ -3598,6 +3913,78 @@
}
}
},
"node_modules/vitest": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.1.tgz",
"integrity": "sha512-VZ40MBnlE1/V5uTgdqY3DmjUgZtIzsYq758JGlyQrv5syIsaYcabkfPkEuWML49Ph0D/SoqpVFd0dyVTr551oA==",
"dev": true,
"dependencies": {
"@types/chai": "^5.2.2",
"@vitest/expect": "3.2.1",
"@vitest/mocker": "3.2.1",
"@vitest/pretty-format": "^3.2.1",
"@vitest/runner": "3.2.1",
"@vitest/snapshot": "3.2.1",
"@vitest/spy": "3.2.1",
"@vitest/utils": "3.2.1",
"chai": "^5.2.0",
"debug": "^4.4.1",
"expect-type": "^1.2.1",
"magic-string": "^0.30.17",
"pathe": "^2.0.3",
"picomatch": "^4.0.2",
"std-env": "^3.9.0",
"tinybench": "^2.9.0",
"tinyexec": "^0.3.2",
"tinyglobby": "^0.2.14",
"tinypool": "^1.1.0",
"tinyrainbow": "^2.0.0",
"vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0",
"vite-node": "3.2.1",
"why-is-node-running": "^2.3.0"
},
"bin": {
"vitest": "vitest.mjs"
},
"engines": {
"node": "^18.0.0 || ^20.0.0 || >=22.0.0"
},
"funding": {
"url": "https://opencollective.com/vitest"
},
"peerDependencies": {
"@edge-runtime/vm": "*",
"@types/debug": "^4.1.12",
"@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
"@vitest/browser": "3.2.1",
"@vitest/ui": "3.2.1",
"happy-dom": "*",
"jsdom": "*"
},
"peerDependenciesMeta": {
"@edge-runtime/vm": {
"optional": true
},
"@types/debug": {
"optional": true
},
"@types/node": {
"optional": true
},
"@vitest/browser": {
"optional": true
},
"@vitest/ui": {
"optional": true
},
"happy-dom": {
"optional": true
},
"jsdom": {
"optional": true
}
}
},
"node_modules/w3c-keyname": {
"version": "2.2.8",
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz",
@ -3620,6 +4007,22 @@
"node": ">= 8"
}
},
"node_modules/why-is-node-running": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz",
"integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==",
"dev": true,
"dependencies": {
"siginfo": "^2.0.0",
"stackback": "0.0.2"
},
"bin": {
"why-is-node-running": "cli.js"
},
"engines": {
"node": ">=8"
}
},
"node_modules/word-wrap": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",

View file

@ -7,6 +7,7 @@
"scripts": {
"lint": "eslint . --ext .ts",
"dev": "npm run lint && vite build --watch",
"test": "vitest",
"build": "npx svelte-check && vite build",
"bumpversion": "node version-bump.mjs && git add manifest.json versions.json && git commit -m 'bump version'",
"postversion": "npm run bumpversion",
@ -23,6 +24,7 @@
"@svelte-plugins/tooltips": "^3.0.3",
"@sveltejs/vite-plugin-svelte": "^5.1.0",
"@tsconfig/svelte": "^5.0.4",
"@types/node": "^22.15.29",
"@typescript-eslint/parser": "^8.33.1",
"builtin-modules": "^5.0.0",
"esbuild-svelte": "^0.9.3",
@ -40,7 +42,8 @@
"typescript": "~5.8.3",
"typescript-eslint": "^8.33.0",
"vite": "^6.3.5",
"vite-plugin-static-copy": "^3.0.0"
"vite-plugin-static-copy": "^3.0.0",
"vitest": "^3.2.1"
},
"dependencies": {
"svelte-range-slider-pips": "^4.0.0"

View file

@ -16,6 +16,7 @@ import View from "./ui/View.svelte";
import { DEFAULT_SETTINGS, Settings, type CookLangSettings } from "./ui/Settings.js";
import { getI18n, isTFile } from "./ui/utils.js";
import { mount, unmount } from "svelte";
import { Parser, type ParseResult } from "@cooklang/cooklang-ts";
const VIEW_TYPE = "svelte-cooklang";
@ -125,9 +126,13 @@ class CooklangSvelteView extends TextFileView {
return acc;
}, {} as Record<string, string>);
this.images = images;
if(this.settings.autoLanguage){
const lang = getI18n(data);
const recipe: ParseResult = new Parser().parse(data);
if(recipe.metadata.locale){
const lang = recipe.metadata.locale.split("_")[0]
i18next.changeLanguage(lang);
} else if(this.settings.autoLanguage){
const lang = getI18n(data);
i18next.changeLanguage(lang);
}

View file

@ -16,7 +16,7 @@
let scaleIdx = $state(2);
let scale = $derived(scales[scaleIdx]);
const translateIngredientsQuantity = (quantity: string | number, scale: number) =>
const translateIngredientsQuantity = (quantity: string | number, scale: number = 1) =>
quantity === 'some'
? $i18n.t('some')
: formatNumber(quantity, settings.showFractionsInQuantities, scale);
@ -109,7 +109,7 @@
<style>
.image-main {
width: 100%;
max-width: 300px;
}
section {
border: 1px solid #ccc;

36
src/ui/utils.test.ts Normal file
View file

@ -0,0 +1,36 @@
import { describe, it, expect, vi } from 'vitest';
import { formatNumber } from './utils.js';
describe('formatNumber', () => {
it('Should parse a simple string with a number only', () => {
expect(formatNumber(2)).toBe("2");
});
it('Should parse a simple string with a string only', () => {
expect(formatNumber("hello")).toBe("hello");
});
it('Should parse a string with a number and a string', () => {
expect(formatNumber("2 kilos")).toBe("2 kilos");
expect(formatNumber("about 2 kilos")).toBe("about 2 kilos");
});
it('Should parse a string with a scaled number and a string', () => {
expect(formatNumber("2 kilos", true, 2)).toBe("4 kilos");
expect(formatNumber("2 kilos", true, 0.5)).toBe("1 kilos");
});
it('Should parse a string with a scaled number with decimals', () => {
expect(formatNumber("2.5 kilos", true, 2)).toBe("5 kilos");
});
it('Should parse a string with a scaled number with decimals, rounding to une decimal', () => {
expect(formatNumber("2.55 kilos")).toBe("2.5 kilos");
expect(formatNumber("1 kilos", false, 0.3333333)).toBe("0.3 kilos");
});
it('Should convert to fractions', () => {
expect(formatNumber(0.33333, true)).toBe("1/3");
expect(formatNumber(0.5, true)).toBe("1/2");
expect(formatNumber(0.2, true)).toBe("1/5");
});
});

View file

@ -40,7 +40,7 @@ export const getI18n = (data:string) => {
}
const formatFraction = (num:number, useFraction:boolean=false) =>{
if(!useFraction) return num.toString();
if(!useFraction) return +num.toFixed( 1 );
const epsilon = 0.0001;
if (Math.abs(num - 1 / 2) < epsilon) return "1/2";
else if (Math.abs(num - 1 / 3) < epsilon) return "1/3";
@ -69,7 +69,7 @@ const formatFraction = (num:number, useFraction:boolean=false) =>{
}
export const formatNumber = (num: number|string, useFraction:boolean=false, scale=1): string => {
const str = String(num);
const parts = str.match(/\d+|[a-zA-Z']+/g);
const parts = str.match(/\d+(\.\d+)?|[a-zA-Z']+/g);
if (!parts) return str;
return parts.map(part => /^\d+$/.test(part) ? formatFraction(Number(part)*scale, useFraction) : part).join("");
return parts.map(part => /^\d+(\.\d+)?$/.test(part) ? formatFraction(Number(part)*scale, useFraction) : part).join(" ");
};

View file

@ -1327,17 +1327,17 @@
transition: opacity 0.2s ease;
}
.image-main.svelte-13gknjv {
width: 100%;
.image-main.svelte-8gj1x5 {
max-width: 300px;
}
section.svelte-13gknjv {
section.svelte-8gj1x5 {
border: 1px solid #ccc;
border-radius: 0.25rem;
padding: 10px;
margin-top: 10px;
position: relative;
}
.section-title.svelte-13gknjv {
.section-title.svelte-8gj1x5 {
display: inline-block;
left: 5px;
top: -1.5rem;
@ -1353,27 +1353,27 @@
background-color: var(--background-primary);
}
.servings.svelte-13gknjv {
.servings.svelte-8gj1x5 {
width: fit-content;
}
ul.ingredients.svelte-13gknjv {
ul.ingredients.svelte-8gj1x5 {
column-count: 2;
}
ul.cookware.svelte-13gknjv {
ul.cookware.svelte-8gj1x5 {
column-count: 2;
}
span.cookware.svelte-13gknjv {
span.cookware.svelte-8gj1x5 {
font-weight: 600;
}
span.ingredient.svelte-13gknjv {
span.ingredient.svelte-8gj1x5 {
font-weight: 600;
}
span.timer.svelte-13gknjv {
span.timer.svelte-8gj1x5 {
font-weight: 600;
}

View file

@ -0,0 +1,7 @@
// test/__mocks__/obsidian.ts
export class TFile {
path: string = "";
name: string = "";
}
export type TAbstractFile = TFile;

14
vitest.config.ts Normal file
View file

@ -0,0 +1,14 @@
import { defineConfig } from 'vitest/config';
import path from 'path';
export default defineConfig({
test: {
environment: 'node',
globals: true,
},
resolve: {
alias: {
obsidian: path.resolve(__dirname, 'test/__mocks__/obsidian.ts'),
},
},
});