Skip to content

Commit

Permalink
Merge pull request #9 from drolsen/dev
Browse files Browse the repository at this point in the history
Dev 1.2.3 Release
  • Loading branch information
drolsen committed Jan 13, 2022
2 parents 5db3955 + 190078a commit 6e25b28
Show file tree
Hide file tree
Showing 12 changed files with 265 additions and 62 deletions.
26 changes: 22 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ Option | Types | Description | Default
`files.filter` | Function | Filters away imported .JSX files that you wish NOT to be exported | --
`globals` | Object | Defines any global namespaces or libraries required to process your JSX
`plugins` | Array | Defines custom plugins used during the processing of each exported JSX file | --
`comment` | String or Boolean | Defines a custom comment, or no comment at all pre-pended to the top of exported files | --
`comment` | String, Boolean or Function | Defines a custom comment prepended to the top of exported files | --


## options.files
With the `files` option, you must specify both `input` and `output` for source JSX files and location where exports will be written:
Expand Down Expand Up @@ -265,15 +266,33 @@ Please note there is currently no large community behind export plugins, so each


## options.comment
At the top of each exported file, a comment is included to denote to developers at a later point that this file was auto generated. You can supply your own comment here using the `comment` option.
At the top of each exported file, a comment is included to denote to developers (at a later point) that these file(s) were auto generated. You can supply your own comment here using the `comment` option.

```js
new WebpackJSXExport({
comment: 'Please do not edit this file! This was generated at build!'
})
```

Or, if you wish to have no comment (not recommended), simply supply a `false` value:
or, if you would like to have custom comments based on different files being exported, you can supply a function to the `comment` option:

```js
new WebpackJSXExport({
comment: (file) => {
if (file.name.indexOf('something') !== -1) {
file.comment = 'Custom comment for "something" files';
}

if (file.name.indexOf('other') !== -1) {
file.comment = 'Custom comment for "other" files';
}

return file;
}
})
```

Lastly, if you wish to have no comment (not recommended), simply supply a `false` value:

