salix/print/core/component.js

118 lines
3.0 KiB
JavaScript

const Vue = require('vue');
const VueI18n = require('vue-i18n');
const renderer = require('vue-server-renderer').createRenderer();
Vue.use(VueI18n);
const fs = require('fs');
const yaml = require('js-yaml');
const juice = require('juice');
const path = require('path');
const config = require('./config');
class Component {
constructor(name) {
this.name = name;
}
get path() {
return `./components/${this.name}`;
}
get template() {
const templatePath = `${this.path}/${this.name}.html`;
const fullPath = path.resolve(__dirname, templatePath);
return fs.readFileSync(fullPath, 'utf8');
}
get locale() {
if (!this._locale)
this.getLocale();
return this._locale;
}
getLocale() {
const mergedLocale = {messages: {}};
const localePath = path.resolve(__dirname, `${this.path}/locale`);
if (!fs.existsSync(localePath))
return mergedLocale;
const localeDir = fs.readdirSync(localePath);
localeDir.forEach(locale => {
const fullPath = path.join(localePath, '/', locale);
const yamlLocale = fs.readFileSync(fullPath, 'utf8');
const jsonLocale = yaml.safeLoad(yamlLocale);
const localeName = locale.replace('.yml', '');
mergedLocale.messages[localeName] = jsonLocale;
});
this._locale = mergedLocale;
}
get stylesheet() {
let mergedStyles = '';
const stylePath = path.resolve(__dirname, `${this.path}/assets/css`);
if (!fs.existsSync(stylePath))
return mergedStyles;
return require(`${stylePath}/import`);
}
get attachments() {
const attachmentsPath = `${this.path}/attachments.json`;
const fullPath = path.resolve(__dirname, attachmentsPath);
if (!fs.existsSync(fullPath))
return [];
return require(fullPath);
}
build() {
const fullPath = path.resolve(__dirname, this.path);
if (!fs.existsSync(fullPath))
throw new Error(`Sample "${this.name}" not found`);
const component = require(`${this.path}/${this.name}`);
component.i18n = this.locale;
component.attachments = this.attachments;
component.template = juice.inlineContent(this.template, this.stylesheet, {
inlinePseudoElements: true
});
return component;
}
component() {
if (this._component)
return this._component;
const component = this.build();
const i18n = new VueI18n(config.i18n);
const props = {tplPath: this.path, ...this.args};
this._component = new Vue({
i18n: i18n,
render: h => h(component, {
props: props
})
});
return this._component;
}
/**
* @return {Promise} Rendered component
*/
async render() {
return renderer.renderToString(
this.component()
);
}
}
module.exports = Component;