diff --git a/cli/cli.ts b/cli/cli.ts index 80b24c2a4..d4e11e742 100644 --- a/cli/cli.ts +++ b/cli/cli.ts @@ -1841,6 +1841,8 @@ function replaceStaticImagesInJsonBlob(cfg: any, staticAssetHandler: (fileLocati return pxt.replaceStringsInJsonBlob(cfg, /^\.?\/static\/.+\.(png|gif|jpeg|jpg|svg|mp4|ico)$/i, staticAssetHandler); } +const GENERATED_FILE_DECLARATION = `\n\n`; + function saveThemeJson(cfg: pxt.TargetBundle, localDir?: boolean, packaged?: boolean) { cfg.appTheme.id = cfg.id cfg.appTheme.title = cfg.title @@ -1929,10 +1931,7 @@ function saveThemeJson(cfg: pxt.TargetBundle, localDir?: boolean, packaged?: boo if (targetConfig?.galleries) { const docsRoot = nodeutil.targetDir; let gcards: pxt.CodeCard[] = []; - let tocmd: string = - `# Projects - -`; + let tocmd: string = GENERATED_FILE_DECLARATION + `# Projects\n`; Object.keys(targetConfig.galleries).forEach(k => { targetStrings[k] = k; const galleryUrl = getGalleryUrl(targetConfig.galleries[k]) @@ -1940,8 +1939,7 @@ function saveThemeJson(cfg: pxt.TargetBundle, localDir?: boolean, packaged?: boo const gallery = pxt.gallery.parseGalleryMardown(gallerymd); const gurl = `/${galleryUrl.replace(/^\//, '')}`; tocmd += - `* [${k}](${gurl}) -`; + `* [${k}](${gurl})\n`; const gcard: pxt.CodeCard = { name: k, url: gurl @@ -1964,18 +1962,21 @@ function saveThemeJson(cfg: pxt.TargetBundle, localDir?: boolean, packaged?: boo }); nodeutil.writeFileSync(path.join(docsRoot, "docs/projects/SUMMARY.md"), tocmd, { encoding: "utf8" }); - nodeutil.writeFileSync(path.join(docsRoot, "docs/projects.md"), - `# Projects - -\`\`\`codecard -${JSON.stringify(gcards, null, 4)} -\`\`\` - -## See Also - -${gcards.map(gcard => `[${gcard.name}](${gcard.url})`).join(',\n')} - -`, { encoding: "utf8" }); + const PROJECTS_MD_CONTENT = [ + GENERATED_FILE_DECLARATION, + '', + '# Projects', + '', + '```codecard', + JSON.stringify(gcards, null, 4), + '```', + '', + '## See Also', + '', + gcards.map(gcard => `[${gcard.name}](${gcard.url})`).join(',\n') + ].join('\n'); + + nodeutil.writeFileSync(path.join(docsRoot, "docs/projects.md"), PROJECTS_MD_CONTENT, { encoding: "utf8" }); } const multiplayerGames = targetConfig?.multiplayer?.games; for (const game of (multiplayerGames ?? [])) { diff --git a/package.json b/package.json index ac48f6dc1..2affad619 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pxt-core", - "version": "11.4.7", + "version": "11.4.8", "description": "Microsoft MakeCode provides Blocks / JavaScript / Python tools and editors", "keywords": [ "TypeScript", @@ -79,7 +79,7 @@ "cssnano": "4.1.10", "dashjs": "^4.4.0", "diff-match-patch": "^1.0.5", - "dompurify": "2.0.17", + "dompurify": "3.2.6", "faye-websocket": "0.11.1", "karma": "6.4.4", "karma-chai": "0.1.0", @@ -90,15 +90,15 @@ "marked": "0.3.19", "mocha": "8.4.0", "pngjs": "3.4.0", - "postcss": "6.0.21", + "postcss": "^8.5.4", "promise.prototype.finally": "^3.1.2", "puppeteer": "23.11.1", "request": "2.88.0", "rimraf": "2.5.4", "rtlcss": "2.2.1", - "sanitize-html": "2.3.2", + "sanitize-html": "^2.17.0", "semantic-ui-less": "2.4.1", - "terser": "5.6.0" + "terser": "^5.42.0" }, "lazyDependencies": { "node-hid": "^0.7.2", @@ -132,16 +132,16 @@ "eslint-plugin-jsx-a11y": "^6.4.1", "eslint-plugin-react": "^7.23.1", "fuse.js": "3.2.0", - "gulp": "4.0.0", + "gulp": "^5.0.1", "gulp-concat": "2.6.1", "gulp-header": "2.0.9", "gulp-replace": "1.0.0", "gulp-typescript": "5.0.1", - "highlight.js": "9.12.0", + "highlight.js": "^11.11.1", "jquery": "3.5.0", "merge-stream": "2.0.0", "monaco-editor": "0.24.0", - "pouchdb": "7.2.1", + "pouchdb": "^7.3.1", "pouchdb-adapter-memory": "7.2.1", "react": "17.0.2", "react-dom": "17.0.2", @@ -149,9 +149,9 @@ "react-redux": "7.2.9", "react-tooltip": "3.9.0", "redux": "4.2.0", - "smoothie": "1.35.0", + "smoothie": "^1.36.1", "typescript": "4.8.3", - "uglifyify": "5.0.2" + "uglifyify": "^5.0.0" }, "overrides": { "@blockly/field-colour": { diff --git a/pxtlib/main.ts b/pxtlib/main.ts index 78ce52070..5eff49ba2 100644 --- a/pxtlib/main.ts +++ b/pxtlib/main.ts @@ -178,7 +178,9 @@ namespace pxt { export function replaceStringsInJsonBlob(blobPart: any, matcher: RegExp, matchHandler: (matchingString: string) => string): any { - if (Array.isArray(blobPart)) { + if (blobPart == null) { + return blobPart; // Return null or undefined as is + } else if (Array.isArray(blobPart)) { return blobPart.map(el => replaceStringsInJsonBlob(el, matcher, matchHandler)); } else if (typeof blobPart === "object") { for (const key of Object.keys(blobPart)) {