diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e863cb1c4..1ea1f1681 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,14 +8,15 @@ on: - main - template schedule: - - cron: '0 0 1 * *' # every 1st of the month at 12 am UTC + - cron: '30 1 1 * *' # every 1st of the month at 1:30 am UTC concurrency: group: ${{ github.ref }} cancel-in-progress: true -# env: +env: # GH_TOKEN: ${{ secrets.GH_TOKEN }} + BACKEND_MANAGER_KEY: ${{ secrets.BACKEND_MANAGER_KEY }} jobs: build: @@ -105,7 +106,7 @@ jobs: uses: kolpav/purge-artifacts-action@v1 with: token: ${{ secrets.GH_TOKEN }} - expire-in: 5 minutes # Set this to 0 to delete instantly + expire-in: 30 minutes # Set this to 0 to delete instantly # - name: Purge artifacts # uses: c-hive/gha-remove-artifacts@v1 # with: diff --git a/.nvmrc copy b/.nvmrc copy new file mode 100644 index 000000000..180fcca1d --- /dev/null +++ b/.nvmrc copy @@ -0,0 +1 @@ +v18/* diff --git a/_includes/master/assets/css/defaults.css b/_includes/master/assets/css/defaults.css index 0808e5a0f..2733c2207 100644 --- a/_includes/master/assets/css/defaults.css +++ b/_includes/master/assets/css/defaults.css @@ -70,6 +70,13 @@ footer, header, hgroup, menu, nav, section { } } +.animation-hover-up { + -webkit-transition: all .3s cubic-bezier(.2,.3,0,1); + -moz-transition: all .3s cubic-bezier(.2,.3,0,1); + -ms-transition: all .3s cubic-bezier(.2,.3,0,1); + -o-transition: all .3s cubic-bezier(.2,.3,0,1); + transition: all .3s cubic-bezier(.2,.3,0,1); +} .animation-hover-up:hover { -moz-transform: translate(0,-8px); -o-transform: translate(0,-8px); @@ -77,13 +84,21 @@ footer, header, hgroup, menu, nav, section { -webkit-transform: translate(0,-8px); transform: translateY(-8px); } -.animation-hover-up { + +.animation-hover-zoom { -webkit-transition: all .3s cubic-bezier(.2,.3,0,1); -moz-transition: all .3s cubic-bezier(.2,.3,0,1); -ms-transition: all .3s cubic-bezier(.2,.3,0,1); -o-transition: all .3s cubic-bezier(.2,.3,0,1); transition: all .3s cubic-bezier(.2,.3,0,1); } +.animation-hover-zoom:hover { + -moz-transform: scale(1.05); + -o-transform: scale(1.05); + -ms-transform: scale(1.05); + -webkit-transform: scale(1.05); + transform: scale(1.05); +} /* @keyframes opacity { 0% { @@ -246,6 +261,24 @@ footer, header, hgroup, menu, nav, section { animation: shimmer 3s ease-out infinite alternate; } +@keyframes flex { + 0% { + transform: scaleX(1) + } + + 50% { + transform: scale3d(1.05, 1.05, 1.05) + } + + to { + transform: scaleX(1) + } +} + +.animation-flex { + animation: flex 1s ease-in-out infinite; +} + @keyframes wiggle { 0%, 20%, @@ -276,3 +309,76 @@ footer, header, hgroup, menu, nav, section { .animation-wiggle { animation: wiggle 1.5s ease-in-out infinite; } + +@keyframes up-down { + 0%, 100% { transform: translateY(0); } + 50% { transform: translateY(-10px); } +} + +.animation-up-down { + animation: up-down 3s ease-in-out infinite; +} + +/* Filters */ +.filter-white { + filter: brightness(0) invert(1); +} + +.filter-black { + filter: brightness(0) invert(1) hue-rotate(180deg); +} + +/* Buttons */ +/* .btn-gradient { + animation: shimmer 3s ease-out infinite alternate !important; + border-width: 0 !important; + border-color: transparent !important; + background-color: transparent !important; + background-image: linear-gradient(60deg, #f79533, #f37055, #ef4e7b, #a166ab, #5073b8, #1098ad, #07b39b, #6fba82) !important; + background-size: 300% 300% !important; + text-transform: none !important; + --tw-text-opacity: 1 !important; + color: rgb(255 255 255/ 1!important) !important; + --tw-shadow: 0 1px 3px 0 rgba(0,0,0,.1), 0 1px 2px -1px rgba(0,0,0,.1); + --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); + transition-duration: .1s; + animation-duration: .1s; +} */ + +.btn-gradient { + animation: shimmer 3s ease-out infinite alternate !important; + border-width: 0 !important; + border-color: transparent !important; + background-color: transparent !important; + background-image: linear-gradient(60deg, #f79533, #f37055, #ef4e7b, #a166ab, #5073b8, #1098ad, #07b39b, #6fba82) !important; + background-size: 300% 300% !important; + text-transform: none !important; + color: rgba(255, 255, 255, 1) !important; + /* Replacing Tailwind CSS custom properties with a specific box-shadow value */ + box-shadow: 0px 4px 6px -1px rgba(0, 0, 0, 0.1), 0px 2px 4px -1px rgba(0, 0, 0, 0.06) !important; + transition-duration: 3s !important; + animation-duration: 3s !important; +} +.btn-gradient:hover { + opacity: 0.70; +} + +.text-gradient { + background-image: linear-gradient(60deg, #f79533, #f37055, #ef4e7b, #a166ab, #5073b8, #1098ad, #07b39b, #6fba82); + background-size: 300% 300%; + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + animation: shimmer 3s ease-out infinite alternate; +} + +@keyframes shimmer { + 0% { + background-position: 0% 50%; + } + 100% { + background-position: 100% 50%; + } +} + + diff --git a/_includes/master/misc/embed-manager.html b/_includes/master/misc/embed-manager.html index f10220465..ea707e389 100644 --- a/_includes/master/misc/embed-manager.html +++ b/_includes/master/misc/embed-manager.html @@ -73,7 +73,7 @@ } }) .catch(function (e) { - var error = new Error('Failed to fetch build.json: ' + e) + var error = new Error('Failed to fetch build.json @ {{ site.url }}: ' + e) console.error(error); alert(error) }) @@ -90,7 +90,6 @@ uid: user.uid, email: user.email, }, - } }) }) diff --git a/_includes/master/modules/adunits/fallback/insert.html b/_includes/master/modules/adunits/fallback/insert.html index 5788ca0a4..ea739f205 100644 --- a/_includes/master/modules/adunits/fallback/insert.html +++ b/_includes/master/modules/adunits/fallback/insert.html @@ -3,7 +3,7 @@ id="{id}" name="{id}" class="lazyload" - style="max-height: 300px;" + style="_max-height: 300px;" sandbox="allow-forms allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-scripts allow-top-navigation-by-user-activation" width="100%" height="100%" frameborder="0" marginwidth="0" marginheight="0" vspace="0" hspace="0" allowtransparency="true" scrolling="no" @@ -57,6 +57,11 @@ var command = message.command || ''; var payload = message.payload || {}; + // Auto-set id + if (!payload.id && event.source.name) { + payload.id = event.source.name.replace('uj-vert-', ''); + } + // Log console.log('Message', command, message, event.source); diff --git a/_includes/master/modules/user/dashboard.html b/_includes/master/modules/user/dashboard.html index c5c6edef5..8d79cd10d 100644 --- a/_includes/master/modules/user/dashboard.html +++ b/_includes/master/modules/user/dashboard.html @@ -81,12 +81,32 @@

