@zeropress/build-pages 0.5.2 → 0.5.4

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": "@zeropress/build-pages",
3
- "version": "0.5.2",
3
+ "version": "0.5.4",
4
4
  "description": "ZeroPress Markdown build action and CLI for static hosting",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/src/action.js CHANGED
@@ -8,7 +8,7 @@ const options = {
8
8
  config: input('config'),
9
9
  siteUrl: input('site-url'),
10
10
  skipUntitledMarkdown: booleanInput('skip-untitled-markdown', false),
11
- checkLinks: booleanInput('check-links', true),
11
+ skipLinkCheck: booleanInput('skip-link-check', false),
12
12
  };
13
13
 
14
14
  try {
package/src/index.js CHANGED
@@ -7,7 +7,9 @@ import { checkInternalLinks } from './check-links.js';
7
7
 
8
8
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
9
9
  const packageDir = path.resolve(__dirname, '..');
10
- const prebuildScript = path.join(packageDir, 'src', 'prebuild.js');
10
+ const prebuildScript = __dirname === path.join(packageDir, 'dist')
11
+ ? path.join(__dirname, 'prebuild.js')
12
+ : path.join(packageDir, 'src', 'prebuild.js');
11
13
  const PREVIEW_DATA_PATH = '.zeropress/preview-data.json';
12
14
  const STAGING_DIR = '.zeropress/public-assets';
13
15
  const DEFAULT_THEME = 'docs';
@@ -42,6 +44,13 @@ export async function runBuildPages(options) {
42
44
  const previewDataPath = path.join(cwd, PREVIEW_DATA_PATH);
43
45
  const themeDir = resolveThemeDir(cwd, options);
44
46
 
47
+ assertBuildPagesPathLayout({
48
+ cwd,
49
+ sourceDir,
50
+ destinationDir,
51
+ themeDir,
52
+ generatedDir,
53
+ });
45
54
  await assertDirectory(sourceDir, 'Source directory');
46
55
  await fs.rm(generatedDir, { recursive: true, force: true });
47
56
  await fs.mkdir(generatedDir, { recursive: true });
@@ -93,7 +102,7 @@ export async function runBuildPages(options) {
93
102
  }
94
103
  }
95
104
 
96
- if (options.checkLinks) {
105
+ if (!options.skipLinkCheck) {
97
106
  const result = await checkInternalLinks(destinationDir);
98
107
  if (result.brokenLinks.length) {
99
108
  console.warn('Warning: broken internal links found:');
@@ -105,7 +114,7 @@ export async function runBuildPages(options) {
105
114
  }
106
115
  }
107
116
 
108
- export function parseArgs(argv, env = process.env) {
117
+ export function parseArgs(argv) {
109
118
  const flags = {};
110
119
 
111
120
  for (let index = 0; index < argv.length; index += 1) {
@@ -114,8 +123,8 @@ export function parseArgs(argv, env = process.env) {
114
123
  flags.skipUntitledMarkdown = true;
115
124
  continue;
116
125
  }
117
- if (arg === '--no-check-links') {
118
- flags.checkLinks = false;
126
+ if (arg === '--skip-link-check') {
127
+ flags.skipLinkCheck = true;
119
128
  continue;
120
129
  }
121
130
 
@@ -140,24 +149,24 @@ export function parseArgs(argv, env = process.env) {
140
149
  throw new Error(`Invalid arguments: unknown option ${arg}`);
141
150
  }
142
151
 
143
- const source = flags.source || env.ZEROPRESS_PUBLIC_DIR || '';
144
- const destination = flags.destination || env.ZEROPRESS_OUT_DIR || '';
152
+ const source = flags.source || '';
153
+ const destination = flags.destination || '';
145
154
  if (!source) {
146
- throw new Error('Invalid arguments: --source <dir> is required. You can also set ZEROPRESS_PUBLIC_DIR.');
155
+ throw new Error('Invalid arguments: --source <dir> is required.');
147
156
  }
148
157
  if (!destination) {
149
- throw new Error('Invalid arguments: --destination <dir> is required. You can also set ZEROPRESS_OUT_DIR.');
158
+ throw new Error('Invalid arguments: --destination <dir> is required.');
150
159
  }
151
160
 
152
161
  return {
153
162
  source,
154
163
  destination,
155
164
  theme: flags.theme || DEFAULT_THEME,
156
- themePath: flags['theme-path'] || env.ZEROPRESS_THEME_DIR || '',
157
- config: flags.config || env.ZEROPRESS_BUILD_PAGES_CONFIG || '',
158
- siteUrl: flags['site-url'] || env.ZEROPRESS_SITE_URL || '',
159
- skipUntitledMarkdown: flags.skipUntitledMarkdown ?? env.ZEROPRESS_SKIP_UNTITLED_MARKDOWN === 'true',
160
- checkLinks: flags.checkLinks ?? true,
165
+ themePath: flags['theme-path'] || '',
166
+ config: flags.config || '',
167
+ siteUrl: flags['site-url'] || '',
168
+ skipUntitledMarkdown: flags.skipUntitledMarkdown === true,
169
+ skipLinkCheck: flags.skipLinkCheck === true,
161
170
  };
162
171
  }
163
172
 
@@ -168,14 +177,14 @@ Usage:
168
177
  zeropress-build-pages [options]
169
178
 
170
179
  Options:
171
- --source <dir> Source directory (required, or ZEROPRESS_PUBLIC_DIR)
172
- --destination <dir> Output directory (required, or ZEROPRESS_OUT_DIR)
180
+ --source <dir> Dedicated source directory (required)
181
+ --destination <dir> Output directory (required)
173
182
  --theme docs Bundled theme name (default: docs)
174
183
  --theme-path <dir> Custom ZeroPress theme directory
175
184
  --config <path> Config file (default: <source>/.zeropress/config.json)
176
185
  --site-url <url> Canonical site URL override
177
186
  --skip-untitled-markdown Skip Markdown files without a page title
178
- --no-check-links Skip internal link checking
187
+ --skip-link-check Skip internal link checking
179
188
  --help, -h Show help
180
189
  --version, -v Show version`);
181
190
  }
@@ -205,6 +214,32 @@ async function assertDirectory(dir, label) {
205
214
  }
206
215
  }
207
216
 
217
+ function assertBuildPagesPathLayout({ cwd, sourceDir, destinationDir, themeDir, generatedDir }) {
218
+ if (samePath(sourceDir, cwd)) {
219
+ throw new Error(
220
+ 'Source directory must be a dedicated content directory, not the current working directory. '
221
+ + `Received: ${formatPath(cwd, sourceDir)}`,
222
+ );
223
+ }
224
+
225
+ assertNoPathOverlap(cwd, 'Source directory', sourceDir, 'internal .zeropress working directory', generatedDir);
226
+ assertNoPathOverlap(cwd, 'Destination directory', destinationDir, 'internal .zeropress working directory', generatedDir);
227
+ assertNoPathOverlap(cwd, 'Theme directory', themeDir, 'internal .zeropress working directory', generatedDir);
228
+ assertNoPathOverlap(cwd, 'Source directory', sourceDir, 'destination directory', destinationDir);
229
+ assertNoPathOverlap(cwd, 'Source directory', sourceDir, 'theme directory', themeDir);
230
+ }
231
+
232
+ function assertNoPathOverlap(cwd, firstLabel, firstPath, secondLabel, secondPath) {
233
+ if (!pathsOverlap(firstPath, secondPath)) {
234
+ return;
235
+ }
236
+ throw new Error(
237
+ `${firstLabel} must not overlap the ${secondLabel}. `
238
+ + `${firstLabel}: ${formatPath(cwd, firstPath)}; `
239
+ + `${secondLabel}: ${formatPath(cwd, secondPath)}`,
240
+ );
241
+ }
242
+
208
243
  async function copyPublicStaging(sourceDir, targetDir, options) {
209
244
  const entries = await fs.readdir(sourceDir, { withFileTypes: true });
210
245
 
@@ -256,6 +291,10 @@ function pathsOverlap(firstPath, secondPath) {
256
291
  return first === second || isPathInside(first, second) || isPathInside(second, first);
257
292
  }
258
293
 
294
+ function samePath(firstPath, secondPath) {
295
+ return path.resolve(firstPath) === path.resolve(secondPath);
296
+ }
297
+
259
298
  function isPathInside(parentPath, childPath) {
260
299
  const relativePath = path.relative(parentPath, childPath);
261
300
  return Boolean(relativePath) && !relativePath.startsWith('..') && !path.isAbsolute(relativePath);
package/src/prebuild.js CHANGED
@@ -5,7 +5,7 @@ import matter from 'gray-matter';
5
5
 
6
6
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
7
7
  const rootDir = process.cwd();
8
- const sourceDir = resolveEnvPath(['ZEROPRESS_BUILD_PAGES_SOURCE', 'ZEROPRESS_PUBLIC_DIR'], 'docs');
8
+ const sourceDir = resolveEnvPath(['ZEROPRESS_BUILD_PAGES_SOURCE'], 'docs');
9
9
  const defaultConfigPath = path.join(sourceDir, '.zeropress', 'config.json');
10
10
  const configPath = resolveOptionalEnvPath(['ZEROPRESS_BUILD_PAGES_CONFIG'], defaultConfigPath);
11
11
  const outDir = path.join(rootDir, '.zeropress');