Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(plugins): Add api wrapper for plugins #306

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
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
13 changes: 11 additions & 2 deletions src/transform/plugins/images/collect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,19 @@ import {isLocalUrl} from '../../utils';
import {resolveRelativePath} from '../../utilsFS';
import imsize from '../imsize';
import {MarkdownItPluginOpts} from '../typings';
import {EnvApi} from '../../yfmlint';

type Options = MarkdownItPluginOpts & {
destPath: string;
copyFile: (path: string, dest: string) => void;
singlePage: boolean;
envApi?: EnvApi;
};

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, envApi} = options;
const tokens = md.parse(input, {});
let result = input;

Expand Down Expand Up @@ -46,7 +48,14 @@ const collect = (input: string, options: Options) => {
result = result.replace(src, newSrc);
}

copyFile(targetPath, targetDestPath);
if (envApi) {
envApi.copyFileAsync(
relative(envApi.root, targetPath),
relative(envApi.distRoot, targetDestPath),
);
} else {
copyFile(targetPath, targetDestPath);
}
});
});

Expand Down
26 changes: 21 additions & 5 deletions src/transform/plugins/images/index.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
import {readFileSync} from 'fs';
import {join, sep} from 'path';
import {join, relative, sep} from 'path';
import {bold} from 'chalk';

import {resolveRelativePath, isFileExists} from '../../utilsFS';
import {isLocalUrl, isExternalHref} from '../../utils';
import Token from 'markdown-it/lib/token';
import {MarkdownItPluginCb, MarkdownItPluginOpts} from '../typings';
import {StateCore} from '../../typings';
import {EnvApi} from '../../yfmlint';

interface ImageOpts extends MarkdownItPluginOpts {
assetsPublicPath: string;
envApi?: EnvApi;
}

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

const path = resolveRelativePath(currentPath, src);