```js
new WebpackJSXExport({
Expand Down Expand Up @@ -307,7 +326,6 @@ Webpack JSX Export uses babel plugin register approach to transpile JSX source (
Plugin | Description | URL
--- | --- | ---
`babel-plugin-file-loader` | File loader | [Plugin Details](https://www.npmjs.com/package/babel-plugin-file-loader)
`babel-plugin-css-modules-transform` | Inline Style & Block Style | [Plugin Details](https://www.npmjs.com/package/babel-plugin-css-modules-transform)
`babel-plugin-transform-require-context` | Require importing | [Plugin Details](https://www.npmjs.com/package/babel-plugin-transform-require-context)
`@babel/plugin-transform-react-jsx` | JSX Transpile | [Plugin Details](https://babeljs.io/docs/en/babel-plugin-transform-react-jsx)
`@babel/plugin-proposal-object-rest-spread` | Object Spread | [Plugin Details](https://babeljs.io/docs/en/babel-plugin-transform-object-rest-spread)
Expand Down
103 changes: 68 additions & 35 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,30 @@ const path = require('path');
const { parse } = require('node-html-parser');
const ReactDOM = require('react-dom/server');
const pretty = require('pretty');
const merge = require('merge-deep');

class WebpackJSXExport {
constructor(options) {
this.options = Object.assign({
this.defaultFilter = (file) => { return file; }

this.defaultExtension = (file) => {
file.extension = '.html';
return file;
};

this.defaultComment = (file) => {
file.comment = 'THIS FILE IS AUTO GENERATED BY WebpackJSXExport';
return file;
};

this.options = merge(options, {
files: [],
plugins: {
input: [],
output: [],
},
globals:{},
comment: 'THIS FILE IS AUTO GENERATED BY WebpackJSXExport'
}, options);

this.defaultExtension = '.html';
this.defaultFilter = (file) => { return file; };
globals:{}
});
}

// Helper method used to clean up markup results
Expand All @@ -32,10 +41,23 @@ class WebpackJSXExport {
}

// Helper method that is used procure JSX into Markup and write to disk
write(source, name, index, path){
write(fileInfo) {
// Process plugin PreParse hooks
try {
Object.keys(this.options.plugins.output).map((i) => {
const plugin = this.options.plugins.output[i]().PreParse;

if (plugin) {
if (plugin(fileInfo)) {
fileInfo = plugin(fileInfo);
}
}
});
} catch (err) { console.error(err); }

let DOM = parse(
this.clean(
ReactDOM.renderToStaticMarkup(source.default),
ReactDOM.renderToStaticMarkup(fileInfo.source.default),
{
'data-sly-unwrap=""': 'data-sly-unwrap',
'"': '"',
Expand All @@ -48,10 +70,10 @@ class WebpackJSXExport {
)
);

// Process output plugins
// Process plugin PostParse hooks
try {
Object.keys(this.options.plugins.output).map((i) => {
const plugin = this.options.plugins.output[i]().Parse;
const plugin = this.options.plugins.output[i]().PostParse;

if (plugin) {
if (plugin(DOM)) {
Expand All @@ -63,12 +85,12 @@ class WebpackJSXExport {

// Make pretty and write processed export to disk
fs.writeFile(
path,
fileInfo.path,
pretty(
`
${
(this.options.comment)
? `<!--/* ${this.options.comment} */-->`
(fileInfo.comment)
? `<!--/* ${ fileInfo.comment } */-->`
: ''
}
${DOM.toString()}
Expand Down Expand Up @@ -113,7 +135,6 @@ class WebpackJSXExport {
? this.options.plugins.input : {}
: {},
'babel-plugin-file-loader', // (see: https://www.npmjs.com/package/babel-plugin-file-loader)
'babel-plugin-css-modules-transform', // (see: https://www.npmjs.com/package/babel-plugin-css-modules-transform)
'babel-plugin-transform-require-context', // (see: https://www.npmjs.com/package/babel-plugin-transform-require-context)
'@babel/plugin-transform-react-jsx', // (see: https://babeljs.io/docs/en/babel-plugin-transform-react-jsx)
'@babel/plugin-proposal-object-rest-spread', // (see: https://babeljs.io/docs/en/babel-plugin-transform-object-rest-spread)
Expand All @@ -128,7 +149,7 @@ class WebpackJSXExport {
});

