forked from wagtail/wagtail
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
159 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import { getContentMetrics } from './contentMetrics'; | ||
|
||
describe('getContentMetrics', () => { | ||
it('should return correct wordCount and readingTime using Intl.Segmenter', () => { | ||
const result = getContentMetrics('en-US', 'This is a test sentence.'); | ||
expect(result.wordCount).toBe(5); | ||
expect(result.readingTime).toBe(0); | ||
}); | ||
|
||
it('should handle empty text', () => { | ||
const result = getContentMetrics('en-US', ''); | ||
expect(result.wordCount).toBe(0); | ||
expect(result.readingTime).toBe(0); | ||
}); | ||
|
||
it('should handle text with punctuation correctly', () => { | ||
const text = `This is a longer text to test the word count and reading time calculation! | ||
Bread is a staple food prepared from a dough of flour and water; usually by baking. | ||
Throughout recorded history it has been popular around the world and is one of the | ||
oldest artificial foods: having been of importance since the dawn of agriculture. | ||
Proportions of types of flour and other ingredients vary widely? as do modes of preparation. | ||
As a result, types, shapes, sizes, and textures of breads differ around the world. | ||
Bread may be leavened by processes such as reliance on naturally occurring sourdough | ||
microbes, chemicals, industrially produced yeast, or high-pressure aeration... | ||
Some breads are baked before they have a chance to rise, often for traditional | ||
or religious reasons. Inclusions like fruits; nuts, and fats are sometimes added. | ||
Commercial bread typically includes additives to enhance flavor, texture, color, | ||
longevity, and production efficiency! | ||
`; | ||
const result = getContentMetrics('en-US', text); | ||
expect(result.wordCount).toBe(147); | ||
expect(result.readingTime).toBe(1); | ||
}); | ||
|
||
it('should return integers for wordCount and readingTime', () => { | ||
const text = 'Yet another text'; | ||
const result = getContentMetrics('en-US', text); | ||
expect(Number.isInteger(result.wordCount)).toBe(true); | ||
expect(Number.isInteger(result.readingTime)).toBe(true); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
interface ContentMetrics { | ||
wordCount: number; | ||
readingTime: number; | ||
} | ||
|
||
interface SegmentData { | ||
segment: string; | ||
isWordLike?: boolean | undefined; | ||
} | ||
|
||
export const getContentMetrics = ( | ||
lang: string, | ||
text: string, | ||
): ContentMetrics => { | ||
let wordCount = 0; | ||
|
||
if (typeof Intl.Segmenter === 'function') { | ||
const segmenter = new Intl.Segmenter(lang, { granularity: 'word' }); | ||
const segments: SegmentData[] = Array.from(segmenter.segment(text)); | ||
wordCount = segments.reduce( | ||
(count, segment) => (segment.isWordLike ? count + 1 : count), | ||
0, | ||
); | ||
} else { | ||
// Fallback to regex if Intl.Segmenter is not supported | ||
wordCount = | ||
text | ||
.trim() | ||
.replace(/['";:,.?¿\-!¡]+/g, '') | ||
.match(/\S+/g)?.length || 0; | ||
} | ||
|
||
// Silent-reading adults average 238 words per minute | ||
const readingTime = Math.round(wordCount / 238); | ||
|
||
return { | ||
wordCount, | ||
readingTime, | ||
}; | ||
}; | ||
|
||
const renderContentMetrics = ({ wordCount, readingTime }: ContentMetrics) => { | ||
const wordCountContainer = document.querySelector<HTMLElement>( | ||
'[data-content-word-count]', | ||
); | ||
const readingTimeContainer = document.querySelector<HTMLElement>( | ||
'[data-content-reading-time]', | ||
); | ||
const readingTimeSingleUnit = document.querySelector<HTMLElement>( | ||
'[data-content-reading-time-single]', | ||
); | ||
const readingTimeUnitPluralUnit = document.querySelector<HTMLElement>( | ||
'[data-content-reading-time-plural]', | ||
); | ||
|
||
if ( | ||
!wordCountContainer || | ||
!readingTimeContainer || | ||
!readingTimeSingleUnit || | ||
!readingTimeUnitPluralUnit | ||
) | ||
return; | ||
|
||
if (readingTime === 1) { | ||
readingTimeSingleUnit.hidden = false; | ||
readingTimeUnitPluralUnit.hidden = true; | ||
} | ||
wordCountContainer.textContent = wordCount.toString(); | ||
readingTimeContainer.textContent = readingTime.toString(); | ||
}; | ||
|
||
export const runContentCheck = () => { | ||
const iframe = document.querySelector<HTMLIFrameElement>( | ||
'[data-preview-iframe]', | ||
); | ||
const iframeDocument = | ||
iframe?.contentDocument || iframe?.contentWindow?.document; | ||
const text = iframeDocument?.querySelector('main')?.innerText; | ||
if (!iframe || !iframeDocument || !text) { | ||
return; | ||
} | ||
const lang = iframeDocument.documentElement.lang || 'en-US'; | ||
const contentMetrics = getContentMetrics(lang, text); | ||
|
||
renderContentMetrics(contentMetrics); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters