- 修复Dockerfile构建问题,暂时禁用ideal-image插件 - 更新所有配置文件中的registry端口为5003 - 添加.dockerignore文件优化构建性能 - 创建docker-compose.yml文件支持本地部署 - 添加部署脚本scripts/deploy-docker.sh - 更新Gitea Actions工作流,添加Docker部署步骤 - 创建DOCKER_DEPLOYMENT.md部署文档 - 支持通过3001端口提供lingjingwanxiang web portal服务
237 lines
7.3 KiB
JavaScript
237 lines
7.3 KiB
JavaScript
"use strict";
|
|
|
|
var _path = _interopRequireDefault(require("path"));
|
|
|
|
var _loaderUtils = _interopRequireDefault(require("loader-utils"));
|
|
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
|
|
const MIMES = {
|
|
'jpg': 'image/jpeg',
|
|
'jpeg': 'image/jpeg',
|
|
'png': 'image/png',
|
|
'webp': 'image/webp',
|
|
'avif': 'image/avif'
|
|
};
|
|
const EXTS = {
|
|
'image/jpeg': 'jpg',
|
|
'image/png': 'png',
|
|
'image/webp': 'webp',
|
|
'image/avif': 'avif'
|
|
};
|
|
/*
|
|
type Config = {
|
|
size: string | number | void,
|
|
sizes: [string | number] | void,
|
|
min: string | number | void,
|
|
max: string | number | void,
|
|
steps: string | number | void,
|
|
name: string | void,
|
|
outputPath: Function | string | void,
|
|
publicPath: Function | string | void,
|
|
context: string | void,
|
|
placeholderSize: string | number | void,
|
|
quality: string | number | void,
|
|
background: string | number | void,
|
|
placeholder: string | boolean | void,
|
|
adapter: ?Function,
|
|
format: 'png' | 'jpg' | 'jpeg',
|
|
disable: ?boolean,
|
|
emitFile: ?boolean,
|
|
};
|
|
*/
|
|
|
|
const getOutputAndPublicPath = (fileName, {
|
|
outputPath: configOutputPath,
|
|
publicPath: configPublicPath
|
|
}) => {
|
|
let outputPath = fileName;
|
|
|
|
if (configOutputPath) {
|
|
if (typeof configOutputPath === 'function') {
|
|
outputPath = configOutputPath(fileName);
|
|
} else {
|
|
outputPath = _path.default.posix.join(configOutputPath, fileName);
|
|
}
|
|
}
|
|
|
|
let publicPath = `__webpack_public_path__ + ${JSON.stringify(outputPath)}`;
|
|
|
|
if (configPublicPath) {
|
|
if (typeof configPublicPath === 'function') {
|
|
publicPath = configPublicPath(fileName);
|
|
} else if (configPublicPath.endsWith('/')) {
|
|
publicPath = configPublicPath + fileName;
|
|
} else {
|
|
publicPath = `${configPublicPath}/${fileName}`;
|
|
}
|
|
|
|
publicPath = JSON.stringify(publicPath);
|
|
}
|
|
|
|
return {
|
|
outputPath,
|
|
publicPath
|
|
};
|
|
};
|
|
|
|
module.exports = function loader(content) {
|
|
const loaderCallback = this.async();
|
|
const parsedResourceQuery = this.resourceQuery ? _loaderUtils.default.parseQuery(this.resourceQuery) : {};
|
|
const config = Object.assign({}, _loaderUtils.default.getOptions(this), parsedResourceQuery);
|
|
const outputContext = config.context || this.rootContext || this.options && this.options.context;
|
|
const outputPlaceholder = Boolean(config.placeholder) || false;
|
|
const placeholderSize = parseInt(config.placeholderSize, 10) || 40; // JPEG compression
|
|
|
|
const quality = parseInt(config.quality, 10) || 85; // Useful when converting from PNG to JPG
|
|
|
|
const background = config.background; // Specify mimetype to convert to another format
|
|
|
|
let mime;
|
|
let ext;
|
|
|
|
if (config.format) {
|
|
if (!MIMES.hasOwnProperty(config.format)) {
|
|
return loaderCallback(new Error('[Docusaurus responsive loader] Format "' + config.format + '" not supported'));
|
|
}
|
|
|
|
mime = MIMES[config.format];
|
|
ext = EXTS[mime];
|
|
} else {
|
|
ext = _path.default.extname(this.resourcePath).replace(/\./, '');
|
|
mime = MIMES[ext];
|
|
|
|
if (!mime) {
|
|
return loaderCallback(new Error('[Docusaurus responsive loader] No mime type for file with extension ' + ext + ' supported'));
|
|
}
|
|
}
|
|
|
|
const name = (config.name || '[hash]-[width].[ext]').replace(/\[ext\]/ig, ext);
|
|
const emitFile = config.emitFile !== false;
|
|
|
|
const adapter = config.adapter || require('./adapters/jimp');
|
|
|
|
const loaderContext = this; // The config that is passed to the adatpers
|
|
|
|
const adapterOptions = Object.assign({}, config, {
|
|
quality,
|
|
background
|
|
});
|
|
const min = config.min !== undefined ? parseInt(config.min, 10) : undefined;
|
|
const max = config.max !== undefined ? parseInt(config.max, 10) : undefined;
|
|
const steps = config.steps === undefined ? 4 : parseInt(config.steps, 10);
|
|
let generatedSizes;
|
|
|
|
if (typeof min === 'number' && max) {
|
|
generatedSizes = [];
|
|
|
|
for (let step = 0; step < steps; step++) {
|
|
const size = min + (max - min) / (steps - 1) * step;
|
|
generatedSizes.push(Math.ceil(size));
|
|
}
|
|
}
|
|
|
|
const sizes = parsedResourceQuery.size || parsedResourceQuery.sizes || generatedSizes || config.size || config.sizes || [Number.MAX_SAFE_INTEGER];
|
|
|
|
if (!sizes) {
|
|
return loaderCallback(null, content);
|
|
}
|
|
|
|
if (config.disable) {
|
|
// emit original content only
|
|
const fileName = _loaderUtils.default.interpolateName(loaderContext, name, {
|
|
context: outputContext,
|
|
content: content
|
|
}).replace(/\[width\]/ig, '100').replace(/\[height\]/ig, '100');
|
|
|
|
const {
|
|
outputPath,
|
|
publicPath
|
|
} = getOutputAndPublicPath(fileName, config);
|
|
|
|
if (emitFile) {
|
|
loaderContext.emitFile(outputPath, content);
|
|
}
|
|
|
|
return loaderCallback(null, 'module.exports = Object.assign(Object.create({toString(){return this.src;}}),{srcSet:' + publicPath + ',images:[{path:' + publicPath + ',width:100,height:100}],src: ' + publicPath + '});');
|
|
}
|
|
|
|
const createFile = ({
|
|
data,
|
|
width,
|
|
height
|
|
}) => {
|
|
const fileName = _loaderUtils.default.interpolateName(loaderContext, name, {
|
|
context: outputContext,
|
|
content: data
|
|
}).replace(/\[width\]/ig, width).replace(/\[height\]/ig, height);
|
|
|
|
const {
|
|
outputPath,
|
|
publicPath
|
|
} = getOutputAndPublicPath(fileName, config);
|
|
|
|
if (emitFile) {
|
|
loaderContext.emitFile(outputPath, data);
|
|
}
|
|
|
|
return {
|
|
src: publicPath + `+${JSON.stringify(` ${width}w`)}`,
|
|
path: publicPath,
|
|
width: width,
|
|
height: height
|
|
};
|
|
};
|
|
|
|
const createPlaceholder = ({
|
|
data
|
|
}) => {
|
|
const placeholder = data.toString('base64');
|
|
return JSON.stringify('data:' + (mime ? mime + ';' : '') + 'base64,' + placeholder);
|
|
};
|
|
|
|
const img = adapter(loaderContext.resourcePath);
|
|
return img.metadata().then(metadata => {
|
|
let promises = [];
|
|
const widthsToGenerate = new Set();
|
|
(Array.isArray(sizes) ? sizes : [sizes]).forEach(size => {
|
|
const width = Math.min(metadata.width, parseInt(size, 10)); // Only resize images if they aren't an exact copy of one already being resized...
|
|
|
|
if (!widthsToGenerate.has(width)) {
|
|
widthsToGenerate.add(width);
|
|
promises.push(img.resize({
|
|
width,
|
|
mime,
|
|
options: adapterOptions
|
|
}));
|
|
}
|
|
});
|
|
|
|
if (outputPlaceholder) {
|
|
promises.push(img.resize({
|
|
width: placeholderSize,
|
|
options: adapterOptions,
|
|
mime
|
|
}));
|
|
}
|
|
|
|
return Promise.all(promises).then(results => outputPlaceholder ? {
|
|
files: results.slice(0, -1).map(createFile),
|
|
placeholder: createPlaceholder(results[results.length - 1])
|
|
} : {
|
|
files: results.map(createFile)
|
|
});
|
|
}).then(({
|
|
files,
|
|
placeholder
|
|
}) => {
|
|
const srcset = files.map(f => f.src).join('+","+');
|
|
const images = files.map(f => '{path:' + f.path + ',width:' + f.width + ',height:' + f.height + '}').join(',');
|
|
const firstImage = files[0]; // prevent toString from injected into {...img} or JSON.stringify
|
|
// Object.assign is to avoid verbose syntax in Object.create; __proto__ is shorter but deprecated
|
|
|
|
loaderCallback(null, 'module.exports = Object.assign(Object.create({toString(){return this.src;}}),{' + 'srcSet:' + srcset + ',' + 'images:[' + images + '],' + 'src:' + firstImage.path + ',' + 'placeholder: ' + placeholder + ',' + 'width:' + firstImage.width + ',' + 'height:' + firstImage.height + '});');
|
|
}).catch(err => loaderCallback(err));
|
|
};
|
|
|
|
module.exports.raw = true; // get buffer stream instead of utf8 string
|