@llm-newsletter-kit/core 1.3.1 → 1.3.2
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 +4 -2
- package/dist/index.cjs +28 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +28 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -83,6 +83,8 @@ const config: GenerateNewsletterConfig<string> = {
|
|
|
83
83
|
contentOptions: {
|
|
84
84
|
outputLanguage: 'English',
|
|
85
85
|
expertField: ['Technology', 'AI'],
|
|
86
|
+
// freeFormIntro: true, // Optional: free-form briefing intro
|
|
87
|
+
// titleContext: 'AI Weekly', // Optional: keyword to include in title
|
|
86
88
|
},
|
|
87
89
|
dateService: {
|
|
88
90
|
getCurrentISODateString: () => new Date().toISOString().split('T')[0],
|
|
@@ -93,7 +95,7 @@ const config: GenerateNewsletterConfig<string> = {
|
|
|
93
95
|
end: async () => {},
|
|
94
96
|
},
|
|
95
97
|
crawlingProvider: {
|
|
96
|
-
//
|
|
98
|
+
// customFetch: myProxyFetch, // Optional: custom fetch for proxy support
|
|
97
99
|
crawlingTargetGroups: [/* ... */],
|
|
98
100
|
fetchExistingArticlesByUrls: async (urls) => [/* ... */],
|
|
99
101
|
saveCrawledArticles: async (articles, context) => articles.length,
|
|
@@ -141,7 +143,7 @@ Entry point: `src/index.ts`
|
|
|
141
143
|
- generate(): Promise<string | number | null>
|
|
142
144
|
- Main Types
|
|
143
145
|
- TaskService<TaskId> { start(): Promise<TaskId>; end(): Promise<void> }
|
|
144
|
-
- CrawlingProvider { crawlingTargetGroups, fetchExistingArticlesByUrls, saveCrawledArticles, ... }
|
|
146
|
+
- CrawlingProvider { crawlingTargetGroups, customFetch?, fetchExistingArticlesByUrls, saveCrawledArticles, ... }
|
|
145
147
|
- AnalysisProvider { classifyTagOptions.model, analyzeImagesOptions.model, determineScoreOptions(model, minimumImportanceScoreRules), fetchUnscoredArticles, fetchTags, update }
|
|
146
148
|
- ContentGenerateProvider { model and generation options, issueOrder, publicationCriteria, subscribePageUrl, newsletterBrandName, fetchArticleCandidates, htmlTemplate, saveNewsletter }
|
|
147
149
|
- GenerateNewsletterOptions { logger, llm, chain, previewNewsletter(emailService/emailMessage/fetchNewsletterForPreview) }
|
package/dist/index.cjs
CHANGED
|
@@ -94,6 +94,33 @@ class LoggingExecutor {
|
|
|
94
94
|
const ensureStringArray = (value) => {
|
|
95
95
|
return typeof value === 'string' ? [value] : value;
|
|
96
96
|
};
|
|
97
|
+
const isBrTag = (value) => /^<br\s*\/?>$/i.test(value);
|
|
98
|
+
const ensureHrBeforeH2 = (markdown) => {
|
|
99
|
+
const lines = markdown.split('\n');
|
|
100
|
+
const result = [];
|
|
101
|
+
let hasContentBefore = false;
|
|
102
|
+
for (const line of lines) {
|
|
103
|
+
const trimmed = line.trim();
|
|
104
|
+
if (line.startsWith('## ') && hasContentBefore) {
|
|
105
|
+
let alreadyHasHr = false;
|
|
106
|
+
for (let i = result.length - 1; i >= 0; i--) {
|
|
107
|
+
const prev = result[i].trim();
|
|
108
|
+
if (prev !== '' && !isBrTag(prev)) {
|
|
109
|
+
alreadyHasHr = prev === '---';
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (!alreadyHasHr) {
|
|
114
|
+
result.push('---');
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
else if (trimmed !== '' && trimmed !== '---' && !isBrTag(trimmed)) {
|
|
118
|
+
hasContentBefore = true;
|
|
119
|
+
}
|
|
120
|
+
result.push(line);
|
|
121
|
+
}
|
|
122
|
+
return result.join('\n');
|
|
123
|
+
};
|
|
97
124
|
|
|
98
125
|
class BaseLLMQuery {
|
|
99
126
|
model;
|
|
@@ -1215,7 +1242,7 @@ class ContentGenerateChain extends Chain {
|
|
|
1215
1242
|
}
|
|
1216
1243
|
return this.htmlTemplate.html
|
|
1217
1244
|
.replaceAll(`{{${this.htmlTemplate.markers.title}}}`, coreContent.title)
|
|
1218
|
-
.replaceAll(`{{${this.htmlTemplate.markers.content}}}`, safeMarkdown2Html(coreContent.content, {
|
|
1245
|
+
.replaceAll(`{{${this.htmlTemplate.markers.content}}}`, safeMarkdown2Html(ensureHrBeforeH2(coreContent.content), {
|
|
1219
1246
|
window: new jsdom.JSDOM('').window,
|
|
1220
1247
|
linkTargetBlank: true,
|
|
1221
1248
|
fixMalformedUrls: true,
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/index.js
CHANGED
|
@@ -92,6 +92,33 @@ class LoggingExecutor {
|
|
|
92
92
|
const ensureStringArray = (value) => {
|
|
93
93
|
return typeof value === 'string' ? [value] : value;
|
|
94
94
|
};
|
|
95
|
+
const isBrTag = (value) => /^<br\s*\/?>$/i.test(value);
|
|
96
|
+
const ensureHrBeforeH2 = (markdown) => {
|
|
97
|
+
const lines = markdown.split('\n');
|
|
98
|
+
const result = [];
|
|
99
|
+
let hasContentBefore = false;
|
|
100
|
+
for (const line of lines) {
|
|
101
|
+
const trimmed = line.trim();
|
|
102
|
+
if (line.startsWith('## ') && hasContentBefore) {
|
|
103
|
+
let alreadyHasHr = false;
|
|
104
|
+
for (let i = result.length - 1; i >= 0; i--) {
|
|
105
|
+
const prev = result[i].trim();
|
|
106
|
+
if (prev !== '' && !isBrTag(prev)) {
|
|
107
|
+
alreadyHasHr = prev === '---';
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
if (!alreadyHasHr) {
|
|
112
|
+
result.push('---');
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
else if (trimmed !== '' && trimmed !== '---' && !isBrTag(trimmed)) {
|
|
116
|
+
hasContentBefore = true;
|
|
117
|
+
}
|
|
118
|
+
result.push(line);
|
|
119
|
+
}
|
|
120
|
+
return result.join('\n');
|
|
121
|
+
};
|
|
95
122
|
|
|
96
123
|
class BaseLLMQuery {
|
|
97
124
|
model;
|
|
@@ -1213,7 +1240,7 @@ class ContentGenerateChain extends Chain {
|
|
|
1213
1240
|
}
|
|
1214
1241
|
return this.htmlTemplate.html
|
|
1215
1242
|
.replaceAll(`{{${this.htmlTemplate.markers.title}}}`, coreContent.title)
|
|
1216
|
-
.replaceAll(`{{${this.htmlTemplate.markers.content}}}`, safeMarkdown2Html(coreContent.content, {
|
|
1243
|
+
.replaceAll(`{{${this.htmlTemplate.markers.content}}}`, safeMarkdown2Html(ensureHrBeforeH2(coreContent.content), {
|
|
1217
1244
|
window: new JSDOM('').window,
|
|
1218
1245
|
linkTargetBlank: true,
|
|
1219
1246
|
fixMalformedUrls: true,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@llm-newsletter-kit/core",
|
|
3
3
|
"private": false,
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "1.3.
|
|
5
|
+
"version": "1.3.2",
|
|
6
6
|
"description": "An extensible framework to automate your entire newsletter workflow. Handles data collection, LLM-based content analysis, and email generation, letting you focus on your unique domain logic.",
|
|
7
7
|
"main": "dist/index.cjs",
|
|
8
8
|
"module": "dist/index.js",
|