277 lines
9.1 KiB
JavaScript
277 lines
9.1 KiB
JavaScript
"use strict";
|
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.ThemeSassParser = exports.initTheme = exports.normalizeThemeConfigOnce = exports.parseThemeJson = exports.hasThemeJson = void 0;
|
|
const fs_1 = __importDefault(require("fs"));
|
|
const path_1 = __importDefault(require("path"));
|
|
const json_1 = require("./json");
|
|
const uni_shared_1 = require("@dcloudio/uni-shared");
|
|
const manifest_1 = require("./manifest");
|
|
function hasThemeJson(themeLocation) {
|
|
if (!fs_1.default.existsSync(themeLocation)) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
exports.hasThemeJson = hasThemeJson;
|
|
const parseThemeJson = (themeLocation = 'theme.json') => {
|
|
if (!themeLocation || !process.env.UNI_INPUT_DIR) {
|
|
return {};
|
|
}
|
|
themeLocation = path_1.default.join(process.env.UNI_INPUT_DIR, themeLocation);
|
|
if (!hasThemeJson(themeLocation)) {
|
|
return {};
|
|
}
|
|
const jsonStr = fs_1.default.readFileSync(themeLocation, 'utf8');
|
|
return (0, json_1.parseJson)(jsonStr, true);
|
|
};
|
|
exports.parseThemeJson = parseThemeJson;
|
|
const SCHEME_RE = /^([a-z-]+:)?\/\//i;
|
|
const DATA_RE = /^data:.*,.*/;
|
|
function normalizeFilepath(filepath) {
|
|
if (!(SCHEME_RE.test(filepath) || DATA_RE.test(filepath)) &&
|
|
filepath.indexOf('/') !== 0) {
|
|
return (0, uni_shared_1.addLeadingSlash)(filepath);
|
|
}
|
|
return filepath;
|
|
}
|
|
const parseThemeJsonIconPath = (themeConfig, curPathThemeJsonKey) => {
|
|
if (themeConfig.light?.[curPathThemeJsonKey]) {
|
|
themeConfig.light[curPathThemeJsonKey] = normalizeFilepath(themeConfig.light[curPathThemeJsonKey]);
|
|
}
|
|
if (themeConfig.dark?.[curPathThemeJsonKey]) {
|
|
themeConfig.dark[curPathThemeJsonKey] = normalizeFilepath(themeConfig.dark[curPathThemeJsonKey]);
|
|
}
|
|
};
|
|
function normalizeUniConfigThemeJsonIconPath(themeConfig, pagesJson) {
|
|
// 处理 tabbar 下 list -> item -> iconPath、selectedIconPath; midButton -> backgroundImage 路径 / 不开头的情况
|
|
const tabBar = pagesJson.tabBar;
|
|
if (tabBar && tabBar.list && tabBar.list.length) {
|
|
tabBar.list.forEach((item) => {
|
|
if (item.iconPath && item.iconPath.indexOf('@') === 0) {
|
|
parseThemeJsonIconPath(themeConfig, item.iconPath.replace(/^@/, ''));
|
|
}
|
|
if (item.selectedIconPath && item.selectedIconPath.indexOf('@') === 0) {
|
|
parseThemeJsonIconPath(themeConfig, item.selectedIconPath.replace(/^@/, ''));
|
|
}
|
|
});
|
|
const midButtonBackgroundImage = tabBar.midButton?.backgroundImage;
|
|
if (midButtonBackgroundImage &&
|
|
midButtonBackgroundImage.indexOf('@') === 0) {
|
|
parseThemeJsonIconPath(themeConfig, midButtonBackgroundImage.replace(/^@/, ''));
|
|
}
|
|
}
|
|
return themeConfig;
|
|
}
|
|
const getPagesJson = (inputDir) => {
|
|
const pagesFilename = path_1.default.join(inputDir, 'pages.json');
|
|
if (!fs_1.default.existsSync(pagesFilename)) {
|
|
return {
|
|
pages: [],
|
|
globalStyle: { navigationBar: {} },
|
|
};
|
|
}
|
|
const jsonStr = fs_1.default.readFileSync(pagesFilename, 'utf8');
|
|
return (0, json_1.parseJson)(jsonStr, true);
|
|
};
|
|
exports.normalizeThemeConfigOnce = (0, uni_shared_1.once)((manifestJsonPlatform = {}) => {
|
|
const themeConfig = (0, exports.parseThemeJson)(manifestJsonPlatform.themeLocation);
|
|
if (process.env.UNI_INPUT_DIR) {
|
|
normalizeUniConfigThemeJsonIconPath(themeConfig, getPagesJson(process.env.UNI_INPUT_DIR));
|
|
}
|
|
return themeConfig;
|
|
});
|
|
function initTheme(manifestJson, pagesJson) {
|
|
const platform = process.env.UNI_PLATFORM === 'app' ? 'app-plus' : process.env.UNI_PLATFORM;
|
|
const manifestPlatform = (0, manifest_1.getPlatformManifestJson)(manifestJson, platform) || {};
|
|
const themeConfig = (0, exports.normalizeThemeConfigOnce)(manifestPlatform);
|
|
return (0, uni_shared_1.normalizeStyles)(pagesJson, themeConfig);
|
|
}
|
|
exports.initTheme = initTheme;
|
|
// TODO
|
|
class ThemeSassParser {
|
|
constructor() {
|
|
this._index = 0;
|
|
this._input = '';
|
|
this._theme = {};
|
|
}
|
|
parse(input) {
|
|
this._index = 0;
|
|
this._input = input;
|
|
this._theme = {};
|
|
this._theme['light'] = {};
|
|
this._theme['dark'] = {};
|
|
this.parseVariable();
|
|
return this._theme;
|
|
}
|
|
parseVariable() {
|
|
this.skipWhiteSpaceAndComments();
|
|
this.consume('$');
|
|
this.skipWhiteSpaceAndComments();
|
|
let key = this.parseString();
|
|
this.skipWhiteSpaceAndComments();
|
|
this.consume(':');
|
|
this.skipWhiteSpace();
|
|
const value = this.parseVariableValue();
|
|
if (Array.isArray(value)) {
|
|
this.pushThemeValue(key, value);
|
|
}
|
|
this.consume(';');
|
|
this.skipWhiteSpaceAndComments();
|
|
if (this._index < this._input.length) {
|
|
this.parseVariable();
|
|
}
|
|
}
|
|
parseVariableValue() {
|
|
switch (this.currentChar) {
|
|
case 'l':
|
|
return this.parseFunction();
|
|
default:
|
|
return this.skipOtherValue();
|
|
}
|
|
}
|
|
parseFunction() {
|
|
let functionName = '';
|
|
while (this.currentChar != '(') {
|
|
functionName += this.currentChar;
|
|
if (this._index + 1 < this._input.length) {
|
|
++this._index;
|
|
}
|
|
else {
|
|
break;
|
|
}
|
|
}
|
|
if (functionName != 'light-dark') {
|
|
return this.skipOtherValue();
|
|
}
|
|
let valuePair = new Array(2);
|
|
valuePair[0] = '';
|
|
valuePair[1] = '';
|
|
this.consume('(');
|
|
let index = 0;
|
|
// TODO rgb?
|
|
while (this.currentChar != ')') {
|
|
valuePair[index] += this.currentChar;
|
|
if (this.currentChar === ',') {
|
|
index++;
|
|
}
|
|
++this._index;
|
|
}
|
|
this.consume(')');
|
|
valuePair[0] = valuePair[0].trim();
|
|
valuePair[1] = valuePair[1].trim();
|
|
return valuePair;
|
|
}
|
|
skipOtherValue() {
|
|
while (this.currentChar != ';') {
|
|
if (this._index + 1 < this._input.length) {
|
|
++this._index;
|
|
}
|
|
else {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
parseString() {
|
|
let str = '';
|
|
while (this.currentChar != ':') {
|
|
if (this.currentChar == '\\') {
|
|
str += this.currentChar;
|
|
if (this._index + 1 < this._input.length) {
|
|
str += this._input[++this._index];
|
|
}
|
|
}
|
|
str += this.currentChar;
|
|
if (this._index + 1 < this._input.length) {
|
|
++this._index;
|
|
}
|
|
else {
|
|
break;
|
|
}
|
|
}
|
|
return str;
|
|
}
|
|
pushThemeValue(key, valuePair) {
|
|
this._theme['light'][key] = valuePair[0];
|
|
this._theme['dark'][key] = valuePair[1];
|
|
}
|
|
consume(expected) {
|
|
if (this.currentChar != expected) {
|
|
throw new Error('Unexpected character ' +
|
|
expected +
|
|
' index=' +
|
|
this._index +
|
|
' ' +
|
|
this.currentChar);
|
|
}
|
|
++this._index;
|
|
}
|
|
get currentChar() {
|
|
if (this._index >= this._input.length) {
|
|
throw new Error('Unexpected end of input');
|
|
}
|
|
return this._input[this._index];
|
|
}
|
|
skipWhiteSpaceAndComments() {
|
|
while (this._index < this._input.length) {
|
|
const c = this._input[this._index];
|
|
if (this.isspace(c)) {
|
|
++this._index;
|
|
}
|
|
else if (c == '/') {
|
|
this.skipComment();
|
|
}
|
|
else {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
skipComment() {
|
|
if (this.currentChar != '/') {
|
|
return;
|
|
}
|
|
this.consume('/');
|
|
let nextChar = this.currentChar;
|
|
if (nextChar == '/') {
|
|
// Single line comment
|
|
while (
|
|
// @ts-expect-error
|
|
this.currentChar !== '\n' &&
|
|
this._index < this._input.length - 1) {
|
|
++this._index;
|
|
}
|
|
this.skipWhiteSpace();
|
|
}
|
|
else if (nextChar === '*') {
|
|
// Multi-line comment
|
|
while (true) {
|
|
if (this._index + 1 >= this._input.length) {
|
|
throw new Error('Unterminated multi-line comment');
|
|
}
|
|
++this._index;
|
|
// @ts-expect-error
|
|
if (this.currentChar === '*' && this._input[this._index + 1] === '/') {
|
|
this._index += 2;
|
|
break;
|
|
}
|
|
}
|
|
this.skipWhiteSpace();
|
|
}
|
|
else {
|
|
throw new Error('Invalid comment');
|
|
}
|
|
}
|
|
skipWhiteSpace() {
|
|
while (this._index < this._input.length &&
|
|
this.isspace(this._input[this._index])) {
|
|
++this._index;
|
|
}
|
|
}
|
|
isspace(str) {
|
|
return str == ' ' || str == '\n' || str == '\r' || str == "'";
|
|
}
|
|
}
|
|
exports.ThemeSassParser = ThemeSassParser;
|