Skip to content

Commit

Permalink
Pass the webbook tests
Browse files Browse the repository at this point in the history
  • Loading branch information
spring-raining committed Jan 12, 2025
1 parent 537aa48 commit b8c375f
Show file tree
Hide file tree
Showing 6 changed files with 170 additions and 194 deletions.
32 changes: 30 additions & 2 deletions src/config/resolve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Metadata, StringifyMarkdownOptions, VFM } from '@vivliostyle/vfm';
import { lookup as mime } from 'mime-types';
import fs from 'node:fs';
import { pathToFileURL } from 'node:url';
import npa from 'npm-package-arg';
import { Processor } from 'unified';
import upath from 'upath';
import { ResolvedConfig as ResolvedViteConfig, UserConfig } from 'vite';
Expand All @@ -28,7 +29,6 @@ import {
import { CONTAINER_IMAGE, CONTAINER_LOCAL_HOSTNAME } from '../container.js';
import { Logger } from '../logger.js';
import { readMarkdownMetadata } from '../processor/markdown.js';
import { parsePackageName } from '../processor/theme.js';
import {
cwd as defaultCwd,
getEpubRootDir,
Expand Down Expand Up @@ -155,6 +155,7 @@ export interface EpubOpfEntryConfig {
export interface WebBookEntryConfig {
type: 'webbook';
webbookEntryUrl: string;
webbookPath: string | undefined;
}

export type ViewerInputConfig =
Expand Down Expand Up @@ -295,6 +296,31 @@ export function isWebPubConfig(
return config.viewerInput.type === 'webpub';
}

export function isWebbookConfig(
config: ResolvedTaskConfig,
): config is ResolvedTaskConfig & {
viewerInput: WebBookEntryConfig;
} {
return config.viewerInput.type === 'webbook';
}

export function parsePackageName(
specifier: string,
cwd: string,
): npa.Result | null {
try {
let result = npa(specifier, cwd);
// #373: Relative path specifiers may be assumed as shorthand of hosted git
// (ex: foo/bar -> github:foo/bar)
if (result.type === 'git' && result.saveSpec?.startsWith('github:')) {
result = npa(`file:${specifier}`, cwd);
}
return result;
} catch (error) {
return null;
}
}

// parse theme locator
export function parseTheme({
theme,
Expand Down Expand Up @@ -817,6 +843,7 @@ function resolveSingleInputConfig({
};
} else if (inputFormat === 'webbook') {
let webbookEntryUrl: string;
let webbookPath: string | undefined;
if (isValidUri(sourcePath)) {
const url = new URL(sourcePath);
// Ensures trailing slash or explicit HTML extensions
Expand All @@ -832,8 +859,9 @@ function resolveSingleInputConfig({
const rootFileUrl = pathToFileURL(workspaceDir).href;
const urlPath = pathToFileURL(sourcePath).href.slice(rootFileUrl.length);
webbookEntryUrl = `${base}${urlPath}`;
webbookPath = sourcePath;
}
viewerInput = { type: 'webbook', webbookEntryUrl };
viewerInput = { type: 'webbook', webbookEntryUrl, webbookPath };
} else if (inputFormat === 'pub-manifest') {
viewerInput = {
type: 'webpub',
Expand Down
31 changes: 19 additions & 12 deletions src/output/webbook.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
import { copy, remove } from 'fs-extra/esm';
import { lookup as mime } from 'mime-types';
import fs from 'node:fs';
import { pathToFileURL } from 'node:url';
import { glob } from 'tinyglobby';
import upath from 'upath';
import {
EpubOutput,
isWebbookConfig,
ResolvedTaskConfig,
WebBookEntryConfig,
WebPublicationOutput,
} from '../config/resolve.js';
import { ArticleEntryConfig } from '../config/schema.js';
import { MANIFEST_FILENAME } from '../const.js';
import { Logger } from '../logger.js';
import {
getDefaultIgnorePatterns,
getIgnoreAssetPatterns,
getIgnoreThemeExamplePatterns,
globAssetFiles,
} from '../processor/compile.js';
import {
Expand Down Expand Up @@ -192,15 +195,18 @@ export function writePublicationManifest(
}

export async function retrieveWebbookEntry({
webbookEntryUrl,
viewerInput,
outputDir,
}: {
webbookEntryUrl: string;
viewerInput: WebBookEntryConfig;
outputDir: string;
}): Promise<{
entryHtmlFile: string;
manifest: PublicationManifest | undefined;
}> {
const webbookEntryUrl = viewerInput.webbookPath
? pathToFileURL(viewerInput.webbookPath).href
: viewerInput.webbookEntryUrl;
if (/^https?:/i.test(webbookEntryUrl)) {
Logger.logUpdate('Fetching remote contents');
}
Expand All @@ -209,6 +215,10 @@ export async function retrieveWebbookEntry({
src: webbookEntryUrl,
resourceLoader,
});
const entryHtml = viewerInput.webbookPath
? upath.basename(viewerInput.webbookPath)
: decodeURI(dom.window.location.pathname);

const { manifest, manifestUrl } =
(await fetchLinkedPublicationManifest({
dom,
Expand Down Expand Up @@ -295,12 +305,7 @@ export async function retrieveWebbookEntry({
);

return {
entryHtmlFile: upath.join(
outputDir,
upath.extname(webbookEntryUrl)
? upath.basename(webbookEntryUrl)
: 'index.html',
),
entryHtmlFile: upath.join(outputDir, entryHtml),
manifest,
};
}
Expand Down Expand Up @@ -409,10 +414,12 @@ export async function copyWebPublicationAssets({
outputs,
entries,
}),
...getDefaultIgnorePatterns({
...getIgnoreThemeExamplePatterns({
cwd: input,
themesDir,
}),
// Ignore node_modules in the root directory
'node_modules/**',
// only include dotfiles starting with `.vs-`
'**/.!(vs-*)/**',
],
Expand Down Expand Up @@ -552,9 +559,9 @@ export async function buildWebPublication({
);
}
}
} else if (config.viewerInput.type === 'webbook') {
} else if (isWebbookConfig(config)) {
const ret = await retrieveWebbookEntry({
webbookEntryUrl: config.viewerInput.webbookEntryUrl,
viewerInput: config.viewerInput,
outputDir,
});
entryHtmlFile = ret.entryHtmlFile;
Expand Down
36 changes: 19 additions & 17 deletions src/processor/compile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,16 @@ export async function cleanupWorkspace({
entryContextDir,
workspaceDir,
themesDir,
entries,
}: ResolvedTaskConfig) {
if (
pathEquals(workspaceDir, entryContextDir) ||
pathContains(workspaceDir, entryContextDir)
pathContains(workspaceDir, entryContextDir) ||
entries.some(
(entry) =>
entry.source?.type === 'file' &&
pathContains(workspaceDir, entry.source.pathname),
)
) {
return;
}
Expand Down Expand Up @@ -383,24 +389,18 @@ export async function compile(
}
}

export function getDefaultIgnorePatterns({
export function getIgnoreThemeExamplePatterns({
themesDir,
cwd,
}: Pick<ResolvedTaskConfig, 'themesDir'> & {
cwd: string;
}): string[] {
const ignorePatterns = [
// ignore node_modules directory
'**/node_modules',
];
if (pathContains(cwd, themesDir)) {
// ignore example files of theme packages
ignorePatterns.push(
`${upath.relative(cwd, themesDir)}/packages/*/example`,
`${upath.relative(cwd, themesDir)}/packages/*/*/example`,
);
}
return ignorePatterns;
return pathContains(cwd, themesDir)
? [
`${upath.relative(cwd, themesDir)}/node_modules/*/example`,
`${upath.relative(cwd, themesDir)}/node_modules/*/*/example`,
]
: [];
}

export function getIgnoreAssetPatterns({
Expand Down Expand Up @@ -445,16 +445,18 @@ function getAssetMatcherSettings({
...excludes,
...getIgnoreAssetPatterns({ outputs, entries, cwd }),
];
const weakIgnorePatterns = getDefaultIgnorePatterns({ themesDir, cwd });
Logger.debug('globAssetFiles > ignorePatterns', ignorePatterns);
Logger.debug('globAssetFiles > weakIgnorePatterns', weakIgnorePatterns);

return [
// Step 1: Glob files with an extension in `fileExtension`
// Ignore files in node_modules directory, theme example files and files matched `excludes`
{
patterns: fileExtensions.map((ext) => `**/*.${ext}`),
ignore: [...ignorePatterns, ...weakIgnorePatterns],
ignore: [
'**/node_modules/**',
...ignorePatterns,
...getIgnoreThemeExamplePatterns({ themesDir, cwd }),
],
},
// Step 2: Glob files matched with `includes`
// Ignore only files matched `excludes`
Expand Down
18 changes: 0 additions & 18 deletions src/processor/theme.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import Arborist from '@npmcli/arborist';
import fs from 'node:fs';
import npa from 'npm-package-arg';
import { ResolvedTaskConfig } from '../config/resolve.js';
import { DetailError } from '../util.js';

Expand Down Expand Up @@ -60,20 +59,3 @@ export async function installThemeDependencies({
);
}
}

export function parsePackageName(
specifier: string,
cwd: string,
): npa.Result | null {
try {
let result = npa(specifier, cwd);
// #373: Relative path specifiers may be assumed as shorthand of hosted git
// (ex: foo/bar -> github:foo/bar)
if (result.type === 'git' && result.saveSpec?.startsWith('github:')) {
result = npa(`file:${specifier}`, cwd);
}
return result;
} catch (error) {
return null;
}
}
Loading

0 comments on commit b8c375f

Please sign in to comment.