diff --git a/v3/scripts/v2-support/package-lock.json b/v3/scripts/v2-support/package-lock.json new file mode 100644 index 0000000000..6ad2a30f52 --- /dev/null +++ b/v3/scripts/v2-support/package-lock.json @@ -0,0 +1,825 @@ +{ + "name": "v2-support", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "v2-support", + "dependencies": { + "ajv-cli": "^5.0.0", + "jsonschema": "^1.4.1", + "ts-json-schema-generator": "^2.3.0" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "license": "MIT" + }, + "node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-cli": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ajv-cli/-/ajv-cli-5.0.0.tgz", + "integrity": "sha512-LY4m6dUv44HTyhV+u2z5uX4EhPYTM38Iv1jdgDJJJCyOOuqB8KtZEGjPZ2T+sh5ZIJrXUfgErYx/j3gLd3+PlQ==", + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0", + "fast-json-patch": "^2.0.0", + "glob": "^7.1.0", + "js-yaml": "^3.14.0", + "json-schema-migrate": "^2.0.0", + "json5": "^2.1.3", + "minimist": "^1.2.0" + }, + "bin": { + "ajv": "dist/index.js" + }, + "peerDependencies": { + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "ts-node": { + "optional": true + } + } + }, + "node_modules/ajv-cli/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/ajv-cli/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/ajv-cli/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "license": "MIT" + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "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==", + "license": "MIT" + }, + "node_modules/fast-json-patch": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-2.2.1.tgz", + "integrity": "sha512-4j5uBaTnsYAV5ebkidvxiLUYOwjQ+JSFljeqfTxCrH9bDmlCQaOJFS84oDJ2rAXZq2yskmk3ORfoP9DCwqFNig==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^2.0.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/fast-json-patch/node_modules/fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w==", + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.3.tgz", + "integrity": "sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==", + "license": "BSD-3-Clause" + }, + "node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "license": "ISC" + }, + "node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-schema-migrate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/json-schema-migrate/-/json-schema-migrate-2.0.0.tgz", + "integrity": "sha512-r38SVTtojDRp4eD6WsCqiE0eNDt4v1WalBXb9cyZYw9ai5cGtBwzRNWjHzJl38w6TxFkXAIA7h+fyX3tnrAFhQ==", + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + } + }, + "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==", + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonschema": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.4.1.tgz", + "integrity": "sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "license": "BlueOak-1.0.0" + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "license": "BSD-3-Clause" + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ts-json-schema-generator": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/ts-json-schema-generator/-/ts-json-schema-generator-2.3.0.tgz", + "integrity": "sha512-t4lBQAwZc0sOJq9LJt3NgbznIcslVnm0JeEMFq8qIRklpMRY8jlYD0YmnRWbqBKANxkby91P1XanSSlSOFpUmg==", + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.15", + "commander": "^12.0.0", + "glob": "^10.3.12", + "json5": "^2.2.3", + "normalize-path": "^3.0.0", + "safe-stable-stringify": "^2.4.3", + "tslib": "^2.6.2", + "typescript": "^5.4.5" + }, + "bin": { + "ts-json-schema-generator": "bin/ts-json-schema-generator.js" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/typescript": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", + "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + } + } +} diff --git a/v3/scripts/v2-support/package.json b/v3/scripts/v2-support/package.json new file mode 100644 index 0000000000..9752d1f90f --- /dev/null +++ b/v3/scripts/v2-support/package.json @@ -0,0 +1,15 @@ +{ + "name": "v2-support", + "description": "scripts for analyzing v2 files", + "scripts": { + "generate:schema": "ts-json-schema-generator --unstable --additional-properties --path '../../src/**/*.ts' --type 'ICodapV2DocumentJson' --no-type-check -o v2-schema.json", + "test": "echo \"Error: no test specified\" && exit 1", + "validate": "ajv validate --verbose --errors=js --inline-refs=false --allow-union-types -s v2-schema.json -d", + "generate-and-validate": "npm-run-all generate:schema \"validate -- {1}\" --" + }, + "dependencies": { + "ajv-cli": "^5.0.0", + "jsonschema": "^1.4.1", + "ts-json-schema-generator": "^2.3.0" + } +} diff --git a/v3/scripts/v2-support/v2-schema.json b/v3/scripts/v2-support/v2-schema.json new file mode 100644 index 0000000000..3799b47e92 --- /dev/null +++ b/v3/scripts/v2-support/v2-schema.json @@ -0,0 +1,2690 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$ref": "#/definitions/ICodapV2DocumentJson", + "definitions": { + "ICodapV2DocumentJson": { + "type": "object", + "properties": { + "type": { + "type": "string" + }, + "id": { + "type": "number" + }, + "guid": { + "type": "number" + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "appName": { + "type": "string" + }, + "appVersion": { + "type": "string" + }, + "appBuildNum": { + "type": "string" + }, + "metadata": { + "type": "object" + }, + "components": { + "type": "array", + "items": { + "$ref": "#/definitions/CodapV2Component" + } + }, + "contexts": { + "type": "array", + "items": { + "$ref": "#/definitions/CodapV2Context" + } + }, + "globalValues": { + "type": "array", + "items": { + "$ref": "#/definitions/ICodapV2GlobalValue" + } + }, + "lang": { + "type": "string" + }, + "idCount": { + "type": "number" + } + }, + "required": [ + "guid", + "appName", + "appVersion", + "appBuildNum", + "components", + "contexts", + "globalValues" + ] + }, + "CodapV2Component": { + "anyOf": [ + { + "$ref": "#/definitions/ICodapV2CalculatorComponent" + }, + { + "$ref": "#/definitions/ICodapV2CaseCardComponent" + }, + { + "$ref": "#/definitions/ICodapGameViewComponent" + }, + { + "$ref": "#/definitions/ICodapV2GraphComponent" + }, + { + "$ref": "#/definitions/ICodapV2GuideComponent" + }, + { + "$ref": "#/definitions/ICodapV2ImageComponent" + }, + { + "$ref": "#/definitions/ICodapV2MapComponent" + }, + { + "$ref": "#/definitions/ICodapV2SliderComponent" + }, + { + "$ref": "#/definitions/ICodapV2TableComponent" + }, + { + "$ref": "#/definitions/ICodapV2TextComponent" + }, + { + "$ref": "#/definitions/ICodapV2WebViewComponent" + } + ] + }, + "ICodapV2CalculatorComponent": { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "DG.Calculator" + }, + "guid": { + "type": "number" + }, + "id": { + "type": "number" + }, + "componentStorage": { + "anyOf": [ + { + "$ref": "#/definitions/ICodapV2CalculatorStorage" + }, + { + "type": "null" + } + ] + }, + "layout": { + "type": "object", + "properties": { + "width": { + "type": "number" + }, + "height": { + "type": "number" + }, + "left": { + "type": "number" + }, + "top": { + "type": "number" + }, + "isVisible": { + "type": "boolean" + }, + "zIndex": { + "type": "number" + } + } + }, + "savedHeight": { + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "guid", + "layout", + "type" + ] + }, + "ICodapV2CalculatorStorage": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "name": { + "type": "string" + }, + "userSetTitle": { + "type": "boolean" + }, + "cannotClose": { + "type": "boolean" + } + } + }, + "ICodapV2CaseCardComponent": { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "DG.CaseCard" + }, + "guid": { + "type": "number" + }, + "id": { + "type": "number" + }, + "componentStorage": { + "$ref": "#/definitions/ICodapV2CaseCardStorage" + }, + "layout": { + "type": "object", + "properties": { + "width": { + "type": "number" + }, + "height": { + "type": "number" + }, + "left": { + "type": "number" + }, + "top": { + "type": "number" + }, + "isVisible": { + "type": "boolean" + }, + "zIndex": { + "type": "number" + } + } + }, + "savedHeight": { + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "componentStorage", + "guid", + "layout", + "type" + ] + }, + "ICodapV2CaseCardStorage": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "name": { + "type": "string" + }, + "userSetTitle": { + "type": "boolean" + }, + "cannotClose": { + "type": "boolean" + }, + "_links_": { + "type": "object", + "properties": { + "context": { + "$ref": "#/definitions/IGuidLink%3C%22DG.DataContextRecord%22%3E" + } + }, + "required": [ + "context" + ] + } + }, + "required": [ + "_links_" + ] + }, + "IGuidLink<\"DG.DataContextRecord\">": { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "DG.DataContextRecord" + }, + "id": { + "type": "number" + } + }, + "required": [ + "type", + "id" + ] + }, + "ICodapGameViewComponent": { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "DG.GameView" + }, + "guid": { + "type": "number" + }, + "id": { + "type": "number" + }, + "componentStorage": { + "$ref": "#/definitions/ICodapV2GameViewStorage" + }, + "layout": { + "type": "object", + "properties": { + "width": { + "type": "number" + }, + "height": { + "type": "number" + }, + "left": { + "type": "number" + }, + "top": { + "type": "number" + }, + "isVisible": { + "type": "boolean" + }, + "zIndex": { + "type": "number" + } + } + }, + "savedHeight": { + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "componentStorage", + "guid", + "layout", + "type" + ] + }, + "ICodapV2GameViewStorage": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "name": { + "type": "string" + }, + "userSetTitle": { + "type": "boolean" + }, + "cannotClose": { + "type": "boolean" + }, + "currentGameUrl": { + "type": "string" + }, + "savedGameState": {} + }, + "required": [ + "currentGameUrl" + ] + }, + "ICodapV2GraphComponent": { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "DG.GraphView" + }, + "guid": { + "type": "number" + }, + "id": { + "type": "number" + }, + "componentStorage": { + "$ref": "#/definitions/ICodapV2GraphStorage" + }, + "layout": { + "type": "object", + "properties": { + "width": { + "type": "number" + }, + "height": { + "type": "number" + }, + "left": { + "type": "number" + }, + "top": { + "type": "number" + }, + "isVisible": { + "type": "boolean" + }, + "zIndex": { + "type": "number" + } + } + }, + "savedHeight": { + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "componentStorage", + "guid", + "layout", + "type" + ] + }, + "ICodapV2GraphStorage": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "name": { + "type": "string" + }, + "userSetTitle": { + "type": "boolean" + }, + "cannotClose": { + "type": "boolean" + }, + "_links_": { + "type": "object", + "properties": { + "context": { + "$ref": "#/definitions/IGuidLink%3C%22DG.DataContextRecord%22%3E" + }, + "hiddenCases": { + "type": "array", + "items": {} + }, + "xColl": { + "$ref": "#/definitions/IGuidLink%3C(%22DG.Collection%22%7C%22DG.CollectionRecord%22)%3E" + }, + "xAttr": { + "$ref": "#/definitions/IGuidLink%3C%22DG.Attribute%22%3E" + }, + "yColl": { + "$ref": "#/definitions/IGuidLink%3C(%22DG.Collection%22%7C%22DG.CollectionRecord%22)%3E" + }, + "yAttr": { + "anyOf": [ + { + "$ref": "#/definitions/IGuidLink%3C%22DG.Attribute%22%3E" + }, + { + "type": "array", + "items": { + "$ref": "#/definitions/IGuidLink%3C%22DG.Attribute%22%3E" + } + } + ] + }, + "y2Coll": { + "$ref": "#/definitions/IGuidLink%3C%22DG.Collection%22%3E" + }, + "y2Attr": { + "$ref": "#/definitions/IGuidLink%3C%22DG.Attribute%22%3E" + }, + "rightColl": { + "$ref": "#/definitions/IGuidLink%3C%22DG.Collection%22%3E" + }, + "rightAttr": { + "$ref": "#/definitions/IGuidLink%3C%22DG.Attribute%22%3E" + } + } + }, + "displayOnlySelected": { + "type": "boolean" + }, + "legendRole": { + "type": "number" + }, + "legendAttributeType": { + "type": "number" + }, + "numberOfLegendQuantiles": { + "type": "number" + }, + "legendQuantilesAreLocked": { + "type": "boolean" + }, + "pointColor": { + "type": "string" + }, + "strokeColor": { + "type": "string" + }, + "pointSizeMultiplier": { + "type": "number" + }, + "transparency": { + "type": "number" + }, + "strokeTransparency": { + "type": "number" + }, + "strokeSameAsFill": { + "type": "boolean" + }, + "isTransparent": { + "type": "boolean" + }, + "plotBackgroundColor": { + "type": [ + "string", + "null" + ] + }, + "plotBackgroundOpacity": { + "type": "number" + }, + "plotBackgroundImageLockInfo": {}, + "plotBackgroundImage": { + "type": [ + "string", + "null" + ] + }, + "xRole": { + "type": "number" + }, + "xAttributeType": { + "type": "number" + }, + "xAxisClass": { + "type": "string" + }, + "xLowerBound": { + "type": [ + "number", + "null" + ] + }, + "xUpperBound": { + "type": [ + "number", + "null" + ] + }, + "yRole": { + "type": "number" + }, + "yAttributeType": { + "type": "number" + }, + "yAxisClass": { + "type": "string" + }, + "yLowerBound": { + "type": [ + "number", + "null" + ] + }, + "yUpperBound": { + "type": [ + "number", + "null" + ] + }, + "y2Role": { + "type": "number" + }, + "y2AttributeType": { + "type": "number" + }, + "y2AxisClass": { + "type": "string" + }, + "y2LowerBound": { + "type": [ + "number", + "null" + ] + }, + "y2UpperBound": { + "type": [ + "number", + "null" + ] + }, + "topRole": { + "type": "number" + }, + "topAttributeType": { + "type": "number" + }, + "topAxisClass": { + "type": "string" + }, + "rightRole": { + "type": "number" + }, + "rightAttributeType": { + "type": "number" + }, + "rightAxisClass": { + "type": "string" + }, + "plotModels": { + "type": "array", + "items": { + "$ref": "#/definitions/ICodapV2PlotModel" + } + } + }, + "required": [ + "_links_", + "legendRole", + "legendAttributeType", + "xRole", + "xAttributeType", + "xAxisClass", + "yRole", + "yAttributeType", + "yAxisClass", + "plotModels" + ] + }, + "IGuidLink<(\"DG.Collection\"|\"DG.CollectionRecord\")>": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "DG.Collection", + "DG.CollectionRecord" + ] + }, + "id": { + "type": "number" + } + }, + "required": [ + "type", + "id" + ] + }, + "IGuidLink<\"DG.Attribute\">": { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "DG.Attribute" + }, + "id": { + "type": "number" + } + }, + "required": [ + "type", + "id" + ] + }, + "IGuidLink<\"DG.Collection\">": { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "DG.Collection" + }, + "id": { + "type": "number" + } + }, + "required": [ + "type", + "id" + ] + }, + "ICodapV2PlotModel": { + "type": "object", + "properties": { + "plotClass": { + "type": "string" + }, + "plotModelStorage": { + "$ref": "#/definitions/ICodapV2PlotStorage" + } + }, + "required": [ + "plotClass", + "plotModelStorage" + ] + }, + "ICodapV2PlotStorage": { + "type": "object", + "properties": { + "verticalAxisIsY2": { + "type": "boolean" + }, + "adornments": { + "type": "object", + "properties": { + "connectingLine": { + "type": "object", + "properties": { + "isVisible": { + "type": "boolean" + }, + "enableMeasuresForSelection": { + "type": "boolean" + } + }, + "required": [ + "isVisible" + ] + }, + "multipleMovableValues": { + "type": "object", + "properties": { + "isVisible": { + "type": "boolean" + }, + "enableMeasuresForSelection": { + "type": "boolean" + }, + "isShowingCount": { + "type": "boolean" + }, + "isShowingPercent": { + "type": "boolean" + }, + "values": { + "type": "array", + "items": { + "type": "object", + "properties": { + "isVisible": { + "type": "boolean" + }, + "value": { + "type": "number" + } + }, + "required": [ + "isVisible", + "value" + ] + } + }, + "valueModels": { + "type": "array", + "items": { + "type": "object", + "properties": { + "isVisible": { + "type": "boolean" + }, + "enableMeasuresForSelection": { + "type": "boolean" + }, + "values": { + "type": "object", + "additionalProperties": { + "type": "number" + } + } + }, + "required": [ + "isVisible", + "values" + ] + } + } + }, + "required": [ + "isShowingCount", + "isShowingPercent", + "isVisible" + ] + }, + "plottedBoxPlot": { + "type": "object", + "properties": { + "isVisible": { + "type": "boolean" + }, + "enableMeasuresForSelection": { + "type": "boolean" + }, + "equationCoordsArray": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "object", + "properties": { + "proportionX": { + "type": "number" + }, + "proportionY": { + "type": "number" + } + }, + "required": [ + "proportionX", + "proportionY" + ] + }, + { + "type": "object", + "properties": { + "proportionCenterX": { + "type": "number" + }, + "proportionCenterY": { + "type": "number" + } + }, + "required": [ + "proportionCenterX", + "proportionCenterY" + ] + }, + { + "type": "null" + } + ] + } + }, + "showOutliers": { + "type": "boolean" + }, + "showICI": { + "type": "boolean" + } + }, + "required": [ + "isVisible" + ] + }, + "plottedCount": { + "type": "object", + "properties": { + "isVisible": { + "type": "boolean" + }, + "enableMeasuresForSelection": { + "type": "boolean" + }, + "isShowingCount": { + "type": "boolean" + }, + "isShowingPercent": { + "type": "boolean" + }, + "percentKind": { + "type": "number" + } + }, + "required": [ + "isVisible" + ] + }, + "plottedFunction": { + "type": "object", + "properties": { + "isVisible": { + "type": "boolean" + }, + "enableMeasuresForSelection": { + "type": "boolean" + }, + "adornmentKey": { + "type": "string" + }, + "expression": { + "type": "string" + } + }, + "required": [ + "expression", + "isVisible" + ] + }, + "plottedMad": { + "$ref": "#/definitions/ICodapV2UnivariateAdornment" + }, + "plottedMean": { + "$ref": "#/definitions/ICodapV2UnivariateAdornment" + }, + "plottedMedian": { + "$ref": "#/definitions/ICodapV2UnivariateAdornment" + }, + "plottedNormal": { + "$ref": "#/definitions/ICodapV2UnivariateAdornment" + }, + "plottedStDev": { + "$ref": "#/definitions/ICodapV2UnivariateAdornment" + }, + "plottedStErr": { + "type": "object", + "properties": { + "isVisible": { + "type": "boolean" + }, + "enableMeasuresForSelection": { + "type": "boolean" + }, + "equationCoordsArray": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "object", + "properties": { + "proportionX": { + "type": "number" + }, + "proportionY": { + "type": "number" + } + }, + "required": [ + "proportionX", + "proportionY" + ] + }, + { + "type": "object", + "properties": { + "proportionCenterX": { + "type": "number" + }, + "proportionCenterY": { + "type": "number" + } + }, + "required": [ + "proportionCenterX", + "proportionCenterY" + ] + }, + { + "type": "null" + } + ] + } + }, + "numberOfStdErrs": { + "type": "number" + } + }, + "required": [ + "isVisible", + "numberOfStdErrs" + ] + }, + "plottedValue": { + "type": "object", + "properties": { + "isVisible": { + "type": "boolean" + }, + "enableMeasuresForSelection": { + "type": "boolean" + }, + "adornmentKey": { + "type": "string" + }, + "expression": { + "type": "string" + } + }, + "required": [ + "expression", + "isVisible" + ] + } + } + }, + "areSquaresVisible": { + "type": "boolean" + }, + "isLSRLVisible": { + "type": "boolean" + }, + "movableLineStorage": { + "type": "object", + "properties": { + "isVisible": { + "type": "boolean" + }, + "enableMeasuresForSelection": { + "type": "boolean" + }, + "isInterceptLocked": { + "type": "boolean" + }, + "equationCoords": { + "anyOf": [ + { + "type": "object", + "properties": { + "proportionCenterX": { + "type": "number" + }, + "proportionCenterY": { + "type": "number" + } + }, + "required": [ + "proportionCenterX", + "proportionCenterY" + ] + }, + { + "type": "null" + } + ] + }, + "intercept": { + "type": "number" + }, + "slope": { + "type": "number" + }, + "isVertical": { + "type": "boolean" + }, + "xIntercept": { + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "isVisible", + "isInterceptLocked", + "intercept", + "slope", + "isVertical", + "xIntercept" + ] + }, + "movablePointStorage": { + "type": "object", + "properties": { + "isVisible": { + "type": "boolean" + }, + "enableMeasuresForSelection": { + "type": "boolean" + }, + "coordinates": { + "type": "object", + "properties": { + "x": { + "type": "number" + }, + "y": { + "type": "number" + } + }, + "required": [ + "x", + "y" + ] + } + }, + "required": [ + "isVisible", + "coordinates" + ] + }, + "multipleLSRLsStorage": { + "type": "object", + "properties": { + "isVisible": { + "type": "boolean" + }, + "enableMeasuresForSelection": { + "type": "boolean" + }, + "showSumSquares": { + "type": "boolean" + }, + "isInterceptLocked": { + "type": "boolean" + }, + "showConfidenceBands": { + "type": "boolean" + }, + "lsrls": { + "type": "array", + "items": { + "type": "object", + "properties": { + "isVisible": { + "type": "boolean" + }, + "enableMeasuresForSelection": { + "type": "boolean" + }, + "isInterceptLocked": { + "type": "boolean" + }, + "equationCoords": { + "anyOf": [ + { + "type": "object", + "properties": { + "proportionCenterX": { + "type": "number" + }, + "proportionCenterY": { + "type": "number" + } + }, + "required": [ + "proportionCenterX", + "proportionCenterY" + ] + }, + { + "type": "null" + } + ] + }, + "showConfidenceBands": { + "type": "boolean" + } + }, + "required": [ + "isVisible", + "isInterceptLocked" + ] + } + } + }, + "required": [ + "isVisible", + "isInterceptLocked" + ] + }, + "showMeasureLabels": { + "type": "boolean" + } + } + }, + "ICodapV2UnivariateAdornment": { + "type": "object", + "properties": { + "isVisible": { + "type": "boolean" + }, + "enableMeasuresForSelection": { + "type": "boolean" + }, + "equationCoordsArray": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "object", + "properties": { + "proportionX": { + "type": "number" + }, + "proportionY": { + "type": "number" + } + }, + "required": [ + "proportionX", + "proportionY" + ] + }, + { + "type": "object", + "properties": { + "proportionCenterX": { + "type": "number" + }, + "proportionCenterY": { + "type": "number" + } + }, + "required": [ + "proportionCenterX", + "proportionCenterY" + ] + }, + { + "type": "null" + } + ] + } + } + }, + "required": [ + "isVisible" + ] + }, + "ICodapV2GuideComponent": { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "DG.GuideView" + }, + "guid": { + "type": "number" + }, + "id": { + "type": "number" + }, + "componentStorage": { + "$ref": "#/definitions/ICodapV2GuideStorage" + }, + "layout": { + "type": "object", + "properties": { + "width": { + "type": "number" + }, + "height": { + "type": "number" + }, + "left": { + "type": "number" + }, + "top": { + "type": "number" + }, + "isVisible": { + "type": "boolean" + }, + "zIndex": { + "type": "number" + } + } + }, + "savedHeight": { + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "componentStorage", + "guid", + "layout", + "type" + ] + }, + "ICodapV2GuideStorage": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "name": { + "type": "string" + }, + "userSetTitle": { + "type": "boolean" + }, + "cannotClose": { + "type": "boolean" + }, + "currentItemIndex": { + "type": [ + "number", + "null" + ] + }, + "isVisible": { + "type": "boolean" + }, + "items": { + "type": "array", + "items": { + "type": "object", + "properties": { + "itemTitle": { + "type": [ + "string", + "null" + ] + }, + "url": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "itemTitle", + "url" + ] + } + } + }, + "required": [ + "items" + ] + }, + "ICodapV2ImageComponent": { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "DG.ImageComponentView" + }, + "guid": { + "type": "number" + }, + "id": { + "type": "number" + }, + "componentStorage": { + "$ref": "#/definitions/ICodapV2ImageStorage" + }, + "layout": { + "type": "object", + "properties": { + "width": { + "type": "number" + }, + "height": { + "type": "number" + }, + "left": { + "type": "number" + }, + "top": { + "type": "number" + }, + "isVisible": { + "type": "boolean" + }, + "zIndex": { + "type": "number" + } + } + }, + "savedHeight": { + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "componentStorage", + "guid", + "layout", + "type" + ] + }, + "ICodapV2ImageStorage": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "name": { + "type": "string" + }, + "userSetTitle": { + "type": "boolean" + }, + "cannotClose": { + "type": "boolean" + }, + "URL": { + "type": "string" + } + }, + "required": [ + "title", + "URL", + "name" + ] + }, + "ICodapV2MapComponent": { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "DG.MapView" + }, + "guid": { + "type": "number" + }, + "id": { + "type": "number" + }, + "componentStorage": { + "$ref": "#/definitions/ICodapV2MapStorage" + }, + "layout": { + "type": "object", + "properties": { + "width": { + "type": "number" + }, + "height": { + "type": "number" + }, + "left": { + "type": "number" + }, + "top": { + "type": "number" + }, + "isVisible": { + "type": "boolean" + }, + "zIndex": { + "type": "number" + } + } + }, + "savedHeight": { + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "componentStorage", + "guid", + "layout", + "type" + ] + }, + "ICodapV2MapStorage": { + "anyOf": [ + { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "name": { + "type": "string" + }, + "userSetTitle": { + "type": "boolean" + }, + "cannotClose": { + "type": "boolean" + }, + "_links_": { + "type": "object", + "properties": { + "context": { + "$ref": "#/definitions/IGuidLink%3C%22DG.DataContextRecord%22%3E" + }, + "hiddenCases": { + "type": "array", + "items": {} + } + } + }, + "legendRole": { + "type": "number" + }, + "legendAttributeType": { + "type": "number" + }, + "pointColor": { + "type": "string" + }, + "strokeColor": { + "type": "string" + }, + "pointSizeMultiplier": { + "type": "number" + }, + "transparency": { + "type": "number" + }, + "strokeTransparency": { + "type": "number" + }, + "mapModelStorage": { + "type": "object", + "properties": { + "center": { + "anyOf": [ + { + "type": "object", + "properties": { + "lat": { + "type": "number" + }, + "lng": { + "type": "number" + } + }, + "required": [ + "lat", + "lng" + ] + }, + { + "type": "array", + "minItems": 2, + "items": [ + { + "type": "number", + "title": "lat" + }, + { + "type": "number", + "title": "lng" + } + ], + "maxItems": 2 + } + ] + }, + "zoom": { + "type": "number" + }, + "baseMapLayerName": { + "type": "string" + }, + "gridMultiplier": { + "type": "number" + }, + "pointsShouldBeVisible": { + "type": "boolean" + }, + "linesShouldBeVisible": { + "type": "boolean" + }, + "grid": { + "type": "object", + "properties": { + "gridMultiplier": { + "type": "number" + }, + "visible": { + "type": "boolean" + } + }, + "required": [ + "gridMultiplier", + "visible" + ] + }, + "areaColor": { + "type": "string" + }, + "areaTransparency": { + "type": [ + "string", + "number" + ] + }, + "areaStrokeColor": { + "type": "string" + }, + "areaStrokeTransparency": { + "type": [ + "string", + "number" + ] + } + }, + "required": [ + "center", + "zoom", + "baseMapLayerName", + "grid" + ] + } + }, + "required": [ + "_links_", + "legendRole", + "legendAttributeType", + "mapModelStorage" + ] + }, + { + "$ref": "#/definitions/ICodapV2MapCurrentStorage" + } + ] + }, + "ICodapV2MapCurrentStorage": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "name": { + "type": "string" + }, + "userSetTitle": { + "type": "boolean" + }, + "cannotClose": { + "type": "boolean" + }, + "mapModelStorage": { + "type": "object", + "properties": { + "center": { + "anyOf": [ + { + "type": "object", + "properties": { + "lat": { + "type": "number" + }, + "lng": { + "type": "number" + } + }, + "required": [ + "lat", + "lng" + ] + }, + { + "type": "array", + "minItems": 2, + "items": [ + { + "type": "number", + "title": "lat" + }, + { + "type": "number", + "title": "lng" + } + ], + "maxItems": 2 + } + ] + }, + "zoom": { + "type": "number" + }, + "baseMapLayerName": { + "type": "string" + }, + "gridMultiplier": { + "type": "number" + }, + "layerModels": { + "type": "array", + "items": { + "$ref": "#/definitions/ICodapV2MapLayerStorage" + } + } + }, + "required": [ + "center", + "zoom", + "baseMapLayerName", + "gridMultiplier", + "layerModels" + ] + } + }, + "required": [ + "mapModelStorage" + ] + }, + "ICodapV2MapLayerStorage": { + "anyOf": [ + { + "$ref": "#/definitions/ICodapV2MapPointLayerStorage" + }, + { + "$ref": "#/definitions/ICodapV2MapPolygonLayerStorage" + } + ] + }, + "ICodapV2MapPointLayerStorage": { + "type": "object", + "properties": { + "_links_": { + "type": "object", + "properties": { + "context": { + "$ref": "#/definitions/IGuidLink%3C%22DG.DataContextRecord%22%3E" + }, + "hiddenCases": { + "type": "array", + "items": {} + }, + "legendColl": { + "$ref": "#/definitions/IGuidLink%3C%22DG.Collection%22%3E" + }, + "legendAttr": { + "anyOf": [ + { + "$ref": "#/definitions/IGuidLink%3C%22DG.Attribute%22%3E" + }, + { + "type": "array", + "items": { + "$ref": "#/definitions/IGuidLink%3C%22DG.Attribute%22%3E" + } + } + ] + } + }, + "required": [ + "context" + ] + }, + "legendRole": { + "type": "number" + }, + "legendAttributeType": { + "type": "number" + }, + "isVisible": { + "type": "boolean" + }, + "strokeSameAsFill": { + "type": "boolean" + }, + "pointColor": { + "type": "string" + }, + "strokeColor": { + "type": "string" + }, + "pointSizeMultiplier": { + "type": "number" + }, + "transparency": { + "type": "number" + }, + "strokeTransparency": { + "type": "number" + }, + "pointsShouldBeVisible": { + "type": "boolean" + }, + "grid": { + "type": "object", + "properties": { + "gridMultiplier": { + "type": "number" + }, + "isVisible": { + "type": "boolean" + } + }, + "required": [ + "gridMultiplier" + ] + }, + "connectingLines": { + "type": "object", + "properties": { + "isVisible": { + "type": "boolean" + }, + "enableMeasuresForSelection": { + "type": "boolean" + } + }, + "required": [ + "isVisible" + ] + } + }, + "required": [ + "_links_", + "connectingLines", + "grid", + "isVisible", + "legendAttributeType", + "legendRole", + "pointColor", + "pointSizeMultiplier", + "pointsShouldBeVisible", + "strokeColor", + "strokeTransparency", + "transparency" + ] + }, + "ICodapV2MapPolygonLayerStorage": { + "type": "object", + "properties": { + "_links_": { + "type": "object", + "properties": { + "context": { + "$ref": "#/definitions/IGuidLink%3C%22DG.DataContextRecord%22%3E" + }, + "hiddenCases": { + "type": "array", + "items": {} + }, + "legendColl": { + "$ref": "#/definitions/IGuidLink%3C%22DG.Collection%22%3E" + }, + "legendAttr": { + "anyOf": [ + { + "$ref": "#/definitions/IGuidLink%3C%22DG.Attribute%22%3E" + }, + { + "type": "array", + "items": { + "$ref": "#/definitions/IGuidLink%3C%22DG.Attribute%22%3E" + } + } + ] + } + }, + "required": [ + "context" + ] + }, + "legendRole": { + "type": "number" + }, + "legendAttributeType": { + "type": "number" + }, + "isVisible": { + "type": "boolean" + }, + "strokeSameAsFill": { + "type": "boolean" + }, + "areaColor": { + "type": "string" + }, + "areaTransparency": { + "type": [ + "number", + "string" + ] + }, + "areaStrokeColor": { + "type": "string" + }, + "areaStrokeTransparency": { + "type": [ + "number", + "string" + ] + } + }, + "required": [ + "_links_", + "areaColor", + "areaStrokeColor", + "areaStrokeTransparency", + "areaTransparency", + "isVisible", + "legendAttributeType", + "legendRole" + ] + }, + "ICodapV2SliderComponent": { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "DG.SliderView" + }, + "guid": { + "type": "number" + }, + "id": { + "type": "number" + }, + "componentStorage": { + "$ref": "#/definitions/ICodapV2SliderStorage" + }, + "layout": { + "type": "object", + "properties": { + "width": { + "type": "number" + }, + "height": { + "type": "number" + }, + "left": { + "type": "number" + }, + "top": { + "type": "number" + }, + "isVisible": { + "type": "boolean" + }, + "zIndex": { + "type": "number" + } + } + }, + "savedHeight": { + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "componentStorage", + "guid", + "layout", + "type" + ] + }, + "ICodapV2SliderStorage": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "name": { + "type": "string" + }, + "userSetTitle": { + "type": "boolean" + }, + "cannotClose": { + "type": "boolean" + }, + "_links_": { + "type": "object", + "properties": { + "model": { + "$ref": "#/definitions/IGuidLink%3C%22DG.GlobalValue%22%3E" + } + }, + "required": [ + "model" + ] + }, + "lowerBound": { + "type": "number" + }, + "upperBound": { + "type": "number" + }, + "animationDirection": { + "type": "number" + }, + "animationMode": { + "type": "number" + }, + "restrictToMultiplesOf": { + "type": [ + "number", + "null" + ] + }, + "maxPerSecond": { + "type": [ + "number", + "null" + ] + }, + "userTitle": { + "type": "boolean" + } + }, + "required": [ + "_links_" + ] + }, + "IGuidLink<\"DG.GlobalValue\">": { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "DG.GlobalValue" + }, + "id": { + "type": "number" + } + }, + "required": [ + "type", + "id" + ] + }, + "ICodapV2TableComponent": { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "DG.TableView" + }, + "guid": { + "type": "number" + }, + "id": { + "type": "number" + }, + "componentStorage": { + "$ref": "#/definitions/ICodapV2TableStorage" + }, + "layout": { + "type": "object", + "properties": { + "width": { + "type": "number" + }, + "height": { + "type": "number" + }, + "left": { + "type": "number" + }, + "top": { + "type": "number" + }, + "isVisible": { + "type": "boolean" + }, + "zIndex": { + "type": "number" + } + } + }, + "savedHeight": { + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "componentStorage", + "guid", + "layout", + "type" + ] + }, + "ICodapV2TableStorage": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "name": { + "type": "string" + }, + "userSetTitle": { + "type": "boolean" + }, + "cannotClose": { + "type": "boolean" + }, + "_links_": { + "type": "object", + "properties": { + "context": { + "$ref": "#/definitions/IGuidLink%3C%22DG.DataContextRecord%22%3E" + } + }, + "required": [ + "context" + ] + }, + "attributeWidths": { + "type": "array", + "items": { + "type": "object", + "properties": { + "_links_": { + "type": "object", + "properties": { + "attr": { + "$ref": "#/definitions/IGuidLink%3C%22DG.Attribute%22%3E" + } + }, + "required": [ + "attr" + ] + }, + "width": { + "type": "number" + } + }, + "required": [ + "_links_" + ] + } + } + } + }, + "ICodapV2TextComponent": { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "DG.TextView" + }, + "guid": { + "type": "number" + }, + "id": { + "type": "number" + }, + "componentStorage": { + "$ref": "#/definitions/ICodapV2TextStorage" + }, + "layout": { + "type": "object", + "properties": { + "width": { + "type": "number" + }, + "height": { + "type": "number" + }, + "left": { + "type": "number" + }, + "top": { + "type": "number" + }, + "isVisible": { + "type": "boolean" + }, + "zIndex": { + "type": "number" + } + } + }, + "savedHeight": { + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "componentStorage", + "guid", + "layout", + "type" + ] + }, + "ICodapV2TextStorage": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "name": { + "type": "string" + }, + "userSetTitle": { + "type": "boolean" + }, + "cannotClose": { + "type": "boolean" + }, + "text": { + "type": "string" + } + } + }, + "ICodapV2WebViewComponent": { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "DG.WebView" + }, + "guid": { + "type": "number" + }, + "id": { + "type": "number" + }, + "componentStorage": { + "$ref": "#/definitions/ICodapV2WebViewStorage" + }, + "layout": { + "type": "object", + "properties": { + "width": { + "type": "number" + }, + "height": { + "type": "number" + }, + "left": { + "type": "number" + }, + "top": { + "type": "number" + }, + "isVisible": { + "type": "boolean" + }, + "zIndex": { + "type": "number" + } + } + }, + "savedHeight": { + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "componentStorage", + "guid", + "layout", + "type" + ] + }, + "ICodapV2WebViewStorage": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "name": { + "type": "string" + }, + "userSetTitle": { + "type": "boolean" + }, + "cannotClose": { + "type": "boolean" + }, + "URL": { + "type": "string" + } + }, + "required": [ + "URL" + ] + }, + "CodapV2Context": { + "anyOf": [ + { + "$ref": "#/definitions/ICodapV2DataContext" + }, + { + "$ref": "#/definitions/ICodapV2GameContext" + }, + { + "$ref": "#/definitions/ICodapV2ExternalContext" + } + ] + }, + "ICodapV2DataContext": { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "DG.DataContext" + }, + "document": { + "type": "number" + }, + "guid": { + "type": "number" + }, + "id": { + "type": "number" + }, + "flexibleGroupingChangeFlag": { + "type": [ + "boolean", + "null" + ] + }, + "name": { + "type": "string" + }, + "title": { + "type": "string" + }, + "collections": { + "type": "array", + "items": { + "$ref": "#/definitions/ICodapV2Collection" + } + }, + "description": { + "type": "string" + }, + "metadata": { + "anyOf": [ + { + "$ref": "#/definitions/ICodapV2DataContextMetadata" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "type", + "guid", + "collections" + ] + }, + "ICodapV2Collection": { + "type": "object", + "properties": { + "attrs": { + "type": "array", + "items": { + "$ref": "#/definitions/ICodapV2Attribute" + } + }, + "cases": { + "type": "array", + "items": { + "$ref": "#/definitions/ICodapV2Case" + } + }, + "caseName": { + "type": [ + "string", + "null" + ] + }, + "childAttrName": { + "type": [ + "string", + "null" + ] + }, + "cid": { + "type": "string" + }, + "collapseChildren": { + "type": [ + "boolean", + "null" + ] + }, + "defaults": { + "type": "object", + "properties": { + "xAttr": { + "type": "string" + }, + "yAttr": { + "type": "string" + } + } + }, + "guid": { + "type": "number" + }, + "id": { + "type": "number" + }, + "labels": { + "type": "object", + "properties": { + "singleCase": { + "type": "string" + }, + "pluralCase": { + "type": "string" + }, + "singleCaseWithArticle": { + "type": "string" + }, + "setOfCases": { + "type": "string" + }, + "setOfCasesWithArticle": { + "type": "string" + } + } + }, + "name": { + "type": "string" + }, + "parent": { + "type": "number" + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "type": { + "type": "string", + "const": "DG.Collection" + } + }, + "required": [ + "attrs", + "cases", + "guid", + "name" + ] + }, + "ICodapV2Attribute": { + "type": "object", + "properties": { + "guid": { + "type": "number" + }, + "id": { + "type": "number" + }, + "name": { + "type": "string" + }, + "type": { + "type": [ + "string", + "null" + ] + }, + "title": { + "type": "string" + }, + "cid": { + "type": "string" + }, + "defaultMin": { + "type": "number" + }, + "defaultMax": { + "type": "number" + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "categoryMap": {}, + "_categoryMap": {}, + "colormap": {}, + "_colormap": {}, + "blockDisplayOfEmptyCategories": { + "type": "boolean" + }, + "editable": { + "anyOf": [ + { + "type": "boolean" + }, + {} + ] + }, + "hidden": { + "type": "boolean" + }, + "renameable": { + "type": "boolean" + }, + "deleteable": { + "type": "boolean" + }, + "formula": { + "type": "string" + }, + "deletedFormula": { + "type": "string" + }, + "precision": { + "type": [ + "number", + "string", + "null" + ] + }, + "unit": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "guid", + "name" + ] + }, + "ICodapV2Case": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "guid": { + "type": "number" + }, + "itemID": { + "type": "string" + }, + "parent": { + "type": "number" + }, + "values": { + "type": "object", + "additionalProperties": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "type": "object" + } + ] + } + } + }, + "required": [ + "guid", + "values" + ] + }, + "ICodapV2DataContextMetadata": { + "type": "object", + "properties": { + "description": { + "type": "string" + } + } + }, + "ICodapV2GameContext": { + "type": "object", + "properties": { + "document": { + "type": "number" + }, + "guid": { + "type": "number" + }, + "id": { + "type": "number" + }, + "flexibleGroupingChangeFlag": { + "type": [ + "boolean", + "null" + ] + }, + "name": { + "type": "string" + }, + "title": { + "type": "string" + }, + "collections": { + "type": "array", + "items": { + "$ref": "#/definitions/ICodapV2Collection" + } + }, + "description": { + "type": "string" + }, + "metadata": { + "anyOf": [ + { + "$ref": "#/definitions/ICodapV2DataContextMetadata" + }, + { + "type": "null" + } + ] + }, + "type": { + "type": "string", + "const": "DG.GameContext" + }, + "contextStorage": { + "$ref": "#/definitions/ICodapV2GameContextStorage" + } + }, + "required": [ + "collections", + "contextStorage", + "guid", + "type" + ] + }, + "ICodapV2GameContextStorage": { + "type": "object", + "properties": { + "gameName": { + "type": [ + "string", + "null" + ] + }, + "gameUrl": { + "type": [ + "string", + "null" + ] + }, + "gameState": {}, + "_links_": { + "type": "object", + "properties": { + "selectedCases": { + "type": "array", + "items": { + "$ref": "#/definitions/ICodapV2GameContextSelectedCase" + } + } + }, + "required": [ + "selectedCases" + ] + } + } + }, + "ICodapV2GameContextSelectedCase": { + "type": "object", + "properties": { + "type": { + "type": "string" + }, + "id": { + "type": "number" + } + }, + "required": [ + "type", + "id" + ] + }, + "ICodapV2ExternalContext": { + "type": "object", + "properties": { + "externalDocumentId": { + "type": "string" + } + }, + "required": [ + "externalDocumentId" + ] + }, + "ICodapV2GlobalValue": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "value": { + "type": "number" + }, + "guid": { + "type": "number" + } + }, + "required": [ + "name", + "value", + "guid" + ] + } + } +} \ No newline at end of file diff --git a/v3/scripts/v2-support/validate-files.sh b/v3/scripts/v2-support/validate-files.sh new file mode 100755 index 0000000000..607bef32e2 --- /dev/null +++ b/v3/scripts/v2-support/validate-files.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +# This script runs the npm script `validate` over a subset of files. +# The output of each validate is sent to the console. +# The status of validation (pass/fail) will be saved into a results.csv file + +# The files to be analyzed were downloaded with +# aws s3 cp --recursive s3://models-resources/cfm-shared/ . +# That is a lot of files so will take a couple of hours download + +# It uses basic shell path filtering to get the list of folders +# to pass to the find command. It is currently set to `/1*` to +# get a subset of all of the cfm-shared files. + +# This script ignores files that: +# - have `"appName": "CFM` +# - do not have `"appName": "DG"` +# Those files are either wrapped CODAP files, non CODAP files, or +# CODAP data context only files + +find /Users/scytacki/Development/cfm-shared/1* -type f -print0 | \ +xargs -0 -n1 -I {} bash -c ' +if grep -E -q "\"appName\": ?\"DG\"" "$1" && ! grep -E -q "\"appName\": ?\"CFM" "$1"; then + if npm run validate "$1"; then + echo "$1,pass" >> results.csv; + else + echo "$1,fail" >> results.csv; + fi +fi' _ {} diff --git a/v3/scripts/v2-support/validate-results.sh b/v3/scripts/v2-support/validate-results.sh new file mode 100755 index 0000000000..9fc8864e53 --- /dev/null +++ b/v3/scripts/v2-support/validate-results.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +# This looks at a copy of the results.csv generated by +# validate-files.sh +# It only validates the files that failed before. +# This is useful when a large number of files were processed before and it'd +# be slow to reprocess all of them. +# It writes out to results.csv so you should clear out that file first. + +# To be safe this also ignore files that don't have `"appName": "DG"`` and +# files that have `"appName": "CFM` just like the original script +grep ',fail$' results-1.csv | cut -d',' -f1 | \ +xargs -n1 -I {} bash -c ' +if grep -E -q "\"appName\": ?\"DG\"" "$1" && ! grep -E -q "\"appName\": ?\"CFM" "$1"; then + if npm run validate "$1"; then + echo "$1,pass" >> results.csv; + else + echo "$1,fail" >> results.csv; + fi +fi' _ {} diff --git a/v3/src/components/calculator/calculator-registration.test.ts b/v3/src/components/calculator/calculator-registration.test.ts index 260f16c6b0..3250a27bfd 100644 --- a/v3/src/components/calculator/calculator-registration.test.ts +++ b/v3/src/components/calculator/calculator-registration.test.ts @@ -61,6 +61,6 @@ describe("Calculator registration", () => { })! const output = exportV2Component({ tile, row: freeTileRow }) expect(output?.type).toBe(kV2CalculatorDGType) - expect(output?.componentStorage.name).toBe(calculatorContentInfo?.defaultName?.()) + expect(output?.componentStorage?.name).toBe(calculatorContentInfo?.defaultName?.()) }) }) diff --git a/v3/src/components/calculator/calculator-registration.ts b/v3/src/components/calculator/calculator-registration.ts index b6efbba573..960ff26419 100644 --- a/v3/src/components/calculator/calculator-registration.ts +++ b/v3/src/components/calculator/calculator-registration.ts @@ -50,7 +50,8 @@ registerTileComponentInfo({ registerV2TileImporter(kV2CalculatorDGType, ({ v2Component, insertTile }) => { if (!isV2CalculatorComponent(v2Component)) return - const { guid, componentStorage: { name = "", title = "" } } = v2Component + const { guid, componentStorage } = v2Component + const { name = "", title = "" } = componentStorage || {} const content: ICalculatorSnapshot = { type: kCalculatorTileType, diff --git a/v3/src/components/case-table/case-table-registration.ts b/v3/src/components/case-table/case-table-registration.ts index 74157b84dd..c14a2eea98 100644 --- a/v3/src/components/case-table/case-table-registration.ts +++ b/v3/src/components/case-table/case-table-registration.ts @@ -56,6 +56,9 @@ registerV2TileImporter("DG.TableView", ({ v2Component, v2Document, sharedModelMa const { guid, componentStorage: { name, title = "", _links_, attributeWidths } } = v2Component + // Handle broken tables that don't have any links + if (!_links_) return + const content: SetRequired = { type: kCaseTableTileType, columnWidths: {} diff --git a/v3/src/components/graph/adornments/v2-adornment-importer.ts b/v3/src/components/graph/adornments/v2-adornment-importer.ts index 39a0fc6dba..ed6043af13 100644 --- a/v3/src/components/graph/adornments/v2-adornment-importer.ts +++ b/v3/src/components/graph/adornments/v2-adornment-importer.ts @@ -67,10 +67,20 @@ interface IInstanceKeysForAdornmentsProps { } const univariateMeasureInstances = (adornment: ICodapV2UnivariateAdornment, instanceKeys?: string[]) => { - const equationCoords = adornment.equationCoordsArray?.[0] + // TODO_V2_IMPORT: most documents with an equationCoordsArray have multiple items in the array + // we are only looking at the first item here + const equationCoordsV2 = adornment.equationCoordsArray?.[0] + + // TODO_V2_IMPORT: 93 files in cfm-shared have equationCoordsArray with values with + // proportionCenterX and proportionCenterY instead of proportionX and proportionY. + // For now we are just skipping those and treating them as undefined + // example doc: cfm-shared/1caDhoHFlpuNQgSfOdhh/file.json + const equationCoords = (equationCoordsV2 && ("proportionX" in equationCoordsV2)) + ? equationCoordsV2 + : { proportionX: NaN, proportionY: NaN } const measures: Record = {} instanceKeys?.forEach((key: string) => { - const { proportionX, proportionY } = equationCoords ?? { proportionX: NaN, proportionY: NaN } + const { proportionX, proportionY } = equationCoords const labelCoords = isFinite(proportionX) && isFinite(proportionY) ? { x: proportionX, y: proportionY } : undefined @@ -176,7 +186,7 @@ export const v2AdornmentImporter = ({data, plotModels, attributeDescriptions, yA const countAdornmentImport: ICountAdornmentModelSnapshot = { id: typedId("ADRN"), isVisible: countAdornment.isVisible, - percentType: percentTypeMap[countAdornment.percentKind], + percentType: countAdornment.percentKind != null ? percentTypeMap[countAdornment.percentKind] : undefined, showCount: countAdornment.isShowingCount, showPercent: countAdornment.isShowingPercent, type: kCountType @@ -213,6 +223,8 @@ export const v2AdornmentImporter = ({data, plotModels, attributeDescriptions, yA const lines: Record = {} instanceKeys?.forEach((key: string) => { const lineInstance = { + // TODO_V2_IMPORT: equationCoords are not handled correctly, the model stores x and y + // but the loaded equationCoords have proportionCenterX and proportionCenterY equationCoords: equationCoords ?? undefined, // The V2 default is null, but we want undefined intercept: movableLineAdornment.intercept, slope: movableLineAdornment.slope @@ -235,8 +247,10 @@ export const v2AdornmentImporter = ({data, plotModels, attributeDescriptions, yA const lines: Record = {} instanceKeys?.forEach((key: string) => { const lsrlInstances: ILSRLInstanceSnapshot[] = [] - lsrlAdornment.lsrls.forEach((lsrl) => { + lsrlAdornment.lsrls?.forEach((lsrl) => { const lsrlInstance = { + // TODO_V2_IMPORT: equationCoords are not handled correctly, the model stores x and y + // but the loaded equationCoords have proportionCenterX and proportionCenterY equationCoords: lsrl.equationCoords ?? undefined // The V2 default is null, but we want undefined } lsrlInstances.push(lsrlInstance) diff --git a/v3/src/components/graph/v2-graph-importer.test.ts b/v3/src/components/graph/v2-graph-importer.test.ts index 4d1a58dd34..bb625898cc 100644 --- a/v3/src/components/graph/v2-graph-importer.test.ts +++ b/v3/src/components/graph/v2-graph-importer.test.ts @@ -21,7 +21,7 @@ function firstGraphComponent(v2Document: CodapV2Document) { } function graphComponentWithTitle(v2Document: CodapV2Document, title: string) { - return v2Document.components.find(c => c.componentStorage.title === title)! + return v2Document.components.find(c => c.componentStorage?.title === title)! } describe("V2GraphImporter", () => { @@ -45,7 +45,7 @@ describe("V2GraphImporter", () => { sharedModelManager.setDocument(docContent) // load shared models into sharedModelManager - v2Document.contexts.forEach(({ guid }) => { + v2Document.dataContexts.forEach(({ guid }) => { const { data, metadata } = v2Document.getDataAndMetadata(guid) data && sharedModelManager!.addSharedModel(data) metadata?.setData(data?.dataSet) diff --git a/v3/src/components/graph/v2-graph-importer.ts b/v3/src/components/graph/v2-graph-importer.ts index 2b81f3351a..215e9fe7d5 100644 --- a/v3/src/components/graph/v2-graph-importer.ts +++ b/v3/src/components/graph/v2-graph-importer.ts @@ -27,7 +27,7 @@ export function v2GraphImporter({v2Component, v2Document, sharedModelManager, in pointColor, strokeColor, pointSizeMultiplier, strokeSameAsFill, isTransparent, plotBackgroundImageLockInfo, - /* The following are present in the componentStorage but not used in the V3 content model (yet): + /* TODO_V2_IMPORT: The following are present in the componentStorage but not used in the V3 content model (yet): displayOnlySelected, legendRole, legendAttributeType, numberOfLegendQuantiles, legendQuantilesAreLocked, plotBackgroundImage, transparency, strokeTransparency, plotBackgroundOpacity, @@ -65,6 +65,8 @@ export function v2GraphImporter({v2Component, v2Document, sharedModelManager, in const v2AttrId = aLink.id, attribute = v2Document.getV3Attribute(v2AttrId), v3AttrId = attribute?.id ?? '', + // This approach of dynamic key computation bypasses the typing in ICodapV2GraphStorage, + // there might be a typescript approach which fixes this. attrRoleKey = `${attrKey}Role` as keyof ICodapV2GraphStorage, v2Role = v2Component.componentStorage[attrRoleKey], attrTypeKey = `${attrKey}AttributeType` as keyof ICodapV2GraphStorage, diff --git a/v3/src/components/map/v2-map-importer.test.ts b/v3/src/components/map/v2-map-importer.test.ts index e9426ff3b1..d369ba982b 100644 --- a/v3/src/components/map/v2-map-importer.test.ts +++ b/v3/src/components/map/v2-map-importer.test.ts @@ -38,7 +38,7 @@ describe("V2MapImporter imports legacy v2 map documents", () => { sharedModelManager.setDocument(docContent) // load shared models into sharedModelManager - v2Document.contexts.forEach(({ guid }) => { + v2Document.dataContexts.forEach(({ guid }) => { const { data, metadata } = v2Document.getDataAndMetadata(guid) data && sharedModelManager!.addSharedModel(data) metadata?.setData(data?.dataSet) @@ -84,7 +84,7 @@ describe("V2MapImporter imports current v2 map documents", () => { sharedModelManager.setDocument(docContent) // load shared models into sharedModelManager - v2Document.contexts.forEach(({ guid }) => { + v2Document.dataContexts.forEach(({ guid }) => { const { data, metadata } = v2Document.getDataAndMetadata(guid) data && sharedModelManager!.addSharedModel(data) metadata?.setData(data?.dataSet) diff --git a/v3/src/components/map/v2-map-importer.ts b/v3/src/components/map/v2-map-importer.ts index 6ffc137a64..2ff7687481 100644 --- a/v3/src/components/map/v2-map-importer.ts +++ b/v3/src/components/map/v2-map-importer.ts @@ -64,7 +64,7 @@ export function v2MapImporter({v2Component, v2Document, insertTile}: V2TileImpor const { pointColor, strokeColor, pointSizeMultiplier, grid, pointsShouldBeVisible, connectingLines - /* Present in v2 layer model but not yet used in V3 layer model: + /* TODO_V2_IMPORT: Present in v2 layer model but not yet used in V3 layer model: transparency, strokeTransparency */ } = v2LayerModel @@ -72,6 +72,7 @@ export function v2MapImporter({v2Component, v2Document, insertTile}: V2TileImpor const {latId, longId} = latLongAttributesFromDataSet(data.dataSet) _attributeDescriptions.lat = {attributeID: latId, type: 'numeric'} _attributeDescriptions.long = {attributeID: longId, type: 'numeric'} + const pointLayerSnapshot: IMapPointLayerModelSnapshot = { type: kMapPointLayerType, layerIndex, @@ -100,7 +101,7 @@ export function v2MapImporter({v2Component, v2Document, insertTile}: V2TileImpor else if (isV2MapPolygonLayerStorage(v2LayerModel)) { const { areaColor, areaStrokeColor, - /* Present in v2 layer model but not yet used in V3 layer model: + /* TODO_V2_IMPORT: Present in v2 layer model but not yet used in V3 layer model: areaTransparency, areaStrokeTransparency */ } = v2LayerModel diff --git a/v3/src/components/slider/slider-registration.ts b/v3/src/components/slider/slider-registration.ts index 7d044d58d7..9b66647f30 100644 --- a/v3/src/components/slider/slider-registration.ts +++ b/v3/src/components/slider/slider-registration.ts @@ -90,13 +90,23 @@ registerV2TileImporter("DG.SliderView", ({ v2Component, v2Document, sharedModelM const { guid, ...globalSnap } = v2Global const globalValue = globalValueManager.addValueSnapshot({ id: toV3GlobalId(guid), ...globalSnap }) + const getAnimationDirectionStr = (direction: number | undefined) => { + if (direction == null) return kDefaultAnimationDirection + return AnimationDirections[direction] || kDefaultAnimationDirection + } + + const getAnimationModeStr = (mode: number | undefined) => { + if (mode == null) return kDefaultAnimationMode + return AnimationModes[mode] || kDefaultAnimationMode + } + // create slider model const content: ISliderSnapshot = { type: kSliderTileType, globalValue: globalValue.id, multipleOf: restrictToMultiplesOf ?? undefined, - animationDirection: AnimationDirections[animationDirection] || kDefaultAnimationDirection, - animationMode: AnimationModes[animationMode] || kDefaultAnimationMode, + animationDirection: getAnimationDirectionStr(animationDirection), + animationMode: getAnimationModeStr(animationMode), _animationRate: maxPerSecond ?? undefined, axis: { type: "numeric", place: "bottom", min: lowerBound ?? 0, max: upperBound ?? 12 } } @@ -152,7 +162,7 @@ registerComponentHandler(kV2SliderType, { globalValue: global.id } as SetRequired } - + return { content } }, get(content) { diff --git a/v3/src/components/web-view/web-view-registration.ts b/v3/src/components/web-view/web-view-registration.ts index a479ac93cf..0db3588371 100644 --- a/v3/src/components/web-view/web-view-registration.ts +++ b/v3/src/components/web-view/web-view-registration.ts @@ -42,7 +42,7 @@ registerTileComponentInfo({ function addWebViewSnapshot(args: V2TileImportArgs, guid: number, url?: string, state?: unknown) { const { v2Component, insertTile } = args - const { name, title, userSetTitle } = v2Component.componentStorage + const { name, title, userSetTitle } = v2Component.componentStorage || {} const content: IWebViewSnapshot = { type: kWebViewTileType, diff --git a/v3/src/v2/codap-v2-document.ts b/v3/src/v2/codap-v2-document.ts index 9550e8a104..d59bd07755 100644 --- a/v3/src/v2/codap-v2-document.ts +++ b/v3/src/v2/codap-v2-document.ts @@ -11,8 +11,8 @@ import { kItemIdPrefix, toV3AttrId, toV3CaseId, toV3CollectionId, toV3DataSetId, v3Id } from "../utilities/codap-utils" import { - CodapV2Component, ICodapV2Attribute, ICodapV2Case, ICodapV2Collection, ICodapV2DataContext, ICodapV2DocumentJson, - ICodapV2SetAsideItem, v3TypeFromV2TypeString + CodapV2Component, CodapV2Context, ICodapV2Attribute, ICodapV2Case, ICodapV2Collection, ICodapV2DocumentJson, + isV2ExternalContext, isV2InternalContext, ICodapV2SetAsideItem, v3TypeFromV2TypeString } from "./codap-v2-types" interface V2CaseIdInfo { @@ -50,6 +50,10 @@ export class CodapV2Document { return this.document.contexts } + get dataContexts() { + return this.document.contexts.filter(isV2InternalContext) + } + get components() { return this.document.components } @@ -98,8 +102,11 @@ export class CodapV2Document { }) } - registerContexts(contexts?: ICodapV2DataContext[]) { + registerContexts(contexts?: CodapV2Context[]) { contexts?.forEach(context => { + // TODO_V2_IMPORT: external contexts are not imported + // There are 75 cases of external contexts in cfm-shared + if (isV2ExternalContext(context)) return const { guid, type = "DG.DataContext", document, name = "", title, collections = [] } = context if (document && this.guidMap.get(document)?.type !== "DG.Document") { console.warn("CodapV2Document.registerContexts: context with invalid document guid:", context.document) @@ -197,10 +204,16 @@ export class CodapV2Document { this.guidMap.set(guid, { type: "DG.Case", object: _case }) // for level 0 (child-most collection), add items with their item ids and stash case ids if (level === 0) { - let itemValues = { __id__: itemID, ...toCanonical(data, values) } + // FIXME: values can include objects not just the primitives defined by IValueType + // FIXME: should the itemID overwrite any __id__ returned by toCanonical? + let itemValues = { ...toCanonical(data, values as any), __id__: itemID } // look up parent case attributes and add them to caseValues for (let parentCase = this.getParentCase(_case); parentCase; parentCase = this.getParentCase(parentCase)) { - itemValues = { ...(parentCase.values ? toCanonical(data, parentCase.values) : undefined), ...itemValues } + itemValues = { + // FIXME: see above + ...(parentCase.values ? toCanonical(data, parentCase.values as any) : undefined), + ...itemValues + } } itemsToAdd.push(itemValues) if (itemID) { diff --git a/v3/src/v2/codap-v2-import.test.ts b/v3/src/v2/codap-v2-import.test.ts index 7c9faeda2d..6efb5b1168 100644 --- a/v3/src/v2/codap-v2-import.test.ts +++ b/v3/src/v2/codap-v2-import.test.ts @@ -1,6 +1,6 @@ import { kV2CalculatorDGType } from "../components/calculator/calculator-defs" import { CodapV2Document } from "./codap-v2-document" -import { ICodapV2DocumentJson, isCodapV2Document } from "./codap-v2-types" +import { ICodapV2DocumentJson, isCodapV2Document, isV2ExternalContext } from "./codap-v2-types" const fs = require("fs") const path = require("path") @@ -56,9 +56,11 @@ describe(`V2 "mammals.codap"`, () => { expect(mammalsData.name).toBe("Mammals Sample") expect(mammalsData.components?.length).toBe(5) expect(mammalsData.contexts?.length).toBe(1) - expect(mammalsData.contexts?.[0].collections.length).toBe(1) - expect(mammalsData.contexts?.[0].collections?.[0].attrs.length).toBe(9) - expect(mammalsData.contexts?.[0].collections?.[0].cases.length).toBe(27) + const context = mammalsData.contexts?.[0] + if (isV2ExternalContext(context)) throw new Error("Context is external") + expect(context.collections.length).toBe(1) + expect(context.collections?.[0].attrs.length).toBe(9) + expect(context.collections?.[0].cases.length).toBe(27) expect(mammalsData.globalValues?.length).toBe(0) }) @@ -70,7 +72,7 @@ describe(`V2 "mammals.codap"`, () => { expect(mammals.dataSets.length).toBe(1) // numeric ids are converted to strings on import - const context = mammals.contexts[0] + const context = mammals.dataContexts[0] const collection = context.collections[0] const data = mammals.dataSets[0].dataSet data.validateCases() @@ -103,11 +105,13 @@ describe(`V2 "24cats.codap"`, () => { expect(catsData.name).toBe("24cats") expect(catsData.components?.length).toBe(5) expect(catsData.contexts?.length).toBe(1) - expect(catsData.contexts?.[0].collections.length).toBe(2) - expect(catsData.contexts?.[0].collections?.[0].attrs.length).toBe(1) - expect(catsData.contexts?.[0].collections?.[0].cases.length).toBe(2) - expect(catsData.contexts?.[0].collections?.[1].attrs.length).toBe(8) - expect(catsData.contexts?.[0].collections?.[1].cases.length).toBe(24) + const context = catsData.contexts?.[0] + if (isV2ExternalContext(context)) throw new Error("Context is external") + expect(context.collections.length).toBe(2) + expect(context.collections?.[0].attrs.length).toBe(1) + expect(context.collections?.[0].cases.length).toBe(2) + expect(context.collections?.[1].attrs.length).toBe(8) + expect(context.collections?.[1].cases.length).toBe(24) expect(catsData.globalValues?.length).toBe(0) }) @@ -119,7 +123,7 @@ describe(`V2 "24cats.codap"`, () => { expect(cats.dataSets.length).toBe(1) // numeric ids are converted to strings on import - const context = cats.contexts[0] + const context = cats.dataContexts[0] const [v2ParentCollection, v2ChildCollection] = context.collections const data = cats.dataSets[0].dataSet data.validateCases() diff --git a/v3/src/v2/codap-v2-tile-exporters.ts b/v3/src/v2/codap-v2-tile-exporters.ts index 4a18dce2c4..cada983a40 100644 --- a/v3/src/v2/codap-v2-tile-exporters.ts +++ b/v3/src/v2/codap-v2-tile-exporters.ts @@ -1,4 +1,3 @@ -import { SetOptional } from "type-fest" import { kDefaultTileHeight, kDefaultTileWidth, kTitleBarHeight } from "../components/constants" import { IFreeTileRow, isFreeTileLayout } from "../models/document/free-tile-row" import { ISharedModelManager } from "../models/shared/shared-model-manager" @@ -8,7 +7,7 @@ import { CodapV2Component, CodapV2ComponentStorage } from "./codap-v2-types" export interface V2ExporterOutput { type: CodapV2Component["type"] - storage?: SetOptional + storage?: CodapV2ComponentStorage } export interface V2TileExportArgs { diff --git a/v3/src/v2/codap-v2-types.ts b/v3/src/v2/codap-v2-types.ts index c07ca3508d..3da120b88e 100644 --- a/v3/src/v2/codap-v2-types.ts +++ b/v3/src/v2/codap-v2-types.ts @@ -3,7 +3,7 @@ import {AttributeType} from "../models/data/attribute" export interface ICodapV2Attribute { guid: number - id: number + id?: number name: string type?: string | null title?: string @@ -17,8 +17,8 @@ export interface ICodapV2Attribute { _colormap?: any blockDisplayOfEmptyCategories?: boolean // plugin bugs have led to documents in the field with values like `[true]` - editable: boolean | unknown - hidden: boolean + editable?: boolean | unknown + hidden?: boolean renameable?: boolean deleteable?: boolean formula?: string @@ -43,27 +43,40 @@ export function v3TypeFromV2TypeString(v2Type?: string | null): AttributeType | return v2Type as AttributeType } + +type CaseValue = number | string | boolean | null | object + export interface ICodapV2Case { id?: number guid: number itemID?: string parent?: number - values: Record + values: Record } export interface ICodapV2Collection { attrs: ICodapV2Attribute[] cases: ICodapV2Case[] - caseName: string | null - childAttrName: string | null + // TODO_V2_IMPORT: caseName is not imported + // There are 2,500 cases where this has a value in cfm-shared + caseName?: string | null + // TODO_V2_IMPORT: childAttrName is not imported + // There are 8,592 cases where this has a value in cfm-shared + childAttrName?: string | null cid?: string - collapseChildren: boolean | null + // TODO_V2_IMPORT: collapseChildren is not imported + // There are 250 cases where this is true in cfm-shared + collapseChildren?: boolean | null + // TODO_V2_IMPORT: defaults does not seem to be imported + // There are 825 cases where it is defined in cfm-shared defaults?: { - xAttr: string - yAttr: string + xAttr?: string + yAttr?: string } guid: number id?: number + // TODO_V2_IMPORT: labels seem to be handled by the plugin api, and stored in v3 structures but + // they don't seem to be imported when opening a v2 document labels?: { singleCase?: string pluralCase?: string @@ -73,8 +86,8 @@ export interface ICodapV2Collection { } name: string parent?: number - title: string - type: "DG.Collection" + title?: string | null + type?: "DG.Collection" } // when exporting a v3 collection to v2 type CollectionNotYetExported = "cases" | "caseName" | "childAttrName" | "collapseChildren" @@ -88,6 +101,9 @@ export interface ICodapV2SetAsideItem { values: Record } +export interface ICodapV2ExternalContext { + externalDocumentId: string +} export interface ICodapV2DataContextMetadata { description?: string } @@ -95,10 +111,15 @@ export interface ICodapV2DataContext { type: "DG.DataContext" document?: number // id of containing document guid: number - id: number - flexibleGroupingChangeFlag: boolean - name: string - title: string + // TODO_V2_IMPORT do we need to import id so we can export it + // it again? + // It is not always present in v2 files. + id?: number + // TODO_V2_IMPORT flexibleGroupingChangeFlag is not imported + // This is set to true in 11,000 cfm-shared files + flexibleGroupingChangeFlag?: boolean | null + name?: string + title?: string collections: ICodapV2Collection[] description?: string metadata?: ICodapV2DataContextMetadata | null @@ -106,6 +127,53 @@ export interface ICodapV2DataContext { setAsideItems?: ICodapV2SetAsideItem[] // contextStorage: this.contextStorage } + +export interface ICodapV2GameContextSelectedCase { + type: string + id: number +} + +export interface ICodapV2GameContextStorage { + gameName?: string | null + gameUrl?: string | null + gameState?: any + _links_?: { + selectedCases: ICodapV2GameContextSelectedCase[] + } +} + +// TODO_V2_IMPORT: we don't fully handle the GameContext +// It seems it is legacy version of the DataContext specific for plugins. +// v2 can open documents with GameContext objects. +// There are about 4,000 documents in cfm-shared with a GameContext. +// If v2 opens a document with a GameContext it will preserve it when +// saving the document. +// In v3 the "dataset" of the GameContext will be loaded but the +// plugin state will be ignored. +// +// Here is an example document using the Markov plugin: +// cfm-shared/0b5715a7dab0a92ef332c8407bf51c53cc3ae710/file.json +// It has gameState in the GameContext +// It restores the gameState in v2 +// +// An example with Next Gen MW games: +// cfm-shared/0b65185859c238170055bde1fef60830e52bd63d49bec96e0b1db84c65ea3356/file.json +// - this document cannot be opened by CODAP build 0730 +// +// Here is one with the CartWeight plugin: +// cfm-shared/1d38b1c8597644dfee50687adc66661a55b0ca21/file.json +// It opens in v2 and has saved game state and saved cases (you need to open the table) +// +// Here is one with Sage Modeler: +// cfm-shared/003a3f0c482fdda8c9d3a7ac77ddfcbb9375420b/file.json +// +// There are also documents that are just GameContext nothing else: +// cfm-shared/19a5cbdb252a03e168d5b7541f70189ff6b47381ec70842e1bd4a7beef0bb42f/file.json +export interface ICodapV2GameContext extends Omit { + type: "DG.GameContext" + contextStorage: ICodapV2GameContextStorage +} + // when exporting a v3 data set to v2 data context type DCNotYetExported = "flexibleGroupingChangeFlag" export interface ICodapV2DataContextV3 @@ -130,8 +198,15 @@ export interface ICodapV2BaseComponentStorage { // from DG.Component.toArchive title?: string name?: string - userSetTitle: boolean - cannotClose: boolean + userSetTitle?: boolean + // in a document saved by build 0441 this property didn't exist + // TODO_V2_IMPORT: this property seems to be ignored by the import code + // The v3 models do support it, but from what I can tell each component + // importer needs to read this property from componentStorage and then + // set it on the tile snapshot they pass to insertTile + // In the CFM shared files there are more than 20,000 examples of cannotClose: true + // and more 20,000 examples cannotClose: false + cannotClose?: boolean } export interface ICodapV2CalculatorStorage extends ICodapV2BaseComponentStorage { @@ -144,24 +219,39 @@ export interface ICodapV2SliderStorage extends ICodapV2BaseComponentStorage { }, lowerBound?: number upperBound?: number - animationDirection: number - animationMode: number - restrictToMultiplesOf: number | null - maxPerSecond: number | null - userTitle: boolean + animationDirection?: number + animationMode?: number + restrictToMultiplesOf?: number | null + maxPerSecond?: number | null + userTitle?: boolean } export interface ICodapV2TableStorage extends ICodapV2BaseComponentStorage { - _links_: { + // There are some documents which have broken tables which are not linked to + // a context + _links_?: { context: IGuidLink<"DG.DataContextRecord"> } - attributeWidths: Array<{ + attributeWidths?: Array<{ _links_: { attr: IGuidLink<"DG.Attribute"> } - width: number + width?: number }> + title?: string +} + +export interface ICodapV2CaseCardStorage extends ICodapV2BaseComponentStorage { + _links_: { + context: IGuidLink<"DG.DataContextRecord"> + } + title?: string +} + +export interface ICodapV2ImageStorage extends ICodapV2BaseComponentStorage { title: string + URL: string + name: string } export interface ICodapV2WebViewStorage extends ICodapV2BaseComponentStorage { @@ -193,9 +283,13 @@ interface ICodapV2LegacyValueModel { value: number } +// TODO_V2_IMPORT: enableMeasuresForSelection is not imported +// There are 1,600 files in cfm-shared that have it set to true +// It can be set in various places within a v2 documents + interface ICodapV2ValueModel { isVisible: boolean - enableMeasuresForSelection: boolean + enableMeasuresForSelection?: boolean values: Record } @@ -205,9 +299,9 @@ interface ICodapV2Adornment { } interface ICodapV2CountAdornment extends ICodapV2Adornment { - isShowingCount: boolean - isShowingPercent: boolean - percentKind: number + isShowingCount?: boolean + isShowingPercent?: boolean + percentKind?: number } interface ICodapV2MovableValueAdornment extends ICodapV2Adornment { @@ -221,7 +315,9 @@ interface ICodapV2MovableValueAdornment extends ICodapV2Adornment { } export interface ICodapV2UnivariateAdornment extends ICodapV2Adornment { - equationCoordsArray?: ICodapV2ProportionCoordinates[] + // TODO_V2_IMPORT: there are 267 instances in cfm-shared where + // the equationCoordsArray has items with the type of ICodapV2LineEquationCoords + equationCoordsArray?: (ICodapV2ProportionCoordinates | ICodapV2LineEquationCoords | null)[] } interface ICodapV2StErrAdornment extends ICodapV2UnivariateAdornment { @@ -229,18 +325,26 @@ interface ICodapV2StErrAdornment extends ICodapV2UnivariateAdornment { } interface ICodapV2BoxPlotAdornment extends ICodapV2UnivariateAdornment { - showOutliers: boolean + showOutliers?: boolean // TODO_V2_IMPORT: this does not seem to be handled showICI?: boolean } interface ICodapV2PlottedFunctionAdornment extends ICodapV2Adornment { - adornmentKey: string + // TODO_V2_EXPORT: this key seems unnecessary because it is basically defining + // the type of the adornment. The type of adornment is already determined from + // the key in ICodapV2AdornmentMap. However the v2 code does use this key, and + // it looks necessary to set it on export. + adornmentKey?: string expression: string } interface ICodapV2PlottedValueAdornment extends ICodapV2Adornment { - adornmentKey: string + // TODO_V2_EXPORT: this key seems unnecessary because it is basically defining + // the type of the adornment. The type of adornment is already determined from + // the key in ICodapV2AdornmentMap. However the v2 code does use this key, and + // it looks necessary to set it on export. + adornmentKey?: string expression: string } @@ -261,40 +365,60 @@ interface ICodapV2AdornmentMap { interface ICodapV2MovablePointStorage { isVisible: boolean - enableMeasuresForSelection: boolean + enableMeasuresForSelection?: boolean coordinates: ICodapV2Coordinates } +interface ICodapV2LineEquationCoords { + proportionCenterX: number + proportionCenterY: number +} + interface ICodapV2MovableLineStorage { isVisible: boolean - enableMeasuresForSelection: boolean + enableMeasuresForSelection?: boolean isInterceptLocked: boolean - equationCoords: ICodapV2Coordinates | null + // TODO_V2_IMPORT: equationCoords are not handled correctly, the import code assumes they have + // an x and y instead of proportionCenterX and proportionCenterY + // There are 2,000 instances of this in cfm-shared + // example: cfm-shared/02RllCJzS0Nt4wX3c6XL/file.json + equationCoords?: ICodapV2LineEquationCoords | null intercept: number slope: number isVertical: boolean - xIntercept: number + xIntercept: number | null } interface ICodapV2LSRL { + // TODO_V2_IMPORT: isVisible is not imported. Unknown how many files have it set to true isVisible: boolean - enableMeasuresForSelection: boolean + enableMeasuresForSelection?: boolean + // TODO_V2_IMPORT: isInterceptLocked is not imported. Unknown how many files have it set to true isInterceptLocked: boolean - equationCoords: ICodapV2Coordinates | null, - showConfidenceBands: boolean + // TODO_V2_IMPORT: equationCoords are not handled correctly, the import code assumes they have + // an x and y instead of proportionCenterX and proportionCenterY + // There are 4,000 instances of this in cfm-shared + // example: cfm-shared/00JG6PytJ4Zfhk3Yw4Xf/file.json + equationCoords?: ICodapV2LineEquationCoords | null, + // TODO_V2_IMPORT: showConfidenceBands is not imported. Unknown how many files have it set to true + showConfidenceBands?: boolean } interface ICodapV2MultipleLSRLsStorage { isVisible: boolean - enableMeasuresForSelection: boolean - showSumSquares: boolean + enableMeasuresForSelection?: boolean + // TODO_V2_IMPORT: showSumSquares is not imported + // This is set to true in 900 files in cfm-shared + showSumSquares?: boolean isInterceptLocked: boolean - showConfidenceBands: boolean - lsrls: ICodapV2LSRL[] + showConfidenceBands?: boolean + lsrls?: ICodapV2LSRL[] } export interface ICodapV2PlotStorage { - verticalAxisIsY2: boolean + // TODO_V2_IMPORT: verticalAxisIsY2 is not imported + // it is true 2,859 times in cfm-shared + verticalAxisIsY2?: boolean adornments?: ICodapV2AdornmentMap areSquaresVisible?: boolean isLSRLVisible?: boolean @@ -312,10 +436,12 @@ export interface ICodapV2PlotModel { export interface ICodapV2GraphStorage extends ICodapV2BaseComponentStorage { _links_: { context?: IGuidLink<"DG.DataContextRecord"> - hiddenCases: any[] - xColl?: IGuidLink<"DG.Collection"> + // TODO_V2_IMPORT: hiddenCases is not imported + hiddenCases?: any[] + // TODO_V2_IMPORT: it doesn't seem like any of the *Coll fields are imported + xColl?: IGuidLink<"DG.Collection" | "DG.CollectionRecord"> xAttr?: IGuidLink<"DG.Attribute"> - yColl?: IGuidLink<"DG.Collection"> + yColl?: IGuidLink<"DG.Collection" | "DG.CollectionRecord"> yAttr?: IGuidLink<"DG.Attribute"> | Array> y2Coll?: IGuidLink<"DG.Collection"> y2Attr?: IGuidLink<"DG.Attribute"> @@ -327,73 +453,87 @@ export interface ICodapV2GraphStorage extends ICodapV2BaseComponentStorage { legendAttributeType: number numberOfLegendQuantiles?: number legendQuantilesAreLocked?: boolean - pointColor: string - strokeColor: string - pointSizeMultiplier: 1 - transparency: number - strokeTransparency: number - strokeSameAsFill: boolean - isTransparent: boolean + pointColor?: string + strokeColor?: string + pointSizeMultiplier?: number + // TODO_V2_IMPORT: transparency is not imported + transparency?: number + // TODO_V2_IMPORT: strokeTransparency is not imported + strokeTransparency?: number + strokeSameAsFill?: boolean + isTransparent?: boolean plotBackgroundColor?: string | null - plotBackgroundOpacity: number - plotBackgroundImageLockInfo: any - plotBackgroundImage: string | null + // TODO_V2_IMPORT: plotBackgroundOpacity is not imported + plotBackgroundOpacity?: number + plotBackgroundImageLockInfo?: any + plotBackgroundImage?: string | null + xRole: number xAttributeType: number + xAxisClass: string + // TODO_V2_IMPORT: it looks like undefined and null might not be handled correctly + // for *LowerBound and *UpperBound when the *AxisClass is DG.CellLinearAxisModel. + // There are 966 instances of `xUpperBound: null` in cfm-shared + xLowerBound?: number | null + xUpperBound?: number | null + yRole: number yAttributeType: number - y2Role: number - y2AttributeType: number - topRole: number - topAttributeType: number - rightRole: number - rightAttributeType: number - xAxisClass: string - xLowerBound?: number - xUpperBound?: number yAxisClass: string - yLowerBound?: number - yUpperBound?: number - y2AxisClass: string - y2LowerBound?: number - y2UpperBound?: number - topAxisClass: string - rightAxisClass: string + yLowerBound?: number | null + yUpperBound?: number | null + + y2Role?: number + y2AttributeType?: number + y2AxisClass?: string + y2LowerBound?: number | null + y2UpperBound?: number | null + + topRole?: number + topAttributeType?: number + topAxisClass?: string + + rightRole?: number + rightAttributeType?: number + rightAxisClass?: string + plotModels: ICodapV2PlotModel[] } +// This is differentiated from the current storage because it has no +// layerModels and it has a legendRole interface ICodapV2MapLegacyStorage extends ICodapV2BaseComponentStorage { // [begin] legacy top-level properties ignored by current v2 code _links_: { - context: IGuidLink<"DG.DataContextRecord"> - hiddenCases: any[] + context?: IGuidLink<"DG.DataContextRecord"> + hiddenCases?: any[] } legendRole: number legendAttributeType: number - pointColor: string - strokeColor: string - pointSizeMultiplier: number - transparency: number - strokeTransparency: number + pointColor?: string + strokeColor?: string + pointSizeMultiplier?: number + transparency?: number + strokeTransparency?: number // [end] legacy top-level properties ignored by current v2 code mapModelStorage: { center: { lat: number, lng: number } | [lat: number, lng: number] zoom: number baseMapLayerName: string - gridMultiplier: number + gridMultiplier?: number // [begin] legacy mapModelStorage properties ignored by current v2 code - pointsShouldBeVisible: boolean - linesShouldBeVisible: boolean + pointsShouldBeVisible?: boolean + linesShouldBeVisible?: boolean grid: { gridMultiplier: number visible: boolean } - areaColor: string - areaTransparency: string // e.g. "0.5" - areaStrokeColor: string - areaStrokeTransparency: string // e.g. "0.6" + areaColor?: string + areaTransparency?: string | number // e.g. "0.5" + areaStrokeColor?: string + areaStrokeTransparency?: string | number // e.g. "0.6" // [end] legacy mapModelStorage properties ignored by current v2 code } } @@ -404,7 +544,7 @@ export function isV2MapLegacyStorage(obj: unknown): obj is ICodapV2MapCurrentSto interface ICodapV2MapLayerBaseStorage { _links_: { context: IGuidLink<"DG.DataContextRecord"> - hiddenCases: any[], + hiddenCases?: any[], legendColl?: IGuidLink<"DG.Collection">, // We sometimes see an array of links here legendAttr?: IGuidLink<"DG.Attribute"> | IGuidLink<"DG.Attribute">[], @@ -412,7 +552,7 @@ interface ICodapV2MapLayerBaseStorage { legendRole: number legendAttributeType: number isVisible: boolean - strokeSameAsFill: boolean + strokeSameAsFill?: boolean } export interface ICodapV2MapPointLayerStorage extends ICodapV2MapLayerBaseStorage { @@ -422,8 +562,17 @@ export interface ICodapV2MapPointLayerStorage extends ICodapV2MapLayerBaseStorag transparency: number strokeTransparency: number pointsShouldBeVisible: boolean - grid: { gridMultiplier: number, isVisible: boolean } - connectingLines: { isVisible: boolean, enableMeasuresForSelection: boolean } + grid: { + gridMultiplier: number + isVisible?: boolean + } + connectingLines: { + isVisible: boolean, + // TODO_V2_IMPORT: as noted above enableMeasuresForSelection is not imported + // There are 0 cases in cfm-shared where enableMeasuresForSelection is `true` in this + // location + enableMeasuresForSelection?: boolean + } } export function isV2MapPointLayerStorage(obj: unknown): obj is ICodapV2MapPointLayerStorage { return !!obj && typeof obj === "object" && "pointColor" in obj && obj.pointColor != null @@ -431,8 +580,10 @@ export function isV2MapPointLayerStorage(obj: unknown): obj is ICodapV2MapPointL export interface ICodapV2MapPolygonLayerStorage extends ICodapV2MapLayerBaseStorage { areaColor: string + // TODO_V2_IMPORT: areaTransparency is not be imported areaTransparency: number | string // e.g. "0.5" areaStrokeColor: string + // TODO_V2_IMPORT: areaStrokeTransparency is not imported areaStrokeTransparency: number | string // e.g. "0.6" } export function isV2MapPolygonLayerStorage(obj: unknown): obj is ICodapV2MapPolygonLayerStorage { @@ -446,6 +597,9 @@ export interface ICodapV2MapCurrentStorage extends ICodapV2BaseComponentStorage center: { lat: number, lng: number } | [lat: number, lng: number] zoom: number baseMapLayerName: string + // TODO_V2_IMPORT: gridMultiplier is not imported at this level + // It appears 8,612 times in cfm-shared either here or + // inside of the grid object gridMultiplier: number layerModels: ICodapV2MapLayerStorage[] } @@ -463,13 +617,13 @@ export function isV2MapCurrentStorage(obj: unknown): obj is ICodapV2MapCurrentSt export type ICodapV2MapStorage = ICodapV2MapLegacyStorage | ICodapV2MapCurrentStorage export interface ICodapV2GuideStorage extends ICodapV2BaseComponentStorage { - currentItemIndex?: number + currentItemIndex?: number | null isVisible?: boolean - items: Array<{ itemTitle: string, url: string }> + items: Array<{ itemTitle: string | null, url: string | null }> } export interface ICodapV2TextStorage extends ICodapV2BaseComponentStorage { - text: string + text?: string // v2's TextController.restoreComponentStorage references an `apiText` property, // but TextController.createComponentStorage doesn't write one out. ¯\_(ツ)_/¯ // apiText: string @@ -479,21 +633,22 @@ export interface ICodapV2BaseComponent { type: string // e.g. "DG.TableView", "DG.GraphView", "DG.GuideView", etc. guid: number id?: number - componentStorage: Record + componentStorage?: Record | null layout: { - width: number - height: number + // A GameView saved by build 0606 had no width or height + width?: number + height?: number left?: number top?: number - isVisible: boolean + isVisible?: boolean zIndex?: number } - savedHeight: number | null + savedHeight?: number | null } export interface ICodapV2CalculatorComponent extends ICodapV2BaseComponent { type: "DG.Calculator" - componentStorage: ICodapV2CalculatorStorage + componentStorage?: ICodapV2CalculatorStorage | null } export const isV2CalculatorComponent = (component: ICodapV2BaseComponent): component is ICodapV2CalculatorComponent => component.type === "DG.Calculator" @@ -512,6 +667,20 @@ export interface ICodapV2TableComponent extends ICodapV2BaseComponent { export const isV2TableComponent = (component: ICodapV2BaseComponent): component is ICodapV2TableComponent => component.type === "DG.TableView" +// TODO_V2_IMPORT: handle importing case cards: +// https://www.pivotaltracker.com/story/show/188596023 +export interface ICodapV2CaseCardComponent extends ICodapV2BaseComponent { + type: "DG.CaseCard" + componentStorage: ICodapV2CaseCardStorage +} + +// TODO_V2_IMPORT: handle importing images +// This is used 3,971 times in cfm-shared +export interface ICodapV2ImageComponent extends ICodapV2BaseComponent { + type: "DG.ImageComponentView" + componentStorage: ICodapV2ImageStorage +} + export interface ICodapV2WebViewComponent extends ICodapV2BaseComponent { type: "DG.WebView" componentStorage: ICodapV2WebViewStorage @@ -519,12 +688,12 @@ export interface ICodapV2WebViewComponent extends ICodapV2BaseComponent { export const isV2WebViewComponent = (component: ICodapV2BaseComponent): component is ICodapV2WebViewComponent => component.type === "DG.WebView" -export interface ICodapGameViewComponent extends ICodapV2BaseComponent { +export interface ICodapV2GameViewComponent extends ICodapV2BaseComponent { type: "DG.GameView" componentStorage: ICodapV2GameViewStorage } export const isV2GameViewComponent = - (component: ICodapV2BaseComponent): component is ICodapGameViewComponent => component.type === "DG.GameView" + (component: ICodapV2BaseComponent): component is ICodapV2GameViewComponent => component.type === "DG.GameView" export interface ICodapV2GraphComponent extends ICodapV2BaseComponent { type: "DG.GraphView" @@ -554,23 +723,39 @@ export interface ICodapV2TextComponent extends ICodapV2BaseComponent { export const isV2TextComponent = (component: ICodapV2BaseComponent): component is ICodapV2TextComponent => component.type === "DG.TextView" -export type CodapV2Component = ICodapV2CalculatorComponent | ICodapGameViewComponent | ICodapV2GraphComponent | - ICodapV2GuideComponent | ICodapV2MapComponent | ICodapV2SliderComponent | - ICodapV2TableComponent | ICodapV2TextComponent | ICodapV2WebViewComponent +export type CodapV2Component = + ICodapV2CalculatorComponent | + ICodapV2CaseCardComponent| + ICodapV2GameViewComponent | + ICodapV2GraphComponent | + ICodapV2GuideComponent | + ICodapV2ImageComponent | + ICodapV2MapComponent | + ICodapV2SliderComponent | + ICodapV2TableComponent | + ICodapV2TextComponent | + ICodapV2WebViewComponent export type CodapV2ComponentStorage = CodapV2Component["componentStorage"] +export type CodapV2Context = ICodapV2DataContext | ICodapV2GameContext | ICodapV2ExternalContext +export const isV2ExternalContext = (context: CodapV2Context): context is ICodapV2ExternalContext => + !("type" in context) && ("externalDocumentId" in context) +export const isV2InternalContext = (context: CodapV2Context): context is ICodapV2DataContext | ICodapV2GameContext => + ("type" in context) + + export interface ICodapV2DocumentJson { type?: string // "DG.Document" id?: number guid: number - name: string + name?: string | null appName: string // "DG" appVersion: string appBuildNum: string - metadata: Record + metadata?: Record // these three are maintained as maps internally but serialized as arrays components: CodapV2Component[] - contexts: ICodapV2DataContext[] + contexts: CodapV2Context[] globalValues: ICodapV2GlobalValue[] lang?: string idCount?: number diff --git a/v3/src/v2/import-v2-document.ts b/v3/src/v2/import-v2-document.ts index 7222dd6640..e7bec5c700 100644 --- a/v3/src/v2/import-v2-document.ts +++ b/v3/src/v2/import-v2-document.ts @@ -46,7 +46,7 @@ export function importV2Document(v2Document: CodapV2Document) { layout: { left = 0, top = 0, width, height: v2Height, isVisible, zIndex }, savedHeight } = v2Component const isHidden = isVisible === false - const v2Minimized = (!!savedHeight && savedHeight >= v2Height) || undefined + const v2Minimized = (!!savedHeight && v2Height != null && savedHeight >= v2Height) || undefined const isMinimized = v2Minimized && !isHidden const height = savedHeight && v2Minimized ? savedHeight : v2Height // only apply imported width and height to resizable tiles