Skip to content

Commit

Permalink
Merge pull request #43 from irskep/bugfix/path-separators
Browse files Browse the repository at this point in the history
Be rigorous about different kinds of paths
  • Loading branch information
irskep authored Sep 4, 2024
2 parents 18bd7fb + b2d1974 commit f0b5e56
Show file tree
Hide file tree
Showing 19 changed files with 202 additions and 132 deletions.
6 changes: 3 additions & 3 deletions docs/out/gfm/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
-->
- [Changelog](./changelog.md#Changelog)
- [0.2](./changelog.md#0-2)
- [0.3.3 - 2024-09-03](./changelog.md#0-3-3---2024-09-03)
- [0.2.3 - 2024-09-03](./changelog.md#0-2-3---2024-09-03)
- [0.2.2 - 2024-09-03](./changelog.md#0-2-2---2024-09-03)
- [0.2.1 - 2024-09-03](./changelog.md#0-2-1---2024-09-03)
- [0.2.0 - 2024-09-03](./changelog.md#0-2-0---2024-09-03)
Expand All @@ -22,9 +22,9 @@

## 0.2

<div id="0-3-3---2024-09-03" class="section" id="0-3-3---2024-09-03">
<div id="0-2-3---2024-09-03" class="section" id="0-2-3---2024-09-03">

### 0.3.3 - 2024-09-03
### 0.2.3 - 2024-09-03

- Search box can be dismissed by clicking anywhere in the backdrop and
not just by pressing Esc
Expand Down
11 changes: 6 additions & 5 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
import { getExtensionForInputFormat } from "./input/fileExtensions.js";
import { getIsPandocInstalled } from "./pandoc.js";
import { log } from "./utils/logUtils.js";
import { fsjoin } from "./utils/pathUtils.js";

export function getNeedsPandoc(fmt: DjockeyInputFormat): boolean {
return fmt !== "djot";
Expand Down Expand Up @@ -62,7 +63,7 @@ export function readConfig(path_: string): DjockeyConfig {

function absify(rootPath: string, path_: string): string {
if (path.isAbsolute(path_)) return path_;
return `${rootPath}/${path_}`;
return fsjoin([rootPath, path_]);
}

export function resolveConfig(
Expand Down Expand Up @@ -95,9 +96,9 @@ export function resolveConfig(
gfm: absify(rootPath, config.output_dir.gfm),
},
fileList: fastGlob.sync(
`${absify(rootPath, config.input_dir)}/**/*.(${inputExtensions.join(
"|"
)})`
`${fastGlob.convertPathToPattern(
absify(rootPath, config.input_dir)
)}/**/*.(${inputExtensions.join("|")})`
),
};

Expand All @@ -119,7 +120,7 @@ export function resolveConfigFromDirectory(
path_: string,
isLocal: boolean
): DjockeyConfigResolved | null {
const configPath = `${path_}/djockey.yaml`;
const configPath = fsjoin([path_, "djockey.yaml"]);
if (fs.existsSync(configPath)) {
return resolveConfig(path.resolve(path_), readConfig(configPath), isLocal);
} else {
Expand Down
6 changes: 2 additions & 4 deletions src/engine/docset.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { AstNode, HasAttributes } from "@djot/djot";
import {
DjockeyConfigResolved,
DjockeyDoc,
Expand All @@ -8,7 +7,6 @@ import {
} from "../types.js";
import { LogCollector } from "../utils/logUtils.js";
import { DocTree } from "./doctree.js";
import { getHasClass } from "../utils/djotUtils.js";

export class DocSet {
public tree: DocTree | null = null;
Expand Down Expand Up @@ -36,8 +34,8 @@ export class DocSet {
.flatMap((list) => list);
}

public getDoc(relativePath: string): DjockeyDoc | null {
return this.docs.find((d) => d.relativePath === relativePath) || null;
public getDoc(refPath: string): DjockeyDoc | null {
return this.docs.find((d) => d.refPath === refPath) || null;
}

public async runPasses(logCollector: LogCollector) {
Expand Down
64 changes: 35 additions & 29 deletions src/engine/doctree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,16 @@ import { DjockeyDoc } from "../types.js";
import { CustomSortValue } from "./customSortValue.js";
import { Inline } from "@djot/djot";
import { djotASTToText } from "../utils/djotUtils.js";
import {
CANONICAL_SEPARATOR,
refjoin,
refname,
refsplit,
} from "../utils/pathUtils.js";

export type DocTreeSection = {
title: Inline[];
relativePath: string;
refPath: string;
selfDoc: DjockeyDoc | null;
selfDocHasContent: boolean;
children: DocTreeSection[];
Expand All @@ -24,33 +30,33 @@ export function loadDocTree(docs: DjockeyDoc[]): DocTree {

const root: DocTreeSection = {
title: [],
relativePath: "",
refPath: "",
selfDoc: null,
selfDocHasContent: false,
children: [],
docs: [],
};
const sectionsByRelativePath: Record<string, DocTreeSection> = {};
const sectionsByRefPath: Record<string, DocTreeSection> = {};

function ensureDirCreated(relativePath: string): DocTreeSection {
if (sectionsByRelativePath[relativePath]) {
return sectionsByRelativePath[relativePath];
function ensureSectionCreated(refPath: string): DocTreeSection {
if (sectionsByRefPath[refPath]) {
return sectionsByRefPath[refPath];
}

const newSection: DocTreeSection = {
title: [{ tag: "str", text: path.parse(relativePath).name }],
relativePath,
title: [{ tag: "str", text: refname(refPath) }],
refPath,
selfDoc: null,
selfDocHasContent: false,
children: [],
docs: [],
};
sectionsByRelativePath[relativePath] = newSection;
sectionsByRefPath[refPath] = newSection;

const parts = relativePath.split("/");
const parts = refsplit(refPath);
if (parts.length > 1) {
const parent = parts.slice(0, parts.length - 1).join("/");
const parentSection = sectionsByRelativePath[parent];
const parent = refjoin(parts.slice(0, parts.length - 1));
const parentSection = sectionsByRefPath[parent];
parentSection.children.push(newSection);
} else {
root.children.push(newSection);
Expand All @@ -60,13 +66,13 @@ export function loadDocTree(docs: DjockeyDoc[]): DocTree {
}

for (const doc of docs) {
const dirs = getDirs(doc.relativePath);
for (const dir of dirs) {
ensureDirCreated(dir);
const refDirs = getRefDirs(doc.refPath);
for (const dir of refDirs) {
ensureSectionCreated(dir);
}

const docSection = dirs.length
? sectionsByRelativePath[dirs[dirs.length - 1]]
const docSection = refDirs.length
? sectionsByRefPath[refDirs[refDirs.length - 1]]
: root;

if (path.parse(doc.filename).name === "index") {
Expand Down Expand Up @@ -138,9 +144,9 @@ export function connectNextAndPrevious(
let lastDoc = lastDoc_;

function processDoc(doc: DjockeyDoc) {
prevMap[doc.relativePath] = lastDoc?.relativePath || null;
nextMap[doc.relativePath] = null; // will be overwritten shortly
if (lastDoc) nextMap[lastDoc.relativePath] = doc.relativePath;
prevMap[doc.refPath] = lastDoc?.refPath || null;
nextMap[doc.refPath] = null; // will be overwritten shortly
if (lastDoc) nextMap[lastDoc.refPath] = doc.refPath;
lastDoc = doc;
}

Expand All @@ -165,11 +171,11 @@ export function connectNextAndPrevious(
* @param path_
* @returns
*/
function getDirs(path_: string): string[] {
const parts = path_.split("/");
function getRefDirs(refPath: string): string[] {
const parts = refsplit(refPath);
const result = new Array<string>();
for (let i = 1; i < parts.length; i++) {
result.push(parts.slice(0, i).join("/"));
result.push(refjoin(parts.slice(0, i)));
}
return result;
}
Expand All @@ -187,13 +193,13 @@ function sortDocsByPathWithFilesBeforeDirectories(
if (result !== 0) return result; // otherwise break the tie
}

const a = docA.relativePath;
const b = docB.relativePath;
const partsA = a.split("/");
const partsB = b.split("/");
const a = docA.refPath;
const b = docB.refPath;
const partsA = a.split(CANONICAL_SEPARATOR);
const partsB = b.split(CANONICAL_SEPARATOR);

const aDir = partsA.slice(0, partsA.length - 1).join("/");
const bDir = partsB.slice(0, partsB.length - 1).join("/");
const aDir = partsA.slice(0, partsA.length - 1).join(CANONICAL_SEPARATOR);
const bDir = partsB.slice(0, partsB.length - 1).join(CANONICAL_SEPARATOR);

if (aDir === bDir) {
const aName = path.parse(a).name;
Expand Down
6 changes: 3 additions & 3 deletions src/engine/populateDocTreeDoc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export function populateNextOrPreviousLinkDoc(
map: Record<string, string | null> | null
) {
if (!map) return null;
const relativePath = map[doc.relativePath];
const relativePath = map[doc.refPath];
if (!relativePath) return null;

const destDoc = docSet.getDoc(relativePath);
Expand Down Expand Up @@ -79,10 +79,10 @@ function renderSection(
children: structuredClone(doc.titleAST),
destination: renderer.transformLink({
config,
sourcePath: activeDoc.relativePath,
sourcePath: activeDoc.refPath,
anchorWithoutHash: null,
docOriginalExtension: doc.originalExtension,
docRelativePath: doc.relativePath,
docRefPath: doc.refPath,
isLinkToStaticFile: false,
logCollector: logCollector,
}),
Expand Down
4 changes: 4 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
/**
* In practice, this file is where we list every type that shows up in TypeDoc.
*/

export {
DjockeyDoc,
DjockeyInputFormat,
Expand Down
26 changes: 14 additions & 12 deletions src/input/parseDjot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { DjockeyDoc } from "../types.js";
import { getPandocAST } from "../pandoc.js";
import { getInputFormatForFileExtension } from "./fileExtensions.js";
import { LogCollector } from "../utils/logUtils.js";
import { fsext, fsname, fssplit, refjoin } from "../utils/pathUtils.js";

function removeExtensionFromPath(path_: string): string {
return path_.slice(0, path_.length - path.parse(path_).ext.length);
Expand All @@ -32,42 +33,43 @@ export function parseFrontmatter(text: string): {

export async function parseDjot(
inputRoot: string,
absolutePath: string,
fsPath: string,
logCollector: LogCollector
): Promise<DjockeyDoc | null> {
const relativePath = path.relative(inputRoot, absolutePath);
const { text, frontMatter } = parseFrontmatter(
fs.readFileSync(absolutePath, "utf8")
fs.readFileSync(fsPath, "utf8")
);

let djotDoc: Doc | undefined;

switch (getInputFormatForFileExtension(path.parse(absolutePath).ext)) {
switch (getInputFormatForFileExtension(fsext(fsPath))) {
case "djot":
djotDoc = parse(text, {
sourcePositions: true,
warn: (warning) => logCollector.warning(warning.render()),
});
break;
case "gfm":
const ast = getPandocAST(absolutePath);
const ast = getPandocAST(fsPath);
djotDoc = fromPandoc(ast as any);
break;
}

if (!djotDoc) {
logCollector.error(`Couldn't figure out how to parse ${absolutePath}`);
logCollector.error(`Couldn't figure out how to parse ${fsPath}`);
return null;
}

return {
docs: { content: djotDoc },
title: path.parse(relativePath).name,
titleAST: [{ tag: "str", text: path.parse(relativePath).name }],
originalExtension: path.parse(relativePath).ext,
absolutePath,
relativePath: removeExtensionFromPath(relativePath),
filename: basename(absolutePath),
title: path.parse(fsPath).name,
titleAST: [{ tag: "str", text: fsname(fsPath) }],
originalExtension: fsext(fsPath),
fsPath,
refPath: refjoin(
fssplit(removeExtensionFromPath(path.relative(inputRoot, fsPath)))
),
filename: basename(fsPath),
frontMatter,
data: {},
};
Expand Down
4 changes: 2 additions & 2 deletions src/pandoc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ export function getIsPandocInstalled(): boolean {
return result.status === 0;
}

export function getPandocAST(path_: string): unknown {
export function getPandocAST(fsPath: string): unknown {
const result = spawnSync(
"pandoc",
[path.resolve(path_), "-f", "gfm", "-t", "json"],
[path.resolve(fsPath), "-f", "gfm", "-t", "json"],
{
encoding: "utf-8",
}
Expand Down
8 changes: 4 additions & 4 deletions src/plugins/autoTitlePlugin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ test("Title is set to first heading by default", () => {
title: "Test doc",
titleAST: [{ tag: "str", text: "Test doc" }],
originalExtension: ".dj",
absolutePath: "Test Doc.dj",
relativePath: "Test Doc.dj",
fsPath: "Test Doc.dj",
refPath: "Test Doc.dj",
filename: "Test Doc",
frontMatter: {},
data: {},
Expand Down Expand Up @@ -63,8 +63,8 @@ test("Title is set to frontMatter.title if present", () => {
title: "Test doc",
titleAST: [{ tag: "str", text: "Test doc" }],
originalExtension: ".dj",
absolutePath: "Test Doc.dj",
relativePath: "Test Doc.dj",
fsPath: "Test Doc.dj",
refPath: "Test Doc.dj",
filename: "Test Doc",
frontMatter: { title: "Custom title" },
data: {},
Expand Down
4 changes: 2 additions & 2 deletions src/plugins/gfmAlertsPlugin.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { DjockeyDoc, DjockeyPlugin } from "../types.js";
import { applyFilter } from "../engine/djotFiltersPlus.js";
import { djotASTToText, getHasClass } from "../utils/djotUtils.js";
import { AstNode, Block } from "@djot/djot";
import { getHasClass } from "../utils/djotUtils.js";
import { AstNode } from "@djot/djot";

// These happen to correspond to Djockey's 'aside' classes, so we're just going
// to replace the 'div' tag with the 'aside' tag and remove the starting paragraph.
Expand Down
Loading

0 comments on commit f0b5e56

Please sign in to comment.