if (isFileExists(path)) {
let pathExists: boolean;
if (envApi) {
pathExists = envApi.fileExists(relative(envApi.root, path));
} else {
pathExists = isFileExists(path);
}

if (pathExists) {
state.md.assets?.push(path);
} else {
log.error(`Asset not found: ${bold(src)} in ${bold(currentPath)}`);
Expand All @@ -40,18 +49,25 @@ function replaceImageSrc(

interface SVGOpts extends MarkdownItPluginOpts {
notFoundCb: (s: string) => void;
envApi?: EnvApi;
}

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

try {
const content = readFileSync(path, 'utf8');
let content: string;
if (envApi) {
content = envApi?.readFile(relative(root, path), 'utf8') as string;
} else {
content = readFileSync(path, 'utf8');
}

const svgToken = new state.Token('image_svg', '', 0);
svgToken.attrSet('content', content);

Expand Down
20 changes: 16 additions & 4 deletions src/transform/plugins/includes/collect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,19 @@ import {bold} from 'chalk';

import {isFileExists, resolveRelativePath} from '../../utilsFS';
import {MarkdownItPluginOpts} from '../typings';
import {EnvApi} from '../../yfmlint';

const includesPaths: string[] = [];

type Opts = MarkdownItPluginOpts & {
destPath: string;
copyFile(path: string, dest: string, opts: Opts): void;
singlePage: Boolean;
envApi?: EnvApi;
};

const collect = (input: string, options: Opts) => {
const {root, path, destPath = '', log, copyFile, singlePage} = options;
const {root, path, destPath = '', log, copyFile, singlePage, envApi} = options;
const INCLUDE_REGEXP = /{%\s*include\s*(notitle)?\s*\[(.+?)]\((.+?)\)\s*%}/g;

let match,
Expand All @@ -25,9 +27,19 @@ const collect = (input: string, options: Opts) => {

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

if (hashIndex > -1) {
let includePathExists: boolean;
if (envApi) {
includePathExists = envApi.fileExists(relative(envApi.root, includePath));
} else {
includePathExists = isFileExists(includePath);
}

if (!includePathExists) {
includePath = includePath.slice(0, includePath.lastIndexOf('#'));
relativePath = relativePath.slice(0, hashIndex);
}
}

const targetDestPath = resolveRelativePath(destPath, relativePath);
Expand Down
21 changes: 17 additions & 4 deletions src/transform/plugins/includes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import {findBlockTokens} from '../../utils';
import Token from 'markdown-it/lib/token';
import {MarkdownItPluginCb, MarkdownItPluginOpts} from '../typings';
import {StateCore} from 'src/transform/typings';
import {EnvApi} from '../../yfmlint';
import {relative} from 'path';

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

Expand All @@ -18,10 +20,11 @@ type Options = MarkdownItPluginOpts &
GetFileTokensOpts & {
notFoundCb: (v: string) => void;
noReplaceInclude: boolean;
envApi?: EnvApi;
};

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

Expand All @@ -44,9 +47,19 @@ function unfoldIncludes(state: StateCore, path: string, options: Options) {
let pathname = fullIncludePath;
let hash = '';
const hashIndex = fullIncludePath.lastIndexOf('#');
if (hashIndex > -1 && !isFileExists(pathname)) {
pathname = fullIncludePath.slice(0, hashIndex);
hash = fullIncludePath.slice(hashIndex + 1);

if (hashIndex > -1) {
let pathnameExists: boolean;
if (envApi) {
pathnameExists = envApi.fileExists(relative(envApi.root, pathname));
} else {
pathnameExists = isFileExists(pathname);
}

if (!pathnameExists) {
pathname = fullIncludePath.slice(0, hashIndex);
hash = fullIncludePath.slice(hashIndex + 1);
}
}

if (!pathname.startsWith(root)) {
Expand Down
13 changes: 11 additions & 2 deletions src/transform/plugins/links/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {Logger} from 'src/transform/log';
import {MarkdownItPluginCb, MarkdownItPluginOpts} from '../typings';
import path, {isAbsolute, parse, relative, resolve} from 'path';
import {StateCore} from 'src/transform/typings';
import {EnvApi} from '../../yfmlint';

function defaultTransformLink(href: string) {
const parsed = url.parse(href);
Expand Down Expand Up @@ -49,6 +50,7 @@ type Options = {
href: string;
currentPath: string;
log: Logger;
envApi?: EnvApi;
};

const addTitle = (options: Options) => {
Expand Down Expand Up @@ -86,11 +88,12 @@ interface ProcOpts extends MarkdownItPluginOpts {
transformLink: (v: string) => string;
notFoundCb: (v: string) => void;
needSkipLinkFn: (v: string) => boolean;
envApi?: EnvApi;
}

// eslint-disable-next-line complexity
function processLink(state: StateCore, tokens: Token[], idx: number, opts: ProcOpts) {
const {path: startPath, root, transformLink, notFoundCb, needSkipLinkFn, log} = opts;
const {path: startPath, root, transformLink, notFoundCb, needSkipLinkFn, log, envApi} = opts;
const currentPath = state.env.path || startPath;
const linkToken = tokens[idx];
const nextToken = tokens[idx + 1];
Expand All @@ -115,7 +118,13 @@ function processLink(state: StateCore, tokens: Token[], idx: number, opts: ProcO

if (pathname) {
file = resolve(path.parse(currentPath).dir, pathname);
fileExists = isFileExists(file);

if (envApi) {
fileExists = envApi.fileExists(relative(envApi.root, file));
} else {
fileExists = isFileExists(file);
}

isPageFile = PAGE_LINK_REGEXP.test(pathname);

if (isPageFile && !fileExists) {
Expand Down
16 changes: 13 additions & 3 deletions src/transform/utilsFS.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import _, {Dictionary} from 'lodash';
import {readFileSync, statSync} from 'fs';

import {parse, resolve, join, sep} from 'path';
import {parse, resolve, join, sep, relative} from 'path';

import liquid from './liquid';
import {StateCore} from './typings';
import {EnvApi} from './yfmlint';

const filesCache: Record<string, string> = {};

Expand Down Expand Up @@ -34,6 +35,7 @@ export type GetFileTokensOpts = {
disableCircularError?: boolean;
inheritVars?: boolean;
conditionsInCode?: boolean;
envApi?: EnvApi;
};

export function getFileTokens(path: string, state: StateCore, options: GetFileTokensOpts) {
Expand All @@ -47,12 +49,20 @@ export function getFileTokens(path: string, state: StateCore, options: GetFileTo
disableCircularError,
inheritVars = true,
conditionsInCode,
envApi,
} = options;
let content;

const builtVars = (getVarsPerFile && !inheritVars ? getVarsPerFile(path) : vars) || {};
let builtVars;
if (envApi) {
builtVars = (inheritVars ? vars : envApi.getFileVars(relative(envApi.root, path))) || {};
} else {
builtVars = (getVarsPerFile && !inheritVars ? getVarsPerFile(path) : vars) || {};
}

if (filesCache[path]) {
if (envApi) {
content = envApi.readFile(relative(envApi.root, path), 'utf-8') as string;
} else if (filesCache[path]) {
content = filesCache[path];
} else {
content = readFileSync(path, 'utf8');
Expand Down
13 changes: 13 additions & 0 deletions src/transform/yfmlint/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,25 @@ namespace yfmlint {
sourceMap?: Dictionary<string>;
}

export interface EnvApi {
root: string;
distRoot: string;
copyFile: (from: string, to: string) => void;
copyFileAsync: (from: string, to: string) => void;
writeFile: (to: string, data: string | Uint8Array) => void;
writeFileAsync: (to: string, data: string | Uint8Array) => void;
readFile: (path: string, encoding: BufferEncoding) => string | Uint8Array;
fileExists: (path: string) => boolean;
getFileVars: (path: string) => Record<string, string>;
}

export interface PluginOptions {
log: Logger;
path?: string;
disableLint?: boolean;
lintMarkdown?: (opts: LintMarkdownFunctionOptions) => void;
[key: string]: unknown;
envApi?: EnvApi;
}

export interface LintConfig {
Expand Down
Loading