// Now that our babel is registered, we can hoist up globals
if (this.options.globals.length) {
if (this.options.globals) {
Object.keys(this.options.globals).map((i) => {
global[i] = require(this.options.globals[i]);
});
Expand All @@ -143,38 +164,48 @@ class WebpackJSXExport {
// we use glob lib instead to collect all example.jsx files
Object.keys(files).map((i) => {
let { output } = files[i];
let extension = (typeof files[i].extension !== 'undefined') ? files[i].extension : this.defaultExtension;
const { input } = files[i];
let { extension } = files[i];
let { filter } = files[i];

// If we have no filter, pass through the default filter
if (!filter) { filter = this.defaultFilter; }
const filter = (files[i].filter) ? files[i].filter : this.defaultFilter;
const comment = (typeof this.options.comment !== 'undefined')
? this.options.comment
: this.defaultComment;

// Glob gather (reguardless if its a direct path to JSX file)
glob.sync(path.resolve(__dirname, input)).forEach((file) => {
// Only .jsx files please
if (path.basename(file).indexOf('.jsx') !== -1) {
// Build up our file information object for export processing
let fileInfo = {
comment,
extension,
name: path.basename(file),
source: require(file),
output,
extension: (path.extname(output).length)
? path.extname(output)
: (typeof extension === 'string')
? extension
: this.defaultExtension
source: require(file)
};

// Scrub our file information against a four filtering
// Scrub our file information against filtering
if (filter(fileInfo)) {
// Scrub our file information against comments
if (typeof comment === 'function') {
fileInfo = comment(fileInfo);
}

// If extension happens to be function, we pass file information through it
if (typeof fileInfo === 'object' && typeof extension === 'function') {
if (typeof extension === 'function') {
fileInfo = extension(fileInfo);
}

// Ensure extension passed in file.input is used instead of options.extension
if (path.extname(fileInfo.output) === fileInfo.extension) {
fileInfo.output = fileInfo.output.replace(
new RegExp(`\\${fileInfo.extension}`),
''
);
}

// Finally we collect file information
collection[file] = fileInfo;
collection[file] = fileInfo;
}
}
});
Expand All @@ -189,6 +220,7 @@ class WebpackJSXExport {
Object.keys(collection).map((i, index) => {
let { source } = collection[i];
let { output } = collection[i];
const { comment } = collection[i];
const { extension } = collection[i];
const isFolder = !path.extname(output) && output.charAt(output.length-1) === '/';
// If the file has source only
Expand Down Expand Up @@ -220,12 +252,13 @@ class WebpackJSXExport {
}

// Pass file information to write (note that output replaces .extension with requested .extension).
this.write(
this.write({
source,
path.basename(output).toLowerCase(),
index,
output.replace(new RegExp(`\\${path.extname(output)}`, 'g'), extension)
);
comment,
index,
name: path.basename(output).toLowerCase(),
path: output.replace(new RegExp(`\\${path.extname(output)}`, 'g'), extension)
});
}
});
}
Expand Down
24 changes: 11 additions & 13 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"webpack jsx static export",
"webpack jsx static render export"
],
"version": "1.2.2",
"version": "1.2.3",
"description": "Plugin to allow for the static rendering and exporting of JSX files to disk",
"repository": "drolsen/webpack-jsx-export",
"bugs": {
Expand All @@ -20,18 +20,15 @@
"author": "Devin R. Olsen <devin@devinrolsen.com> (http://devinrolsen.com)",
"license": "MIT",
"scripts": {
"test": "npm run basic-test && npm run conditions-test && npm run extension-test && npm run custom-test && npm run htl-test && npm run razor-test && npm run php-test && npm run glob-test && npm run filter-test && npm run extension-filter-test && npm run filter-schema-test && npm run node-test && npm run ava-test",
"test": "npm run basic-test && npm run conditions-test && npm run extension-test && npm run custom-test && npm run plugin-test && npm run glob-test && npm run filter-test && npm run node-test && npm run comment-test && npm run ava-test",
"basic-test": "webpack --config ./test/basic/basic.test.config.js --mode production",
"custom-test": "webpack --config ./test/custom/custom.test.config.js --mode production",
"comment-test": "webpack --config ./test/comments/comment-custom.test.config.js --mode production && webpack --config ./test/comments/comment-false.test.config.js --mode production && webpack --config ./test/comments/comment-filter.test.config.js --mode production",
"extension-test": "webpack --config ./test/extensions/extension.test.config.js --mode production",
"conditions-test": "webpack --config ./test/conditions/conditions.test.config.js --mode production",
"htl-test": "webpack --config ./test/plugins/htl.test.config.js --mode production",
"razor-test": "webpack --config ./test/plugins/razor.test.config.js --mode production",
"php-test": "webpack --config ./test/plugins/php.test.config.js --mode production",
"plugin-test": "webpack --config ./test/plugins/htl.test.config.js --mode production && webpack --config ./test/plugins/razor.test.config.js --mode production && webpack --config ./test/plugins/php.test.config.js --mode production",
"filter-test": "webpack --config ./test/filtering/filter.test.config.js --mode production && webpack --config ./test/filtering/filter-alt-schema.test.config.js --mode production && webpack --config ./test/extensions/extension-filter.test.config.js --mode production",
"glob-test": "webpack --config ./test/glob/glob.test.config.js --mode production",
"filter-test": "webpack --config ./test/filtering/filter.test.config.js --mode production",
"filter-schema-test": "webpack --config ./test/filtering/filter-alt-schema.test.config.js --mode production",
"extension-filter-test": "webpack --config ./test/extensions/extension-filter.test.config.js --mode production",
"node-test": "node ./test/node/node.test.js",
"ava-test": "ava ./test/ava.test.js"
},
Expand All @@ -52,20 +49,21 @@
"@babel/preset-env": "7.16.0",
"@babel/preset-react": "7.16.0",
"@babel/register": "7.16.0",
"babel-plugin-css-modules-transform": "1.6.2",
"babel-plugin-file-loader": "2.0.0",
"babel-plugin-import-globals": "2.0.0",
"babel-plugin-module-resolver": "4.1.0",
"babel-plugin-transform-require-context": "0.1.1",
"merge-deep": "3.0.3",
"node-html-parser": "5.2.0",
"pretty": "2.0.0",
"prop-types": "15.7.2",
"react": "16.9.0",
"react-dom": "16.9.0",
"node-html-parser": "5.2.0",
"pretty": "2.0.0"
"react-dom": "16.9.0"
},
"devDependencies": {
"ava": "4.0.1",
"webpack": "5.65.0",
"webpack-cli": "4.9.1"
"webpack-cli": "4.9.1",
"clean-webpack-plugin": "4.0.0"
}
}
22 changes: 14 additions & 8 deletions plugins/README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
## Plugins
## Creating Plugins
Building a output plugin for WebpackJSXExport starts with structure:

```js
const MyPlugin = (options) => {
return {
Parse (document) {
PreParse (document) {

},
PostParse (document) {

}
};
Expand All @@ -13,18 +16,21 @@ const MyPlugin = (options) => {
module.exports = MyPlugin;
```

WebpackJSXExport only offers a single hook of `Parse` which returns the rendered JSX DOM ready for traversing.
All manipulation to the returned DOM (`document` in example above) will be exported and saved to disk.
WebpackJSXExport only offers two hooks for plugin authoring:

Hook | Description
--- | ---
`PreParse` | Hook which returns data before being parsed by Babel, React and DOM parser.
`PostParse` | Hook which returns DOM for traversing / manipulating using DOM parser API. (see below)


### DOM Manipulation API
The returned DOM from a `Parse` hook is a [node-html-parser](https://www.npmjs.com/package/node-html-parser) Object which offers number of methods for DOM and attribute manipulation. These are standard DOM methods you will find in browser, but for NodeJS.

See all available methods that can be used on `Parse` hook's returned DOM:

[DOM Methods](https://www.npmjs.com/package/node-html-parser)
See all available methods that can be used on `Parse` hook's returned DOM: [DOM Methods](https://www.npmjs.com/package/node-html-parser)

### Input vs. Output Plugins

Please note that the above syntax is for making custom `output` plugins.
If you are intrested in building your own `input` plugin, you are looking to craft a babel plugin and is recommended you turn to babel API docs on how to do so.
If you are interested in building your own `input` plugin, you are looking to craft a babel plugin and is recommended you turn to babel API docs on how to do so.

2 changes: 1 addition & 1 deletion plugins/conditions.plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const Conditions = (options = {}) => {
options = Object.assign({}, {});

return {
Parse (document) {
PostParse (document) {
// Remove any elements flagged to NOT be rendered in production views
if (document.querySelector('no-export')) {
const nonExportingFragments = document.querySelectorAll('no-export');
Expand Down
2 changes: 1 addition & 1 deletion plugins/htl.plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const HTL = (options = {}) => {
options = Object.assign({}, {});

return {
Parse (document) {
PostParse (document) {

}
};
Expand Down

0 comments on commit 6e25b28

Please sign in to comment.