@@ -60,6 +60,22 @@ export function flattenArticle(
6060 formatOptions ?: UserFeedFormatOptions ;
6161 useParserRules ?: PostProcessParserRule [ ] ;
6262 }
63+ ) : FlattenedArticleWithoutId {
64+ const base = flattenArticleLightweight ( input , options ) ;
65+
66+ return enrichFlattenedArticle ( base , options ) ;
67+ }
68+
69+ /**
70+ * Lightweight flatten: same as flattenArticle but skips extractExtraInfo and runPostProcessRules.
71+ * Used for pagination/search where extracted::/processed:: fields aren't needed.
72+ */
73+ export function flattenArticleLightweight (
74+ input : Record < string , unknown > ,
75+ options : {
76+ formatOptions ?: UserFeedFormatOptions ;
77+ useParserRules ?: PostProcessParserRule [ ] ;
78+ }
6379) : FlattenedArticleWithoutId {
6480 const flattened = flatten ( input , {
6581 delimiter : ARTICLE_FIELD_DELIMITER ,
@@ -89,7 +105,6 @@ export function flattenArticle(
89105 try {
90106 // eslint-disable-next-line no-control-regex
91107 if ( / [ ^ \x00 - \x7F ] / . test ( requestedTimezone ) ) {
92- // Non-ASCII characters (e.g., Unicode minus) aren't valid in timezones
93108 throw new Error ( "Invalid timezone" ) ;
94109 }
95110 dateVal = dayjs ( value ) . tz ( requestedTimezone ) ;
@@ -139,8 +154,20 @@ export function flattenArticle(
139154 newRecord [ key ] = String ( value ) ;
140155 } ) ;
141156
142- // Extract images and anchors from HTML content
143- const entries = Object . entries ( newRecord ) ;
157+ return newRecord ;
158+ }
159+
160+ /**
161+ * Enrich a lightweight-flattened article with extracted:: and processed:: fields.
162+ * Runs the expensive operations that flattenArticleLightweight skips.
163+ */
164+ export function enrichFlattenedArticle (
165+ flattened : FlattenedArticleWithoutId ,
166+ options : { useParserRules ?: PostProcessParserRule [ ] }
167+ ) : FlattenedArticleWithoutId {
168+ const enriched = { ...flattened } ;
169+
170+ const entries = Object . entries ( flattened ) ;
144171
145172 for ( let i = 0 ; i < entries . length ; i ++ ) {
146173 const [ key , value ] = entries [ i ] ! ;
@@ -149,20 +176,18 @@ export function flattenArticle(
149176
150177 if ( imageList . length ) {
151178 for ( let j = 0 ; j < imageList . length ; j ++ ) {
152- const image = imageList [ j ] ;
153- newRecord [ `extracted::${ key } ::image${ j + 1 } ` ] = image ! ;
179+ enriched [ `extracted::${ key } ::image${ j + 1 } ` ] = imageList [ j ] ! ;
154180 }
155181 }
156182
157183 if ( anchorList . length ) {
158184 for ( let j = 0 ; j < anchorList . length ; j ++ ) {
159- const anchor = anchorList [ j ] ;
160- newRecord [ `extracted::${ key } ::anchor${ j + 1 } ` ] = anchor ! ;
185+ enriched [ `extracted::${ key } ::anchor${ j + 1 } ` ] = anchorList [ j ] ! ;
161186 }
162187 }
163188 }
164189
165- return runPostProcessRules ( newRecord , options . useParserRules ) ;
190+ return runPostProcessRules ( enriched , options . useParserRules ) ;
166191}
167192
168193/**
@@ -176,6 +201,7 @@ export async function parseArticlesFromXml(
176201 useParserRules ?: PostProcessParserRule [ ] ;
177202 externalFeedProperties ?: ExternalFeedProperty [ ] ;
178203 externalFetchFn ?: ExternalFetchFn ;
204+ lightweight ?: boolean ;
179205 } = { }
180206) : Promise < ParseArticlesResult > {
181207 const feedparser = new FeedParser ( { } ) ;
@@ -240,7 +266,10 @@ export async function parseArticlesFromXml(
240266 idType
241267 ) ;
242268
243- const flattened = flattenArticle ( rawArticle as never , {
269+ const flattenFn = options . lightweight
270+ ? flattenArticleLightweight
271+ : flattenArticle ;
272+ const flattened = flattenFn ( rawArticle as never , {
244273 formatOptions : options . formatOptions ,
245274 useParserRules : options . useParserRules ,
246275 } ) ;
@@ -287,8 +316,9 @@ export async function parseArticlesFromXml(
287316 idHashes . add ( idHash ) ;
288317 }
289318
290- // Inject external content if configured
319+ // Inject external content if configured (skip in lightweight mode)
291320 if (
321+ ! options . lightweight &&
292322 options . externalFeedProperties ?. length &&
293323 options . externalFetchFn &&
294324 mappedArticles . length <= MAX_ARTICLE_INJECTION_ARTICLE_COUNT
0 commit comments