astro-relatinator 2.0.1 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -7
- package/integration.ts +25 -11
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -47,35 +47,42 @@ export default defineConfig({
|
|
|
47
47
|
|
|
48
48
|
## Usage
|
|
49
49
|
|
|
50
|
-
The integration hooks into the Astro build (or dev) process, and will train the model based on the files you've provided. You can then use the
|
|
50
|
+
The integration hooks into the Astro build (or dev) process, and will train the model based on the files you've provided. You can then use the utility functions exported by the package (`BM25Utils` or `TfIdfUtils`, depending on your chosen `similarityMethod`) to find related content and terms.
|
|
51
51
|
|
|
52
52
|
### Example:
|
|
53
53
|
|
|
54
54
|
```astro
|
|
55
55
|
---
|
|
56
56
|
import { getCollection } from "astro:content";
|
|
57
|
-
|
|
57
|
+
// Import the utils corresponding to your configured similarityMethod
|
|
58
|
+
// (BM25Utils in this example, matching the config example above)
|
|
59
|
+
import { BM25Utils } from "astro-relatinator";
|
|
58
60
|
|
|
59
61
|
const blogEntries = await getCollection("posts"); // assuming your collection is called posts
|
|
60
62
|
// let's say we want to compare against the first blog entry
|
|
61
63
|
const first = blogEntries[0];
|
|
62
64
|
|
|
63
65
|
// Concatenate the same fields we used for training and declare how many related posts we want to find
|
|
64
|
-
const related = findRelated(`${first.
|
|
66
|
+
const related = await BM25Utils.findRelated(`${first.data.title} ${first.data.description} ${first.data.tags.join(' ')} ${first.body}`, first.id, 3)
|
|
65
67
|
|
|
66
68
|
---
|
|
67
69
|
|
|
68
70
|
<div>
|
|
69
71
|
<!-- render your related posts here -->
|
|
70
72
|
{ related.map((id) => {
|
|
71
|
-
const post =
|
|
73
|
+
const post = blogEntries.find((post) => post.id === id);
|
|
74
|
+
if (!post) return null; // Handle case where post might not be found
|
|
72
75
|
return (
|
|
73
|
-
<a href={post.slug}>
|
|
74
|
-
<h2>{post.
|
|
75
|
-
<p>{post.
|
|
76
|
+
<a href={`/posts/${post.slug}/`}> {/* Adjust href based on your routing */}
|
|
77
|
+
<h2>{post.data.title}</h2>
|
|
78
|
+
<p>{post.data.description}</p>
|
|
76
79
|
</a>
|
|
77
80
|
);
|
|
78
81
|
}) }
|
|
79
82
|
</div>
|
|
80
83
|
|
|
81
84
|
```
|
|
85
|
+
|
|
86
|
+
**Note:** The `BM25Utils` and `TfIdfUtils` objects also provide `getTopTermsForId` and `getTopRelatedDocumentsForTerm` functions, similar to the core `relatinator` library.
|
|
87
|
+
|
|
88
|
+
**Development Server:** When running `astro dev`, the integration uses debouncing (a small delay) before re-training the model after a markdown file change. This improves performance for larger sites by preventing rapid, successive re-trains during saves.
|
package/integration.ts
CHANGED
|
@@ -101,6 +101,8 @@ const relatinatorIntegration = ({
|
|
|
101
101
|
name: "astro-relatinator",
|
|
102
102
|
hooks: {
|
|
103
103
|
"astro:server:setup": async ({ server, logger }) => {
|
|
104
|
+
let debounceTimeout: NodeJS.Timeout | null = null;
|
|
105
|
+
const debounceMs = 500; // Debounce delay in milliseconds
|
|
104
106
|
logger.info("relatinator server:setup");
|
|
105
107
|
|
|
106
108
|
logger.info(
|
|
@@ -114,23 +116,35 @@ const relatinatorIntegration = ({
|
|
|
114
116
|
await trainModel(similarityMethod, paths, schema, debug);
|
|
115
117
|
logger.info("Initial training done.");
|
|
116
118
|
|
|
117
|
-
server.watcher.on("all",
|
|
119
|
+
server.watcher.on("all", (eventName, filePath) => {
|
|
118
120
|
if (!["add", "change"].includes(eventName)) {
|
|
119
121
|
return;
|
|
120
122
|
}
|
|
121
123
|
|
|
122
124
|
if (path.extname(filePath).includes("md")) {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
if (similarityMethod === "tfidf") {
|
|
127
|
-
await TfIdfUtils.getInstance();
|
|
128
|
-
} else {
|
|
129
|
-
await BM25Utils.getInstance();
|
|
125
|
+
// Clear existing timer if there is one
|
|
126
|
+
if (debounceTimeout) {
|
|
127
|
+
clearTimeout(debounceTimeout);
|
|
130
128
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
129
|
+
|
|
130
|
+
// Set a new timer
|
|
131
|
+
debounceTimeout = setTimeout(async () => {
|
|
132
|
+
logger.info(
|
|
133
|
+
`Debounced: Markdown file changed: ${filePath}; Re-training ${similarityMethod}...`
|
|
134
|
+
);
|
|
135
|
+
try {
|
|
136
|
+
// Reset the instance before re-training
|
|
137
|
+
if (similarityMethod === "tfidf") {
|
|
138
|
+
await TfIdfUtils.resetInstance();
|
|
139
|
+
} else {
|
|
140
|
+
await BM25Utils.resetInstance();
|
|
141
|
+
}
|
|
142
|
+
await trainModel(similarityMethod, paths, schema, debug);
|
|
143
|
+
logger.info("Debounced re-training complete.");
|
|
144
|
+
} catch (error) {
|
|
145
|
+
logger.error(`Error during debounced re-training: ${error}`);
|
|
146
|
+
}
|
|
147
|
+
}, debounceMs);
|
|
134
148
|
}
|
|
135
149
|
});
|
|
136
150
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "astro-relatinator",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Find related content in your Astro website or app",
|
|
5
5
|
"author": "Darko Bozhinovski <dbozhinovski@gmail.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"glob": "^11.0.1",
|
|
38
38
|
"gray-matter": "^4.0.3",
|
|
39
|
-
"relatinator": "2.0
|
|
39
|
+
"relatinator": "2.1.0"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
42
|
"astro": ">=5"
|