From e514a79509ed26971de4e3c8edffaa42115e5e5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=A1=E5=93=A5?= Date: Mon, 30 Jun 2025 14:58:50 +0800 Subject: [PATCH] lizhouze@huawei.com MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 卡哥 --- src/element.js | 10 ++++ src/json.js | 9 +++ src/parser.js | 40 +++++++++++++ src/script.js | 11 ++++ src/style.js | 12 ++++ src/template.js | 12 ++++ src/util.js | 148 ++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 242 insertions(+) diff --git a/src/element.js b/src/element.js index 43ea504..bba3c8f 100644 --- a/src/element.js +++ b/src/element.js @@ -23,6 +23,16 @@ import { extractBlocks } from './parser' +/** + * Webpack loader for processing and extracting custom elements from source files + * + * Features: + * - Extracts named elements from source when extract option is enabled + * - Returns raw content when raw option is specified + * - Handles both synchronous and asynchronous processing + * - Includes comprehensive error handling + * - Supports webpack caching + */ module.exports = function (source) { this.cacheable && this.cacheable() diff --git a/src/json.js b/src/json.js index 7191219..877a3cc 100644 --- a/src/json.js +++ b/src/json.js @@ -28,6 +28,15 @@ const REG_EVENT_STRING = /("\s*\$event\..+")|('\s*\$event\..+')/g const REG_EVENT = /\$event\.[\w]+/g const REG_THIS = /this\..*/g +/** + * Webpack loader for processing JSON files in card mode + * Performs transformations specific to card device level including: + * - Comment removal + * - Export statement handling + * - Event reference parsing + * - This binding transformation + * - JSON validation + */ module.exports = function (source) { this.cacheable && this.cacheable() diff --git a/src/parser.js b/src/parser.js index 91aac26..37901ec 100644 --- a/src/parser.js +++ b/src/parser.js @@ -29,6 +29,12 @@ import { stringifyFunction } from './util' +/** + * Gets an attribute value from a node by name + * @param {Object} node - DOM node with attributes + * @param {string} name - Attribute name to find + * @returns {string|undefined} Attribute value if found + */ function getAttribute (node, name) { if (node.attrs) { let i = node.attrs.length @@ -42,6 +48,11 @@ function getAttribute (node, name) { } } +/** + * Recursively extracts dependencies from child nodes + * @param {Object} node - Parent node to scan + * @param {Array} deps - Array to accumulate dependencies + */ function extractDependencies (node, deps) { if (node.childNodes) { node.childNodes.forEach(child => { @@ -55,6 +66,18 @@ function extractDependencies (node, deps) { } } +/** + * Parses a fragment into structured component parts + * @param {string} source - source to parse + * @returns {Object} Structured output containing: + * - deps: Array of dependencies + * - element: Array of custom elements + * - template: Array of hml + * - style: Array of styles + * - script: Array of scripts + * - data: Array of data scripts + * - config: Array of config scripts + */ export function parseFragment (source) { const fragment = parse5.parseFragment(source, { locationInfo: true @@ -112,6 +135,12 @@ export function parseFragment (source) { return output } +/** + * Parses a HML source into JSON format from loader.js + * @param {string} source - Template source + * @param {string} resourcePath - Path to the resource + * @returns {Promise} Resolves with parsed template and logs + */ export function parseTemplate (source, resourcePath) { return new Promise((resolve, reject) => { templater.parse(source, (err, obj) => { @@ -128,6 +157,12 @@ export function parseTemplate (source, resourcePath) { }) } +/** + * Parses style source into JSON format from loader.js + * @param {string} source - Style source + * @param {string} resourcePath - Path to the resource + * @returns {Promise} Resolves with parsed style and logs + */ export function parseStyle (source, resourcePath) { return new Promise((resolve, reject) => { styler.parse(source, (err, obj) => { @@ -142,6 +177,11 @@ export function parseStyle (source, resourcePath) { }) } +/** + * Processes script source with fixes from loader.js + * @param {string} source - Script source + * @returns {Promise} Resolves with processed script + */ export function parseScript (source) { return new Promise((resolve, reject) => { const parsed = scripter.fix(source) diff --git a/src/script.js b/src/script.js index 5147956..5e2fbb6 100644 --- a/src/script.js +++ b/src/script.js @@ -29,6 +29,17 @@ import { const { DEVICE_LEVEL } = require('./lite/lite-enum') +/** + * Webpack loader for processing JavaScript files in ACE framework + * Handles both Rich and Lite device levels with appropriate transformations + * + * Features: + * - Parses and transforms JavaScript for ACE framework compatibility + * - Handles VM object validation and data/accessor merging for Rich devices + * - Preserves source maps + * - Includes comprehensive error handling + * - Supports webpack caching + */ module.exports = function (source, map) { this.cacheable && this.cacheable() const callback = this.async() diff --git a/src/style.js b/src/style.js index 5f0d286..92ceb50 100644 --- a/src/style.js +++ b/src/style.js @@ -26,6 +26,18 @@ import { } from './parser' const compileStyle = require('./lite/lite-transform-style') const { DEVICE_LEVEL } = require('./lite/lite-enum') + +/** + * Webpack loader for processing CSS/Style files in ACE framework + * Handles both Rich and Lite device levels with appropriate transformations + * + * Features: + * - Parses and transforms CSS for ACE framework compatibility + * - Applies device-specific transformations for Lite devices + * - Includes comprehensive error handling and logging + * - Supports webpack caching + * - Preserves source maps + */ module.exports = function (source) { this.cacheable && this.cacheable() diff --git a/src/template.js b/src/template.js index b993fc8..b5e4877 100644 --- a/src/template.js +++ b/src/template.js @@ -26,6 +26,18 @@ import { } from './parser' const compiler = require('./lite/lite-transform-template') const { DEVICE_LEVEL } = require('./lite/lite-enum') + +/** + * Webpack loader for processing HML (Hyper-Markup Language) template files + * Handles both Rich and Lite device levels with appropriate transformations + * + * Features: + * - Processes ACE framework template files + * - Strips Rich device specific elements when not needed + * - Includes comprehensive error handling and logging + * - Supports webpack caching + * - Transforms templates for Lite device compatibility + */ module.exports = function (source) { if (process.env.DEVICE_LEVEL !== DEVICE_LEVEL.RICH && source.lastIndexOf('') > 0) { const count = source.lastIndexOf('') diff --git a/src/util.js b/src/util.js index c8e9eb0..c84ef47 100644 --- a/src/util.js +++ b/src/util.js @@ -32,10 +32,22 @@ const { DEVICE_LEVEL } = require('./lite/lite-enum') export const useOSFiles = new Set(); export const elements = {}; +/** + * Extracts base name from resource path (without extension) + * @param {string} resourcePath - Full file path + * @returns {string} Base filename without extension + */ + export function getNameByPath (resourcePath) { return path.basename(resourcePath).replace(/\..*$/, '') } +/** + * Generates a cache-busted filename with SHA256 hash + * @param {string} resourcePath - File path + * @param {string} content - File content for hash generation + * @returns {string} Relative path with hash query parameter + */ export function getFileNameWithHash (resourcePath, content) { const filename = path.relative('.', resourcePath) const hash = crypto.createHash('sha256') @@ -44,6 +56,11 @@ export function getFileNameWithHash (resourcePath, content) { return `./${filename}?${cacheKey}` } +/** + * Gets relative filename from path + * @param {string} filepath - Absolute file path + * @returns {string} Relative file path + */ export function getFilenameByPath (filepath) { return path.relative('.', filepath) } @@ -53,6 +70,12 @@ export const FUNC_START_REG = new RegExp('["\']' + FUNC_START, 'g') export const FUNC_END = '#####FUN_E#####' export const FUNC_END_REG = new RegExp(FUNC_END + '["\']', 'g') +/** + * Stringifies functions with special markers for JSON serialization + * @param {string} key - Object key + * @param {any} value - Value to stringify + * @returns {string} Stringified value with function markers + */ export function stringifyFunction (key, value) { if (typeof value === 'function') { return FUNC_START + value.toString() + FUNC_END @@ -60,6 +83,12 @@ export function stringifyFunction (key, value) { return value } +/** + * Handles build warnings and errors with configurable log levels + * @param {Object} loader - Webpack loader context + * @param {Array} logs - Array of log messages + * @returns {boolean} True if errors were found + */ export function logWarn (loader, logs) { // add flag to determine if there is an error log let flag = false @@ -98,6 +127,13 @@ export function logWarn (loader, logs) { return flag } +/** + * Generates a require statement string with proper loader chaining + * @param {Object} loaderContext - Webpack loader context + * @param {string} loader - Loader string + * @param {string} filepath - File path to require + * @returns {string} Complete require statement + */ export function getRequireString (loaderContext, loader, filepath) { return 'require(' + loaderUtils.stringifyRequest( @@ -109,6 +145,11 @@ export function getRequireString (loaderContext, loader, filepath) { ')\n' } +/** + * Converts loader objects to webpack loader strings + * @param {Array} loaders - Array of loader configs + * @returns {string} Webpack loader string + */ export function stringifyLoaders (loaders) { return loaders.map(loader => { if (typeof loader === 'string') { @@ -138,6 +179,13 @@ export function stringifyLoaders (loaders) { }).join('!') } +/** + * Generates a source map for transformed code + * @param {Object} loader - Webpack loader context + * @param {string} source - Original source + * @param {Array} iterator - Array of position mappings + * @returns {Object} Source map object + */ export function generateMap (loader, source, iterator) { const filePath = loader.resourcePath @@ -161,6 +209,13 @@ export function generateMap (loader, source, iterator) { return map } +/** + * Consumes a source map to generate position mappings + * @param {Object} loader - Webpack loader context + * @param {string} target - Transformed source + * @param {Object} map - Source map to consume + * @returns {Object} Mapping information + */ export function consumeMap (loader, target, map) { const smc = new SourceMapConsumer(map) let source @@ -205,10 +260,20 @@ export function consumeMap (loader, target, map) { } const LINE_REG = /\r?\n/g + +/** + * Splits source into lines + * @param {string} source - Source content + * @returns {Array} Array of source lines + */ export function splitSourceLine (source) { return source.split(LINE_REG) } +/** + * Prints source with line numbers (debug utility) + * @param {string} source - Source content to print + */ export function printSourceWithLine (source) { console.log('>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>') source = splitSourceLine(source) @@ -218,6 +283,11 @@ export function printSourceWithLine (source) { console.log('<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<') } +/** + * Resolves Babel module path with fallback + * @param {string} moduleName - Module to resolve + * @returns {string} Resolved module path or original name + */ export function loadBabelModule (moduleName) { try { const filePath = require.resolve(moduleName) @@ -276,6 +346,13 @@ function requireModule(moduleName) { return target; } ` + +/** + * Parses and transforms require statements in source code + * @param {string} source - Original source code + * @param {string} resourcePath - Path to the resource file + * @returns {string} Transformed source code + */ export function parseRequireModule (source, resourcePath) { const requireMethod = process.env.DEVICE_LEVEL === DEVICE_LEVEL.LITE ? methodForLite : methodForOthers source = `${source}\n${requireMethod}` @@ -307,6 +384,14 @@ export function parseRequireModule (source, resourcePath) { return source } +/** + * Generates loader strings for different file types + * @param {string} type - File type (template/style/json) + * @param {string} customLoader - Optional custom loader + * @param {boolean} isVisual - Whether to include visual loader + * @param {string} queryType - Query type for visual loader + * @returns {string} Webpack loader string + */ export function jsonLoaders (type, customLoader, isVisual, queryType) { let loaders = [] @@ -352,6 +437,11 @@ export function jsonLoaders (type, customLoader, isVisual, queryType) { return stringifyLoaders(loaders) } +/** + * Recursively copies files from input to output directory + * @param {string} inputPath - Source directory + * @param {string} outputPath - Target directory + */ export function circularFile(inputPath, outputPath) { if ((!inputPath) || (!outputPath)) { return; @@ -373,6 +463,11 @@ export function circularFile(inputPath, outputPath) { }) } +/** + * Copies a file with proper directory creation and JSON merging + * @param {string} inputFile - Source file path + * @param {string} outputFile - Target file path + */ function copyFile(inputFile, outputFile) { try { const parent = path.join(outputFile, '..'); @@ -390,6 +485,17 @@ function copyFile(inputFile, outputFile) { } } +/** + * Checks if a given path is under a specified base directory + * + * @param {string} fullPath - The absolute path to check (e.g., '/project/src/main.js') + * @param {string} basePath - The base directory path (e.g., '/project') + * @returns {boolean} True if fullPath is under basePath, false otherwise + * + * @example + * isPathUnderBase('/project/src/main.js', '/project') // returns true + * isPathUnderBase('/other/src/main.js', '/project') // returns false + */ function isPathUnderBase(fullPath, basePath) { const normalizedFullPath = fullPath.replace(/\\/g, '/').toLowerCase(); const normalizedBasePath = basePath.replace(/\\/g, '/').toLowerCase() + '/'; @@ -397,6 +503,11 @@ function isPathUnderBase(fullPath, basePath) { return normalizedFullPath.startsWith(normalizedBasePath); } +/** + * Checks if a module is valid based on project dependencies + * @param {Array} requireMatch - Regex match result from require statement + * @param {string} resourcePath - Path to the resource file + */ function checkModuleIsVaild(requireStatementExec, resourcePath) { if (process.env.DEVICE_LEVEL !== 'lite' || !requireStatementExec || requireStatementExec.length <= 3) { return; @@ -432,6 +543,17 @@ function checkModuleIsVaild(requireStatementExec, resourcePath) { } } +/** + * Merges and copies JSON files with deep merging capability + * + * @param {string} inputFile - Path to source JSON file + * @param {string} outputFile - Path to target JSON file + * @throws {Error} Throws error if file operations or JSON parsing fails + * + * @example + * // Merges new translations into existing i18n file + * copyJsonFile('new-translations.json', 'existing-translations.json'); + */ function copyJsonFile(inputFile, outputFile) { try { const contentInput = JSON.parse(fs.readFileSync(inputFile, 'utf-8')); @@ -446,6 +568,28 @@ function copyJsonFile(inputFile, outputFile) { } } +/** + * Deep merges two JSON-compatible objects recursively + * + * @param {any} inputValue - The source value to merge from + * @param {any} outputValue - The target value to merge into + * @returns {any} The merged result + * + * @example + * // Basic merge + * mergeJson({a: 1}, {b: 2}) // returns {a: 1, b: 2} + * + * // Deep merge + * mergeJson( + * {nested: {a: 1}}, + * {nested: {b: 2}} + * ) // returns {nested: {a: 1, b: 2}} + * + * // Type handling + * mergeJson({a: 1}, {a: 2}) // returns {a: 1} (input overrides) + * mergeJson(null, {a: 1}) // returns {a: 1} + * mergeJson({a: 1}, null) // returns {a: 1} + */ function mergeJson(inputValue, outputValue) { if (outputValue === null || outputValue === undefined) { return inputValue; @@ -460,6 +604,10 @@ function mergeJson(inputValue, outputValue) { return outputValue; } +/** + * Creates directory recursively + * @param {string} dirPath - Directory path to create + */ export function mkDir(path_) { const parent = path.join(path_, '..'); if (!(fs.existsSync(parent) && !fs.statSync(parent).isFile())) { -- Gitee