Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 68 additions & 12 deletions packages/evidence/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@ import { spawn } from 'child_process';
import * as chokidar from 'chokidar';
import path from 'path';
import { fileURLToPath } from 'url';
import { createRequire } from 'module';
import sade from 'sade';
import { logQueryEvent } from '@evidence-dev/telemetry';
import { enableDebug, enableStrictMode } from '@evidence-dev/sdk/utils';
import { loadEnv } from 'vite';
import { createHash } from 'crypto';

const require = createRequire(import.meta.url);

const increaseNodeMemoryLimit = () => {
// Don't override the memory limit if it's already set
if (process.env.NODE_OPTIONS?.includes('--max-old-space-size')) return;
Expand Down Expand Up @@ -161,24 +164,77 @@ function removeStaticDir(dir) {
const strictMode = function () {
enableStrictMode();
};
const buildHelper = function (command, args) {

const resolveViteBin = (cwd) => {
const candidateSearchPaths = [
path.resolve(cwd),
process.cwd(),
path.dirname(fileURLToPath(import.meta.url))
];

for (const searchPath of candidateSearchPaths) {
try {
return require.resolve('vite/bin/vite.js', { paths: [searchPath] });
} catch {
// continue searching
}
}

try {
return require.resolve('vite/bin/vite.js');
} catch {
// fall through
}

// Fallback for environments that can resolve "vite" but not the bin subpath directly.
for (const searchPath of candidateSearchPaths) {
try {
const viteEntry = require.resolve('vite', { paths: [searchPath] });
let current = path.dirname(viteEntry);
while (current !== path.dirname(current)) {
const viteBin = path.join(current, 'bin', 'vite.js');
if (fs.existsSync(viteBin)) return viteBin;
current = path.dirname(current);
}
} catch {
// continue searching
}
}

throw new Error(
`Unable to resolve vite from ${cwd}. Checked project, workspace, and evidence package contexts.`
);
};

const spawnVite = ({ cwd, viteArgs = [], cliArgs = [], env = {}, detached = false }) => {
const viteBin = resolveViteBin(cwd);
return spawn(process.execPath, [viteBin, ...viteArgs, ...cliArgs], {
shell: false,
detached,
cwd,
stdio: 'inherit',
env
});
};

const buildHelper = function (args) {
const watchers = runFileWatcher(watchPatterns);
const flatArgs = flattenArguments(args);

const dataDir = process.env.EVIDENCE_DATA_DIR ?? './static/data';

// Run svelte kit build in the hidden directory
const child = spawn(command, flatArgs, {
shell: true,
const child = spawnVite({
cwd: '.evidence/template',
stdio: 'inherit',
env: {
...process.env,
// used for source query HMR
EVIDENCE_DATA_URL_PREFIX: process.env.EVIDENCE_DATA_URL_PREFIX ?? 'static/data',
EVIDENCE_DATA_DIR: process.env.EVIDENCE_DATA_DIR ?? './static/data',
EVIDENCE_IS_BUILDING: 'true'
}
},
viteArgs: ['build'],
cliArgs: flatArgs
});
// Copy the outputs to the root of the project upon successful exit
child.on('exit', function (code) {
Expand Down Expand Up @@ -271,17 +327,17 @@ ${chalk.bold('[!] Unable to load source manifest')}

logQueryEvent('dev-server-start', undefined, undefined, undefined, true);
// Run svelte kit dev in the hidden directory
const child = spawn(`npx vite dev --port 3000`, flatArgs, {
shell: true,
detached: false,
const child = spawnVite({
cwd: '.evidence/template',
stdio: 'inherit',
env: {
...process.env,
// used for source query HMR
EVIDENCE_DATA_URL_PREFIX: process.env.EVIDENCE_DATA_URL_PREFIX ?? 'static/data',
EVIDENCE_DATA_DIR: process.env.EVIDENCE_DATA_DIR ?? './static/data'
}
},
viteArgs: ['dev', '--port', '3000'],
cliArgs: flatArgs,
detached: false
});

child.on('exit', function () {
Expand Down Expand Up @@ -322,7 +378,7 @@ prog
populateTemplate();

logQueryEvent('build-start');
buildHelper('npx vite build', args);
buildHelper(args);
});

prog
Expand All @@ -340,7 +396,7 @@ prog
strictMode();

logQueryEvent('build-strict-start');
buildHelper('npx vite build', args);
buildHelper(args);
});

prog
Expand Down
57 changes: 50 additions & 7 deletions sites/example-project/tailwind.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const evidenceConfig = require('@evidence-dev/sdk/config').getEvidenceConfig();
const fs = require('fs');
const path = require('path');
let presets = [evidenceTailwind];
const CONTENT_GLOB = '**/*.{html,js,svelte,ts,md}';

const altConfigFilenames = ['tailwind.config.js', 'tailwind.config.cjs'];
const altConfigFilepaths = altConfigFilenames.map((filename) => path.join('..', '..', filename));
Expand All @@ -16,22 +17,64 @@ altConfigFilepaths.find((file) => {
return false;
});

const toPosixPath = (inputPath) => inputPath.split(path.sep).join('/');

const resolvePackageRoot = (packageName) => {
const resolutionPaths = [process.cwd(), __dirname, path.resolve(__dirname, '..')];
try {
const packageJsonPath = require.resolve(`${packageName}/package.json`, { paths: resolutionPaths });
return path.dirname(packageJsonPath);
} catch {
try {
const entryPath = require.resolve(packageName, { paths: resolutionPaths });
let current = path.dirname(entryPath);
while (current !== path.dirname(current)) {
if (fs.existsSync(path.join(current, 'package.json'))) {
return current;
}
current = path.dirname(current);
}
} catch {
return null;
}
}
return null;
};

const resolveComponentContentGlobs = (pluginName) => {
const globs = new Set([
`./node_modules/${pluginName}/dist/${CONTENT_GLOB}`,
`../../node_modules/${pluginName}/dist/${CONTENT_GLOB}`
]);

const packageRoot = resolvePackageRoot(pluginName);
if (!packageRoot) return Array.from(globs);

const relativePackageRoot = toPosixPath(path.relative(__dirname, packageRoot));
if (relativePackageRoot.length === 0) return Array.from(globs);

if (fs.existsSync(path.join(packageRoot, 'dist'))) {
globs.add(`${relativePackageRoot}/dist/${CONTENT_GLOB}`);
} else {
globs.add(`${relativePackageRoot}/${CONTENT_GLOB}`);
}

return Array.from(globs);
};

/** @type {import("tailwindcss").Config} */
const config = {
content: {
relative: true,
get files() {
const pluginConfig = evidenceConfig.plugins;
const components = pluginConfig.components;
const pluginConfig = evidenceConfig.plugins ?? {};
const components = pluginConfig.components ?? {};
const componentPaths = Object.keys(components)
.map((pluginName) => [
`./node_modules/${pluginName}/dist/**/*.{html,js,svelte,ts,md}`,
`../../node_modules/${pluginName}/dist/**/*.{html,js,svelte,ts,md}`
])
.map((pluginName) => resolveComponentContentGlobs(pluginName))
.flat();

return [
'./src/**/*.{html,js,svelte,ts,md}', // This is used for everything in base evidence template
`./src/${CONTENT_GLOB}`, // This is used for everything in base evidence template
...componentPaths
];
}
Expand Down
Loading