Add support for file settings in themes

Files are added to the SCSS variables as a list of maps like (data: [base64 encoded file contents], type: [file MIME type], url: [data uri]), …
This commit is contained in:
Samuel Elliott 2018-02-21 01:16:41 +00:00
parent 2eaafdb1ac
commit eae9d67649
No known key found for this signature in database
GPG Key ID: 8420C7CDE43DC4D6
7 changed files with 50 additions and 9 deletions

View File

@ -10,6 +10,7 @@
import ContentManager from './contentmanager'; import ContentManager from './contentmanager';
import Theme from './theme'; import Theme from './theme';
import { FileUtils } from 'common';
export default class ThemeManager extends ContentManager { export default class ThemeManager extends ContentManager {
@ -122,6 +123,19 @@ export default class ThemeManager extends ContentManager {
return [name, maps.length ? maps.join(', ') + ',' : '()']; return [name, maps.length ? maps.join(', ') + ',' : '()'];
} }
if (type === 'file' && Array.isArray(value)) {
if (!value || !value.length) return [name, '(),'];
const files = [];
for (let filepath of value) {
const buffer = await FileUtils.readFileBuffer(filepath);
const type = await FileUtils.getFileType(buffer);
files.push(`(data: ${this.toSCSSString(buffer.toString('base64'))}, type: ${this.toSCSSString(type.mime)}, url: ${this.toSCSSString(await FileUtils.toDataURI(buffer, type.mime))})`);
}
return [name, files.length ? files.join(', ') : '()'];
}
if (type === 'slider') { if (type === 'slider') {
return [name, value * setting.multi || 1]; return [name, value * setting.multi || 1];
} }
@ -135,8 +149,13 @@ export default class ThemeManager extends ContentManager {
} }
if (typeof value === 'string') { if (typeof value === 'string') {
return [name, `'${setting.value.replace(/\\/g, '\\\\').replace(/'/g, '\\\'')}'`]; return [name, this.toSCSSString(value)];
} }
} }
static toSCSSString(value) {
if (typeof value !== 'string' && value.toString) value = value.toString();
return `'${typeof value === 'string' ? value.replace(/\\/g, '\\\\').replace(/'/g, '\\\'') : ''}'`;
}
} }

View File

@ -59,4 +59,4 @@ module.exports = {
path.resolve(__dirname, '..', 'node_modules') path.resolve(__dirname, '..', 'node_modules')
] ]
}*/ }*/
}; };

View File

@ -14,6 +14,7 @@ const
_ = require('lodash'); _ = require('lodash');
import { Vendor } from 'modules'; import { Vendor } from 'modules';
import filetype from 'file-type';
export class Utils { export class Utils {
static overload(fn, cb) { static overload(fn, cb) {
@ -150,6 +151,15 @@ export class FileUtils {
}); });
} }
static async readFileBuffer(path, options) {
return new Promise((resolve, reject) => {
fs.readFile(path, options || {}, (err, data) => {
if (err) return reject(err);
resolve(data);
});
});
}
static async writeFile(path, data) { static async writeFile(path, data) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
fs.writeFile(path, data, err => { fs.writeFile(path, data, err => {
@ -196,4 +206,16 @@ export class FileUtils {
static async readDir(path) { static async readDir(path) {
return this.listDirectory(path); return this.listDirectory(path);
} }
static async getFileType(buffer) {
if (typeof buffer === 'string') buffer = await this.readFileBuffer(buffer);
return filetype(buffer);
}
static async toDataURI(buffer, type) {
if (typeof buffer === 'string') buffer = await this.readFileBuffer(buffer);
if (!type) type = this.getFileType(buffer).mime;
return `data:${type};base64,${buffer.toString('base64')}`;
}
} }

View File

@ -27,6 +27,7 @@
"electron-rebuild": "^1.7.3", "electron-rebuild": "^1.7.3",
"eslint": "^4.16.0", "eslint": "^4.16.0",
"eslint-plugin-vue": "^4.2.0", "eslint-plugin-vue": "^4.2.0",
"file-type": "^7.6.0",
"gulp": "^3.9.1", "gulp": "^3.9.1",
"gulp-babel": "^7.0.0", "gulp-babel": "^7.0.0",
"gulp-plumber": "^1.2.0", "gulp-plumber": "^1.2.0",
@ -49,7 +50,7 @@
"build": "npm run build --prefix client && npm run build --prefix core && npm run build --prefix csseditor", "build": "npm run build --prefix client && npm run build --prefix core && npm run build --prefix csseditor",
"build_client": "npm run build --prefix client", "build_client": "npm run build --prefix client",
"watch_client": "npm run watch --prefix client", "watch_client": "npm run watch --prefix client",
"build_core": "npm run build --prefix core", "build_core": "npm run build --prefix core",
"watch_core": "npm run watch --prefix core", "watch_core": "npm run watch --prefix core",
"watch_csseditor": "npm run watch --prefix csseditor", "watch_csseditor": "npm run watch --prefix csseditor",
"lint": "eslint -f unix client/src core/src csseditor/src", "lint": "eslint -f unix client/src core/src csseditor/src",

View File

@ -132,8 +132,7 @@
}, },
{ {
"id": "avatar", "id": "avatar",
"type": "text", "type": "file",
"value": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/0c/Cow_female_black_white.jpg/220px-Cow_female_black_white.jpg",
"text": "Avatar replace", "text": "Avatar replace",
"hint": "Replace all avatars" "hint": "Replace all avatars"
}, },

View File

@ -1,4 +1,4 @@
@import 'vars.scss'; @import 'vars';
div { div {
background: unquote($divBg); background: unquote($divBg);
@ -11,7 +11,7 @@ span {
} }
.avatar-large { .avatar-large {
background-image: url($avatar) !important; background-image: url(map-get($avatar, url)) !important;
border-radius: $avatarRadius !important; border-radius: $avatarRadius !important;
} }

View File

@ -1,6 +1,6 @@
$divBg: green !default; $divBg: green !default;
$spanOpacity: 0.5 !default; $spanOpacity: 0.5 !default;
$avatar: "https://upload.wikimedia.org/wikipedia/commons/thumb/0/0c/Cow_female_black_white.jpg/220px-Cow_female_black_white.jpg" !default; $avatar: (url: "https://upload.wikimedia.org/wikipedia/commons/thumb/0/0c/Cow_female_black_white.jpg/220px-Cow_female_black_white.jpg") !default;
$avatarRadius: 8px !default; $avatarRadius: 8px !default;
$radioTest: red !default; $radioTest: red !default;
$spanOpacity2: 1 !default; $spanOpacity2: 1 !default;