Skip to content

[helpers] CSS and JavaScript content inflates reading time #1077

Open

Description

@itskingori

Issue Summary

The reading-time helper counts CSS and JavaScript inside HTML <style> and <script> elements as article words. Posts containing self-contained interactive embeds can therefore show substantially inflated reading times even though readers never see that code.

The word counter removes the opening and closing HTML tags, but retains their contents. This also counts comments inside those elements.

To Reproduce

Source-level reproduction against SDK commit 7c83d1ffb6e6961a8d8cb5dfba81fa62ff47cb51:

  1. Copy count-words.js, count-images.js and reading-minutes.js from packages/helpers/lib/utils/ into a temporary directory.
  2. Give the copies .mjs extensions and update the two relative imports in reading-minutes.mjs to include .mjs. No counting logic needs changing.
  3. Save the following as repro.mjs in that directory and run node repro.mjs:
import countWords from './count-words.mjs';
import readingMinutes from './reading-minutes.mjs';

const prose = '<p>' + 'word '.repeat(275) + '</p>';
const hidden = '/* ' + 'word '.repeat(2750) + '*/';

for (const [name, html] of [
    ['prose', prose],
    ['style', prose + '<style>' + hidden + '</style>'],
    ['script', prose + '<script>' + hidden + '</script>']
]) {
    console.log(name, {
        words: countWords(html),
        minutes: readingMinutes(html)
    });
}

Actual output:

prose  { words: 275, minutes: 1 }
style  { words: 3025, minutes: 11 }
script { words: 3025, minutes: 11 }

Expected: all three inputs contain the same 275 visible words and should produce the same one-minute estimate. The contents of executable script and stylesheet elements should be excluded. Visible code samples in <pre> or <code> should still count.

Technical details

  • Affected package: @tryghost/helpers; the package manifest at the tested revision reports version 1.1.107.
  • Tested revision: 7c83d1ffb6e6961a8d8cb5dfba81fa62ff47cb51.
  • Node.js: v24.11.0.
  • OS: macOS.
  • Ghost version/database/browser: not required for this isolated helper reproduction; no full Ghost installation was used for this test.

The relevant tag-stripping expression is in count-words.js:

The resulting count feeds directly into reading-minutes.js@7c83d1f.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions