123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613 |
- // v1.1.9
- const ideModuleDir = global.ideModuleDir;
- const workSpaceDir = global.workSpaceDir;
- var Stream = require('stream');
- //引用插件模块
- const gulp = require(ideModuleDir + "gulp");
- const fs = require("fs");
- const path = require("path");
- const del = require(ideModuleDir + "del");
- let copyLibsTask = ["copyPlatformLibsJsFile"];
- let versiontask = ["version2"];
- let exec = require('child_process').exec;
- let tsconfigPath = path.join(workSpaceDir, "tsconfig.json");
- let isTS = fs.existsSync(tsconfigPath);
- let buildOptions = null;
- gulp.task("preCreate_LayaMe", copyLibsTask, function() {
- releaseDir = global.releaseDir;
- config = global.config;
- buildOptions = config.buildOptions;
- commandSuffix = global.commandSuffix;
- });
- // 是否build指定部分(debug版本layame)
- function toBuildPart(part) {
- if (!buildOptions) {
- return true;
- }
- if ('all' == part ) {
- return buildOptions.type == 'all';
- }
- if (buildOptions.type == 'all') {
- return true;
- }
- return (buildOptions.buildList.includes(part));
- }
- function toBuildTs() {
- if (!buildOptions) {
- return true;
- }
- return buildOptions.hasScript;
- }
- gulp.task("del", ["preCreate_LayaMe"], function(cb) {
- let buildFolder = path.join(workSpaceDir, "build");
- if (!isTS || !fs.existsSync(buildFolder)) {
- return cb();
- }
- let delList = [`${buildFolder}/**`];
- del(delList, { force: true }).then(paths => {
- cb();
- }).catch((err) => {
- throw err;
- })
- });
- gulp.task("tsc", ["del"], function(cb) {
- if (!isTS) {
- return cb();
- }
- if(!toBuildTs()) {
- return cb();
- }
- console.log('tsconfigPath', tsconfigPath);
- let tscPath = path.join(ideModuleDir, ".bin", `tsc${commandSuffix}`);
- return exec(` "${tscPath}" -p "${tsconfigPath}"`, {
- cwd: workSpaceDir,
- shell: true
- }, function(error, stdout, stderr) {
- let errStr = stderr || '';
- if (errStr.indexOf(": node: ") >= 0 || errStr.indexOf("'node'") >= 0) {
- // 提示未安装node
- console.log("err");
- console.log("node not installed");
- } else {
- if (error) console.log("error", error);
- if (stdout) console.log("stdout", stdout);
- if (stderr) console.log("stderr", stderr);
- cb();
- }
- });
- });
- function getFolderList(rootPath, fileList, fileType, deep= 0) {
- if (!fs.existsSync(rootPath)) {
- return fileList;
- }
- let dirList = fs.readdirSync(rootPath);
- let fileName, fileFullPath;
- for (let i = 0, len = dirList.length; i < len; i++) {
- fileName = dirList[i];
- fileFullPath = path.join(rootPath, fileName);
- if (fs.statSync(fileFullPath).isDirectory()) {
- getFolderList(fileFullPath, fileList, fileType, deep + 1);
- } else {
- if (!!fileType && !fileFullPath.endsWith(fileType)) {
- continue;
- }
- fileList.push({path: fileFullPath,deep:deep});
- }
- }
- }
- // 把ui里type为view的runtime删除
- gulp.task("deletRuntime", ["tsc"], function() {
- // const pageUIFolder = path.join(releaseDir, "pageUI");
- // let sceneList= [];
- // getFolderList(pageUIFolder, sceneList, ".json");
- // for (let i = 0, len = sceneList.length; i < len; i++) {
- // let filePath = sceneList[i].path;
- // let fileCon = fs.readFileSync(filePath, "utf8");
- // let jsonData = JSON.parse(fileCon);
- // if (jsonData.type == 'View') {
- // if (jsonData.props && jsonData.props.runtime) {
- // delete jsonData.props.runtime;
- // fs.writeFileSync(filePath, JSON.stringify(jsonData), 'utf8');
- // }
- // }
- // }
- });
- // 将引入的库的路径改为src根目录的LayaMeMain,并且将引入的该类合并到最终发布目录的根目录下的LayaMeMain.js里
- function sortJS (a, b) {
-
- return b.c - a.c;
- }
- function getFInfoByPath(path, list) {
- for (let i = 0, len = list.length; i < len; i++) {
- let info = list[i];
- if (info.path === path) {
- return info;
- }
- }
- return null;
- }
- gulp.task("mergeToLayaMeMain", ["deletRuntime"], function() {
- if (!toBuildPart('LayaMeMain')) {
- return;
- }
- let source = "src";
- if (isTS) {
- source = "build";
- }
- let sourceFolder = path.join(workSpaceDir, source);
- const scriptPath = path.join(sourceFolder, "script");
- let jsList= [];
- let scriptStrList = [];
- let filePath, fileCon, deep;
- // 遍历所有的script,合并到LayaMeMain.js
- jsList= [];
- scriptStrList = [];
-
- getFolderList(scriptPath, jsList, ".js");
- // sort jsList
- let needSort = false;
- let sortList = [];
- let otherList = [];
- for (let i = 0, len = jsList.length; i < len; i++) {
- let jsInfo = jsList[i];
- filePath = jsInfo.path;
- fileCon = fs.readFileSync(filePath, "utf8");
- jsInfo.content = fileCon;
- let extendsCls = fileCon.match((/\ s*extends \s*(.+?)\{/));
- if (extendsCls) {
- if (extendsCls[1]) {
- extendsCls = extendsCls[1].trim();
- if (extendsCls && !extendsCls.includes('.')) { // not include Laya.
- let importCls = fileCon.match(`import\\s*[{| ]\\s*${extendsCls}\\s*[}| ]\\s*from (.+?)["']`) ;
- // console.log( extendsCls, jsInfo.path, !!importCls );
- if (importCls && importCls[1]) {
- importCls = importCls[1].trim();
- importCls = importCls.substr(1); console.log( importCls);
- let deep = jsInfo.deep;
- let currPath = null;
- let _index = importCls.lastIndexOf('./');
- let parenPath = '';
- if (_index >= 0) {
- let fPath = jsInfo.path;
- let _index2 = fPath.indexOf('/') >= 0 ? fPath.lastIndexOf('/') : fPath.lastIndexOf('\\') ;
- currPath = fPath.substring(0,_index2);
- currPath = path.join(jsInfo.path,parenPath + '../', importCls) + '.js';
- jsInfo.extendsCls = extendsCls;// currPath;
- // console.log(jsInfo);
- needSort = true;
- if (!sortList.includes(jsInfo)) {
- sortList.push(jsInfo);
- }
- let importJs = getFInfoByPath(currPath, jsList);
- if (!importJs) {
- throw new Error('not found', currPath);
- }
- if (!jsInfo.c) {
- jsInfo.c = 0;
- }
- importJs.c = jsInfo.c + 1;
- if (!sortList.includes(importJs)) {
- sortList.push(importJs);
- }
- // console.log(currPath,_index,parenPath, jsInfo.path, importCls, extendsCls);
- }
-
- }
- }
- }
- }
- // .vs .fs 解析
- let fileConTmp = fileCon + '';
- let vsOrfsImport = fileConTmp.match(/import \s*(.+?) from \s*(.+?).[fv]s['"]/);
-
- while (vsOrfsImport) {
- let importVar = vsOrfsImport[1];
- let filetype = vsOrfsImport[0];
- let importFile = vsOrfsImport[2];
- importFile = importFile.replace("'", '');
- importFile = importFile.replace('"', '');
- if (filetype.indexOf('.vs') >= 0) {
- filetype = '.vs';
- } else {
- filetype = '.fs';
- }
- importFile = importFile + filetype;
- let importFilePath = path.join(filePath,'../',importFile );
- console.log('importFilePath', importFilePath);
- fileConTmp = fileConTmp.replace(vsOrfsImport[0], '');
- // console.log('fileConTmp', fileConTmp);
- vsOrfsImport = fileConTmp.match(/import \s*(.+?) from \s*(.+?).[fv]s['"]/);
- let srcPath = path.join(workSpaceDir, 'src');
- importFilePath = importFilePath.replace(sourceFolder, srcPath);
- let importFileStr = fs.readFileSync(importFilePath, 'utf8');
- importFileStr = importFileStr.replace(/\r?\n/gm, '\\n');
- importFileStr = importFileStr.replace(/"/gm,'\'');
- importFileStr = importFileStr.replace(/\t/gm,'\\t');
- importFileStr = importFileStr.replace(/\\n\s*/g,'\\n');
- importFileStr = importFileStr.replace(/\\n\\n/g,'\\n');
- // let lineList = importFileStr.split('\n');
- // let rStr = '';
- // for(let i = 0,len = lineList.length; i < len; i ++) {
- // let lineStr = lineList[i];
- // lineStr = lineStr.replace(/\r?\n/gm, '\\n');
- // lineStr = lineStr.replace(/"/gm,'\\"');
- // lineStr = lineStr.replace(/\t/gm,'\\t');
- // lineStr = lineStr.trim();
- // rStr = rStr + lineStr + '\\n';
- // }
- // // fs.writeFileSync(importFilePath + '2',rStr.replace(/\\n/gm,'\n'), 'utf8');
- jsInfo.content = `var ${importVar} = "${importFileStr}";\n` + jsInfo.content;
- }
- }
- // console.log('ssssssssss',sortList);
- if (needSort) {
- sortList.sort(sortJS);
- for (let i = 0, len = sortList.length; i < len; i++) {
- let jsInfo = sortList[i];
- scriptStrList.push(jsInfo.content);
- }
- }
- for (let i = 0, len = jsList.length; i < len; i++) {
- let jsInfo = jsList[i];
- if (!needSort || !sortList.includes(jsInfo)) {
- scriptStrList.push(jsInfo.content);
- }
- }
- let layaMeMainStr = '';
- const layaMeMainPath = path.join(sourceFolder, "LayaMeMain.js");
- if (fs.existsSync(layaMeMainPath)) {
- layaMeMainStr = fs.readFileSync(layaMeMainPath, "utf8");
- }
- if (scriptStrList.length > 0) {
- let scriptStrAll = scriptStrList.join('\n');
- layaMeMainStr = scriptStrAll + '\n' + layaMeMainStr;
- }
- if (layaMeMainStr) {
- // console.log(jsList.length,'layaMeMainStr' , layaMeMainStr);
- layaMeMainStr = layaMeMainStr.replace(/import/mg, "// import");
- // 去掉class前面的字符
-
- layaMeMainStr = layaMeMainStr.replace(/export\s+default\s+[class\.]+\s*/mg, "export class ");
- // layaMeMainStr = layaMeMainStr.replace(/export\s+default\s+[class\.]+\s*/mg, "class ");
- // layaMeMainStr = layaMeMainStr.replace(/export\s+[class\.]+\s*/mg, "class ");
- // layaMeMainStr = layaMeMainStr.replace(/export\s+[var\.]+\s*/mg, "var ");
- fs.writeFileSync(`${releaseDir}/LayaMeMain.js`, layaMeMainStr, "utf8");
- }
- });
- gulp.task("mergeToLayaMeLib", ["mergeToLayaMeMain"], function() {
- if (!toBuildPart('LayaMeMain')) {
- return;
- }
- let source = "src";
- if (isTS) {
- source = "build";
- }
- let sourceFolder = path.join(workSpaceDir, source);
- const scriptPath = path.join(sourceFolder, "classLibs");
- let jsList= [];
- let scriptStrList = [];
- let filePath, fileCon, deep;
- // 遍历所有的classLibs,合并到LayaMeLib.js
- jsList= [];
- scriptStrList = [];
-
- getFolderList(scriptPath, jsList, ".js");
- // sort jsList
- let needSort = false;
- let sortList = [];
- let otherList = [];
- for (let i = 0, len = jsList.length; i < len; i++) {
- let jsInfo = jsList[i];
- filePath = jsInfo.path;
- fileCon = fs.readFileSync(filePath, "utf8");
- jsInfo.content = fileCon;
- let extendsCls = fileCon.match((/\ s*extends \s*(.+?)\{/));
- if (extendsCls) {
- if (extendsCls[1]) {
- extendsCls = extendsCls[1].trim();
- if (extendsCls && !extendsCls.includes('.')) { // not include Laya.
- let importCls = fileCon.match(`import\\s*[{| ]\\s*${extendsCls}\\s*[}| ]\\s*from (.+?)["']`) ;
- // console.log( extendsCls, jsInfo.path, !!importCls );
- if (importCls && importCls[1]) {
- importCls = importCls[1].trim();
- importCls = importCls.substr(1); console.log( importCls);
- let deep = jsInfo.deep;
- let currPath = null;
- let _index = importCls.lastIndexOf('./');
- let parenPath = '';
- if (_index >= 0) {
- let fPath = jsInfo.path;
- let _index2 = fPath.indexOf('/') >= 0 ? fPath.lastIndexOf('/') : fPath.lastIndexOf('\\') ;
- currPath = fPath.substring(0,_index2);
- currPath = path.join(jsInfo.path,parenPath + '../', importCls) + '.js';
- jsInfo.extendsCls = extendsCls;// currPath;
- // console.log(jsInfo);
- needSort = true;
- if (!sortList.includes(jsInfo)) {
- sortList.push(jsInfo);
- }
- let importJs = getFInfoByPath(currPath, jsList);
- if (!importJs) {
- throw new Error('not found', currPath);
- }
- if (!jsInfo.c) {
- jsInfo.c = 0;
- }
- importJs.c = jsInfo.c + 1;
- if (!sortList.includes(importJs)) {
- sortList.push(importJs);
- }
- // console.log(currPath,_index,parenPath, jsInfo.path, importCls, extendsCls);
- }
-
- }
- }
- }
- }
-
- }
- // console.log('ssssssssss',sortList);
- if (needSort) {
- sortList.sort(sortJS);
- for (let i = 0, len = sortList.length; i < len; i++) {
- let jsInfo = sortList[i];
- scriptStrList.push(jsInfo.content);
- }
- }
- for (let i = 0, len = jsList.length; i < len; i++) {
- let jsInfo = jsList[i];
- if (!needSort || !sortList.includes(jsInfo)) {
- scriptStrList.push(jsInfo.content);
- }
- }
- let layaMeLibStr = '';
- // const layaMeLibPath = path.join(sourceFolder, "LayaMeLib.js");
- // if (fs.existsSync(layaMeLibPath)) {
- // layaMeLibStr = fs.readFileSync(layaMeLibPath, "utf8");
- // }
- if (scriptStrList.length > 0) {
- let scriptStrAll = scriptStrList.join('\n');
- layaMeLibStr = scriptStrAll + layaMeLibStr;
- }
- if (layaMeLibStr) {
- // console.log(jsList.length,'layaMeLibStr' , layaMeLibStr);
- layaMeLibStr = layaMeLibStr.replace(/import/mg, "// import");
- // 去掉class前面的字符
- layaMeLibStr = layaMeLibStr.replace(/export\s+default\s+[class\.]+\s*/mg, "export class ");
- // layaMeLibStr = layaMeLibStr.replace(/export\s+default\s+[class\.]+\s*/mg, "class ");
- // layaMeLibStr = layaMeLibStr.replace(/export\s+[class\.]+\s*/mg, "class ");
- // layaMeLibStr = layaMeLibStr.replace(/export\s+[var\.]+\s*/mg, "var ");
-
- fs.writeFileSync(`${releaseDir}/LayaMeLib.js`, layaMeLibStr, "utf8");
- }
- });
- // 修改extends Laya.Script3D 为 extends GameScript
- // 修改 config.json,把.ts替换为.js
- function commentImport (str){
-
- str = str.replace(/import/mg, "// import");
- return str;
- }
- function changeComponentsFile() {
- var stream = new Stream.Transform({ objectMode: true });
- let source = "src";
- if (isTS) {
- source = "build";
- }
- let sourceFolder = path.join(workSpaceDir, source);
- const scriptPath = path.join(sourceFolder, "script");
- const componentsPath = path.join(sourceFolder, "components");
- const actionScriptPath = path.join(sourceFolder, "actionScript", "actionFunc.js");
- const uiScriptPath = path.join(sourceFolder, "uiScript");
- let importPathList = [scriptPath, componentsPath, actionScriptPath, uiScriptPath];
- stream._transform = function (originalFile, unused, callback) {
- let fPath = originalFile.path;
- // throw new Error();
- let file = null;
- const getFile = () => {
- if (!file) {
- file = originalFile.clone({ contents: false });
- }
- return file;
- }
- // console.log('fPth', fPath, componentsPath);
- // 注释import
- for(let k =0; k <importPathList.length; k ++) {
- let _path = importPathList[k];
- if (fPath.startsWith(_path)) {
- file = getFile();
- let stringData = String(file.contents);
- stringData = commentImport(stringData);
- let finalBinaryData = Buffer.from(stringData);
- file.contents = finalBinaryData;
- }
- }
- if (fPath.indexOf('components') >= 0) {
- if ( fPath.endsWith('.js')) {
- file = getFile();
- let stringData = String(file.contents);
- stringData = stringData.replace(/extends\s+[Laya.Script3D\.]+\s*{/mg, "extends GameScript {");
- let finalBinaryData = Buffer.from(stringData);
- file.contents = finalBinaryData;
-
- } else if (fPath.endsWith('config.json')) {
- file = getFile();
- let stringData = String(file.contents);
- stringData = stringData.replace(/.ts\"/mg, '.js"');
- let finalBinaryData = Buffer.from(stringData);
- file.contents = finalBinaryData;
- }
- }
- // 去掉class前面的字符
- if (fPath.endsWith('.js')) {
- file = getFile();
- let stringData = String(file.contents);
-
- stringData = stringData.replace(/export\s+default\s+[class\.]+\s*/mg, "export class ");
- // stringData = stringData.replace(/export\s+default\s+[class\.]+\s*/mg, "class ");
- // stringData = stringData.replace(/export\s+[class\.]+\s*/mg, "class ");
- // stringData = stringData.replace(/export\s+[var\.]+\s*/mg, "var ");
-
- let finalBinaryData = Buffer.from(stringData);
- file.contents = finalBinaryData;
- }
- if (fPath.endsWith('.js')) {
- file = getFile();
- let filePath = fPath;
- let fileCon = String(file.contents);
- // .vs .fs 解析
- let fileConTmp = fileCon + '';
- let jsInfo = {content: fileCon};
- let vsOrfsImport = fileConTmp.match(/import \s*(.+?) from \s*(.+?).[fv]s['"]/);
- let hasVf = false;
- while (vsOrfsImport) {
- hasVf = true;
- let importVar = vsOrfsImport[1];
- let filetype = vsOrfsImport[0];
- let importFile = vsOrfsImport[2];
- importFile = importFile.replace("'", '');
- importFile = importFile.replace('"', '');
- if (filetype.indexOf('.vs') >= 0) {
- filetype = '.vs';
- } else {
- filetype = '.fs';
- }
- importFile = importFile + filetype;
- let importFilePath = path.join(filePath,'../',importFile );
- console.log('importFilePath', importFilePath);
- fileConTmp = fileConTmp.replace(vsOrfsImport[0], '');
- // console.log('fileConTmp', fileConTmp);
- vsOrfsImport = fileConTmp.match(/import \s*(.+?) from \s*(.+?).[fv]s['"]/);
- let srcPath = path.join(workSpaceDir, 'src');
- importFilePath = importFilePath.replace(sourceFolder, srcPath);
- let importFileStr = fs.readFileSync(importFilePath, 'utf8');
- importFileStr = importFileStr.replace(/\r?\n/gm, '\\n');
- importFileStr = importFileStr.replace(/"/gm,'\'');
- importFileStr = importFileStr.replace(/\t/gm,'\\t');
- importFileStr = importFileStr.replace(/\\n\s*/g,'\\n');
- importFileStr = importFileStr.replace(/\\n\\n/g,'\\n');
- jsInfo.content = `var ${importVar} = "${importFileStr}";\n` + jsInfo.content;
- }
- if (hasVf) {
- let finalBinaryData = Buffer.from(jsInfo.content);
- file.contents = finalBinaryData;
- }
- }
- if (file) {
- callback(null, file);
- } else {
- callback(null, originalFile);
- }
- };
- return stream;
- }
- gulp.task("genPreloadMap", ["mergeToLayaMeLib"], function() {
- let atlasList = [];
- getFolderList(releaseDir,atlasList, '.atlas');
- let preloadJson = {
- atlas: [],
- atlasPng:[],
- textures: []
- };
- let releaseDirTmp = releaseDir.replace(/\\/g, '/');
- for(let i = 0,len = atlasList.length; i < len; i ++) {
- let file = atlasList[i].path;
- file = file.replace(/\\/g, '/');
- file = file.replace(releaseDirTmp, '');
- file = file.replace('/', '');
- preloadJson.atlas.push(file);
- preloadJson.atlasPng.push( file.replace('.atlas', '.png'));
- }
- let texturesList = [];
- let texturesDir = path.join(releaseDir, 'textures');
- getFolderList(texturesDir,texturesList, '.png');
- getFolderList(texturesDir,texturesList, '.jpg');
- getFolderList(texturesDir,texturesList, '.jpeg');
-
- let texturesDirTmp = releaseDir.replace(/\\/g, '/');
- for(let i = 0,len = texturesList.length; i < len; i ++) {
- let file = texturesList[i].path;
- file = file.replace(/\\/g, '/');
- file = file.replace(texturesDirTmp, '');
- file = file.replace('/', '');
- preloadJson.textures.push(file);
- }
- fs.writeFileSync(path.join(releaseDir, 'preload.json'), JSON.stringify(preloadJson, null ,4), 'utf8');
- // console.log('atlasList', preloadJson);
- });
- gulp.task("copy", ["genPreloadMap"], function() {
-
- let source = "src";
- if (isTS) {
- source = "build";
- }
- let sourceFolder = path.join(workSpaceDir, source);
- let layameInfo = config.layameInfo;
- let filter1list = [];
- if (toBuildPart('uiScript')) {
- filter1list.push('uiScript/**/*.*');
- }
- if (toBuildPart('actionScript')) {
- filter1list.push('actionScript/**/*.*');
- }
- if (toBuildPart('components')) {
- filter1list.push('components/**/*.*');
- }
- let filter1 = ``;
- if (filter1list.length > 1) {
- filter1 = `${sourceFolder}/{`;
- filter1 += filter1list.join(',');
- filter1 += '}';
- } else if (filter1list.length == 1) {
- filter1 = `${sourceFolder}/{,`;
- filter1 += filter1list[0];
- filter1 += '}';
- } else {
- return;
- }
- let filters = [filter1];
- // console.log('filter1', filter1);throw new Error();
- if (isTS) {
- let filter2 = `${workSpaceDir}/src/{,`;
- let filter2list =[];
- if (toBuildPart('uiScript')) {
- filter2list.push('uiScript/**/!(*.ts)');
- }
- if (toBuildPart('actionScript')) {
- filter2list.push('actionScript/**/!(*.ts)');
- }
- if (toBuildPart('components')) {
- filter2list.push('components/**/!(*.ts)');
- }
- if (filter2list.length > 1) {
- filter2 += filter2list.join(',');
- } else if (filter2list.length == 1) {
- filter2 += filter2list[0];
- }
- filter2 += '}';
- filters.push(
- filter2
- );
- }
- return gulp.src(filters)
- .pipe(changeComponentsFile())
- .pipe(gulp.dest(releaseDir));
- });
- gulp.task("buildLayaMeProj", versiontask, function() {
- console.log("all tasks completed");
- });
|