Skip to content

Commit

Permalink
[#54 Computed Fields] (#86)
Browse files Browse the repository at this point in the history
* Computed Fields

* Make configuration optional

* Add changeset for computed fields

* Update changeset
  • Loading branch information
mohamedsalem401 authored Dec 11, 2023
1 parent ac80a1f commit 81f85f6
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 6 deletions.
6 changes: 6 additions & 0 deletions .changeset/flat-bikes-own.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"mddb": minor
---

[#54 Computed Fields]
- Introduce a configuration parameter to support the inclusion of a custom function for computing fields.
37 changes: 34 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,18 +115,49 @@ const blogs = await mddb.getFiles({
});
```

# Configuring `markdowndb.config.js`
## Computed Fields

This feature helps you define functions that compute additional fields you want to include.

### Step 1: Define the Computed Field Function

Next, define a function that computes the additional field you want to include. In this example, we have a function named `addTitle` that extracts the title from the first heading in the AST (Abstract Syntax Tree) of a Markdown file.

```javascript
const addTitle = (fileInfo, ast) => {
// Find the first header node in the AST
const headerNode = ast.children.find((node) => node.type === "heading");

// Extract the text content from the header node
const title = headerNode
? headerNode.children.map((child) => child.value).join("")
: "";

// Add the title property to the fileInfo
fileInfo.title = title;
};
```

### Step 2: Indexing the Folder with Computed Fields

Now, use the `client.indexFolder` method to scan and index the folder containing your Markdown files. Pass the `addTitle` function in the `computedFields` option array to include the computed title in the database.

```javascript
client.indexFolder(folderPath: "PATH_TO_FOLDER", customConfig: { computedFields: [addTitle] });
```

## Configuring `markdowndb.config.js`

- Implement computed fields to dynamically calculate values based on specified logic or dependencies.
- Specify the patterns for including or excluding files in MarkdownDB.

## Example Configuration
### Example Configuration

Here's an example `markdowndb.config.js` with custom configurations:

```javascript
export default {
customFields: [
computedFields: [
(fileInfo, ast) => {
// Your custom logic here
},
Expand Down
6 changes: 6 additions & 0 deletions src/lib/CustomConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { FileInfo } from "./process.js";
import { Root } from "remark-parse/lib/index.js";

export interface CustomConfig {
computedFields?: ((fileInfo: FileInfo, ast: Root) => any)[];
}
6 changes: 5 additions & 1 deletion src/lib/indexFolder.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
import { CustomConfig } from "./CustomConfig.js";
import { FileInfo, processFile } from "./process.js";
import { recursiveWalkDir } from "./recursiveWalkDir.js";

export function indexFolder(
folderPath: string,
pathToUrlResolver: (filePath: string) => string,
config: CustomConfig,
ignorePatterns?: RegExp[]
) {
const filePathsToIndex = recursiveWalkDir(folderPath);
const filteredFilePathsToIndex = filePathsToIndex.filter((filePath) =>
shouldIncludeFile(filePath, ignorePatterns)
);
const files: FileInfo[] = [];
const computedFields = config.computedFields || [];
for (const filePath of filteredFilePathsToIndex) {
const fileObject = processFile(
folderPath,
filePath,
pathToUrlResolver,
filePathsToIndex
filePathsToIndex,
computedFields
);
files.push(fileObject);
}
Expand Down
4 changes: 4 additions & 0 deletions src/lib/markdowndb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
getUniqueValues,
} from "./databaseUtils.js";
import fs from "fs";
import { CustomConfig } from "./CustomConfig.js";

const defaultFilePathToUrl = (filePath: string) => {
let url = filePath
Expand Down Expand Up @@ -72,16 +73,19 @@ export class MarkdownDB {
// TODO support glob patterns
ignorePatterns = [],
pathToUrlResolver = defaultFilePathToUrl,
customConfig = {},
}: {
folderPath: string;
ignorePatterns?: RegExp[];
pathToUrlResolver?: (filePath: string) => string;
customConfig?: CustomConfig;
}) {
await resetDatabaseTables(this.db);

const fileObjects = indexFolder(
folderPath,
pathToUrlResolver,
customConfig,
ignorePatterns
);
const filesToInsert = fileObjects.map(mapFileToInsert);
Expand Down
1 change: 1 addition & 0 deletions src/lib/parseFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export function parseFile(source: string, options?: ParsingOptions) {
metadata.tasks = tasks;

return {
ast,
metadata,
links,
};
Expand Down
10 changes: 8 additions & 2 deletions src/lib/process.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import path from "path";

import { File } from "./schema.js";
import { WikiLink, parseFile } from "./parseFile.js";
import { Root } from "remark-parse/lib/index.js";

export interface FileInfo extends File {
tags: string[];
Expand All @@ -16,7 +17,8 @@ export function processFile(
rootFolder: string,
filePath: string,
pathToUrlResolver: (filePath: string) => string,
filePathsToIndex: string[]
filePathsToIndex: string[],
computedFields: ((fileInfo: FileInfo, ast: Root) => any)[]
) {
// Remove rootFolder from filePath
const relativePath = path.relative(rootFolder, filePath);
Expand Down Expand Up @@ -52,7 +54,7 @@ export function processFile(
flag: "r",
});

const { metadata, links } = parseFile(source, {
const { ast, metadata, links } = parseFile(source, {
from: relativePath,
permalinks: filePathsToIndex,
});
Expand All @@ -66,6 +68,10 @@ export function processFile(

const tags = metadata?.tags || [];
fileInfo.tags = tags;
for (let index = 0; index < computedFields.length; index++) {
const customFieldFunction = computedFields[index];
customFieldFunction(fileInfo, ast);
}

return fileInfo;
}
1 change: 1 addition & 0 deletions src/tests/process.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ describe("Can parse a file and get file info", () => {
pathToContentFixture,
fullPath,
(filePath) => filePath,
[],
[]
);

Expand Down

0 comments on commit 81f85f6

Please sign in to comment.