From e4f6258a7357967263aad9a902e49f73a35c5305 Mon Sep 17 00:00:00 2001 From: Emiliano Heyns Date: Mon, 6 Jun 2022 00:45:14 +0200 Subject: [PATCH 1/6] edtf format validator --- .gitignore | 1 + package-lock.json | 504 ++++++++++++++++++++++++++++++++++++++++++ package.json | 39 ++++ tests/json-schema.js | 29 +++ validator/ajv.js | 8 + validator/formats.js | 24 ++ validator/z-schema.js | 10 + 7 files changed, 615 insertions(+) create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 tests/json-schema.js create mode 100644 validator/ajv.js create mode 100644 validator/formats.js create mode 100644 validator/z-schema.js diff --git a/.gitignore b/.gitignore index 2e59f740..969ca811 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ __pycache__/ .pytest_cache/ venv/ .rng +node_modules diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..4d00c899 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,504 @@ +{ + "name": "csl-schema", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "csl-schema", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "edtf": "^4.1.0" + }, + "devDependencies": { + "ajv": "^8.11.0", + "is-my-json-valid": "^2.20.6", + "jsen": "^0.6.6", + "z-schema": "^5.0.3" + } + }, + "node_modules/ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "node_modules/discontinuous-range": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", + "integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==" + }, + "node_modules/drange": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/drange/-/drange-1.1.1.tgz", + "integrity": "sha512-pYxfDYpued//QpnLIm4Avk7rsNtAtQkUES2cwAYSvD/wd2pKD71gN2Ebj3e7klzXwjocvE8c5vx/1fxwpqmSxA==", + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/edtf": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/edtf/-/edtf-4.1.0.tgz", + "integrity": "sha512-o35Mm58gQVK1onYr/Ro4Obx0OdMrk80WJp2p36rWC+Dr+Duevvm1ptxt76E+xyyEEHGIGaAvypT76poDgQ5o0Q==", + "dependencies": { + "nearley": "^2.19.7" + }, + "optionalDependencies": { + "randexp": "^0.5.3" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "dev": true, + "dependencies": { + "is-property": "^1.0.2" + } + }, + "node_modules/generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha512-TuOwZWgJ2VAMEGJvAyPWvpqxSANF0LDpmyHauMjFYzaACvn+QTT/AZomvPCzVBV7yDN3OmwHQ5OvHaeLKre3JQ==", + "dev": true, + "dependencies": { + "is-property": "^1.0.0" + } + }, + "node_modules/is-my-ip-valid": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.1.tgz", + "integrity": "sha512-jxc8cBcOWbNK2i2aTkCZP6i7wkHF1bqKFrwEHuN5Jtg5BSaZHUZQ/JTOJwoV41YvHnOaRyWWh72T/KvfNz9DJg==", + "dev": true + }, + "node_modules/is-my-json-valid": { + "version": "2.20.6", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.20.6.tgz", + "integrity": "sha512-1JQwulVNjx8UqkPE/bqDaxtH4PXCe/2VRh/y3p99heOV87HG4Id5/VfDswd+YiAfHcRTfDlWgISycnHuhZq1aw==", + "dev": true, + "dependencies": { + "generate-function": "^2.0.0", + "generate-object-property": "^1.1.0", + "is-my-ip-valid": "^1.0.0", + "jsonpointer": "^5.0.0", + "xtend": "^4.0.0" + } + }, + "node_modules/is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==", + "dev": true + }, + "node_modules/jsen": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/jsen/-/jsen-0.6.6.tgz", + "integrity": "sha512-Kq9+wZsdGd/VrCw67vS38HkBFVg6pikAtL9lA8SQvKzlaxV/d2ot87BabQ6b+QH1EsjCCV4l/+14Gq+1kwdkCg==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/jsonpointer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.0.tgz", + "integrity": "sha512-PNYZIdMjVIvVgDSYKTT63Y+KZ6IZvGRNNWcxwD+GNnUz1MKPfv30J8ueCjdwcN0nDx2SlshgyB7Oy0epAzVRRg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", + "dev": true + }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", + "dev": true + }, + "node_modules/moo": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.1.tgz", + "integrity": "sha512-I1mnb5xn4fO80BH9BLcF0yLypy2UKl+Cb01Fu0hJRkJjlCRtxZMWkTdAtDd5ZqCOxtCkhmRwyI57vWT+1iZ67w==" + }, + "node_modules/nearley": { + "version": "2.20.1", + "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz", + "integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==", + "dependencies": { + "commander": "^2.19.0", + "moo": "^0.5.0", + "railroad-diagrams": "^1.0.0", + "randexp": "0.4.6" + }, + "bin": { + "nearley-railroad": "bin/nearley-railroad.js", + "nearley-test": "bin/nearley-test.js", + "nearley-unparse": "bin/nearley-unparse.js", + "nearleyc": "bin/nearleyc.js" + }, + "funding": { + "type": "individual", + "url": "https://nearley.js.org/#give-to-nearley" + } + }, + "node_modules/nearley/node_modules/randexp": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", + "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", + "dependencies": { + "discontinuous-range": "1.0.0", + "ret": "~0.1.10" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/nearley/node_modules/ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "engines": { + "node": ">=0.12" + } + }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/railroad-diagrams": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", + "integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==" + }, + "node_modules/randexp": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.5.3.tgz", + "integrity": "sha512-U+5l2KrcMNOUPYvazA3h5ekF80FHTUG+87SEAmHZmolh1M+i/WyTCxVzmi+tidIa1tM4BSe8g2Y/D3loWDjj+w==", + "optional": true, + "dependencies": { + "drange": "^1.0.2", + "ret": "^0.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ret": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.2.2.tgz", + "integrity": "sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ==", + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/validator": { + "version": "13.7.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz", + "integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/z-schema": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-5.0.3.tgz", + "integrity": "sha512-sGvEcBOTNum68x9jCpCVGPFJ6mWnkD0YxOcddDlJHRx3tKdB2q8pCHExMVZo/AV/6geuVJXG7hljDaWG8+5GDw==", + "dev": true, + "dependencies": { + "lodash.get": "^4.4.2", + "lodash.isequal": "^4.5.0", + "validator": "^13.7.0" + }, + "bin": { + "z-schema": "bin/z-schema" + }, + "engines": { + "node": ">=8.0.0" + }, + "optionalDependencies": { + "commander": "^2.20.3" + } + } + }, + "dependencies": { + "ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "discontinuous-range": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", + "integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==" + }, + "drange": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/drange/-/drange-1.1.1.tgz", + "integrity": "sha512-pYxfDYpued//QpnLIm4Avk7rsNtAtQkUES2cwAYSvD/wd2pKD71gN2Ebj3e7klzXwjocvE8c5vx/1fxwpqmSxA==", + "optional": true + }, + "edtf": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/edtf/-/edtf-4.1.0.tgz", + "integrity": "sha512-o35Mm58gQVK1onYr/Ro4Obx0OdMrk80WJp2p36rWC+Dr+Duevvm1ptxt76E+xyyEEHGIGaAvypT76poDgQ5o0Q==", + "requires": { + "nearley": "^2.19.7", + "randexp": "^0.5.3" + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "dev": true, + "requires": { + "is-property": "^1.0.2" + } + }, + "generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha512-TuOwZWgJ2VAMEGJvAyPWvpqxSANF0LDpmyHauMjFYzaACvn+QTT/AZomvPCzVBV7yDN3OmwHQ5OvHaeLKre3JQ==", + "dev": true, + "requires": { + "is-property": "^1.0.0" + } + }, + "is-my-ip-valid": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.1.tgz", + "integrity": "sha512-jxc8cBcOWbNK2i2aTkCZP6i7wkHF1bqKFrwEHuN5Jtg5BSaZHUZQ/JTOJwoV41YvHnOaRyWWh72T/KvfNz9DJg==", + "dev": true + }, + "is-my-json-valid": { + "version": "2.20.6", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.20.6.tgz", + "integrity": "sha512-1JQwulVNjx8UqkPE/bqDaxtH4PXCe/2VRh/y3p99heOV87HG4Id5/VfDswd+YiAfHcRTfDlWgISycnHuhZq1aw==", + "dev": true, + "requires": { + "generate-function": "^2.0.0", + "generate-object-property": "^1.1.0", + "is-my-ip-valid": "^1.0.0", + "jsonpointer": "^5.0.0", + "xtend": "^4.0.0" + } + }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==", + "dev": true + }, + "jsen": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/jsen/-/jsen-0.6.6.tgz", + "integrity": "sha512-Kq9+wZsdGd/VrCw67vS38HkBFVg6pikAtL9lA8SQvKzlaxV/d2ot87BabQ6b+QH1EsjCCV4l/+14Gq+1kwdkCg==", + "dev": true + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "jsonpointer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.0.tgz", + "integrity": "sha512-PNYZIdMjVIvVgDSYKTT63Y+KZ6IZvGRNNWcxwD+GNnUz1MKPfv30J8ueCjdwcN0nDx2SlshgyB7Oy0epAzVRRg==", + "dev": true + }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", + "dev": true + }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", + "dev": true + }, + "moo": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.1.tgz", + "integrity": "sha512-I1mnb5xn4fO80BH9BLcF0yLypy2UKl+Cb01Fu0hJRkJjlCRtxZMWkTdAtDd5ZqCOxtCkhmRwyI57vWT+1iZ67w==" + }, + "nearley": { + "version": "2.20.1", + "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz", + "integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==", + "requires": { + "commander": "^2.19.0", + "moo": "^0.5.0", + "railroad-diagrams": "^1.0.0", + "randexp": "0.4.6" + }, + "dependencies": { + "randexp": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", + "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", + "requires": { + "discontinuous-range": "1.0.0", + "ret": "~0.1.10" + } + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" + } + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "railroad-diagrams": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", + "integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==" + }, + "randexp": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.5.3.tgz", + "integrity": "sha512-U+5l2KrcMNOUPYvazA3h5ekF80FHTUG+87SEAmHZmolh1M+i/WyTCxVzmi+tidIa1tM4BSe8g2Y/D3loWDjj+w==", + "optional": true, + "requires": { + "drange": "^1.0.2", + "ret": "^0.2.0" + } + }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true + }, + "ret": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.2.2.tgz", + "integrity": "sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ==", + "optional": true + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "validator": { + "version": "13.7.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz", + "integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==", + "dev": true + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + }, + "z-schema": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-5.0.3.tgz", + "integrity": "sha512-sGvEcBOTNum68x9jCpCVGPFJ6mWnkD0YxOcddDlJHRx3tKdB2q8pCHExMVZo/AV/6geuVJXG7hljDaWG8+5GDw==", + "dev": true, + "requires": { + "commander": "^2.20.3", + "lodash.get": "^4.4.2", + "lodash.isequal": "^4.5.0", + "validator": "^13.7.0" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 00000000..6296b055 --- /dev/null +++ b/package.json @@ -0,0 +1,39 @@ +{ + "name": "csl-schema", + "version": "1.0.0", + "description": "Citation Style Language schema", + "main": "index.js", + "directories": { + "test": "tests" + }, + "scripts": { + "test": "node tests/json-schema.js" + }, + "repository": { + "type": "git", + "url": "https://github.com/citation-style-language/schema.git" + }, + "author": "", + "license": "ISC", + "bugs": { + "url": "https://github.com/citation-style-language/schema/issues" + }, + "homepage": "https://github.com/citation-style-language/schema#readme", + "files": [ + "schemas/input/csl-citation.json", + "schemas/input/csl-data.json", + "schemas/styles/stop-words.json", + "validator/ajv.js", + "validator/formats.js", + "validator/z-schema.js" + ], + "dependencies": { + "edtf": "^4.1.0" + }, + "devDependencies": { + "ajv": "^8.11.0", + "is-my-json-valid": "^2.20.6", + "jsen": "^0.6.6", + "z-schema": "^5.0.3" + } +} diff --git a/tests/json-schema.js b/tests/json-schema.js new file mode 100644 index 00000000..b1335193 --- /dev/null +++ b/tests/json-schema.js @@ -0,0 +1,29 @@ +const schema = { + type: "object", + properties: { + baz: { type: 'string', format: 'edtf/level_0+1' } + }, + required: ['baz'], + additionalProperties: false +} + +const formats = require('../validator/formats') + +const Ajv = require("ajv") +const ajv = require('../validator/ajv')(new Ajv) + +const ZSchema = require('../validator/z-schema')(require('z-schema')) +const zschema = new ZSchema + +const IMJV = require('is-my-json-valid') +const imjv = IMJV(schema, { formats }) + +const JSEN = require('jsen') +const jsen = JSEN(schema, { formats }) + +for (const data of [{baz: '2016-XX'}, {baz: 'invalid'}]) { + if (!ajv.validate(schema, data)) console.log('ajv', data, ajv.errors[0].message) + if (!zschema.validate(data, schema)) console.log('zschema', data, zschema.getLastError().details[0].message) + if (!imjv(data)) console.log('imjv', data, imjv.errors[0].message) + if (!jsen(data)) console.log('jsen', data, jsen.errors[0]) +} diff --git a/validator/ajv.js b/validator/ajv.js new file mode 100644 index 00000000..82413554 --- /dev/null +++ b/validator/ajv.js @@ -0,0 +1,8 @@ +const formats = require('./formats') + +module.exports = function(ajv) { + for (const [format, validator] of Object.entries(formats)) { + ajv.addFormat(format, validator) + } + return ajv +} diff --git a/validator/formats.js b/validator/formats.js new file mode 100644 index 00000000..9f7ee424 --- /dev/null +++ b/validator/formats.js @@ -0,0 +1,24 @@ +// see https://rawgit.com/zaggino/z-schema/master/benchmark/results.html for a list of schema engines + +const { parse } = require('edtf') + +const levels = [] +const formats = {} +for (const level of [0, 1, 2]) { + levels.push(level) + formats[`edtf/level_${levels.map(l => '' + l).join('+')}`] = (function(levels) { + return function (date) { + if (typeof date !== 'string') return false + + try { + return levels.includes(parse(date).level) + } + catch (err) { + return false + } + + return true + } + })(levels) +} +module.exports = formats diff --git a/validator/z-schema.js b/validator/z-schema.js new file mode 100644 index 00000000..8ce39e82 --- /dev/null +++ b/validator/z-schema.js @@ -0,0 +1,10 @@ +const formats = require('./formats') + +module.exports = function(zschema) { + for (const [format, validator] of Object.entries(formats)) { + zschema.registerFormat(format, function (date) { + return validator(date) + }) + } + return zschema +} From 3d71a651bfe6973cd483d56ae3d389145189aa8d Mon Sep 17 00:00:00 2001 From: Emiliano Heyns Date: Mon, 6 Jun 2022 00:55:53 +0200 Subject: [PATCH 2/6] cleaner IIFE closure --- validator/formats.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/validator/formats.js b/validator/formats.js index 9f7ee424..8ba420fa 100644 --- a/validator/formats.js +++ b/validator/formats.js @@ -5,9 +5,10 @@ const { parse } = require('edtf') const levels = [] const formats = {} for (const level of [0, 1, 2]) { - levels.push(level) - formats[`edtf/level_${levels.map(l => '' + l).join('+')}`] = (function(levels) { - return function (date) { + levels.push(level); + + (function(levels) { + formats[`edtf/level_${levels.map(l => '' + l).join('+')}`] = function (date) { if (typeof date !== 'string') return false try { From 5d64aea73307e34287a5444995cbc8ebea9a0d9a Mon Sep 17 00:00:00 2001 From: Emiliano Heyns Date: Mon, 6 Jun 2022 01:02:30 +0200 Subject: [PATCH 3/6] level is the only option --- tests/json-schema.js | 3 ++- validator/formats.js | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/json-schema.js b/tests/json-schema.js index b1335193..c7657999 100644 --- a/tests/json-schema.js +++ b/tests/json-schema.js @@ -1,7 +1,7 @@ const schema = { type: "object", properties: { - baz: { type: 'string', format: 'edtf/level_0+1' } + baz: { type: 'string', format: 'edtf/0+1' } }, required: ['baz'], additionalProperties: false @@ -14,6 +14,7 @@ const ajv = require('../validator/ajv')(new Ajv) const ZSchema = require('../validator/z-schema')(require('z-schema')) const zschema = new ZSchema +console.log(ZSchema.getRegisteredFormats()) const IMJV = require('is-my-json-valid') const imjv = IMJV(schema, { formats }) diff --git a/validator/formats.js b/validator/formats.js index 8ba420fa..9656a728 100644 --- a/validator/formats.js +++ b/validator/formats.js @@ -8,7 +8,7 @@ for (const level of [0, 1, 2]) { levels.push(level); (function(levels) { - formats[`edtf/level_${levels.map(l => '' + l).join('+')}`] = function (date) { + formats[`edtf/${levels.map(l => '' + l).join('+')}`] = formats[`edtf/${levels[levels.length - 1]}`] = function (date) { if (typeof date !== 'string') return false try { From 61fbf9ac4a9e01fbbc46a777f415491005c10317 Mon Sep 17 00:00:00 2001 From: Emiliano Heyns Date: Mon, 6 Jun 2022 11:08:04 +0200 Subject: [PATCH 4/6] edtf levels are mostly supersets --- tests/json-schema.js | 6 +++--- validator/formats.js | 33 +++++++++++++++++---------------- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/tests/json-schema.js b/tests/json-schema.js index c7657999..5d8159ca 100644 --- a/tests/json-schema.js +++ b/tests/json-schema.js @@ -1,9 +1,9 @@ const schema = { type: "object", properties: { - baz: { type: 'string', format: 'edtf/0+1' } + date: { type: 'string', format: 'edtf/1+3' } }, - required: ['baz'], + required: ['date'], additionalProperties: false } @@ -22,7 +22,7 @@ const imjv = IMJV(schema, { formats }) const JSEN = require('jsen') const jsen = JSEN(schema, { formats }) -for (const data of [{baz: '2016-XX'}, {baz: 'invalid'}]) { +for (const data of [{date: '2016-XX'}, {date: 'invalid'}]) { if (!ajv.validate(schema, data)) console.log('ajv', data, ajv.errors[0].message) if (!zschema.validate(data, schema)) console.log('zschema', data, zschema.getLastError().details[0].message) if (!imjv(data)) console.log('imjv', data, imjv.errors[0].message) diff --git a/validator/formats.js b/validator/formats.js index 9656a728..c0022c72 100644 --- a/validator/formats.js +++ b/validator/formats.js @@ -2,24 +2,25 @@ const { parse } = require('edtf') -const levels = [] -const formats = {} -for (const level of [0, 1, 2]) { - levels.push(level); +function isLevel(date, expected, also3) { + if (typeof date !== 'string') return false - (function(levels) { - formats[`edtf/${levels.map(l => '' + l).join('+')}`] = formats[`edtf/${levels[levels.length - 1]}`] = function (date) { - if (typeof date !== 'string') return false + try { + const found = parse(date).level + return (found <= expected ) || (found === 3 && also3) + } + catch (err) { + return false + } - try { - return levels.includes(parse(date).level) - } - catch (err) { - return false - } + return true +} - return true - } - })(levels) +const formats = {} +for (const level of [0, 1, 2, 3]) { + (level => { + formats[`edtf/${level}`] = date => isLevel(date, level, false) + if (level < 2) formats[`edtf/${level}+3`] = date => isLevel(date, level, true) + })(level) } module.exports = formats From 1c49230a7765d16d6e5e289ecff48318c22aa75c Mon Sep 17 00:00:00 2001 From: Emiliano Heyns Date: Mon, 6 Jun 2022 11:39:10 +0200 Subject: [PATCH 5/6] must explicitly set level 3 to detect level 3 --- tests/json-schema.js | 2 +- validator/formats.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/json-schema.js b/tests/json-schema.js index 5d8159ca..e4b05a12 100644 --- a/tests/json-schema.js +++ b/tests/json-schema.js @@ -22,7 +22,7 @@ const imjv = IMJV(schema, { formats }) const JSEN = require('jsen') const jsen = JSEN(schema, { formats }) -for (const data of [{date: '2016-XX'}, {date: 'invalid'}]) { +for (const data of [{date: '2016-XX'}, {date: '2017-24/2018-21'}, {date: 'invalid'}]) { if (!ajv.validate(schema, data)) console.log('ajv', data, ajv.errors[0].message) if (!zschema.validate(data, schema)) console.log('zschema', data, zschema.getLastError().details[0].message) if (!imjv(data)) console.log('imjv', data, imjv.errors[0].message) diff --git a/validator/formats.js b/validator/formats.js index c0022c72..786f8c72 100644 --- a/validator/formats.js +++ b/validator/formats.js @@ -6,7 +6,7 @@ function isLevel(date, expected, also3) { if (typeof date !== 'string') return false try { - const found = parse(date).level + const found = parse(date, { level: also3 ? 3 : level }).level return (found <= expected ) || (found === 3 && also3) } catch (err) { From 3414e811cbf6544864e007de8cf978e0f7e421be Mon Sep 17 00:00:00 2001 From: Emiliano Heyns Date: Mon, 6 Jun 2022 17:46:46 +0200 Subject: [PATCH 6/6] combined levels --- validator/formats.js | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/validator/formats.js b/validator/formats.js index 786f8c72..f5d55582 100644 --- a/validator/formats.js +++ b/validator/formats.js @@ -2,18 +2,25 @@ const { parse } = require('edtf') +function testLevel(date, expected, also3) { + if (date.level) { + return (date.level <= expected ) || (date.level === 3 && also3) + } + else if (Array.isArray(date)) { + return !date.find(d => !testLevel(d, expected, also3)) + } + return false +} + function isLevel(date, expected, also3) { if (typeof date !== 'string') return false try { - const found = parse(date, { level: also3 ? 3 : level }).level - return (found <= expected ) || (found === 3 && also3) + return testLevel(parse(date, { level: also3 ? 3 : expected }), expected, also3) } catch (err) { return false } - - return true } const formats = {}