From 52f786ae961424534562b7f21c2d251761176a98 Mon Sep 17 00:00:00 2001 From: Pavel Husa Date: Thu, 10 Oct 2024 08:35:30 +0100 Subject: [PATCH] Refactor regexes, remove header and footer includes based on config (#16) * Refactor regexes, remove header and footer includes based on config * CLI added, readme updated, refactored * Revert config changes --- README.md | 43 +++++++++++++++++++++++++++++-------------- cli.js | 4 +++- index.js | 35 +++++++++++++++++++++++++++-------- 3 files changed, 59 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index d378b07..9eb8729 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ # Shoptet Bender πŸ€– - ## Introduction -Shoptet Bender proxies remote e-shop to localhost while injecting and serving your local `style.css` and `script.js`. This tool enables to development of visual changes without breaking the production e-shop. It is also suitable for Premium e-shop development, while emulation of the Blank mode is possible. +Shoptet Bender proxies remote e-shop to localhost while injecting and serving your local JavaScripts and CSS styles. This tool enables the development of visual changes without breaking the production e-shop. It is also suitable for Premium e-shop development, while emulation of the Blank mode is possible. ## How it works @@ -12,7 +11,7 @@ C(Local files) -- Static served files --> B ``` ## Install -Node >= 14 prerequisited\ +Node >= 18 prerequisited\ Install global using yarn:\ `yarn global add git+https://github.com/shoptet/shoptet-bender.git` @@ -25,20 +24,36 @@ Install global using yarn:\ ## Usage ### Step-by-step guide to start -1. Create a folder for your files (css, js) that need to be injected to remote e-shop on localhost (let's say "my-project") -2. Inside your project folder create another folder named "src" -3. Create or move your "style.css" and "script.js" files into "src" folder -4. Run --remote e-shop in console (let's say "shp-bender --remote https://classic.shoptet.cz/") +1. πŸ“ If you want to use the prepared build step, create a following folder structure: + +``` +src/ +β”œβ”€β”€ footer/ +β”‚ β”œβ”€β”€ script1.js +β”‚ └── script2.js +β”œβ”€β”€ header/ +β”‚ β”œβ”€β”€ markup.html +β”‚ └── style.css +└── orderFinale/ + └── remarketing.js +``` + +2. πŸ“ Create or move your script and styles to the corresponding folders +3. πŸ–₯️ Choose e-shop url, let's say Classic `shp-bender --remote https://classic.shoptet.cz/` -And you're ready to go -> enjoy coding and development ;) +And you're ready to go -> enjoy coding and development πŸŽ‰ **OR** Try `shp-bender -h` for CLI help -## Posible tool improvements -Shoptet Bender is an open-source project, so your PRs are very welcomed. There are some suggestions for possible features, as Shoptet don't have the resources to develop this tool actively. So it is left as is for your active development. Some minor feature updates are possible. -What could be done: -- [ ] tools integration (Gulp, Grunt) -- [ ] files concatenation -- [ ] HEAD and BODY scripts location - this could better emulate admin fields \ No newline at end of file +**OR** + +πŸš€ Use our [Boilerplate wizard](https://github.com/shoptet/create-visual-addon-boilerplate) for even faster start. πŸš€ + +### Removing existing scripts and styles + +If you want to remove existing scripts and styles, you can use the `--removeHeaderIncludes` or `--removeFooterIncludes` flag followed by the string you want to remove. You can target for example number of the addon, or specific URL, project includes or comment in the script. + +## Possible tool improvements +Shoptet Bender is an open-source project, and we’d love your help! Shoptet doesn’t have the resources to work on this tool continuously, so it’s a great chance for you to jump in and make it better. We’ve listed some feature ideas to get you started, but feel free to create your own. Even small updates can make a big difference, and your contributions are really valued! diff --git a/cli.js b/cli.js index 743614d..574515a 100644 --- a/cli.js +++ b/cli.js @@ -12,6 +12,8 @@ command .option('-r, --remote ', 'URL of the remote Eshop with https:// prefix') .option('-w, --watch', 'watch for changes and reload the page', true) .option('-b, --blankMode', 'simulate the blank template.', false) - .option('-n, --notify', 'display pop-over notifications in the browser', false); + .option('-n, --notify', 'display pop-over notifications in the browser', false) + .option('-rh, --removeHeaderIncludes [removeHeaderIncludes...]', 'remove header includes', false) + .option('-rf, --removeFooterIncludes [removeFooterIncludes...]', 'remove footer includes', false); export default command; diff --git a/index.js b/index.js index b0fc1c1..b29dddb 100755 --- a/index.js +++ b/index.js @@ -18,6 +18,9 @@ const rootDir = process.cwd(); const sourceFolder = path.join(rootDir, config.sourceFolder ?? 'src'); const outputFolder = path.join(rootDir, options.folder ?? config.outputFolder); +const includesRegex = //gi; +const includesCodeRegex = new RegExp(includesRegex.source + '[\\s\\S]*?(?=' + includesRegex.source + '|$)', 'g'); + const blankModeStyle = { match: /]*>/gi, fn: function () { @@ -33,8 +36,18 @@ const blankModeScript = { }; const headerIncludes = { - match: /]*>/i, + match: /(?<=)[\s\S]*?(?=)/i, fn: function (req, res, match) { + // Remove includes from the header + const includes = options.removeHeaderIncludes || config.removeHeaderIncludes || []; + const matchedServices = match.match(includesCodeRegex); + if (matchedServices) { + match = matchedServices.filter(service => { + return !includes.some(removedService => service.includes(removedService)); + }).join('') + } + + // Add custom includes to the footer const headerMarkup = (fs.existsSync(outputFolder + '/scripts.header.js') ? '' : '') + (fs.existsSync(outputFolder + '/styles.header.css') ? '' : ''); @@ -43,8 +56,18 @@ const headerIncludes = { }; const footerIncludes = { - match: /<\/body>(?![\s\S]*<\/body>[\s\S]*$)/i, + match: /(?<=\s*
)[\s\S]*?(?=<\/div>\s*)/i, fn: function (req, res, match) { + // Remove includes from the footer + const includes = options.removeFooterIncludes || config.removeFooterIncludes || []; + const matchedServices = match.match(includesCodeRegex); + if (matchedServices) { + match = matchedServices.filter(service => { + return !includes.some(removedService => service.includes(removedService)); + }).join('') + } + + // Add custom includes to the footer const footerMarkup = (fs.existsSync(outputFolder + '/scripts.footer.js') ? '' : '') + (fs.existsSync(outputFolder + '/styles.footer.css') ? '' : ''); @@ -59,7 +82,6 @@ const rewriteRules = [ { ...(options.blankMode && blankModeScript) }, ]; - const bsPlugin = [ new BrowserSyncPlugin({ proxy: { target: options.remote ?? config.defaultUrl }, @@ -69,17 +91,14 @@ const bsPlugin = [ notify: options.notify, open: false, }), -] +]; const baseWebpackConfig = getWebpackConfig('development'); const webpackConfig = { watch: options.watch, ...baseWebpackConfig, - plugins: [ - ...bsPlugin, - ...baseWebpackConfig.plugins, - ], + plugins: [...bsPlugin, ...baseWebpackConfig.plugins], }; webpack(webpackConfig, (err, stats) => {