Alert!

'> + + diff --git a/_layouts/master/authentication/main.html b/_layouts/master/authentication/main.html index 8e2b4c83b..7e0974276 100644 --- a/_layouts/master/authentication/main.html +++ b/_layouts/master/authentication/main.html @@ -165,7 +165,8 @@

Welcome to {{ site.brand.name }}

Welcome, valued customer!
- Resend credentials to the {{ site.brand.name }} app + + Open {{ site.brand.name }}
diff --git a/_layouts/master/global/default.html b/_layouts/master/global/default.html index 72d94c14c..edffb76c1 100644 --- a/_layouts/master/global/default.html +++ b/_layouts/master/global/default.html @@ -2,7 +2,7 @@ layout: null --- - + {%- include /master/global/head.html -%} diff --git a/_layouts/master/placeholder/contact.html b/_layouts/master/placeholder/contact.html index 295b2f40d..ec13ccd62 100644 --- a/_layouts/master/placeholder/contact.html +++ b/_layouts/master/placeholder/contact.html @@ -35,6 +35,10 @@

{{ site.brand.name }}

+
+ +
+
diff --git a/_websrc/gulp_tasks/master/_prefill.js b/_websrc/gulp_tasks/master/_prefill.js index bc6b9dc35..398887cf1 100644 --- a/_websrc/gulp_tasks/master/_prefill.js +++ b/_websrc/gulp_tasks/master/_prefill.js @@ -67,6 +67,9 @@ gulp.task('_prefill', () => { // Create app gulp task await createFile('_websrc/gulp_tasks/app/main.js', await readFile('./_websrc/templates/master/js/app-gulp-task.js')) + // Create build-pre.js + await createFile('_websrc/gulp_tasks/app/build-pre.js', await readFile('./_websrc/templates/master/js/build-pre.js')) + // Create build-post.js await createFile('_websrc/gulp_tasks/app/build-post.js', await readFile('./_websrc/templates/master/js/build-post.js')) diff --git a/_websrc/gulp_tasks/master/browsersync.js b/_websrc/gulp_tasks/master/browsersync.js index f5994e76c..27f9c7aae 100644 --- a/_websrc/gulp_tasks/master/browsersync.js +++ b/_websrc/gulp_tasks/master/browsersync.js @@ -20,13 +20,16 @@ let workingUrl; gulp.task('browsersync', async () => { await tools.quitIfBadBuildEnvironment(); + // Wait for the prefill to be done await tools.poll(() => Global.get('prefillStatus') === 'done', { timeout: 120000 }); + // Check if the index.html file exists if (!fs.exists(`${config.jekyll.dest}/index.html`)) { fs.write(`${config.jekyll.dest}/index.html`, ` Initializing... Initializing... refresh `) } // options: https://www.browsersync.io/docs/options + // Start the Browsersync server let settings = { port: config.port, browser: browser, @@ -34,23 +37,86 @@ gulp.task('browsersync', async () => { server: { baseDir: config.jekyll.dest, middleware: async function (req, res, next) { - const url = new URL(`http://localhost:4000${req.url}`); + const url = new URL(`${localUrl}${req.url}`); const pathname = url.pathname; + // Set the query object + req.query = {}; + req.body = {}; + // If the file has no ext, log it if (!path.extname(pathname)) { console.log(`[Browsersync] Serving ${pathname}`); } - if (pathname.match(/_post.json/)) { - const createPost = require('./create-post.js'); - const post = new createPost(); + // Process the post request + if (pathname.match(/\/_process/)) { + const qsUrl = url.searchParams.get('url'); + let lib; + + // Set query + url.searchParams.forEach((value, key) => { + req.query[key] = value; + }) + + // Set body + if (req.method === 'POST') { + req.body = await receiveRequestBody(req); + } + + // Try to load the library + try { + // Clear the cache + delete require.cache[require.resolve(`../${qsUrl}`)]; + + // Load the library + lib = require(`../${qsUrl}`); + } catch (e) { + // Log the error + console.error(`[Browsersync] Error processing ${qsUrl}`); + + // Set the status code + res.statusCode = 500; + + // Return an error + return res.write(`Cannot find ${qsUrl}`); + } + + // Log + console.log(`[Browsersync] Processing ${qsUrl}`); + + // const createPost = require('./create-post.js'); + // const post = new createPost(); - return await post.create({ + // return await post.create({ + // req: req, + // res: res, + // }) + return await lib({ req: req, res: res, }) + .then((r) => { + res.statusCode = 200; + + // Write the response (if it's JSON, set the content type) + try { + r = JSON.stringify(r); + res.setHeader('Content-Type', 'application/json'); + } catch (e) { + } + + // End the response + res.write(r); + res.end(); + }) + .catch((e) => { + res.statusCode = 500; + res.write(`Error processing ${qsUrl}: ${e}`); + res.end(); + }); } + // Check if the URL is missing a trailing slash and does not have an extension if (!pathname.endsWith('/') && !path.extname(pathname)) { const newURL = `${pathname}.html`; @@ -119,6 +185,33 @@ gulp.task('browsersync', async () => { }); }); +function receiveRequestBody(req) { + return new Promise((resolve, reject) => { + let body = []; + + req.on('data', function (chunk) { + body.push(chunk.toString()); + }); + + req.on('end', function () { + body = body.join(''); + + // Attempt to parse the body as JSON + try { + const parsedBody = JSON.parse(body); + return resolve(parsedBody); + } catch (error) { + // If parsing fails, resolve with the original body string + return resolve(body); + } + }); + + req.on('error', function (err) { + return reject(err); + }); + }); +} + /** * Rebuild Jekyll & do page reload */ diff --git a/_websrc/gulp_tasks/master/build.js b/_websrc/gulp_tasks/master/build.js index c563338f0..76dcc204e 100644 --- a/_websrc/gulp_tasks/master/build.js +++ b/_websrc/gulp_tasks/master/build.js @@ -21,16 +21,28 @@ let firstBuild = true; function areTasksCompleted() { let completed = true; const tasks = Object.keys(Global.get(`completed`, {_faketask: new Date()})); + + // Loop through all tasks for (var i = 0, l = tasks.length; i < l; i++) { const task = tasks[i]; const time = Global.get(`completed.${task}`, new Date(0)); const diff = new Date().getTime() - time.getTime(); const waitTime = firstBuild ? 10000 : 1000; + + // Log + console.log('jekyll-build task', task, diff < waitTime); + + // If the task hasn't completed in the last 10 seconds, we're not done if (diff < waitTime) { completed = false; break; } } + + // Log + console.log('jekyll-build areTasksCompleted', completed); + + // Return whether all tasks are completed return completed; } @@ -103,6 +115,13 @@ gulp.task('jekyll-build', async () => { return Promise.resolve(); } + // Run app post-build.js + await require('../app/build-pre.js')() + .catch((e) => { + console.error('Error running app build-pre.js', e); + process.exit(1); + }); + // Run Jekyll Build await tools.execute(`${jekyll} build --config ${jekyllConfig} --incremental`); @@ -110,7 +129,11 @@ gulp.task('jekyll-build', async () => { await postBuild(); // Run app post-build.js - await require('../app/build-post.js')(); + await require('../app/build-post.js')() + .catch((e) => { + console.error('Error running app build-post.js', e); + process.exit(1); + }); return Promise.resolve(); }); diff --git a/_websrc/libraries/tools.js b/_websrc/libraries/tools.js index ad244c5b4..d1912f79b 100644 --- a/_websrc/libraries/tools.js +++ b/_websrc/libraries/tools.js @@ -16,12 +16,21 @@ Tools.prototype.startTask = function(name, timeout) { const now = new Date(); timeout = timeout || 2; self.task = name; - // self.log('Starting...') + + // Log starting task + console.log(`[${name}] Task starting...`); + + // Set the task as completed in the future Global.set(`completed.${name}`, new Date(now.setTime(now.getTime() + (timeout * 60 * 1000)))); } Tools.prototype.completeTask = function(name) { const self = this; + + // Log completion + console.log(`[${name}] Task completed!`); + + // Set the task as completed now Global.set(`completed.${name}`, new Date()); return through.obj((file, enc, done) => { diff --git a/_websrc/templates/master/js/build-pre.js b/_websrc/templates/master/js/build-pre.js new file mode 100644 index 000000000..505be9ca7 --- /dev/null +++ b/_websrc/templates/master/js/build-pre.js @@ -0,0 +1,12 @@ +// Libraries +// ... + +// Module +module.exports = function () { + return new Promise(function(resolve, reject) { + + // ... + + return resolve(); + }); +} diff --git a/package.json b/package.json index 5e08ba1ad..b17de191a 100755 --- a/package.json +++ b/package.json @@ -57,8 +57,8 @@ "sharp": "0.23.1 (sometime before 2021ish): Hard lock because later versions had issues. Possibly solved in higher node versions" }, "devDependencies": { - "@babel/core": "7.24.7", - "@babel/preset-env": "7.24.7", + "@babel/core": "7.26.0", + "@babel/preset-env": "7.26.0", "autoprefixer": "9.8.8", "browser-sync": "2.23.7", "del": "6.1.1", @@ -86,12 +86,12 @@ "source-map-loader": "2.0.2", "terser-webpack-plugin": "5.3.10", "through2": "4.0.2", - "ultimate-jekyll-poster": "1.0.1", + "ultimate-jekyll-poster": "1.0.2", "vinyl-named": "1.1.0", - "web-manager": "3.2.56", - "webpack": "5.89.0", + "web-manager": "3.2.66", + "webpack": "5.96.1", "webpack-stream": "6.1.2", - "wonderful-fetch": "1.1.12", + "wonderful-fetch": "1.2.2", "yargs": "16.2.0", "zzzzzzzzzz": "9.9.9" } diff --git a/special/master/misc/sitemap.xml b/special/master/misc/sitemap.xml index e3e3727d8..91fea4f4e 100644 --- a/special/master/misc/sitemap.xml +++ b/special/master/misc/sitemap.xml @@ -7,14 +7,24 @@ sitemap: {% assign pages = site.pages %} - {% assign posts = site.posts %} - {% assign data = pages | concat: posts %} {% assign default-time = site.time | date_to_xmlschema %} + {% for collection in site.collections %} + {% assign pages = pages | concat: collection.docs %} + {% endfor %} + {%- if site.sitemap.enable != false -%} - {% for page in data %} + {% for page in pages %} + + {%- if page.url contains '/@reference' or page.url contains '/_' -%} + {%- continue -%} + {%- endif -%} + + {%- if page.layout contains 'redirect' -%} + {%- continue -%} + {%- endif -%} - {%- if page.url contains '/@reference' or page.layout contains 'redirect' or page.layout.sitemap.include == false or page.sitemap.include == false -%} + {%- if page.layout.sitemap.include == false or page.sitemap.include == false or page.layout_data.sitemap.include == false -%} {%- continue -%} {%- endif -%} diff --git a/special/master/pages/checkout/confirmation.html b/special/master/pages/checkout/confirmation.html index 06d7dda00..6157882d7 100644 --- a/special/master/pages/checkout/confirmation.html +++ b/special/master/pages/checkout/confirmation.html @@ -248,7 +248,7 @@

Your payment was successful!

}); // TikTok Pixel - ttq.track('Purchase', { + ttq.track('CompletePayment', { content_type: 'product', value: qsOrderTotal, currency: 'USD',