From 0caaee198887ff226a9d9d10bb48d1e5d5b6564b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 11:22:56 +0000 Subject: [PATCH 01/10] chore(deps): bump the dependencies group in /deployer with 2 updates (#11807) --- deployer/poetry.lock | 24 ++++++++++++------------ deployer/pyproject.toml | 4 ++-- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/deployer/poetry.lock b/deployer/poetry.lock index 2f83222fb857..bde9d0101824 100644 --- a/deployer/poetry.lock +++ b/deployer/poetry.lock @@ -48,17 +48,17 @@ uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "boto3" -version = "1.35.14" +version = "1.35.19" description = "The AWS SDK for Python" optional = false python-versions = ">=3.8" files = [ - {file = "boto3-1.35.14-py3-none-any.whl", hash = "sha256:c3e138e9041d59cd34cdc28a587dfdc899dba02ea26ebc3e10fb4bc88e5cf31b"}, - {file = "boto3-1.35.14.tar.gz", hash = "sha256:7bc78d7140c353b10a637927fe4bc4c4d95a464d1b8f515d5844def2ee52cbd5"}, + {file = "boto3-1.35.19-py3-none-any.whl", hash = "sha256:84b3fe1727945bc3cada832d969ddb3dc0d08fce1677064ca8bdc13a89c1a143"}, + {file = "boto3-1.35.19.tar.gz", hash = "sha256:9979fe674780a0b7100eae9156d74ee374cd1638a9f61c77277e3ce712f3e496"}, ] [package.dependencies] -botocore = ">=1.35.14,<1.36.0" +botocore = ">=1.35.19,<1.36.0" jmespath = ">=0.7.1,<2.0.0" s3transfer = ">=0.10.0,<0.11.0" @@ -67,13 +67,13 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] [[package]] name = "botocore" -version = "1.35.14" +version = "1.35.19" description = "Low-level, data-driven core of boto 3." optional = false python-versions = ">=3.8" files = [ - {file = "botocore-1.35.14-py3-none-any.whl", hash = "sha256:24823135232f88266b66ae8e1d0f3d40872c14cd976781f7fe52b8f0d79035a0"}, - {file = "botocore-1.35.14.tar.gz", hash = "sha256:8515a2fc7ca5bcf0b10016ba05ccf2d642b7cb77d8773026ff2fa5aa3bf38d2e"}, + {file = "botocore-1.35.19-py3-none-any.whl", hash = "sha256:c83f7f0cacfe7c19b109b363ebfa8736e570d24922f16ed371681f58ebab44a9"}, + {file = "botocore-1.35.19.tar.gz", hash = "sha256:42d6d8db7250cbd7899f786f9861e02cab17dc238f64d6acb976098ed9809625"}, ] [package.dependencies] @@ -82,7 +82,7 @@ python-dateutil = ">=2.1,<3.0.0" urllib3 = {version = ">=1.25.4,<2.2.0 || >2.2.0,<3", markers = "python_version >= \"3.10\""} [package.extras] -crt = ["awscrt (==0.21.2)"] +crt = ["awscrt (==0.21.5)"] [[package]] name = "certifi" @@ -634,13 +634,13 @@ tests = ["hypothesis (>=3.27.0)", "pytest (>=3.2.1,!=3.3.0)"] [[package]] name = "pytest" -version = "8.3.2" +version = "8.3.3" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.8" files = [ - {file = "pytest-8.3.2-py3-none-any.whl", hash = "sha256:4ba08f9ae7dcf84ded419494d229b48d0903ea6407b030eaec46df5e6a73bba5"}, - {file = "pytest-8.3.2.tar.gz", hash = "sha256:c132345d12ce551242c87269de812483f5bcc87cdbb4722e48487ba194f9fdce"}, + {file = "pytest-8.3.3-py3-none-any.whl", hash = "sha256:a6853c7375b2663155079443d2e45de913a911a11d669df02a50814944db57b2"}, + {file = "pytest-8.3.3.tar.gz", hash = "sha256:70b98107bd648308a7952b06e6ca9a50bc660be218d53c257cc1fc94fda10181"}, ] [package.dependencies] @@ -931,4 +931,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "30854a8b32ec6583dd9579ef6bdde268a6969ed5e5d00671cb288a53a9f94df3" +content-hash = "c01b8f3c14a209010ec86754e0e1adde504fd8ce69065da03505cc4cc0e1f0fe" diff --git a/deployer/pyproject.toml b/deployer/pyproject.toml index 09a0d7c24f93..eefead0ecd9b 100644 --- a/deployer/pyproject.toml +++ b/deployer/pyproject.toml @@ -10,7 +10,7 @@ readme = "README.md" [tool.poetry.dependencies] python = "^3.10" click = "^8.1.7" -boto3 = "^1.35.14" +boto3 = "^1.35.19" python-decouple = "^3.8" requests = {extras = ["security"], version = "^2.32.3"} elasticsearch-dsl = "^7.4.1" @@ -21,7 +21,7 @@ unidiff = "^0.7.5" [tool.poetry.dev-dependencies] black = "^24.8" flake8 = "^7.1.1" -pytest = "^8.3.2" +pytest = "^8.3.3" [tool.poetry.scripts] deployer = "deployer.main:cli" From 9baf777611cf9f3f7c0f65e5ece25d577290e856 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 11:38:29 +0000 Subject: [PATCH 02/10] chore(deps-dev): bump @types/react from 18.3.5 to 18.3.6 in the types group (#11808) --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index be8e04af8c34..738d61f32b0c 100644 --- a/package.json +++ b/package.json @@ -168,7 +168,7 @@ "@types/js-yaml": "^4.0.9", "@types/mdast": "^4.0.4", "@types/node": "^18.19.50", - "@types/react": "^18.3.5", + "@types/react": "^18.3.6", "@types/react-dom": "^18.3.0", "@types/react-modal": "^3.16.3", "babel-jest": "^29.7.0", diff --git a/yarn.lock b/yarn.lock index 27b735c00601..206b29be0acd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3339,10 +3339,10 @@ dependencies: "@types/react" "*" -"@types/react@*", "@types/react@^18.3.5": - version "18.3.5" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.5.tgz#5f524c2ad2089c0ff372bbdabc77ca2c4dbadf8f" - integrity sha512-WeqMfGJLGuLCqHGYRGHxnKrXcTitc6L/nBUWfWPcTarG3t9PsquqUMuVeXZeca+mglY4Vo5GZjCi0A3Or2lnxA== +"@types/react@*", "@types/react@^18.3.6": + version "18.3.6" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.6.tgz#1cb5895c5ea0d99d8bc7d659e42f72713cbd3942" + integrity sha512-CnGaRYNu2iZlkGXGrOYtdg5mLK8neySj0woZ4e2wF/eli2E6Sazmq5X+Nrj6OBrrFVQfJWTUFeqAzoRhWQXYvg== dependencies: "@types/prop-types" "*" csstype "^3.0.2" From bcc7727d0be0c3eb0abcbba2a256dd718d40b47f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 11:38:37 +0000 Subject: [PATCH 03/10] chore(deps): bump openai from 4.60.0 to 4.61.0 (#11809) --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 738d61f32b0c..c567a02ba4e6 100644 --- a/package.json +++ b/package.json @@ -120,7 +120,7 @@ "mdn-data": "^2.11.1", "open": "^10.1.0", "open-editor": "^5.0.0", - "openai": "^4.60.0", + "openai": "^4.61.0", "pg": "^8.12.0", "pgvector": "^0.2.0", "prism-svelte": "^0.5.0", diff --git a/yarn.lock b/yarn.lock index 206b29be0acd..8bc1ac46f1ea 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11056,10 +11056,10 @@ open@^7.3.1: is-docker "^2.0.0" is-wsl "^2.1.1" -openai@^4.60.0: - version "4.60.0" - resolved "https://registry.yarnpkg.com/openai/-/openai-4.60.0.tgz#4970354b7dfebd92b72aefd205212d3611eb7248" - integrity sha512-U/wNmrUPdfsvU1GrKRP5mY5YHR3ev6vtdfNID6Sauz+oquWD8r+cXPL1xiUlYniosPKajy33muVHhGS/9/t6KA== +openai@^4.61.0: + version "4.61.0" + resolved "https://registry.yarnpkg.com/openai/-/openai-4.61.0.tgz#fa21f2a636595d656e97c4aae6b5d9a8be9f05e2" + integrity sha512-xkygRBRLIUumxzKGb1ug05pWmJROQsHkGuj/N6Jiw2dj0dI19JvbFpErSZKmJ/DA+0IvpcugZqCAyk8iLpyM6Q== dependencies: "@types/node" "^18.11.18" "@types/node-fetch" "^2.6.4" From 2497484c5e94efaf9186940e28b84e3453459d05 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 11:40:46 +0000 Subject: [PATCH 04/10] chore(deps-dev): bump postcss from 8.4.45 to 8.4.47 (#11810) --- package.json | 2 +- yarn.lock | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index c567a02ba4e6..7f06a93849d8 100644 --- a/package.json +++ b/package.json @@ -218,7 +218,7 @@ "mini-css-extract-plugin": "^2.9.1", "node-dev": "^8.0.0", "peggy": "^4.0.3", - "postcss": "^8.4.45", + "postcss": "^8.4.47", "postcss-flexbugs-fixes": "^5.0.2", "postcss-loader": "^8.1.1", "postcss-normalize": "^13.0.0", diff --git a/yarn.lock b/yarn.lock index 8bc1ac46f1ea..827b3518c6ec 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11483,7 +11483,7 @@ pgvector@^0.2.0: resolved "https://registry.yarnpkg.com/pgvector/-/pgvector-0.2.0.tgz#3d10f8e7084b4fc849db9acef0930fbbef75d322" integrity sha512-ef9SggYLzgshzpsFHAha77ghSOucf1ebXcuvokgTQK6V01uihqGJv6i0+U+yjEgiDsiVtTdojDrqOHRcSmcECw== -picocolors@^1.0.0, picocolors@^1.0.1: +picocolors@^1.0.0, picocolors@^1.0.1, picocolors@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.0.tgz#5358b76a78cde483ba5cef6a9dc9671440b27d59" integrity sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw== @@ -12127,14 +12127,14 @@ postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== -postcss@^8.2.14, postcss@^8.4.28, postcss@^8.4.32, postcss@^8.4.33, postcss@^8.4.38, postcss@^8.4.45: - version "8.4.45" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.45.tgz#538d13d89a16ef71edbf75d895284ae06b79e603" - integrity sha512-7KTLTdzdZZYscUc65XmjFiB73vBhBfbPztCYdUNvlaso9PrzjzcmjqBPR0lNGkcVlcO4BjiO5rK/qNz+XAen1Q== +postcss@^8.2.14, postcss@^8.4.28, postcss@^8.4.32, postcss@^8.4.33, postcss@^8.4.38, postcss@^8.4.47: + version "8.4.47" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.47.tgz#5bf6c9a010f3e724c503bf03ef7947dcb0fea365" + integrity sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ== dependencies: nanoid "^3.3.7" - picocolors "^1.0.1" - source-map-js "^1.2.0" + picocolors "^1.1.0" + source-map-js "^1.2.1" postgres-array@~2.0.0: version "2.0.0" @@ -13462,7 +13462,7 @@ source-map-generator@0.8.0: resolved "https://registry.yarnpkg.com/source-map-generator/-/source-map-generator-0.8.0.tgz#10d5ca0651e2c9302ea338739cbd4408849c5d00" integrity sha512-psgxdGMwl5MZM9S3FWee4EgsEaIjahYV5AzGnwUvPhWeITz/j6rKpysQHlQ4USdxvINlb8lKfWGIXwfkrgtqkA== -"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.1, source-map-js@^1.0.2, source-map-js@^1.2.0: +"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.1, source-map-js@^1.0.2, source-map-js@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== From fc3586803901ea4d3a3fc66d0b6c18e57d025545 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 11:41:03 +0000 Subject: [PATCH 05/10] chore(deps-dev): bump babel-loader from 9.1.3 to 9.2.0 (#11811) --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 7f06a93849d8..9c4175d1b912 100644 --- a/package.json +++ b/package.json @@ -172,7 +172,7 @@ "@types/react-dom": "^18.3.0", "@types/react-modal": "^3.16.3", "babel-jest": "^29.7.0", - "babel-loader": "^9.1.3", + "babel-loader": "^9.2.0", "babel-plugin-named-asset-import": "^0.3.8", "babel-preset-react-app": "^10.0.1", "bfj": "^8.0.0", diff --git a/yarn.lock b/yarn.lock index 827b3518c6ec..ad4007e7a3dc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4224,10 +4224,10 @@ babel-jest@^29.7.0: graceful-fs "^4.2.9" slash "^3.0.0" -babel-loader@^9.1.3: - version "9.1.3" - resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-9.1.3.tgz#3d0e01b4e69760cc694ee306fe16d358aa1c6f9a" - integrity sha512-xG3ST4DglodGf8qSwv0MdeWLhrDsw/32QMdTO5T1ZIp9gQur0HkCyFs7Awskr10JKXFXwpAhiCuYX5oGXnRGbw== +babel-loader@^9.2.0: + version "9.2.0" + resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-9.2.0.tgz#e1c6fae52e0715962819ec45aed1eb4f84c23144" + integrity sha512-s4qfbvr85H17Rk7ozQJBIIMcVVjX8eu6NjJHzkPRswOzZcE5h+XSKAgT4KElsdkvywaWezwlu0BptTQivZ6eMQ== dependencies: find-cache-dir "^4.0.0" schema-utils "^4.0.0" From 8e698db7231a8ce0f87630bc50f19667b0deb136 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 11:41:06 +0000 Subject: [PATCH 06/10] chore(deps-dev): bump @playwright/test from 1.47.0 to 1.47.1 (#11812) --- package.json | 2 +- yarn.lock | 28 ++++++++++++++-------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index 9c4175d1b912..da3f64d35bfe 100644 --- a/package.json +++ b/package.json @@ -156,7 +156,7 @@ "@babel/preset-env": "^7.25.4", "@mdn/dinocons": "^0.5.5", "@mdn/minimalist": "^2.0.4", - "@playwright/test": "^1.47.0", + "@playwright/test": "^1.47.1", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.15", "@svgr/webpack": "^8.1.0", "@swc/core": "^1.7.26", diff --git a/yarn.lock b/yarn.lock index ad4007e7a3dc..acdd2ca6e472 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2523,12 +2523,12 @@ resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.1.1.tgz#1ec17e2edbec25c8306d424ecfbf13c7de1aaa31" integrity sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA== -"@playwright/test@^1.47.0": - version "1.47.0" - resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.47.0.tgz#69fc55b10754147cc20021afbfa05747d4961bf0" - integrity sha512-SgAdlSwYVpToI4e/IH19IHHWvoijAYH5hu2MWSXptRypLSnzj51PcGD+rsOXFayde4P9ZLi+loXVwArg6IUkCA== +"@playwright/test@^1.47.1": + version "1.47.1" + resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.47.1.tgz#568a46229a5aef54b74977297a7946bb5ac4b67b" + integrity sha512-dbWpcNQZ5nj16m+A5UNScYx7HX5trIy7g4phrcitn+Nk83S32EBX/CLU4hiF4RGKX/yRc93AAqtfaXB7JWBd4Q== dependencies: - playwright "1.47.0" + playwright "1.47.1" "@pmmmwh/react-refresh-webpack-plugin@^0.5.15": version "0.5.15" @@ -11544,17 +11544,17 @@ pkg-dir@^7.0.0: dependencies: find-up "^6.3.0" -playwright-core@1.47.0: - version "1.47.0" - resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.47.0.tgz#b54ec060fd83e5c2e46b63986b5ebb5e96ace427" - integrity sha512-1DyHT8OqkcfCkYUD9zzUTfg7EfTd+6a8MkD/NWOvjo0u/SCNd5YmY/lJwFvUZOxJbWNds+ei7ic2+R/cRz/PDg== +playwright-core@1.47.1: + version "1.47.1" + resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.47.1.tgz#bb45bdfb0d48412c535501aa3805867282857df8" + integrity sha512-i1iyJdLftqtt51mEk6AhYFaAJCDx0xQ/O5NU8EKaWFgMjItPVma542Nh/Aq8aLCjIJSzjaiEQGW/nyqLkGF1OQ== -playwright@1.47.0: - version "1.47.0" - resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.47.0.tgz#fb9b028883fad11362f9ff63ce7ba44bda0bf626" - integrity sha512-jOWiRq2pdNAX/mwLiwFYnPHpEZ4rM+fRSQpRHwEwZlP2PUANvL3+aJOF/bvISMhFD30rqMxUB4RJx9aQbfh4Ww== +playwright@1.47.1: + version "1.47.1" + resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.47.1.tgz#cdc1116f5265b8d2ff7be0d8942d49900634dc6c" + integrity sha512-SUEKi6947IqYbKxRiqnbUobVZY4bF1uu+ZnZNJX9DfU1tlf2UhWfvVjLf01pQx9URsOr18bFVUKXmanYWhbfkw== dependencies: - playwright-core "1.47.0" + playwright-core "1.47.1" optionalDependencies: fsevents "2.3.2" From d28e462bcec64e9a36028e81d593f3ad39f2d60f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 13:44:29 +0200 Subject: [PATCH 07/10] chore(main): release 2.63.1 (#11788) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .release-please-manifest.json | 2 +- CHANGELOG.md | 40 +++++++++++++++++++++++++++++++++++ package.json | 2 +- 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index a35289732c08..2c8b732d60a7 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "2.63.0" + ".": "2.63.1" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d41d9cdad0f..7c91f97fb704 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,45 @@ # Changelog +## [2.63.1](https://github.com/mdn/yari/compare/v2.63.0...v2.63.1) (2024-09-16) + + +### Bug Fixes + +* **build:** use pipefail to fail function deployments ([#11806](https://github.com/mdn/yari/issues/11806)) ([5141019](https://github.com/mdn/yari/commit/5141019b54e24d8df6db8619dd1585c8fb1a7587)) +* **placement:** use variable for horizontal banner ([#11795](https://github.com/mdn/yari/issues/11795)) ([d880aaf](https://github.com/mdn/yari/commit/d880aaf8116f1fe692452f68107e173d042e5cb9)) +* **sidebar:** reuse icon margin for non-nested entries ([#11786](https://github.com/mdn/yari/issues/11786)) ([2294df0](https://github.com/mdn/yari/commit/2294df00ba8be26bf0767b78c02a0abad5c7894e)) + + +### Enhancements + +* **ad-free:** hide all banners completely ([#11787](https://github.com/mdn/yari/issues/11787)) ([f93b850](https://github.com/mdn/yari/commit/f93b85005b8f921e9f27266d02750af0363e1d06)) + + +### Miscellaneous + +* **deps-dev:** bump @playwright/test from 1.47.0 to 1.47.1 ([#11812](https://github.com/mdn/yari/issues/11812)) ([8e698db](https://github.com/mdn/yari/commit/8e698db7231a8ce0f87630bc50f19667b0deb136)) +* **deps-dev:** bump @swc/core from 1.7.24 to 1.7.25 ([#11791](https://github.com/mdn/yari/issues/11791)) ([0e30971](https://github.com/mdn/yari/commit/0e309719d5193d4dcc193cfd997dbd591475e590)) +* **deps-dev:** bump @swc/core from 1.7.25 to 1.7.26 ([#11793](https://github.com/mdn/yari/issues/11793)) ([51c07ba](https://github.com/mdn/yari/commit/51c07ba14af4d142b9ea16315a92fe65e35999c8)) +* **deps-dev:** bump @types/jest from 29.5.12 to 29.5.13 in the types group ([#11801](https://github.com/mdn/yari/issues/11801)) ([fc79d49](https://github.com/mdn/yari/commit/fc79d49564ba9bbb0fb7edff63c77947532e97d1)) +* **deps-dev:** bump @types/react from 18.3.5 to 18.3.6 in the types group ([#11808](https://github.com/mdn/yari/issues/11808)) ([9baf777](https://github.com/mdn/yari/commit/9baf777611cf9f3f7c0f65e5ece25d577290e856)) +* **deps-dev:** bump babel-loader from 9.1.3 to 9.2.0 ([#11811](https://github.com/mdn/yari/issues/11811)) ([fc35868](https://github.com/mdn/yari/commit/fc3586803901ea4d3a3fc66d0b6c18e57d025545)) +* **deps-dev:** bump eslint-plugin-react from 7.35.2 to 7.36.1 ([#11805](https://github.com/mdn/yari/issues/11805)) ([35fc136](https://github.com/mdn/yari/commit/35fc1362f82b1d6bea60d4a0225cf4e34d5fa6a1)) +* **deps-dev:** bump husky from 9.1.5 to 9.1.6 ([#11798](https://github.com/mdn/yari/issues/11798)) ([b3288e0](https://github.com/mdn/yari/commit/b3288e016c54fa41faac200e6a78be00f74509a0)) +* **deps-dev:** bump postcss from 8.4.45 to 8.4.47 ([#11810](https://github.com/mdn/yari/issues/11810)) ([2497484](https://github.com/mdn/yari/commit/2497484c5e94efaf9186940e28b84e3453459d05)) +* **deps-dev:** bump the types group across 1 directory with 2 updates ([#11743](https://github.com/mdn/yari/issues/11743)) ([a38975e](https://github.com/mdn/yari/commit/a38975ece5e7b4cf588964ea15b1abdb19b8c69b)) +* **deps:** bump express from 4.20.0 to 4.21.0 ([#11796](https://github.com/mdn/yari/issues/11796)) ([90e5231](https://github.com/mdn/yari/commit/90e5231100588a6a65073ff1946d05fff02ab33e)) +* **deps:** bump mdn-data from 2.11.0 to 2.11.1 ([#11802](https://github.com/mdn/yari/issues/11802)) ([16d9403](https://github.com/mdn/yari/commit/16d9403db82e6bb4cfa7e94e7fb36f42ce98e4c5)) +* **deps:** bump openai from 4.58.2 to 4.59.0 ([#11799](https://github.com/mdn/yari/issues/11799)) ([4877d5b](https://github.com/mdn/yari/commit/4877d5bf0dcd1c6baf6cbdeaa46f64d4e2c820ca)) +* **deps:** bump openai from 4.59.0 to 4.60.0 ([#11804](https://github.com/mdn/yari/issues/11804)) ([dd1c110](https://github.com/mdn/yari/commit/dd1c11065374834c0ed4dd48f20fc0a3db9d7657)) +* **deps:** bump openai from 4.60.0 to 4.61.0 ([#11809](https://github.com/mdn/yari/issues/11809)) ([bcc7727](https://github.com/mdn/yari/commit/bcc7727d0be0c3eb0abcbba2a256dd718d40b47f)) +* **deps:** bump the dependencies group in /deployer with 2 updates ([#11807](https://github.com/mdn/yari/issues/11807)) ([0caaee1](https://github.com/mdn/yari/commit/0caaee198887ff226a9d9d10bb48d1e5d5b6564b)) +* **deps:** bump web-features from 1.2.0 to 1.3.0 ([#11800](https://github.com/mdn/yari/issues/11800)) ([39e1574](https://github.com/mdn/yari/commit/39e1574b4a21e15bc287fcd5310755a7b2f7f015)) +* **deps:** run npm audit fix in /cloud-function ([#11792](https://github.com/mdn/yari/issues/11792)) ([43b307f](https://github.com/mdn/yari/commit/43b307fe9c59ee3e16eecb16be943a8dfaad6d7d)) +* **deps:** run yarn upgrade ([#11789](https://github.com/mdn/yari/issues/11789)) ([2777d58](https://github.com/mdn/yari/commit/2777d58faffad32ce25e479968306331cef3b001)) +* **macros:** delete DOMAttributeMethods + unimplemented_inline macros ([#11790](https://github.com/mdn/yari/issues/11790)) ([e0b7616](https://github.com/mdn/yari/commit/e0b76166d13511d773ee67c397a058eb883bb278)) +* **placement:** add scrimba discount ([#11785](https://github.com/mdn/yari/issues/11785)) ([ac157ff](https://github.com/mdn/yari/commit/ac157ff0a659e10b7fed6646d105e1ed90a7ea44)) +* **tools-menu:** remove "New" indicator ([#11794](https://github.com/mdn/yari/issues/11794)) ([f2bca97](https://github.com/mdn/yari/commit/f2bca97057fe51e69fb2ada1e1360767d798b531)) + ## [2.63.0](https://github.com/mdn/yari/compare/v2.62.0...v2.63.0) (2024-09-10) diff --git a/package.json b/package.json index da3f64d35bfe..a1dd596821fb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@mdn/yari", - "version": "2.63.0", + "version": "2.63.1", "repository": "https://github.com/mdn/yari", "license": "MPL-2.0", "author": "MDN Web Docs", From d746b75e0fffffa2b7f0dae82c21d53d2485e063 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 11:48:32 +0000 Subject: [PATCH 08/10] chore(deps): bump @webref/css from 6.15.1 to 6.15.2 (#11803) --- .../tests/lib/__snapshots__/css-syntax.test.ts.snap | 2 +- package.json | 2 +- yarn.lock | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/kumascript/tests/lib/__snapshots__/css-syntax.test.ts.snap b/kumascript/tests/lib/__snapshots__/css-syntax.test.ts.snap index f541c96c2c25..ef311f2859f1 100644 --- a/kumascript/tests/lib/__snapshots__/css-syntax.test.ts.snap +++ b/kumascript/tests/lib/__snapshots__/css-syntax.test.ts.snap @@ -4,7 +4,7 @@ exports[`CSSSyntax renders at-rule: @import 1`] = `"
src = 
<font-src-list>

"`; -exports[`CSSSyntax renders function: polygon 1`] = `"
<polygon()> = 
polygon( <'fill-rule'>? , [ <length-percentage> <length-percentage> ]# )

<fill-rule> =
nonzero |
evenodd

<length-percentage> =
<length> |
<percentage>

"`; +exports[`CSSSyntax renders function: polygon 1`] = `"
<polygon()> = 
polygon( <'fill-rule'>? [ round <length> ]? , [ <length-percentage> <length-percentage> ]# )

<fill-rule> =
nonzero |
evenodd

<length-percentage> =
<length> |
<percentage>

"`; exports[`CSSSyntax renders function: sin 1`] = `"
<sin()> = 
sin( <calc-sum> )

<calc-sum> =
<calc-product> [ [ '+' | '-' ] <calc-product> ]*

<calc-product> =
<calc-value> [ [ '*' | '/' ] <calc-value> ]*

<calc-value> =
<number> |
<dimension> |
<percentage> |
<calc-keyword> |
( <calc-sum> )

<calc-keyword> =
e |
pi |
infinity |
-infinity |
NaN

"`; diff --git a/package.json b/package.json index a1dd596821fb..f18f8ce343e5 100644 --- a/package.json +++ b/package.json @@ -78,7 +78,7 @@ "@stripe/stripe-js": "^4.4.0", "@use-it/interval": "^1.0.0", "@vscode/ripgrep": "^1.15.9", - "@webref/css": "^6.15.1", + "@webref/css": "^6.15.2", "accept-language-parser": "^1.5.0", "async": "^3.2.6", "chalk": "^5.3.0", diff --git a/yarn.lock b/yarn.lock index acdd2ca6e472..f2dea8c90e97 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3781,10 +3781,10 @@ resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-2.0.5.tgz#325db42395cd49fe6c14057f9a900e427df8810e" integrity sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ== -"@webref/css@^6.15.1": - version "6.15.1" - resolved "https://registry.yarnpkg.com/@webref/css/-/css-6.15.1.tgz#245c6c8002d3caad7baa8ab7317d5ecef3abc4cf" - integrity sha512-sK6/HqoIpTPbCleDiHc5eXis4EYBz/111rL7pzAotYCgv6vEjEjBEDJmEjGhHP5sRbadHIGLTqlCsQ65FG0wag== +"@webref/css@^6.15.2": + version "6.15.2" + resolved "https://registry.yarnpkg.com/@webref/css/-/css-6.15.2.tgz#2ab55bad6977b2498565c285b9935958edb2e1f7" + integrity sha512-Y1UOqVPU4vVWi5DLEauYOZXGbaP8oJbZ0/SFKticz4e79uOsZFz8wuAPb0Ys6/2D5dJ2v6Gq6XFx0wC5LwSeMQ== "@xtuc/ieee754@^1.2.0": version "1.2.0" From 678bdb2a7cd9b1ff396ab6f1886d7fd2080680fa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 11:57:14 +0000 Subject: [PATCH 09/10] chore(deps): bump pytest from 8.3.2 to 8.3.3 in /testing/integration in the dependencies group (#11814) --- testing/integration/poetry.lock | 8 ++++---- testing/integration/pyproject.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/testing/integration/poetry.lock b/testing/integration/poetry.lock index b2d9b6dd4c29..000d47611386 100644 --- a/testing/integration/poetry.lock +++ b/testing/integration/poetry.lock @@ -461,13 +461,13 @@ test = ["pytest", "pytest-cov", "requests", "webob", "webtest"] [[package]] name = "pytest" -version = "8.3.2" +version = "8.3.3" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.8" files = [ - {file = "pytest-8.3.2-py3-none-any.whl", hash = "sha256:4ba08f9ae7dcf84ded419494d229b48d0903ea6407b030eaec46df5e6a73bba5"}, - {file = "pytest-8.3.2.tar.gz", hash = "sha256:c132345d12ce551242c87269de812483f5bcc87cdbb4722e48487ba194f9fdce"}, + {file = "pytest-8.3.3-py3-none-any.whl", hash = "sha256:a6853c7375b2663155079443d2e45de913a911a11d669df02a50814944db57b2"}, + {file = "pytest-8.3.3.tar.gz", hash = "sha256:70b98107bd648308a7952b06e6ca9a50bc660be218d53c257cc1fc94fda10181"}, ] [package.dependencies] @@ -576,4 +576,4 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "9b746a25738ccc0a6ef1cb0176812e06f62cb90c37b851678275816a5c379566" +content-hash = "7448676cb1a62613490d7a93bb96967c3b03ed966f34420e991ca3f64d373c30" diff --git a/testing/integration/pyproject.toml b/testing/integration/pyproject.toml index 857b78772fec..fe3896f32573 100644 --- a/testing/integration/pyproject.toml +++ b/testing/integration/pyproject.toml @@ -9,7 +9,7 @@ readme = "README.md" [tool.poetry.dependencies] python = "^3.10" -pytest = "^8.3.2" +pytest = "^8.3.3" pytest-base-url = "^2.1.0" pytest-rerunfailures = "^14.0" requests = "^2.32.3" From 6b75edd96e09b1152b332683c3fa8faf6734df69 Mon Sep 17 00:00:00 2001 From: Leo McArdle Date: Mon, 16 Sep 2024 13:23:55 +0100 Subject: [PATCH 10/10] feat(ssr): render JSX instead of index.html (#11672) rather than importing our index.html template in javascript and manually replacing and concatenating tags to build each page, now we use jsx to build each page, also: - generate csp hashes in webpack - remove manual asset hashing --- .gitignore | 3 - client/config/webpack.config.js | 35 +-- client/public/index.html | 126 +--------- client/scripts/build.js | 13 - client/scripts/postprocess-client-build.js | 121 --------- libs/constants/index.js | 2 +- package.json | 8 +- ssr/include.d.ts | 8 +- ssr/prepare.ts | 16 +- ssr/print.css | 22 ++ ssr/react-app.d.ts | 10 + ssr/render.ts | 252 ------------------- ssr/render.tsx | 271 +++++++++++++++++++++ ssr/theme.js | 32 +++ ssr/webpack.config.js | 182 ++++++++++---- testing/tests/csp.test.ts | 14 +- testing/tests/index.test.ts | 11 +- yarn.lock | 25 +- 18 files changed, 533 insertions(+), 618 deletions(-) delete mode 100644 client/scripts/postprocess-client-build.js create mode 100644 ssr/print.css delete mode 100644 ssr/render.ts create mode 100644 ssr/render.tsx create mode 100644 ssr/theme.js diff --git a/.gitignore b/.gitignore index 2426cd7bcd72..db0c3e8198af 100644 --- a/.gitignore +++ b/.gitignore @@ -46,9 +46,6 @@ yarn-error.log* /server/*.js /server/*.js.map /ssr/dist/ -/ssr/*.js -!/ssr/mozilla.dnthelper.min.js -!/ssr/webpack.config.js /ssr/*.js.map /tool/*.js /tool/*.js.map diff --git a/client/config/webpack.config.js b/client/config/webpack.config.js index db2139910913..f6245409aa1e 100644 --- a/client/config/webpack.config.js +++ b/client/config/webpack.config.js @@ -383,31 +383,16 @@ function config(webpackEnv) { }, plugins: [ // Generates an `index.html` file with the
diff --git a/client/scripts/build.js b/client/scripts/build.js index 3f1091c13e84..fac73d1b79fd 100644 --- a/client/scripts/build.js +++ b/client/scripts/build.js @@ -1,14 +1,12 @@ // Ensure environment variables are read. import "../config/env.js"; -import path from "node:path"; import chalk from "chalk"; import fs from "fs-extra"; import webpack from "webpack"; import configFactory from "../config/webpack.config.js"; import paths from "../config/paths.js"; -import { hashSomeStaticFilesForClientBuild } from "./postprocess-client-build.js"; // Makes the script crash on unhandled rejections instead of silently // ignoring them. In the future, promise rejections that are not handled will @@ -37,17 +35,6 @@ build() process.exit(1); } ) - .then(async () => { - const { results } = await hashSomeStaticFilesForClientBuild(paths.appBuild); - console.log( - chalk.green( - `Hashed ${results.length} files in ${path.join( - paths.appBuild, - "index.html" - )}` - ) - ); - }) .catch((err) => { if (err && err.message) { console.log(err.message); diff --git a/client/scripts/postprocess-client-build.js b/client/scripts/postprocess-client-build.js deleted file mode 100644 index 446f27d6420e..000000000000 --- a/client/scripts/postprocess-client-build.js +++ /dev/null @@ -1,121 +0,0 @@ -/** - * This script does all the necessary things the `yarn client:build` - * (react-scripts) can't do. - * - */ -import fs from "node:fs"; -import path from "node:path"; - -import cheerio from "cheerio"; -import md5File from "md5-file"; - -export async function hashSomeStaticFilesForClientBuild(buildRoot) { - const indexHtmlFilePath = path.join(buildRoot, "index.html"); - const indexHtml = fs.readFileSync(indexHtmlFilePath, "utf-8"); - - const results = []; - - // For every favicon referred there, change it to a file URL that - // has a hash in it. - const $ = cheerio.load(indexHtml); - $('link[rel], meta[property="og:image"]').each((i, element) => { - let href; - let attributeKey; - let hrefPrefix = ""; - if (element.tagName === "meta") { - if (element.attribs.property !== "og:image") { - return; - } - // This is a can of worms. Using from environment for now. - // We need to use an absolute URL for "og:image". - hrefPrefix = process.env.BASE_URL || ""; - href = element.attribs.content; - attributeKey = "content"; - } else { - href = element.attribs.href; - if (!href) { - return; - } - const rel = element.attribs.rel; - if ( - ![ - "icon", - "shortcut icon", - "apple-touch-icon", - "apple-touch-icon-precomposed", - "manifest", - ].includes(rel) - ) { - return; - } - attributeKey = "href"; - } - - // If this script is, for some reason, already run before we can - // bail if it looks like the href already is hashed. - if (/\.[a-f0-9]{8}\./.test(href)) { - console.warn(`Looks like ${href} is already hashed`); - return; - } - const filePath = hrefToFilePath(buildRoot, href); - if (!filePath || !fs.existsSync(filePath)) { - console.warn(`Unable to turn '${href}' into a valid file path`); - return; - } - // 8 because that's what react-scripts (which uses webpack somehow) - // uses to create those `build/static/**/*` files it builds. - const hash = md5File.sync(filePath).slice(0, 8); - const extName = path.extname(filePath); - const splitName = filePath.split(extName); - const hashedFilePath = `${splitName[0]}.${hash}${extName}`; - fs.copyFileSync(filePath, hashedFilePath); - const hashedHref = filePathToHref(buildRoot, hashedFilePath, href); - results.push({ - filePath, - href, - url: hrefPrefix + hashedHref, - hashedFilePath, - attributeKey, - }); - }); - - if (results.length > 0) { - // It clearly hashed some files. Let's update the HTML! - let newIndexHtml = indexHtml; - for (const { href, url, attributeKey } of results) { - newIndexHtml = newIndexHtml.replace( - new RegExp(`${attributeKey}="${href}"`), - `${attributeKey}="${url}"` - ); - } - fs.writeFileSync(indexHtmlFilePath, newIndexHtml, "utf-8"); - } - - return { results }; -} - -// Turn 'C:\Path\to\client\build\favicon.ico' to '/favicon.ico' -// or 'https://foo.bar/favicon.ico' if href is an absolute URL. -function filePathToHref(root, filePath, href) { - let dummyOrExistingUrl = new URL(href, "http://localhost.example"); - dummyOrExistingUrl.pathname = ""; - let url = new URL( - `${filePath.replace(root, "").replace(path.sep, "/")}`, - dummyOrExistingUrl - ); - if (url.hostname === "localhost.example") { - return url.pathname; - } else { - return url.href; - } -} - -// Turn '/favicon.ico' to 'C:\Path\to\client\build\favicon.ico' -function hrefToFilePath(root, href) { - // The href is always expected to start with a `/` which is part of a - // URL and not a file path. - const pathname = new URL(href, "http://localhost.example").pathname; - if (pathname.startsWith("/")) { - return path.join(root, pathname.slice(1).replace(/\//g, path.sep)); - } -} diff --git a/libs/constants/index.js b/libs/constants/index.js index cf445f4149f2..a6fd9289b8ad 100644 --- a/libs/constants/index.js +++ b/libs/constants/index.js @@ -74,7 +74,7 @@ export const CSP_SCRIPT_SRC_VALUES = [ "https://js.stripe.com", /* - * Inline scripts (defined in `client/public/index.html`). + * Inline scripts (imported in `ssr/render.tsx`). * * If we modify them, we must always update their CSP hash here. * diff --git a/package.json b/package.json index f18f8ce343e5..afa3fe85a40d 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "build:docs": "cross-env NODE_ENV=production NODE_OPTIONS='--no-warnings=ExperimentalWarning --loader ts-node/esm' node build/cli.ts -n", "build:glean": "cd client && cross-env VIRTUAL_ENV=venv glean translate src/telemetry/metrics.yaml src/telemetry/pings.yaml -f typescript -o src/telemetry/generated", "build:prepare": "yarn build:client && yarn build:ssr && yarn tool popularities && yarn tool spas && yarn tool gather-git-history && yarn tool build-robots-txt", - "build:ssr": "cross-env NODE_ENV=production NODE_OPTIONS='--no-warnings=ExperimentalWarning --loader ts-node/esm' node ssr/prepare.ts && cd ssr && webpack --mode=production", + "build:ssr": "cross-env NODE_ENV=production NODE_OPTIONS='--no-warnings=ExperimentalWarning --loader ts-node/esm' node ssr/prepare.ts && webpack --mode=production --config=ssr/webpack.config.js", "build:sw": "cd client/pwa && yarn && yarn build:prod", "build:sw-dev": "cd client/pwa && yarn && yarn build", "check:tsc": "find . -name 'tsconfig.json' ! -wholename '**/node_modules/**' -print0 | xargs -n1 -P 2 -0 sh -c 'cd `dirname $0` && echo \"🔄 $(pwd)\" && npx tsc --noEmit && echo \"☑️ $(pwd)\" || exit 255'", @@ -41,7 +41,7 @@ "prettier-check": "prettier --check .", "prettier-format": "prettier --write .", "render:html": "cross-env NODE_ENV=production NODE_OPTIONS='--no-warnings=ExperimentalWarning --loader ts-node/esm' node build/ssr-cli.ts", - "start": "(test -f client/build/index.html || yarn build:client) && (test -f ssr/dist/main.js || yarn build:ssr) && (test -f popularities.json || yarn tool popularities) && (test -d client/build/en-us/_spas || yarn tool spas) && nf -j Procfile.start start", + "start": "(test -f client/build/asset-manifest.json || yarn build:client) && (test -f ssr/dist/main.js || yarn build:ssr) && (test -f popularities.json || yarn tool popularities) && (test -d client/build/en-us/_spas || yarn tool spas) && nf -j Procfile.start start", "start:client": "cd client && cross-env NODE_ENV=development BABEL_ENV=development PORT=3000 node scripts/start.js", "start:server": "node-dev --experimental-loader ts-node/esm server/index.ts", "start:static-server": "cross-env NODE_OPTIONS='--no-warnings=ExperimentalWarning --loader ts-node/esm' node server/static.ts", @@ -56,7 +56,7 @@ "test:prepare": "yarn build:prepare && yarn build:docs && yarn render:html && yarn start:static-server", "test:testing": "yarn jest --rootDir testing", "tool": "cross-env NODE_OPTIONS='--no-warnings=ExperimentalWarning --loader ts-node/esm' node ./tool/cli.ts", - "watch:ssr": "cd ssr && webpack --mode=production --watch" + "watch:ssr": "webpack --mode=production --watch --config=ssr/webpack.config.js" }, "resolutions": { "http-cache-semantics": ">=4.1.1", @@ -183,6 +183,7 @@ "cross-env": "^7.0.3", "css-loader": "^7.1.2", "css-minimizer-webpack-plugin": "^7.0.0", + "cssnano": "^7.0.6", "diff": "^7.0.0", "downshift": "^7.6.1", "eslint": "^8.57.0", @@ -251,6 +252,7 @@ "stylelint-prettier": "^4.1.0", "stylelint-scss": "^5.3.2", "swr": "^2.2.5", + "terser-loader": "^2.0.3", "terser-webpack-plugin": "^5.3.10", "ts-jest": "^29.2.5", "ts-loader": "^9.5.1", diff --git a/ssr/include.d.ts b/ssr/include.d.ts index b7b76f87e0c2..894812f5d06d 100644 --- a/ssr/include.d.ts +++ b/ssr/include.d.ts @@ -1,4 +1,10 @@ -export const WEBFONT_TAGS: string; +interface AssetManifest { + files: Record; + entrypoints: string[]; +} + +export const WEBFONT_URLS: string[]; export const GTAG_PATH: null | string; export const BASE_URL: string; export const ALWAYS_ALLOW_ROBOTS: boolean; +export const ASSET_MANIFEST: AssetManifest; diff --git a/ssr/prepare.ts b/ssr/prepare.ts index fce23157a5fa..b9d05334538c 100644 --- a/ssr/prepare.ts +++ b/ssr/prepare.ts @@ -37,15 +37,6 @@ function* extractCSSURLs(css, filterFunction) { } } -function webfontTags(webfontURLs): string { - return webfontURLs - .map( - (url) => - `` - ) - .join(""); -} - function gtagScriptPath(relPath = "/static/js/gtag.js") { const filePath = relPath.split("/").slice(1).join(path.sep); if (fs.existsSync(path.join(BUILD_OUT_ROOT, filePath))) { @@ -56,16 +47,19 @@ function gtagScriptPath(relPath = "/static/js/gtag.js") { function prepare() { const webfontURLs = extractWebFontURLs(); - const tags = webfontTags(webfontURLs); const gtagPath = gtagScriptPath(); + const assetManifest = JSON.parse( + fs.readFileSync(path.join(clientBuildRoot, "asset-manifest.json"), "utf-8") + ); fs.writeFileSync( path.join(dirname, "ssr", "include.ts"), ` -export const WEBFONT_TAGS = ${JSON.stringify(tags)}; +export const WEBFONT_URLS = ${JSON.stringify(webfontURLs)}; export const GTAG_PATH = ${JSON.stringify(gtagPath)}; export const BASE_URL = ${JSON.stringify(BASE_URL)}; export const ALWAYS_ALLOW_ROBOTS = ${JSON.stringify(ALWAYS_ALLOW_ROBOTS)}; +export const ASSET_MANIFEST = ${JSON.stringify(assetManifest)}; ` ); } diff --git a/ssr/print.css b/ssr/print.css new file mode 100644 index 000000000000..de4edbf69eac --- /dev/null +++ b/ssr/print.css @@ -0,0 +1,22 @@ +.article-actions-container, +.main-menu-toggle, +.document-toc-container, +.on-github, +.sidebar, +.top-navigation-main, +.page-footer, +.top-banner, +.place, +ul.prev-next, +.language-menu { + display: none !important; +} + +.main-page-content, +.main-page-content pre { + padding: 2px; +} + +.main-page-content pre { + border-left-width: 2px; +} diff --git a/ssr/react-app.d.ts b/ssr/react-app.d.ts index 8206136fee8c..8930f7c00dc1 100644 --- a/ssr/react-app.d.ts +++ b/ssr/react-app.d.ts @@ -89,3 +89,13 @@ declare module "*.module.sass" { const classes: { readonly [key: string]: string }; export default classes; } + +declare module "*?inline" { + const source: string; + export default source; +} + +declare module "*?public" { + const src: string; + export default src; +} diff --git a/ssr/render.ts b/ssr/render.ts deleted file mode 100644 index f3fcb41ff11c..000000000000 --- a/ssr/render.ts +++ /dev/null @@ -1,252 +0,0 @@ -import { renderToString } from "react-dom/server"; -import { HydrationData } from "../libs/types/hydration"; - -import { DEFAULT_LOCALE } from "../libs/constants/index"; -import { - ALWAYS_ALLOW_ROBOTS, - BASE_URL, - WEBFONT_TAGS, - GTAG_PATH, -} from "./include"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore -import HTML from "../client/build/index.html?raw"; -import { getMetaDescription } from "./meta-description"; - -// When there are multiple options for a given language, this gives the -// preferred locale for that language (language => preferred locale). -const PREFERRED_LOCALE = { - pt: "pt-PT", - zh: "zh-CN", -}; - -// We should use the language tag (e.g. "zh-Hans") instead of the locale. -// This is a map of locale => language tag. -// See https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry -const LANGUAGE_TAGS = Object.freeze({ - "zh-CN": "zh-Hans", - "zh-TW": "zh-Hant", -}); - -function htmlEscape(s: string) { - if (!s) { - return s; - } - return s - .replace(/&/gim, "&") - .replace(/"/gim, """) - .replace(//gim, ">") - .replace(/'/gim, "'"); -} - -function getHrefLang(locale: string, allLocales: Array) { - // In most cases, just return the language code, removing the country - // code if present (so, for example, 'en-US' becomes 'en'). - const hreflang = locale.split("-")[0]; - - // Suppose the locale is one that is ambiguous, we need to fall back on a - // a preferred one. For example, if the document is available in 'zh-CN' and - // in 'zh-TW', we need to output something like this: - // - // - // - // But other bother if both ambigious locale-to-hreflang are present. - const preferred = PREFERRED_LOCALE[hreflang]; - if (preferred) { - // e.g. `preferred===zh-CN` if hreflang was `zh` - if (locale !== preferred) { - // e.g. `locale===zh-TW` - if (allLocales.includes(preferred)) { - // If the more preferred one was there, use the locale + region format. - return LANGUAGE_TAGS[locale] ?? locale; - } - } - } - return hreflang; -} - -const lazy = (creator) => { - let res; - let processed = false; - return (...args) => { - if (processed) return res; - res = creator.apply(this, ...args); - processed = true; - return res; - }; -}; - -// Path strings are preferred over URLs here to mitigate Webpack resolution - -const readBuildHTML = lazy(() => { - if (!HTML.includes('
')) { - throw new Error( - 'The render depends on being able to inject into
' - ); - } - const scripts: string[] = []; - const gaScriptPathName = GTAG_PATH; - if (gaScriptPathName) { - scripts.push(``); - } - - const html = HTML.replace('', () => - scripts.join("") - ); - return html; -}); - -export default function render( - renderApp, - url: string, - { - doc = null, - pageNotFound = false, - hyData = null, - pageTitle = null, - pageDescription = "", - possibleLocales = null, - locale = null, - noIndexing = false, - onlyFollow = false, - image = null, - blogMeta = null, - }: HydrationData = { url } -) { - const buildHtml = readBuildHTML(); - const rendered = renderToString(renderApp); - - const canonicalURL = `${BASE_URL}${url}`; - - let escapedPageTitle = htmlEscape(pageTitle); - let metaDescription = pageDescription; - - const hydrationData: HydrationData = { url }; - const translations: string[] = []; - if (blogMeta) { - hydrationData.blogMeta = blogMeta; - } - if (pageNotFound) { - escapedPageTitle = `🤷🏽‍♀️ Page not found | ${ - escapedPageTitle || "MDN Web Docs" - }`; - hydrationData.pageNotFound = true; - } else if (hyData) { - hydrationData.hyData = hyData; - } else if (doc) { - // Use the doc's title instead - escapedPageTitle = htmlEscape(doc.pageTitle); - - metaDescription = htmlEscape(getMetaDescription(doc)); - if (doc.summary) { - pageDescription = htmlEscape(doc.summary); - } - - hydrationData.doc = doc; - - if (doc.other_translations) { - // Note, we also always include "self" as a locale. That's why we concat - // this doc's locale plus doc.other_translations. - const thisLocale = { - locale: doc.locale, - title: doc.title, - url: doc.mdn_url, - }; - - const allTranslations = [...doc.other_translations, thisLocale]; - const allLocales = allTranslations.map((t) => t.locale); - - for (const translation of allTranslations) { - const translationURL = doc.mdn_url.replace( - `/${doc.locale}/`, - () => `/${translation.locale}/` - ); - // The locale used in `` needs to be the ISO-639-1 - // code. For example, it's "en", not "en-US". And it's "sv" not "sv-SE". - // See https://developers.google.com/search/docs/specialty/international/localized-versions#language-codes - translations.push( - `` - ); - } - } - } - - if (possibleLocales) { - hydrationData.possibleLocales = possibleLocales; - } - - const titleTag = `${escapedPageTitle || "MDN Web Docs"}`; - - // Open Graph protocol expects `language_TERRITORY` format. - const ogLocale = (locale || (doc && doc.locale) || DEFAULT_LOCALE).replace( - "-", - "_" - ); - - const og = new Map([ - ["title", escapedPageTitle], - ["url", canonicalURL], - ["locale", ogLocale], - ]); - - if (pageDescription) { - og.set("description", pageDescription); - } - - if (image) { - og.set("image", image); - } - - const root = `
${rendered}
`; - - const robotsContent = - !ALWAYS_ALLOW_ROBOTS || (doc && doc.noIndexing) || noIndexing - ? "noindex, nofollow" - : onlyFollow - ? "noindex, follow" - : ""; - const robotsMeta = robotsContent - ? `` - : ""; - const rssLink = ``; - const ssr_data = [...translations, ...WEBFONT_TAGS, rssLink, robotsMeta]; - let html = buildHtml; - html = html.replace( - ' `/g, - (_, typ, content) => { - return ``; - } - ); - if (metaDescription) { - html = html.replace(//g, () => { - return ``; - }); - } - html = html.replace("MDN Web Docs", () => `${titleTag}`); - - html = html.replace( - '', - () => (pageNotFound ? "" : ``) - ); - - html = html.replace('', () => ssr_data.join("")); - html = html.replace('
', () => root); - return html; -} diff --git a/ssr/render.tsx b/ssr/render.tsx new file mode 100644 index 000000000000..cd8164e256fd --- /dev/null +++ b/ssr/render.tsx @@ -0,0 +1,271 @@ +import { renderToString } from "react-dom/server"; +import { HydrationData } from "../libs/types/hydration"; + +import { DEFAULT_LOCALE } from "../libs/constants/index"; +import { + ALWAYS_ALLOW_ROBOTS, + BASE_URL, + WEBFONT_URLS, + GTAG_PATH, + ASSET_MANIFEST, +} from "./include"; +import { getMetaDescription } from "./meta-description"; + +import favicon from "../client/public/favicon-48x48.png?public"; +import appleIcon from "../client/public/apple-touch-icon.png?public"; +import manifest from "../client/public/manifest.json?public"; +import ogImage from "../client/public/mdn-social-share.png?public"; +import printCSS from "./print.css?inline"; +import themeJS from "./theme.js?inline"; + +// When there are multiple options for a given language, this gives the +// preferred locale for that language (language => preferred locale). +const PREFERRED_LOCALE = { + pt: "pt-PT", + zh: "zh-CN", +}; + +// We should use the language tag (e.g. "zh-Hans") instead of the locale. +// This is a map of locale => language tag. +// See https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry +const LANGUAGE_TAGS = Object.freeze({ + "zh-CN": "zh-Hans", + "zh-TW": "zh-Hant", +}); + +function getHrefLang(locale: string, allLocales: Array) { + // In most cases, just return the language code, removing the country + // code if present (so, for example, 'en-US' becomes 'en'). + const hreflang = locale.split("-")[0]; + + // Suppose the locale is one that is ambiguous, we need to fall back on a + // a preferred one. For example, if the document is available in 'zh-CN' and + // in 'zh-TW', we need to output something like this: + // + // + // + // But other bother if both ambigious locale-to-hreflang are present. + const preferred = PREFERRED_LOCALE[hreflang]; + if (preferred) { + // e.g. `preferred===zh-CN` if hreflang was `zh` + if (locale !== preferred) { + // e.g. `locale===zh-TW` + if (allLocales.includes(preferred)) { + // If the more preferred one was there, use the locale + region format. + return LANGUAGE_TAGS[locale] ?? locale; + } + } + } + return hreflang; +} + +export default function render( + renderApp, + url: string, + { + doc = null, + pageNotFound = false, + hyData = null, + pageTitle = null, + pageDescription = "", + possibleLocales = null, + locale = null, + noIndexing = false, + onlyFollow = false, + image = null, + blogMeta = null, + }: HydrationData = { url } +) { + const canonicalURL = `${BASE_URL}${url}`; + + let realPageTitle = pageTitle; + let metaDescription = pageDescription; + + const hydrationData: HydrationData = { url }; + const translations: JSX.Element[] = []; + if (blogMeta) { + hydrationData.blogMeta = blogMeta; + } + if (pageNotFound) { + realPageTitle = `🤷🏽‍♀️ Page not found | ${realPageTitle || "MDN Web Docs"}`; + hydrationData.pageNotFound = true; + } else if (hyData) { + hydrationData.hyData = hyData; + } else if (doc) { + // Use the doc's title instead + realPageTitle = doc.pageTitle; + + metaDescription = getMetaDescription(doc); + if (doc.summary) { + pageDescription = doc.summary; + } + + hydrationData.doc = doc; + + if (doc.other_translations) { + // Note, we also always include "self" as a locale. That's why we concat + // this doc's locale plus doc.other_translations. + const thisLocale = { + locale: doc.locale, + title: doc.title, + url: doc.mdn_url, + }; + + const allTranslations = [...doc.other_translations, thisLocale]; + const allLocales = allTranslations.map((t) => t.locale); + + for (const translation of allTranslations) { + const translationURL = doc.mdn_url.replace( + `/${doc.locale}/`, + () => `/${translation.locale}/` + ); + // The locale used in `` needs to be the ISO-639-1 + // code. For example, it's "en", not "en-US". And it's "sv" not "sv-SE". + // See https://developers.google.com/search/docs/specialty/international/localized-versions#language-codes + translations.push( + + ); + } + } + } + + if (possibleLocales) { + hydrationData.possibleLocales = possibleLocales; + } + + // Open Graph protocol expects `language_TERRITORY` format. + const ogLocale = (locale || (doc && doc.locale) || DEFAULT_LOCALE).replace( + "-", + "_" + ); + + const robotsContent = + !ALWAYS_ALLOW_ROBOTS || (doc && doc.noIndexing) || noIndexing + ? "noindex, nofollow" + : onlyFollow + ? "noindex, follow" + : ""; + + return ( + "" + + renderToString( + + + + + + + + + + + + + + + + {realPageTitle || "MDN Web Docs"} + {translations} + {WEBFONT_URLS.map((url) => ( + + ))} + + {robotsContent && } + + + + + + + + + + + + + + + + + {!pageNotFound && } +