diff --git a/.gitignore b/.gitignore index 29535ac..649ba59 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,6 @@ coverage # app src/data.json public/answers +public/homepage.webp +public/logo.png +public/favicon/*.png diff --git a/index.html b/index.html index cd6d1ab..6ff2131 100644 --- a/index.html +++ b/index.html @@ -2,7 +2,22 @@ - + + + + + + + + + + + + + + + + Scores Ceiba diff --git a/package-lock.json b/package-lock.json index cad894a..958a67b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "0.1.0", "dependencies": { "@splidejs/vue-splide": "^0.5.18", + "html2canvas": "^1.4.1", "pinia": "^2.0.11", "pinia-plugin-persist": "^1.0.0", "sass": "^1.49.9", @@ -542,6 +543,14 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -844,6 +853,14 @@ "node": ">= 8" } }, + "node_modules/css-line-break": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz", + "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==", + "dependencies": { + "utrie": "^1.0.2" + } + }, "node_modules/csstype": { "version": "2.6.20", "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.20.tgz", @@ -1779,6 +1796,18 @@ "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" }, + "node_modules/html2canvas": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz", + "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==", + "dependencies": { + "css-line-break": "^2.1.0", + "text-segmentation": "^1.0.3" + }, + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -3059,6 +3088,14 @@ "node": ">= 8" } }, + "node_modules/text-segmentation": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz", + "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==", + "dependencies": { + "utrie": "^1.0.2" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -3124,6 +3161,14 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, + "node_modules/utrie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz", + "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==", + "dependencies": { + "base64-arraybuffer": "^1.0.2" + } + }, "node_modules/v8-compile-cache": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", @@ -3814,6 +3859,11 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==" + }, "base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -4019,6 +4069,14 @@ "which": "^2.0.1" } }, + "css-line-break": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz", + "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==", + "requires": { + "utrie": "^1.0.2" + } + }, "csstype": { "version": "2.6.20", "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.20.tgz", @@ -4622,6 +4680,15 @@ "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" }, + "html2canvas": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz", + "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==", + "requires": { + "css-line-break": "^2.1.0", + "text-segmentation": "^1.0.3" + } + }, "ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -5490,6 +5557,14 @@ "terser": "^5.7.2" } }, + "text-segmentation": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz", + "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==", + "requires": { + "utrie": "^1.0.2" + } + }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -5540,6 +5615,14 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, + "utrie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz", + "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==", + "requires": { + "base64-arraybuffer": "^1.0.2" + } + }, "v8-compile-cache": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", diff --git a/package.json b/package.json index bbd06ae..6bb1093 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ }, "dependencies": { "@splidejs/vue-splide": "^0.5.18", + "html2canvas": "^1.4.1", "pinia": "^2.0.11", "pinia-plugin-persist": "^1.0.0", "sass": "^1.49.9", diff --git a/public/arbre.webp b/public/arbre.webp deleted file mode 100644 index a8ce735..0000000 Binary files a/public/arbre.webp and /dev/null differ diff --git a/public/favicon/browserconfig.xml b/public/favicon/browserconfig.xml new file mode 100644 index 0000000..1a8136d --- /dev/null +++ b/public/favicon/browserconfig.xml @@ -0,0 +1,2 @@ + +#ffffff \ No newline at end of file diff --git a/public/favicon/manifest.json b/public/favicon/manifest.json new file mode 100644 index 0000000..6139bd1 --- /dev/null +++ b/public/favicon/manifest.json @@ -0,0 +1,41 @@ +{ + "name": "App", + "icons": [ + { + "src": "\/favicon\/android-icon-36x36.png", + "sizes": "36x36", + "type": "image\/png", + "density": "0.75" + }, + { + "src": "\/favicon\/android-icon-48x48.png", + "sizes": "48x48", + "type": "image\/png", + "density": "1.0" + }, + { + "src": "\/favicon\/android-icon-72x72.png", + "sizes": "72x72", + "type": "image\/png", + "density": "1.5" + }, + { + "src": "\/favicon\/android-icon-96x96.png", + "sizes": "96x96", + "type": "image\/png", + "density": "2.0" + }, + { + "src": "\/favicon\/android-icon-144x144.png", + "sizes": "144x144", + "type": "image\/png", + "density": "3.0" + }, + { + "src": "\/favicon\/android-icon-192x192.png", + "sizes": "192x192", + "type": "image\/png", + "density": "4.0" + } + ] +} \ No newline at end of file diff --git a/public/test.html b/public/test.html new file mode 100644 index 0000000..22d0a53 --- /dev/null +++ b/public/test.html @@ -0,0 +1,41 @@ + + + + + + Web share test + + + +

