Skip to content

Commit

Permalink
Refactor regexes, remove header and footer includes based on config (#16
Browse files Browse the repository at this point in the history
)

* Refactor regexes, remove header and footer includes based on config

* CLI added, readme updated, refactored

* Revert config changes
  • Loading branch information
pavelhusa authored Oct 10, 2024
1 parent dc24329 commit 52f786a
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 23 deletions.
43 changes: 29 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -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`

Expand All @@ -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
**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!
4 changes: 3 additions & 1 deletion cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ command
.option('-r, --remote <url>', '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;
35 changes: 27 additions & 8 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 = /<!-- (?:service\s\d+\(\d+\)|api\s\d+\(\d+\)|project)\shtml\s+code\s+(?:header|footer) -->/gi;
const includesCodeRegex = new RegExp(includesRegex.source + '[\\s\\S]*?(?=' + includesRegex.source + '|$)', 'g');

const blankModeStyle = {
match: /<link\s+href="https:\/\/cdn\.myshoptet\.com\/prj\/[^"]+"[^>]*>/gi,
fn: function () {
Expand All @@ -33,8 +36,18 @@ const blankModeScript = {
};

const headerIncludes = {
match: /<body[^>]*>/i,
match: /(?<=<head[\s\S]*?<!--\sUser include\s-->)[\s\S]*?(?=<!--\s\/User include\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') ? '<script src="/scripts.header.js"></script>' : '') +
(fs.existsSync(outputFolder + '/styles.header.css') ? '<link rel="stylesheet" href="/styles.header.css">' : '');
Expand All @@ -43,8 +56,18 @@ const headerIncludes = {
};

const footerIncludes = {
match: /<\/body>(?![\s\S]*<\/body>[\s\S]*$)/i,
match: /(?<=<body[\s\S]*?<!--\sUser include\s-->\s*<div class="container">)[\s\S]*?(?=<\/div>\s*<!--\s\/User include\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') ? '<script src="/scripts.footer.js"></script>' : '') +
(fs.existsSync(outputFolder + '/styles.footer.css') ? '<link rel="stylesheet" href="/styles.footer.css">' : '');
Expand All @@ -59,7 +82,6 @@ const rewriteRules = [
{ ...(options.blankMode && blankModeScript) },
];


const bsPlugin = [
new BrowserSyncPlugin({
proxy: { target: options.remote ?? config.defaultUrl },
Expand All @@ -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) => {
Expand Down

0 comments on commit 52f786a

Please sign in to comment.