mirror of
https://github.com/elyby/emails-renderer.git
synced 2024-11-23 05:33:13 +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",
|
||||
"scripts": {
|
||||
"start": "rm -rf dist/ && webpack-dev-server --progress --colors",
|
||||
"up": "npm update",
|
||||
"test": "karma start ./karma.conf.js",
|
||||
"lint": "eslint ./src",
|
||||
"i18n": "cd ./scripts && ../node_modules/.bin/babel-node i18n-collect.js",
|
||||
"build": "rm -rf dist/ && NODE_ENV=production webpack --progress --colors",
|
||||
"render": ""
|
||||
"build": "rm -rf dist/ && NODE_ENV=production webpack --progress --colors"
|
||||
},
|
||||
"dependencies": {
|
||||
"babel-polyfill": "^6.3.14",
|
||||
@ -45,27 +42,13 @@
|
||||
"babel-preset-react-hmre": "^1.0.1",
|
||||
"babel-preset-stage-0": "^6.3.13",
|
||||
"babel-runtime": "^6.0.0",
|
||||
"bundle-loader": "^0.5.4",
|
||||
"css-loader": "^0.23.0",
|
||||
"eslint": "^3.1.1",
|
||||
"eslint-plugin-react": "^6.0.0",
|
||||
"exports-loader": "^0.6.3",
|
||||
"extract-text-webpack-plugin": "^1.0.0",
|
||||
"file-loader": "^0.9.0",
|
||||
"html-loader": "^0.4.3",
|
||||
"html-webpack-plugin": "^2.0.0",
|
||||
"imports-loader": "^0.6.5",
|
||||
"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",
|
||||
"style-loader": "^0.13.0",
|
||||
"url-loader": "^0.5.7",
|
||||
"webpack": "^1.12.9",
|
||||
"webpack-dev-server": "^1.14.0",
|
||||
|
@ -2,6 +2,8 @@ export default function Activation() {
|
||||
return (
|
||||
<div>
|
||||
Activated!
|
||||
<br />
|
||||
<img src={require('./images/kitty.jpg')} />
|
||||
</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 webpack = require('webpack');
|
||||
const loaderUtils = require('loader-utils');
|
||||
const ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
const cssUrl = require('webpack-utils/cssUrl');
|
||||
const cssImport = require('postcss-import');
|
||||
|
||||
const rootPath = path.resolve('./src');
|
||||
|
||||
@ -15,36 +11,7 @@ const isProduction = process.env.NODE_ENV === 'production';
|
||||
|
||||
process.env.NODE_ENV = isProduction ? 'production' : 'development';
|
||||
|
||||
const CSS_CLASS_TEMPLATE = isProduction ? '[hash:base64:5]' : '[path][name]-[local]';
|
||||
|
||||
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 = {
|
||||
const webpackConfig = {
|
||||
entry: {
|
||||
app: path.join(__dirname, 'src')
|
||||
},
|
||||
@ -66,20 +33,12 @@ var webpackConfig = {
|
||||
devServer: {
|
||||
host: 'localhost',
|
||||
port: 8080,
|
||||
// proxy: {
|
||||
// '/api*': {
|
||||
// headers: {
|
||||
// host: config.apiHost.replace(/https?:|\//g, '')
|
||||
// },
|
||||
// target: config.apiHost
|
||||
// }
|
||||
// },
|
||||
hot: true,
|
||||
inline: true,
|
||||
historyApiFallback: true
|
||||
},
|
||||
|
||||
devtool: 'eval',
|
||||
devtool: isProduction ? 'eval' : false,
|
||||
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
@ -102,11 +61,6 @@ var webpackConfig = {
|
||||
|
||||
module: {
|
||||
loaders: [
|
||||
{
|
||||
test: /\.scss$/,
|
||||
extractInProduction: true,
|
||||
loader: 'style!css?' + JSON.stringify(cssLoaderQuery) + '!sass!postcss?syntax=postcss-scss'
|
||||
},
|
||||
{
|
||||
test: /\.jsx?$/,
|
||||
exclude: /node_modules/,
|
||||
@ -114,35 +68,19 @@ var webpackConfig = {
|
||||
},
|
||||
{
|
||||
test: /\.(png|gif|jpg|svg)$/,
|
||||
loader: 'file',
|
||||
loader: 'url',
|
||||
query: {
|
||||
name: 'assets/[name].[ext]?[hash]'
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.(woff|woff2|ttf)$/,
|
||||
loader: 'file',
|
||||
query: {
|
||||
name: 'assets/fonts/[name].[ext]?[hash]'
|
||||
}
|
||||
|
||||
},
|
||||
{
|
||||
test: /\.json$/,
|
||||
exclude: /(intl|font)\.json/,
|
||||
loader: 'json'
|
||||
},
|
||||
{
|
||||
test: /\.html$/,
|
||||
loader: 'html'
|
||||
},
|
||||
{
|
||||
test: /\.intl\.json$/,
|
||||
loader: 'babel!intl!json'
|
||||
},
|
||||
{
|
||||
test: /\.font\.(js|json)$/,
|
||||
loader: 'raw!fontgen'
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -151,68 +89,9 @@ var webpackConfig = {
|
||||
alias: {
|
||||
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) {
|
||||
webpackConfig.plugins.push(
|
||||
new webpack.HotModuleReplacementPlugin(),
|
||||
|
Loading…
Reference in New Issue
Block a user