vite-plugin-fenom 1.0.11 → 1.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vite-plugin-fenom",
3
- "version": "1.0.11",
3
+ "version": "1.0.12",
4
4
  "type": "module",
5
5
  "main": "./vite-plugin-fenom.cjs",
6
6
  "exports": {
@@ -1981,93 +1981,99 @@ function fenomPlugin(options = {}) {
1981
1981
  const searchPath = require$$0.resolve(config.root, pages);
1982
1982
  const pattern = require$$0.join(searchPath, '**/*.tpl').replace(/\\/g, '/');
1983
1983
  try {
1984
- const files = await fastGlob(pattern);
1984
+ const templateFiles = await fastGlob(pattern);
1985
1985
  if (debug)
1986
- console.log('\x1b[36m[Fenom Plugin]\x1b[0m Found templates:', files);
1987
- // === Сбор информации о выходных файлах ===
1988
- const entryChunks = {}; // inputPath → /out/path.js
1989
- const cssAssets = {}; // inputPath → /out/path.css
1986
+ console.log('[Fenom Plugin] Found templates:', templateFiles);
1987
+ // === Сбор всех выходных файлов ===
1988
+ const emittedJs = {}; // relative moduleId → /out.js
1989
+ const emittedCss = {}; // input basename → /out.css
1990
1990
  for (const [fileName, file] of Object.entries(bundle)) {
1991
- const outFile = `/${fileName}`;
1991
+ const publicPath = `/${fileName}`;
1992
1992
  if (file.type === 'chunk' && file.facadeModuleId) {
1993
- // Это JS-чанк, сопоставим с входом
1994
- const inputPath = require$$0.relative(config.root, file.facadeModuleId).replace(/\\/g, '/');
1995
- entryChunks[inputPath] = outFile;
1993
+ const moduleId = require$$0.relative(config.root, file.facadeModuleId).replace(/\\/g, '/');
1994
+ emittedJs[moduleId] = publicPath;
1996
1995
  }
1997
1996
  if (file.type === 'asset' && fileName.endsWith('.css')) {
1998
- // Это CSS-ассет. Попробуем найти, из какого входа.
1999
- // Vite не всегда хранит source, но имя может помочь
2000
- if (file.name && file.name.endsWith('.css')) {
2001
- // Пример: file.name = 'style.css' или 'style-hash.css'
2002
- const baseName = require$$0.basename(file.name, '.css');
2003
- // Пока просто запоминаем — уточним позже
2004
- cssAssets[file.name] = outFile;
2005
- }
1997
+ // Сохраняем по базовому имени (без хеша)
1998
+ const baseName = fileName.replace(/\.[^.]+\.css$/, '.css'); // main.hash.css main.css
1999
+ const keyName = baseName === fileName ? require$$0.basename(fileName, '.css') : baseName.replace('.css', '');
2000
+ emittedCss[keyName] = publicPath;
2006
2001
  }
2007
2002
  }
2008
- // === Анализ входов ===
2003
+ // === Получаем все входы как массив строк ===
2009
2004
  const inputEntries = config.build.rollupOptions.input;
2010
- const inputs = [];
2005
+ const inputPaths = [];
2011
2006
  if (Array.isArray(inputEntries)) {
2012
- inputs.push(...inputEntries.filter((i) => typeof i === 'string'));
2007
+ inputPaths.push(...inputEntries);
2013
2008
  }
2014
2009
  else if (typeof inputEntries === 'object' && inputEntries !== null) {
2015
- inputs.push(...Object.values(inputEntries).filter((i) => typeof i === 'string'));
2010
+ inputPaths.push(...Object.values(inputEntries));
2016
2011
  }
2017
2012
  else if (typeof inputEntries === 'string') {
2018
- inputs.push(inputEntries);
2013
+ inputPaths.push(inputEntries);
2019
2014
  }
2020
- // === Карта замены: исходный путь собранный файл ===
2015
+ // Нормализуем: приводим к абсолютному пути, затем к относительному от корня
2016
+ const normalizedInputs = inputPaths.map((input) => {
2017
+ // Если путь абсолютный (начинается с /), считаем его относительно корня
2018
+ const absolute = input.startsWith('/')
2019
+ ? require$$0.resolve(config.root, '.' + input) // /src/main.ts → root/src/main.ts
2020
+ : require$$0.resolve(config.root, input); // src/main.ts → root/src/main.ts
2021
+ return require$$0.relative(config.root, absolute).replace(/\\/g, '/');
2022
+ });
2023
+ // === Карта замены: исходный путь (в шаблоне) → выходной ассет ===
2021
2024
  const replacementMap = new Map();
2022
- for (const input of inputs) {
2023
- if (!input.endsWith('.js') && !input.endsWith('.ts') && !input.endsWith('.css'))
2024
- continue;
2025
- const normalizedInput = require$$0.resolve(input).replace(/\\/g, '/');
2026
- const relativeInput = require$$0.relative(config.root, normalizedInput).replace(/\\/g, '/');
2027
- if (input.endsWith('.ts') || input.endsWith('.js')) {
2028
- const moduleId = require$$0.relative(config.root, normalizedInput).replace(/\\/g, '/');
2029
- if (entryChunks[moduleId]) {
2030
- replacementMap.set(relativeInput, entryChunks[moduleId]);
2025
+ for (const input of normalizedInputs) {
2026
+ const ext = require$$0.extname(input).toLowerCase();
2027
+ const baseInputName = require$$0.basename(input, ext);
2028
+ if (ext === '.ts' || ext === '.js') {
2029
+ if (emittedJs[input]) {
2030
+ // Прямое совпадение
2031
+ replacementMap.set(`/${input}`, { type: 'js', path: emittedJs[input] });
2031
2032
  }
2032
2033
  }
2033
- if (input.endsWith('.css')) {
2034
- const cssFileName = require$$0.basename(input);
2035
- // Ищем ассет, содержащий имя файла
2036
- const matchedCss = Object.keys(cssAssets).find(name => name === cssFileName || name.startsWith(require$$0.basename(cssFileName, '.css')));
2034
+ if (ext === '.scss' || ext === '.css') {
2035
+ // Ищем CSS-файл по базовому имени
2036
+ const matchedCss = Object.keys(emittedCss).find(key => key === baseInputName ||
2037
+ key === require$$0.basename(input) ||
2038
+ key.includes(baseInputName));
2037
2039
  if (matchedCss) {
2038
- replacementMap.set(relativeInput, cssAssets[matchedCss]);
2040
+ replacementMap.set(`/${input}`, { type: 'css', path: emittedCss[matchedCss] });
2039
2041
  }
2040
2042
  }
2041
2043
  }
2042
2044
  // === Генерация HTML ===
2043
- for (const file of files) {
2044
- const fileName = require$$0.basename(file, '.tpl');
2045
- const outputFileName = fileName === 'index' ? 'index.html' : `${fileName}.html`;
2045
+ for (const file of templateFiles) {
2046
+ const pageName = require$$0.basename(file, '.tpl');
2047
+ const outputFileName = pageName === 'index' ? 'index.html' : `${pageName}.html`;
2046
2048
  const source = await fs__namespace.readFile(file, 'utf-8');
2047
2049
  const context = {
2048
- title: `${fileName.charAt(0).toUpperCase() + fileName.slice(1)} Page`,
2050
+ title: `${pageName.charAt(0).toUpperCase() + pageName.slice(1)} Page`,
2049
2051
  debug: false,
2050
- url: '/' + (fileName === 'index' ? '' : fileName),
2052
+ url: '/' + (pageName === 'index' ? '' : pageName),
2051
2053
  ...globalData,
2052
2054
  };
2053
2055
  let html = await FenomJs(source, {
2054
- context: context,
2056
+ context,
2055
2057
  loader: templateLoader,
2056
2058
  minify: minifyHtml,
2057
2059
  });
2058
- // === Замена путей ===
2059
- for (const [devPath, prodPath] of replacementMap) {
2060
- const fullDevPath = '/' + devPath;
2061
- const escaped = fullDevPath.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
2062
- const scriptRegex = new RegExp(`<script[^>]+src=["']${escaped}["'][^>]*/?>`, 'gi');
2063
- if (scriptRegex.test(html)) {
2064
- html = html.replace(scriptRegex, `<script type="module" src="${prodPath}"></script>`);
2060
+ // === Замена тегов: поддержка путей с / и без / ===
2061
+ for (const [devPath, { type, path }] of replacementMap) {
2062
+ // devPath уже с `/` в начале: `/src/main.ts`
2063
+ const escaped = devPath.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
2064
+ if (type === 'js') {
2065
+ const scriptRegex = new RegExp(`<script[^>]+src=["']${escaped}["'][^>]*/?>`, 'gi');
2066
+ html = html.replace(scriptRegex, `<script type="module" src="${path}"></script>`);
2065
2067
  }
2066
- const linkRegex = new RegExp(`<link[^>]+href=["']${escaped}["'][^>]*/?>`, 'gi');
2067
- if (linkRegex.test(html)) {
2068
- html = html.replace(linkRegex, `<link rel="stylesheet" href="${prodPath}">`);
2068
+ if (type === 'css') {
2069
+ const linkRegex = new RegExp(`<link[^>]+href=["']${escaped}["'][^>]*/?>`, 'gi');
2070
+ html = html.replace(linkRegex, `<link rel="stylesheet" href="${path}">`);
2069
2071
  }
2070
2072
  }
2073
+ // Минификация
2074
+ if (minifyHtml) {
2075
+ html = html.replace(/>\s+</g, '><').replace(/\s+/g, ' ').trim();
2076
+ }
2071
2077
  this.emitFile({
2072
2078
  type: 'asset',
2073
2079
  fileName: outputFileName,
@@ -2078,7 +2084,7 @@ function fenomPlugin(options = {}) {
2078
2084
  }
2079
2085
  }
2080
2086
  catch (err) {
2081
- console.error('\x1b[31m[Fenom Plugin]\x1b[0m Error during HTML generation:', err);
2087
+ console.error('\x1b[31m[Fenom Plugin]\x1b[0m Build error:', err);
2082
2088
  }
2083
2089
  },
2084
2090
  };