mirror of
https://github.com/elyby/emails-renderer.git
synced 2024-12-22 13:19:45 +05:30
README. Clean up. Images usage demo
This commit is contained in:
parent
fc87c8aa80
commit
4e7980a175
22
README.md
22
README.md
@ -1 +1,21 @@
|
|||||||
# Hello World
|
This package allows rendering of React components into plain HTML to use it in emails. Each directory in `emails` dir corresponds to separate email template. Each email component will receive payload, passed from command line:
|
||||||
|
|
||||||
|
```
|
||||||
|
node cli --type=<email_dir_name> --payload=<json_encoded_in_base64>
|
||||||
|
```
|
||||||
|
|
||||||
|
Try `php example.php` for demo.
|
||||||
|
|
||||||
|
# Email component structure
|
||||||
|
|
||||||
|
* `index.js` — required. This file should export the main component, wich will receive payload.
|
||||||
|
* `fixtures.js` — an optional file exports hash `{featureId: payload, featureId2: payload}`. Use this to create data samples for testing in dev mode.
|
||||||
|
* `styles.js` — an optional file, that will hold style objects for email components to allow style inlining.
|
||||||
|
* `messages.intl.json` — an optional file, that exports hash with `{messageId: defaultMessage}` for `react-intl`.
|
||||||
|
|
||||||
|
# Available npm scripts
|
||||||
|
|
||||||
|
* `npm start` — starts app in dev mode.
|
||||||
|
* `npm run i18n` — collects translations and places in `src/i18n`.
|
||||||
|
* `npm run build` — builds app for usage in `cli.js`.
|
||||||
|
* `npm run eslint` — lints source files.
|
||||||
|
19
package.json
19
package.json
@ -16,12 +16,9 @@
|
|||||||
"homepage": "https://gitlab.com/elyby/email-renderer#README",
|
"homepage": "https://gitlab.com/elyby/email-renderer#README",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "rm -rf dist/ && webpack-dev-server --progress --colors",
|
"start": "rm -rf dist/ && webpack-dev-server --progress --colors",
|
||||||
"up": "npm update",
|
|
||||||
"test": "karma start ./karma.conf.js",
|
|
||||||
"lint": "eslint ./src",
|
"lint": "eslint ./src",
|
||||||
"i18n": "cd ./scripts && ../node_modules/.bin/babel-node i18n-collect.js",
|
"i18n": "cd ./scripts && ../node_modules/.bin/babel-node i18n-collect.js",
|
||||||
"build": "rm -rf dist/ && NODE_ENV=production webpack --progress --colors",
|
"build": "rm -rf dist/ && NODE_ENV=production webpack --progress --colors"
|
||||||
"render": ""
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"babel-polyfill": "^6.3.14",
|
"babel-polyfill": "^6.3.14",
|
||||||
@ -45,27 +42,13 @@
|
|||||||
"babel-preset-react-hmre": "^1.0.1",
|
"babel-preset-react-hmre": "^1.0.1",
|
||||||
"babel-preset-stage-0": "^6.3.13",
|
"babel-preset-stage-0": "^6.3.13",
|
||||||
"babel-runtime": "^6.0.0",
|
"babel-runtime": "^6.0.0",
|
||||||
"bundle-loader": "^0.5.4",
|
|
||||||
"css-loader": "^0.23.0",
|
|
||||||
"eslint": "^3.1.1",
|
"eslint": "^3.1.1",
|
||||||
"eslint-plugin-react": "^6.0.0",
|
"eslint-plugin-react": "^6.0.0",
|
||||||
"exports-loader": "^0.6.3",
|
|
||||||
"extract-text-webpack-plugin": "^1.0.0",
|
"extract-text-webpack-plugin": "^1.0.0",
|
||||||
"file-loader": "^0.9.0",
|
"file-loader": "^0.9.0",
|
||||||
"html-loader": "^0.4.3",
|
|
||||||
"html-webpack-plugin": "^2.0.0",
|
"html-webpack-plugin": "^2.0.0",
|
||||||
"imports-loader": "^0.6.5",
|
|
||||||
"json-loader": "^0.5.4",
|
"json-loader": "^0.5.4",
|
||||||
"loader-utils": "^0.2.15",
|
|
||||||
"node-sass": "^3.4.2",
|
|
||||||
"postcss-import": "^8.1.2",
|
|
||||||
"postcss-loader": "^0.9.0",
|
|
||||||
"postcss-scss": "^0.1.8",
|
|
||||||
"postcss-url": "SleepWalker/postcss-url#switch-to-async-api",
|
|
||||||
"raw-loader": "^0.5.1",
|
|
||||||
"sass-loader": "^4.0.0",
|
|
||||||
"scripts": "file:scripts",
|
"scripts": "file:scripts",
|
||||||
"style-loader": "^0.13.0",
|
|
||||||
"url-loader": "^0.5.7",
|
"url-loader": "^0.5.7",
|
||||||
"webpack": "^1.12.9",
|
"webpack": "^1.12.9",
|
||||||
"webpack-dev-server": "^1.14.0",
|
"webpack-dev-server": "^1.14.0",
|
||||||
|
@ -2,6 +2,8 @@ export default function Activation() {
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
Activated!
|
Activated!
|
||||||
|
<br />
|
||||||
|
<img src={require('./images/kitty.jpg')} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,36 +0,0 @@
|
|||||||
// при использовании sass-loader теряется контекст в импортированных модулях
|
|
||||||
// из-за чего css-loader не может правильно обработать относительные url
|
|
||||||
//
|
|
||||||
// препроцессим урлы перед тем, как пропускать их через sass-loader
|
|
||||||
// урлы, начинающиеся с / будут оставлены как есть
|
|
||||||
|
|
||||||
const cssUrl = require('postcss-url');
|
|
||||||
const loaderUtils = require('loader-utils');
|
|
||||||
|
|
||||||
// /#.+$/ - strip #hash part of svg font url
|
|
||||||
const urlToRequest = (url) => loaderUtils.urlToRequest(url.replace(/\??#.+$/, ''), true);
|
|
||||||
const urlPostfix = (url) => {
|
|
||||||
var idx = url.indexOf('?#');
|
|
||||||
|
|
||||||
if (idx < 0) {
|
|
||||||
idx = url.indexOf('#');
|
|
||||||
}
|
|
||||||
|
|
||||||
return idx >= 0 ? url.slice(idx) : '';
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = function(loader) {
|
|
||||||
return cssUrl({
|
|
||||||
url: (url, decl, from, dirname, to, options, result) =>
|
|
||||||
new Promise((resolve, reject) =>
|
|
||||||
loaderUtils.isUrlRequest(url) ? loader.loadModule(urlToRequest(url), (err, source) =>
|
|
||||||
err ? reject(err) : resolve(
|
|
||||||
loader.exec(`
|
|
||||||
var __webpack_public_path__ = '${loader.options.output.publicPath}';
|
|
||||||
${source}
|
|
||||||
`) + urlPostfix(url)
|
|
||||||
)
|
|
||||||
) : resolve(url)
|
|
||||||
)
|
|
||||||
});
|
|
||||||
};
|
|
@ -3,11 +3,7 @@
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
const webpack = require('webpack');
|
const webpack = require('webpack');
|
||||||
const loaderUtils = require('loader-utils');
|
|
||||||
const ExtractTextPlugin = require('extract-text-webpack-plugin');
|
|
||||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||||
const cssUrl = require('webpack-utils/cssUrl');
|
|
||||||
const cssImport = require('postcss-import');
|
|
||||||
|
|
||||||
const rootPath = path.resolve('./src');
|
const rootPath = path.resolve('./src');
|
||||||
|
|
||||||
@ -15,36 +11,7 @@ const isProduction = process.env.NODE_ENV === 'production';
|
|||||||
|
|
||||||
process.env.NODE_ENV = isProduction ? 'production' : 'development';
|
process.env.NODE_ENV = isProduction ? 'production' : 'development';
|
||||||
|
|
||||||
const CSS_CLASS_TEMPLATE = isProduction ? '[hash:base64:5]' : '[path][name]-[local]';
|
const webpackConfig = {
|
||||||
|
|
||||||
const fileCache = {};
|
|
||||||
|
|
||||||
|
|
||||||
const cssLoaderQuery = {
|
|
||||||
modules: true,
|
|
||||||
importLoaders: 2,
|
|
||||||
url: false,
|
|
||||||
localIdentName: CSS_CLASS_TEMPLATE,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* cssnano options
|
|
||||||
*/
|
|
||||||
sourcemap: !isProduction,
|
|
||||||
autoprefixer: {
|
|
||||||
add: true,
|
|
||||||
remove: true,
|
|
||||||
browsers: ['last 2 versions']
|
|
||||||
},
|
|
||||||
safe: true,
|
|
||||||
// отключаем минификацию цветов, что бы она не ломала такие выражения:
|
|
||||||
// composes: black from './buttons.scss';
|
|
||||||
colormin: false,
|
|
||||||
discardComments: {
|
|
||||||
removeAll: true
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var webpackConfig = {
|
|
||||||
entry: {
|
entry: {
|
||||||
app: path.join(__dirname, 'src')
|
app: path.join(__dirname, 'src')
|
||||||
},
|
},
|
||||||
@ -66,20 +33,12 @@ var webpackConfig = {
|
|||||||
devServer: {
|
devServer: {
|
||||||
host: 'localhost',
|
host: 'localhost',
|
||||||
port: 8080,
|
port: 8080,
|
||||||
// proxy: {
|
|
||||||
// '/api*': {
|
|
||||||
// headers: {
|
|
||||||
// host: config.apiHost.replace(/https?:|\//g, '')
|
|
||||||
// },
|
|
||||||
// target: config.apiHost
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
hot: true,
|
hot: true,
|
||||||
inline: true,
|
inline: true,
|
||||||
historyApiFallback: true
|
historyApiFallback: true
|
||||||
},
|
},
|
||||||
|
|
||||||
devtool: 'eval',
|
devtool: isProduction ? 'eval' : false,
|
||||||
|
|
||||||
plugins: [
|
plugins: [
|
||||||
new webpack.DefinePlugin({
|
new webpack.DefinePlugin({
|
||||||
@ -102,11 +61,6 @@ var webpackConfig = {
|
|||||||
|
|
||||||
module: {
|
module: {
|
||||||
loaders: [
|
loaders: [
|
||||||
{
|
|
||||||
test: /\.scss$/,
|
|
||||||
extractInProduction: true,
|
|
||||||
loader: 'style!css?' + JSON.stringify(cssLoaderQuery) + '!sass!postcss?syntax=postcss-scss'
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
test: /\.jsx?$/,
|
test: /\.jsx?$/,
|
||||||
exclude: /node_modules/,
|
exclude: /node_modules/,
|
||||||
@ -114,35 +68,19 @@ var webpackConfig = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.(png|gif|jpg|svg)$/,
|
test: /\.(png|gif|jpg|svg)$/,
|
||||||
loader: 'file',
|
loader: 'url',
|
||||||
query: {
|
query: {
|
||||||
name: 'assets/[name].[ext]?[hash]'
|
name: 'assets/[name].[ext]?[hash]'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
test: /\.(woff|woff2|ttf)$/,
|
|
||||||
loader: 'file',
|
|
||||||
query: {
|
|
||||||
name: 'assets/fonts/[name].[ext]?[hash]'
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
test: /\.json$/,
|
test: /\.json$/,
|
||||||
exclude: /(intl|font)\.json/,
|
exclude: /(intl|font)\.json/,
|
||||||
loader: 'json'
|
loader: 'json'
|
||||||
},
|
},
|
||||||
{
|
|
||||||
test: /\.html$/,
|
|
||||||
loader: 'html'
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
test: /\.intl\.json$/,
|
test: /\.intl\.json$/,
|
||||||
loader: 'babel!intl!json'
|
loader: 'babel!intl!json'
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.font\.(js|json)$/,
|
|
||||||
loader: 'raw!fontgen'
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -151,68 +89,9 @@ var webpackConfig = {
|
|||||||
alias: {
|
alias: {
|
||||||
intl: path.resolve('webpack-utils/intl-loader')
|
intl: path.resolve('webpack-utils/intl-loader')
|
||||||
}
|
}
|
||||||
},
|
|
||||||
|
|
||||||
postcss() {
|
|
||||||
return [
|
|
||||||
cssImport({
|
|
||||||
path: rootPath,
|
|
||||||
addDependencyTo: webpack,
|
|
||||||
|
|
||||||
resolve: ((defaultResolve) =>
|
|
||||||
(url, basedir, importOptions) =>
|
|
||||||
defaultResolve(loaderUtils.urlToRequest(url), basedir, importOptions)
|
|
||||||
)(require('postcss-import/lib/resolve-id')),
|
|
||||||
|
|
||||||
load: ((defaultLoad) =>
|
|
||||||
(filename, importOptions) => {
|
|
||||||
if (/\.font.(js|json)$/.test(filename)) {
|
|
||||||
if (!fileCache[filename] || !isProduction) {
|
|
||||||
// do not execute loader on the same file twice
|
|
||||||
// this is an overcome for a bug with ExtractTextPlugin, for isProduction === true
|
|
||||||
// when @imported files may be processed mutiple times
|
|
||||||
fileCache[filename] = new Promise((resolve, reject) =>
|
|
||||||
this.loadModule(filename, (err, source) =>
|
|
||||||
err ? reject(err) : resolve(this.exec(source))
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return fileCache[filename];
|
|
||||||
}
|
|
||||||
|
|
||||||
return defaultLoad(filename, importOptions);
|
|
||||||
}
|
|
||||||
)(require('postcss-import/lib/load-content'))
|
|
||||||
}),
|
|
||||||
|
|
||||||
cssUrl(this)
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (isProduction) {
|
|
||||||
webpackConfig.module.loaders.forEach((loader) => {
|
|
||||||
if (loader.extractInProduction) {
|
|
||||||
// remove style-loader from chain and pass through ExtractTextPlugin
|
|
||||||
const parts = loader.loader.split('!');
|
|
||||||
|
|
||||||
loader.loader = ExtractTextPlugin.extract(
|
|
||||||
parts[0], // style-loader
|
|
||||||
parts.slice(1) // css-loader and rest
|
|
||||||
.join('!')
|
|
||||||
.replace(/[&?]sourcemap/, '')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
webpackConfig.plugins.push(new ExtractTextPlugin('styles.css', {
|
|
||||||
allChunks: true
|
|
||||||
}));
|
|
||||||
|
|
||||||
webpackConfig.devtool = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isProduction) {
|
if (!isProduction) {
|
||||||
webpackConfig.plugins.push(
|
webpackConfig.plugins.push(
|
||||||
new webpack.HotModuleReplacementPlugin(),
|
new webpack.HotModuleReplacementPlugin(),
|
||||||
|
Loading…
Reference in New Issue
Block a user