Sharing MDN

+ +

We love MDN, and want to share it as far as we can! Click the following button to share MDN's home page using your system's native share functionality. See the browsers this currently works on.

+ +

+ +

+ + + + diff --git a/scripts/fetchData.js b/scripts/fetchData.js index d69c915..8c54013 100644 --- a/scripts/fetchData.js +++ b/scripts/fetchData.js @@ -30,7 +30,7 @@ async function fetchAsset(uuid) { return fetch(url); } -async function fetchData() { +async function fetchScoresData() { const fields = [ "*", "translations.*", @@ -72,18 +72,7 @@ async function fetchData() { for (const answer of question.questions_id.answers) { const uuid = answer.answers_id.image; if (uuid) { - console.log(`${folder}/${uuid}`); - const response = await fetchAsset(uuid); - try { - const thumbnail = sharp().resize({ height: 200 }).webp(); - await streamPipeline( - response.body, - thumbnail, - createWriteStream(`${folder}/${uuid}.webp`) - ); - } catch (err) { - console.log(err); - } + await downloadImage(uuid, `${folder}/${uuid}.webp`, { height: 200 }); } } } @@ -92,4 +81,231 @@ async function fetchData() { // await sharp('src/assets/arbre.png').resize({ width: 440, height: 690 }).webp().toFile('public/arbre.webp') } +async function transformImage(response, path, options, format = "webp") { + try { + let thumbnail; + console.log(path); + if (format == "webp") { + thumbnail = sharp().resize(options).webp(); + } else { + thumbnail = sharp().resize(options).toFormat("png"); + } + const stream = createWriteStream(path); + await streamPipeline(response.body, thumbnail, stream); + await stream; + } catch (err) { + console.log(err); + } +} + +async function downloadImage(uuid, path, options, format = "webp") { + const response = await fetchAsset(uuid); + await transformImage(response, path, options, format); +} + +async function fetchHomepageData() { + const fields = ["*"]; + const url = `/items/homepage?${fields + .map((item) => `fields[]=${item}`) + .join("&")}`; + const homepage = (await fetchJSONApi(url)).data; + + await downloadImage(homepage.image, `public/homepage.webp`, { + width: 1280, + height: 720, + fit: sharp.fit.cover, + }); + + const favicons = [ + { + path: `public/favicon/android-icon-192x192.png`, + options: { + width: 192, + height: 192, + fit: sharp.fit.contain, + background: { r: 255, g: 255, b: 255, alpha: 0 }, + }, + format: "png", + }, + { + path: `public/favicon/apple-icon-57x57.png`, + options: { + width: 57, + height: 57, + fit: sharp.fit.contain, + background: { r: 255, g: 255, b: 255, alpha: 0 }, + }, + format: "png", + }, + { + path: `public/favicon/apple-icon-60x60.png`, + options: { + width: 60, + height: 60, + fit: sharp.fit.contain, + background: { r: 255, g: 255, b: 255, alpha: 0 }, + }, + format: "png", + }, + { + path: `public/favicon/apple-icon-72x72.png`, + options: { + width: 72, + height: 72, + fit: sharp.fit.contain, + background: { r: 255, g: 255, b: 255, alpha: 0 }, + }, + format: "png", + }, + { + path: `public/favicon/apple-icon-76x76.png`, + options: { + width: 76, + height: 76, + fit: sharp.fit.contain, + background: { r: 255, g: 255, b: 255, alpha: 0 }, + }, + format: "png", + }, + { + path: `public/favicon/apple-icon-114x114.png`, + options: { + width: 114, + height: 114, + fit: sharp.fit.contain, + background: { r: 255, g: 255, b: 255, alpha: 0 }, + }, + format: "png", + }, + { + path: `public/favicon/apple-icon-120x120.png`, + options: { + width: 120, + height: 120, + fit: sharp.fit.contain, + background: { r: 255, g: 255, b: 255, alpha: 0 }, + }, + format: "png", + }, + { + path: `public/favicon/apple-icon-144x144.png`, + options: { + width: 144, + height: 144, + fit: sharp.fit.contain, + background: { r: 255, g: 255, b: 255, alpha: 0 }, + }, + format: "png", + }, + { + path: `public/favicon/apple-icon-152x152.png`, + options: { + width: 152, + height: 152, + fit: sharp.fit.contain, + background: { r: 255, g: 255, b: 255, alpha: 0 }, + }, + format: "png", + }, + { + path: `public/favicon/apple-icon-180x180.png`, + options: { + width: 180, + height: 180, + fit: sharp.fit.contain, + background: { r: 255, g: 255, b: 255, alpha: 0 }, + }, + format: "png", + }, + { + path: `public/favicon/favicon-16x16.png`, + options: { + width: 16, + height: 16, + fit: sharp.fit.contain, + background: { r: 255, g: 255, b: 255, alpha: 0 }, + }, + format: "png", + }, + { + path: `public/favicon/favicon-32x32.png`, + options: { + width: 32, + height: 32, + fit: sharp.fit.contain, + background: { r: 255, g: 255, b: 255, alpha: 0 }, + }, + format: "png", + }, + { + path: `public/favicon/favicon-96x96.png`, + options: { + width: 96, + height: 96, + fit: sharp.fit.contain, + background: { r: 255, g: 255, b: 255, alpha: 0 }, + }, + format: "png", + }, + { + path: `public/favicon/favicon-256x256.png`, + options: { + width: 256, + height: 256, + fit: sharp.fit.contain, + background: { r: 255, g: 255, b: 255, alpha: 0 }, + }, + format: "png", + }, + { + path: `public/favicon/ms-icon-70x70.png`, + options: { + width: 70, + height: 70, + fit: sharp.fit.contain, + background: { r: 255, g: 255, b: 255, alpha: 0 }, + }, + format: "png", + }, + { + path: `public/favicon/ms-icon-144x144.png`, + options: { + width: 144, + height: 144, + fit: sharp.fit.contain, + background: { r: 255, g: 255, b: 255, alpha: 0 }, + }, + format: "png", + }, + { + path: `public/favicon/ms-icon-150x150.png`, + options: { + width: 150, + height: 150, + fit: sharp.fit.contain, + background: { r: 255, g: 255, b: 255, alpha: 0 }, + }, + format: "png", + }, + { + path: `public/favicon/ms-icon-310x310.png`, + options: { + width: 310, + height: 310, + fit: sharp.fit.contain, + background: { r: 255, g: 255, b: 255, alpha: 0 }, + }, + format: "png", + }, + ]; + for (const favicon of favicons) { + downloadImage(homepage.logo, favicon.path, favicon.options, favicon.format); + } +} + +async function fetchData() { + await fetchHomepageData(); + await fetchScoresData(); +} + fetchData(); diff --git a/src/assets/arbre.png b/src/assets/arbre.png deleted file mode 100644 index 088935a..0000000 Binary files a/src/assets/arbre.png and /dev/null differ diff --git a/src/components/Question.vue b/src/components/Question.vue index 4685473..ee1c2f5 100644 --- a/src/components/Question.vue +++ b/src/components/Question.vue @@ -108,7 +108,7 @@ legend text-align: center font-size: 1.4rem line-height: 2rem - margin: 1rem + margin: 0 1rem .choices list-style-type: none @@ -140,10 +140,12 @@ legend left: 3px width: calc(1rem - 6px) height: calc(1rem - 6px) + &:checked + label + font-weight: bold &:checked + label::before - background-color: white - &:checked + label::after background-color: var(--color-green) + &:checked + label::after + background-color: white .main height: 100% diff --git a/src/components/Score.vue b/src/components/Score.vue index 7c57745..7f0dbab 100644 --- a/src/components/Score.vue +++ b/src/components/Score.vue @@ -9,6 +9,7 @@ import { Splide, SplideSlide } from "@splidejs/vue-splide"; import Question from "./Question.vue"; import "@splidejs/splide/dist/css/splide.min.css"; import ScoreHeader from "./ScoreHeader.vue"; +import html2canvas from "html2canvas"; const props = defineProps({ id: { @@ -110,6 +111,16 @@ function nextQuestion() { console.log(slides); }, 100); } + +async function share() { + console.log(document.querySelector(".latest")); + const canvas = await html2canvas(document.querySelector("body")); + let anchor = document.createElement("a"); + anchor.download = "download.png"; + anchor.href = canvas.toDataURL("image/png"); + anchor.click(); + anchor.remove(); +}