From e1d46507369683604e7dfc69f5cd9b975f03c1ea Mon Sep 17 00:00:00 2001 From: Satya Deep Maheshwari Date: Thu, 21 Sep 2023 11:57:10 +0530 Subject: [PATCH 1/3] Add framework for using external libs --- .eslintignore | 1 + .ext-libs-mapping.json | 7 ++ .../run-and-create-github-summary.bash | 27 +++++++ .github/workflows/compare-folders.yaml | 35 +++++++++ .gitignore | 4 +- ext-libs/jslinq/jslinq.min.js | 10 +++ package-lock.json | 46 ++++++++++++ package.json | 9 ++- scripts/delayed.js | 4 +- scripts/scripts.js | 10 +++ tools/actions/compare.js | 72 +++++++++++++++++++ tools/actions/copy.js | 35 +++++++++ 12 files changed, 257 insertions(+), 3 deletions(-) create mode 100644 .ext-libs-mapping.json create mode 100755 .github/folder-compare/run-and-create-github-summary.bash create mode 100644 .github/workflows/compare-folders.yaml create mode 100644 ext-libs/jslinq/jslinq.min.js create mode 100644 tools/actions/compare.js create mode 100644 tools/actions/copy.js diff --git a/.eslintignore b/.eslintignore index 59b07e47..c0a36a14 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,2 +1,3 @@ helix-importer-ui blocks/embed/lite-yt-embed.js +ext-libs/** diff --git a/.ext-libs-mapping.json b/.ext-libs-mapping.json new file mode 100644 index 00000000..e8e8f768 --- /dev/null +++ b/.ext-libs-mapping.json @@ -0,0 +1,7 @@ +[ + { + "name": "jslinq", + "source": "node_modules/jslinq/build", + "target": "ext-libs/jslinq" + } +] \ No newline at end of file diff --git a/.github/folder-compare/run-and-create-github-summary.bash b/.github/folder-compare/run-and-create-github-summary.bash new file mode 100755 index 00000000..b2f9b941 --- /dev/null +++ b/.github/folder-compare/run-and-create-github-summary.bash @@ -0,0 +1,27 @@ +#!/usr/bin/env bash + +for var in GITHUB_SERVER_URL GITHUB_REPOSITORY GITHUB_RUN_ID GITHUB_STEP_SUMMARY GITHUB_ENV DOMAIN_MAIN DOMAIN_BRANCH; do + if [ -z "${!var}" ]; then + echo "WARN: $var is not set. Link to artifacts will not be added." + fi +done + + +npm run compare ./.ext-libs-mapping.json; + +if grep -q "Difference" difference_results.md; then + echo "Diffs found" + export SUMMARY="$(cat difference_results.md)" + + echo "$SUMMARY" >> "$GITHUB_STEP_SUMMARY" + + # using multi-line-vars from https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#example-of-a-multiline-string + EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64) + echo "SUMMARY<<$EOF" >> "$GITHUB_ENV" + echo "$SUMMARY" >> "$GITHUB_ENV" + echo "$EOF" >> "$GITHUB_ENV" +else + echo "No diffs found" + cat difference_results.md >> "$GITHUB_STEP_SUMMARY" + echo "SUMMARY=" >> "$GITHUB_ENV" +fi \ No newline at end of file diff --git a/.github/workflows/compare-folders.yaml b/.github/workflows/compare-folders.yaml new file mode 100644 index 00000000..e3c3a223 --- /dev/null +++ b/.github/workflows/compare-folders.yaml @@ -0,0 +1,35 @@ +name: Compare Folders + +on: + pull_request: + types: [ opened, synchronize ] + +jobs: + compare-folders: + runs-on: ubuntu-latest + defaults: + run: + working-directory: . + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: 18 + + - name: Install dependencies + run: npm ci + + - name: Compare folders + id: run-compare + run: | + ./.github/folder-compare/run-and-create-github-summary.bash + cat difference_results.md + + - name: Comment on Pull Request + if: env.SUMMARY != '' + uses: peter-evans/create-or-update-comment@v3 + with: + token: ${{ secrets.GITHUB_TOKEN }} + issue-number: ${{ github.event.number }} + body: ${{ env.SUMMARY }} + diff --git a/.gitignore b/.gitignore index fd688e43..3e310932 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,6 @@ helix-importer-ui .github/visual-tests/test-results .github/visual-tests/screenshots/ .github/visual-tests/node_modules/ -.github/visual-tests/generated-test-paths.txt \ No newline at end of file +.github/visual-tests/generated-test-paths.txt + +difference_results.md \ No newline at end of file diff --git a/ext-libs/jslinq/jslinq.min.js b/ext-libs/jslinq/jslinq.min.js new file mode 100644 index 00000000..f920805b --- /dev/null +++ b/ext-libs/jslinq/jslinq.min.js @@ -0,0 +1,10 @@ +/** + * jslinq - Another LINQ provider for Javascript + + * @version : 1.0.22 + * @author : maurobussini + * @license : MIT + * @repository : https://github.com/maurobussini/jslinq.git + * @built : 2020-2-26 + */ +!function(t,e){"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?module.exports=e():t.jslinq=e()}(this,function(){function t(t){if(!t)throw new Error("Provided data is invalid");if(!(t instanceof Array))throw new Error("Provided data is not a valid array");return this.items=t,this.select=r,this.where=i,this.groupBy=n,this.join=s,this.intersect=L,this.distinct=h,this.orderBy=o,this.orderByDescending=u,this.selectMany=f,this.singleOrDefault=l,this.firstOrDefault=a,this.lastOrDefault=m,this.any=c,this.all=v,this.toList=w,this.count=g,this.skip=p,this.take=d,this.max=E,this.min=y,this.remove=b,this.subtract=x,this.sum=k,this.average=B,this}function e(t,i){if(t===i)return!0;if(t==i)return!0;if(typeof t!=typeof i)return!1;if("object"!=typeof t)return t==i;for(var r in t){var n=t[r],s=i[r];if(!("object"==typeof n?e(n,s):n==s))return!1}return!0}function i(e){if(!e)throw new Error("Expression is invalid");for(var i=[],r=0;rn?1:0},r=[],n=0;n0}function v(e){var i;return i=e?t(this.items).where(e).toList():this.items,i.length==this.items.length}function w(){return this.items}function g(){return this.items.length}function p(e){if(e<0)throw new Error("Value must be greater or equals zero");for(var i=[],r=0;r= 0.6" } }, + "node_modules/fs-extra": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", + "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -3741,6 +3758,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", @@ -4569,6 +4591,11 @@ "node": ">=4" } }, + "node_modules/jslinq": { + "version": "1.0.22", + "resolved": "https://registry.npmjs.org/jslinq/-/jslinq-1.0.22.tgz", + "integrity": "sha512-jfuqYok2cB1fPBF/t1Icbp1bpdjaVwUlePETIaaigqTVEjEGghcEcREx14UFm82rK49UdPrkSMN/Kb7UeHkvpw==" + }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -4599,6 +4626,17 @@ "node": ">=6" } }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, "node_modules/just-extend": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", @@ -7593,6 +7631,14 @@ "through": "^2.3.8" } }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", diff --git a/package.json b/package.json index dc0a452f..22f23da0 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,9 @@ "lint:js": "eslint .", "lint:css": "stylelint blocks/**/*.css styles/**/*.css", "lint": "npm run lint:js && npm run lint:css", - "prepare": "husky install" + "prepare": "husky install", + "copy": "node ./tools/actions/copy.js", + "compare": "node ./tools/actions/compare.js" }, "lint-staged": { "*.js": "eslint .", @@ -40,5 +42,10 @@ "sinon": "15.2.0", "stylelint": "15.10.3", "stylelint-config-standard": "34.0.0" + }, + + "dependencies": { + "fs-extra": "^11.1.1", + "jslinq": "^1.0.22" } } diff --git a/scripts/delayed.js b/scripts/delayed.js index 8b05ca50..2fd6d785 100644 --- a/scripts/delayed.js +++ b/scripts/delayed.js @@ -1,7 +1,9 @@ // eslint-disable-next-line import/no-cycle import { sampleRUM, isInternalPage } from './lib-franklin.js'; // eslint-disable-next-line import/no-cycle -import { getEnvType, loadConsentManager, loadScript } from './scripts.js'; +import { + getEnvType, loadConsentManager, loadScript, +} from './scripts.js'; // Core Web Vitals RUM collection sampleRUM('cwv'); diff --git a/scripts/scripts.js b/scripts/scripts.js index ca531139..51a6ea65 100644 --- a/scripts/scripts.js +++ b/scripts/scripts.js @@ -332,6 +332,16 @@ export async function fetchIndex(indexFile, sheet, pageSize = 500) { return newIndex; } +// export async function queryIndex(select, where, orderBy, rowCount, sheet) { +// let index = await fetchIndex('query-index', sheet); +// // Fetch the index until it is complete +// while (!index.complete) { +// // eslint-disable-next-line no-await-in-loop +// index = await fetchIndex('query-index', sheet); +// } +// const result = query(select, index.data, where, orderBy, rowCount); +// return result; +// } /** * Loads everything that happens a lot later, * without impacting the user experience. diff --git a/tools/actions/compare.js b/tools/actions/compare.js new file mode 100644 index 00000000..41b388d8 --- /dev/null +++ b/tools/actions/compare.js @@ -0,0 +1,72 @@ +/* eslint-disable no-console */ +const fs = require('fs'); +const path = require('path'); +const process = require('process'); + +function isDifferent(folder1, folder2) { + let different = false; + const entries1 = fs.readdirSync(folder1); + const entries2 = fs.readdirSync(folder2); + + // Check if the number of entries is different + if (entries1.length !== entries2.length) { + return true; + } + + // Check if the names of entries are different + const sortedEntries1 = entries1.sort(); + const sortedEntries2 = entries2.sort(); + for (let i = 0; i < sortedEntries1.length; i += 1) { + if (sortedEntries1[i] !== sortedEntries2[i]) { + return true; + } + } + + for (let i = 0; i < sortedEntries1.length; i += 1) { + const filePath1 = path.join(folder1, sortedEntries1[i]); + const filePath2 = path.join(folder2, sortedEntries1[i]); + + if (fs.statSync(filePath1).isFile() && fs.statSync(filePath2).isFile()) { + const content1 = fs.readFileSync(filePath1, 'utf8'); + const content2 = fs.readFileSync(filePath2, 'utf8'); + + if (content1 !== content2) { + different = true; + } + } else if (fs.statSync(filePath1).isDirectory() && fs.statSync(filePath2).isDirectory()) { + different = isDifferent(filePath1, filePath2); + } else { + different = true; + } + if (different) { break; } + } + return different; +} +try { + const mappingFilePath = process.argv[2]; + if (!mappingFilePath) { + console.error('Please provide the path to the config JSON file as a command line argument.'); + process.exit(1); + } + const mappings = JSON.parse(fs.readFileSync(mappingFilePath, 'utf8')); + const comparisonResults = []; + + mappings.forEach((mapping) => { + const result = isDifferent(mapping.source, mapping.target); + if (result) { + comparisonResults.push(`### :small_orange_diamond: Difference detected between \`${mapping.source}\` and \`${mapping.target}\` + \n#### Execute this to fix the difference: \n \`npm run copy ${mapping.source} ext-libs ${mapping.target.split('/').pop()}\`\n`); + } + }); + + if (comparisonResults.length > 0) { + fs.writeFileSync('difference_results.md', comparisonResults.join('\n')); + console.log('Comparison results have been written to difference_results.md'); + } else { + fs.writeFileSync('difference_results.md', '### :tada: No external libs differences detected :tada:'); + console.log('No differences detected'); + } +} catch (error) { + fs.writeFileSync('difference_results.md', 'Error reading or processing the JSON file'); + console.error('Error reading or processing the JSON file:', error.message); +} diff --git a/tools/actions/copy.js b/tools/actions/copy.js new file mode 100644 index 00000000..334c489c --- /dev/null +++ b/tools/actions/copy.js @@ -0,0 +1,35 @@ +/* eslint-disable no-console */ +const fs = require('fs-extra'); +const path = require('path'); + +// Get source and target directory paths from command line arguments +const sourceDir = process.argv[2]; +const targetDir = process.argv[3]; +const copiedFolderName = process.argv[4] || path.basename(sourceDir); + +if (!sourceDir || !targetDir) { + console.error('Usage: npm run copy [copied-folder-name]'); + process.exit(1); +} + +// Ensure that the target directory exists +fs.ensureDirSync(targetDir); + +// Construct the path to the target directory including the specified copied folder name +const targetPath = require('path').join(targetDir, copiedFolderName); + +// Check if the target folder already exists +if (fs.existsSync(targetPath)) { + // If it exists, remove it + fs.removeSync(targetPath); + console.log(`Removed existing folder '${targetPath}'.`); +} + +// Perform the folder copy operation (recursively) +try { + fs.copySync(sourceDir, targetPath, { recursive: true }); + console.log(`Folder '${sourceDir}' copied to '${targetPath}' successfully.`); +} catch (error) { + console.error('Error copying folder:', error); + process.exit(1); +} From 2946a3264bb58291115dfe68d96f07a18f18645d Mon Sep 17 00:00:00 2001 From: Satya Deep Maheshwari Date: Sun, 24 Sep 2023 21:50:05 +0530 Subject: [PATCH 2/3] Add support for external libs --- README.md | 41 +++++++++++++++++++++++++++++++++++++++++ scripts/scripts.js | 21 +++++++++++---------- 2 files changed, 52 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 6ee45969..cdc1e3aa 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,9 @@ # Sunstar Website + Franklin project for https://www.sunstar.com/ ## Environments + - Preview: https://main--sunstar--hlxsites.hlx.page/ - Live: https://main--sunstar--hlxsites.hlx.live/ - Edit: https://adobe.sharepoint.com/:f:/r/sites/HelixProjects/Shared%20Documents/sites/sunstar/sunstar @@ -23,3 +25,42 @@ npm run lint 1. Install the [Helix CLI](https://github.com/adobe/helix-cli): `npm install -g @adobe/helix-cli` 1. Start Franklin Proxy: `hlx up` (opens your browser at `http://localhost:3000`) 1. Open the `{repo}` directory in your favorite IDE and start coding :) + +## Adding external JS libraries + +You can add external JS libraries to your project but you need to make sure to copy over the files to be used in front end code in browser to the [ext-libs](./ext-libs/) folder. This would make them avaialble for execution in the client browser. + +Here are the steps to follow: + +1. Add the JS library to the [package.json](./package.json) file in the `dependencies` section. For example, to add the `jslinq` library, add the following line to the [package.json](./package.json) file: + + ``` + "dependencies": { + "jslinq": "^1.0.22" + } + ``` + +2. Run `npm install` to install the library in the [node_modules](./node_modules) folder. + +3. Run + ``` + npm run copy node_modules/jslinq/build ext-libs jslinq + ``` + to copy the library from the [node_modules](./node_modules) folder to the [ext-libs](./ext-libs) folder. + +4. Add a mapping in [.ext-libs-mapping.json](./.ext-libs-mapping.json) file to map the library to its respective location on [ext-libs](./ext-libs/) folder. + + For example, to map the `jslinq` library, add the following line to the [.ext-libs-mapping.json](./.ext-libs-mapping.json) file: + + ``` + { + "name": "jslinq", + "source": "node_modules/jslinq/build", + "target": "ext-libs/jslinq" + } + ``` +5. THe library is now available in the [ext-libs](./ext-libs/) folder and can be used in the front end code in the browser. For e.g. , add the following in the fron end code to load the `jslinq` library: + + ``` + await loadScript('/ext-libs/jslinq/jslinq.min.js'); + ``` \ No newline at end of file diff --git a/scripts/scripts.js b/scripts/scripts.js index 51a6ea65..e646f0c7 100644 --- a/scripts/scripts.js +++ b/scripts/scripts.js @@ -332,16 +332,6 @@ export async function fetchIndex(indexFile, sheet, pageSize = 500) { return newIndex; } -// export async function queryIndex(select, where, orderBy, rowCount, sheet) { -// let index = await fetchIndex('query-index', sheet); -// // Fetch the index until it is complete -// while (!index.complete) { -// // eslint-disable-next-line no-await-in-loop -// index = await fetchIndex('query-index', sheet); -// } -// const result = query(select, index.data, where, orderBy, rowCount); -// return result; -// } /** * Loads everything that happens a lot later, * without impacting the user experience. @@ -450,6 +440,17 @@ export async function loadScript(url, attrs = {}) { return loadingPromise; } +export async function queryIndex(sheet) { + await loadScript('/ext-libs/jslinq/jslinq.min.js'); + const index = await fetchIndex('query-index', sheet); + // Fetch the index until it is complete + while (!index.complete) { + // eslint-disable-next-line no-await-in-loop + await fetchIndex('query-index', sheet); + } + const { jslinq } = window; + return jslinq(index.data); +} /** * Add a paging widget to the div. The paging widget looks like this: *


