Skip to content

Commit

Permalink
feat: add file context
Browse files Browse the repository at this point in the history
  • Loading branch information
makamekm committed Oct 7, 2024
1 parent 435ae84 commit 3fe32c3
Show file tree
Hide file tree
Showing 9 changed files with 133 additions and 52 deletions.
22 changes: 22 additions & 0 deletions src/transform/fsContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import {readFileSync, writeFileSync} from 'fs';

import {FsContext} from './typings';
import {isFileExists} from './utilsFS';

export class DefaultFsContext implements FsContext {
exist(path: string): boolean {
return isFileExists(path);
}

read(path: string): string {
return readFileSync(path, 'utf8');
}

write(path: string, content: string): void {
writeFileSync(path, content, {
encoding: 'utf8',
});
}
}

export const defaultFsContext = new DefaultFsContext();
7 changes: 4 additions & 3 deletions src/transform/plugins/images/collect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ type Options = MarkdownItPluginOpts & {
const collect = (input: string, options: Options) => {
const md = new MarkdownIt().use(imsize);

const {root, path, destPath = '', copyFile, singlePage} = options;
const {root, path, destPath = '', copyFile, singlePage, deps} = options;
const tokens = md.parse(input, {});
let result = input;

Expand All @@ -40,9 +40,10 @@ const collect = (input: string, options: Options) => {
const targetPath = resolveRelativePath(path, src);
const targetDestPath = resolveRelativePath(destPath, src);

if (singlePage && !path.includes('_includes/')) {
const newSrc = relative(root, resolveRelativePath(path, src));
deps?.markDep?.(path, targetPath, 'image');

if (singlePage && !path.includes('_includes/')) {
const newSrc = relative(root, targetPath);
result = result.replace(src, newSrc);
}

Expand Down
26 changes: 17 additions & 9 deletions src/transform/plugins/images/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,23 @@ import {join, sep} from 'path';
import {bold} from 'chalk';
import {optimize} from 'svgo';
import Token from 'markdown-it/lib/token';
import {readFileSync} from 'fs';

import {isFileExists, resolveRelativePath} from '../../utilsFS';
import {resolveRelativePath} from '../../utilsFS';
import {isExternalHref, isLocalUrl} from '../../utils';
import {MarkdownItPluginCb, MarkdownItPluginOpts} from '../typings';
import {StateCore} from '../../typings';
import {FsContext, StateCore} from '../../typings';
import {defaultFsContext} from '../../fsContext';

interface ImageOpts extends MarkdownItPluginOpts {
assetsPublicPath: string;
inlineSvg?: boolean;
}

function replaceImageSrc(
fs: FsContext,
token: Token,
state: StateCore,
{assetsPublicPath = sep, root = '', path: optsPath, log}: ImageOpts,
{assetsPublicPath = sep, root = '', path: optsPath, log, deps}: ImageOpts,
) {
const src = token.attrGet('src') || '';
const currentPath = state.env.path || optsPath;
Expand All @@ -28,7 +29,9 @@ function replaceImageSrc(

const path = resolveRelativePath(currentPath, src);

if (isFileExists(path)) {
deps?.markDep?.(currentPath, path, 'image');

if (fs.exist(path)) {
state.md.assets?.push(path);
} else {
log.error(`Asset not found: ${bold(src)} in ${bold(currentPath)}`);
Expand All @@ -51,15 +54,18 @@ function prefix() {
}

function convertSvg(
fs: FsContext,
token: Token,
state: StateCore,
{path: optsPath, log, notFoundCb, root}: SVGOpts,
{path: optsPath, log, notFoundCb, root, deps}: SVGOpts,
) {
const currentPath = state.env.path || optsPath;
const path = resolveRelativePath(currentPath, token.attrGet('src') || '');

try {
const raw = readFileSync(path).toString();
deps?.markDep?.(currentPath, path, 'image');

const raw = fs.read(path).toString();
const result = optimize(raw, {
plugins: [
{
Expand Down Expand Up @@ -90,6 +96,8 @@ function convertSvg(
type Opts = SVGOpts & ImageOpts;

const index: MarkdownItPluginCb<Opts> = (md, opts) => {
const fs = opts.fs ?? defaultFsContext;

md.assets = [];

const plugin = (state: StateCore) => {
Expand Down Expand Up @@ -117,9 +125,9 @@ const index: MarkdownItPluginCb<Opts> = (md, opts) => {
const shouldInlineSvg = opts.inlineSvg !== false && !isExternalHref(imgSrc);

if (imgSrc.endsWith('.svg') && shouldInlineSvg) {
childrenTokens[j] = convertSvg(childrenTokens[j], state, opts);
childrenTokens[j] = convertSvg(fs, childrenTokens[j], state, opts);
} else {
replaceImageSrc(childrenTokens[j], state, opts);
replaceImageSrc(fs, childrenTokens[j], state, opts);
}

childrenTokens[j].attrSet('yfm_patched', '1');
Expand Down
10 changes: 7 additions & 3 deletions src/transform/plugins/includes/collect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import {relative} from 'path';
import {bold} from 'chalk';
import {readFileSync} from 'fs';

import {getRelativePath, isFileExists, resolveRelativePath} from '../../utilsFS';
import {getRelativePath, resolveRelativePath} from '../../utilsFS';
import {defaultFsContext} from '../../fsContext';

import {IncludeCollectOpts} from './types';

Expand Down Expand Up @@ -64,7 +65,7 @@ function collectRecursive(
options: IncludeCollectOpts,
appendix: Map<string, string>,
) {
const {root, path, destPath = '', log, singlePage} = options;
const {root, path, destPath = '', log, singlePage, fs = defaultFsContext, deps} = options;

const INCLUDE_REGEXP = /{%\s*include\s*(notitle)?\s*\[(.+?)]\((.+?)\)\s*%}/g;

Expand All @@ -76,7 +77,10 @@ function collectRecursive(

let includePath = resolveRelativePath(path, relativePath);
const hashIndex = relativePath.lastIndexOf('#');
if (hashIndex > -1 && !isFileExists(includePath)) {

deps?.markDep?.(path, includePath, 'include');

if (hashIndex > -1 && !fs.exist(includePath)) {
includePath = includePath.slice(0, includePath.lastIndexOf('#'));
relativePath = relativePath.slice(0, hashIndex);
}
Expand Down
14 changes: 9 additions & 5 deletions src/transform/plugins/includes/index.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import {bold} from 'chalk';
import Token from 'markdown-it/lib/token';

import {StateCore} from '../../typings';
import {
GetFileTokensOpts,
getFileTokens,
getFullIncludePath,
isFileExists,
resolveRelativePath,
} from '../../utilsFS';
import {findBlockTokens} from '../../utils';
import {StateCore} from '../../typings';
import {defaultFsContext} from '../../fsContext';
import {MarkdownItPluginCb, MarkdownItPluginOpts} from '../typings';

import {MarkdownItIncluded} from './types';
Expand All @@ -29,7 +29,7 @@ type Options = MarkdownItPluginOpts &
};

function unfoldIncludes(md: MarkdownItIncluded, state: StateCore, path: string, options: Options) {
const {root, notFoundCb, log, noReplaceInclude = false} = options;
const {root, notFoundCb, log, noReplaceInclude = false, fs = defaultFsContext, deps} = options;
const {tokens} = state;
let i = 0;

Expand Down Expand Up @@ -57,7 +57,11 @@ function unfoldIncludes(md: MarkdownItIncluded, state: StateCore, path: string,
let pathname = fullIncludePath;
let hash = '';
const hashIndex = fullIncludePath.lastIndexOf('#');
if (hashIndex > -1 && !isFileExists(pathname)) {
const existed = fs.exist(pathname);

deps?.markDep?.(path, pathname, 'include');

if (hashIndex > -1 && !existed) {
pathname = fullIncludePath.slice(0, hashIndex);
hash = fullIncludePath.slice(hashIndex + 1);
}
Expand All @@ -68,7 +72,7 @@ function unfoldIncludes(md: MarkdownItIncluded, state: StateCore, path: string,
continue;
}

const fileTokens = getFileTokens(pathname, state, {
const fileTokens = getFileTokens(fs, pathname, state, {
...options,
content: included, // The content forces the function to use it instead of reading from the disk
});
Expand Down
9 changes: 5 additions & 4 deletions src/transform/plugins/links/collect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import url from 'url';

import {PAGE_LINK_REGEXP, getHrefTokenAttr, isLocalUrl} from '../../utils';
import {getSinglePageAnchorId, resolveRelativePath} from '../../utilsFS';
import {MarkdownItPluginOpts} from '../typings';

import index from './index';

Expand All @@ -12,17 +13,15 @@ const replaceLinkHref = (input: string, href: string, newHref: string) => {
return input.replace(`](${href})`, `](${newHref})`);
};

type Options = {
root: string;
path: string;
type Options = MarkdownItPluginOpts & {
singlePage: boolean;
};

/* Replace the links to the markdown and yaml files if the singlePage option is passed in the options
* Example: replace [Text](../../path/to/file.md#anchor) with [Text](#_path_to_file_anchor)
* */
const collect = (input: string, options: Options) => {
const {root, path: startPath, singlePage} = options;
const {root, path: startPath, singlePage, deps} = options;

if (!singlePage) {
return;
Expand Down Expand Up @@ -66,6 +65,8 @@ const collect = (input: string, options: Options) => {
if (pathname) {
const isPageFile = PAGE_LINK_REGEXP.test(pathname);
if (isPageFile) {
deps?.markDep?.(startPath, pathname, 'link');

const newHref = getSinglePageAnchorId({
root,
currentPath: startPath,
Expand Down
22 changes: 15 additions & 7 deletions src/transform/plugins/links/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import url from 'url';
import {bold} from 'chalk';
import Token from 'markdown-it/lib/token';
import path, {isAbsolute, parse, relative, resolve} from 'path';

import {Logger} from 'src/transform/log';
import Token from 'markdown-it/lib/token';

import {
PAGE_LINK_REGEXP,
Expand All @@ -13,8 +11,10 @@ import {
headingInfo,
isLocalUrl,
} from '../../utils';
import {getFileTokens, isFileExists} from '../../utilsFS';
import {CacheContext, StateCore} from '../../typings';
import {getFileTokens} from '../../utilsFS';
import {Logger} from '../../log';
import {CacheContext, FsContext, StateCore} from '../../typings';
import {defaultFsContext} from '../../fsContext';
import {MarkdownItPluginCb, MarkdownItPluginOpts} from '../typings';

function getTitleFromTokens(tokens: Token[]) {
Expand Down Expand Up @@ -49,12 +49,13 @@ type Options = {
currentPath: string;
log: Logger;
cache?: CacheContext;
fs: FsContext;
};

const getTitle = (id: string | null, options: Options) => {
const {file, state, opts} = options;

const fileTokens = getFileTokens(file, state, {
const fileTokens = getFileTokens(options.fs, file, state, {
...opts,
disableLint: true,
disableTitleRefSubstitution: true,
Expand Down Expand Up @@ -121,6 +122,8 @@ function processLink(state: StateCore, tokens: Token[], idx: number, opts: ProcO
log,
getPublicPath = getDefaultPublicPath,
cache,
fs = defaultFsContext,
deps,
} = opts;

const currentPath = state.env.path || startPath;
Expand All @@ -147,9 +150,13 @@ function processLink(state: StateCore, tokens: Token[], idx: number, opts: ProcO

if (pathname) {
file = resolve(path.parse(currentPath).dir, pathname);
fileExists = isFileExists(file);
fileExists = fs.exist(file);
isPageFile = PAGE_LINK_REGEXP.test(pathname);

if (isPageFile) {
deps?.markDep?.(currentPath, file, 'link');
}

if (isPageFile && !fileExists) {
let needShowError = true;
if (needSkipLinkFn) {
Expand Down Expand Up @@ -193,6 +200,7 @@ function processLink(state: StateCore, tokens: Token[], idx: number, opts: ProcO
currentPath,
log,
cache,
fs,
});
}

Expand Down
35 changes: 35 additions & 0 deletions src/transform/typings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,35 @@ export type Heading = {
items?: Heading[];
};

export interface FsContext {
read(path: string | null): string;
exist(path: string | null): boolean;
write(path: string | null, content: string): void;
}

export interface DependencyContext {
resetDeps?(path: string): void;
markDep?(path: string, dependencyPath: string, type?: string): void;
unmarkDep?(path: string, dependencyPath: string, type?: string): void;
}

export interface RevisionMeta {
files: {
[key: string]: {
mod_date: number; // modified_at
dependencies: {
[type: string]: string[];
};
changed: boolean;
};
};
}

export interface RevisionContext {
files: string[];
meta: RevisionMeta;
}

export interface OptionsType {
vars?: Record<string, string>;
path?: string;
Expand Down Expand Up @@ -58,6 +87,9 @@ export interface OptionsType {
getPublicPath?: (options: OptionsType, href?: string) => string;
renderInline?: boolean;
cache?: CacheContext;
context?: RevisionContext;
fs?: FsContext;
deps?: DependencyContext;
[x: string]: unknown;
}

Expand All @@ -84,6 +116,9 @@ export interface MarkdownItPluginOpts {
rootPublicPath: string;
isLintRun: boolean;
cache?: CacheContext;
context?: RevisionContext;
fs?: FsContext;
deps?: DependencyContext;
conditionsInCode?: boolean;
vars?: Record<string, string>;
extractTitle?: boolean;
Expand Down
Loading

0 comments on commit 3fe32c3

Please sign in to comment.