From 902e22fc137f4a89e0d0abff62862360c5252309 Mon Sep 17 00:00:00 2001
From: Satya Deep Maheshwari 
Date: Mon, 25 Sep 2023 13:29:45 +0530
Subject: [PATCH 3/3] Address review feedback

---
 README.md          | 2 +-
 scripts/delayed.js | 4 +---
 2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/README.md b/README.md
index cdc1e3aa..12378577 100644
--- a/README.md
+++ b/README.md
@@ -28,7 +28,7 @@ npm run lint
 
 ## Adding external JS libraries
 
-You can add external JS libraries to your project but you need to make sure to copy over the files to be used in front end code in browser to the [ext-libs](./ext-libs/) folder. This would make them avaialble for execution in the client browser.
+You can add external JS libraries to your project but you need to make sure to copy over the files to be used in front end code in browser to the [ext-libs](./ext-libs/) folder. This would make them available for execution in the client browser.
 
 Here are the steps to follow:
 
diff --git a/scripts/delayed.js b/scripts/delayed.js
index 2fd6d785..8b05ca50 100644
--- a/scripts/delayed.js
+++ b/scripts/delayed.js
@@ -1,9 +1,7 @@
 // eslint-disable-next-line import/no-cycle
 import { sampleRUM, isInternalPage } from './lib-franklin.js';
 // eslint-disable-next-line import/no-cycle
-import {
-  getEnvType, loadConsentManager, loadScript,
-} from './scripts.js';
+import { getEnvType, loadConsentManager, loadScript } from './scripts.js';
 
 // Core Web Vitals RUM collection
 sampleRUM('cwv');