dopetalk does not endorse any advertised product nor does it accept any liability for it's use or misuse


Our Discord Notification Server invitation link is https://discord.gg/jB2qmRrxyD

Author Topic: PDF BBCode Tag to Automatically Display All PDFs  (Read 415 times)

Offline Chip (OP)

  • Server Admin
  • Hero Member
  • *****
  • Administrator
  • *****
  • Join Date: Dec 2014
  • Location: Australia
  • Posts: 7304
  • Reputation Power: 0
  • Chip has hidden their reputation power
  • Gender: Male
  • Last Login:Yesterday at 10:48:36 PM
  • Deeply Confused Learner
  • Profession: IT Engineer now retired
PDF BBCode Tag to Automatically Display All PDFs
« on: July 21, 2026, 09:00:11 PM »
📎 CLICK ON ME to view the list of attachments
#FileSizeDL
1PIHKAL-PEA.PDF126.6 KB⬇️
2The biography of Sydney DJ Rob Davis.pdf1.3 MB⬇️
3pdf_bbcode_v1.0.zip4.2 MB⬇️
4Claude PDF Project Contines.pdf902.9 KB⬇️
5Claude PDF Project FULLER lol.pdf320.5 KB⬇️
6Claude Some PDF mod sfuff.pdf1.9 MB⬇️
7Claude PDF Project MORE FULLER lol lol.pdf2.6 MB⬇️
8Claude PDF Project SMF 20 Finished.pdf3.1 MB⬇️
9PDF mod in SMF 2.1.pdf1.8 MB⬇️
10pdf_bbcode_final_checkpoint.md6.1 KB⬇️
11using-the-pdf-viewer.md1.8 KB⬇️
12pdf_bbcode_v2.5.zip15.8 KB⬇️
13pdf_bbcode_v2.24.zip15.8 KB⬇️
14pdfjs.zip5.8 MB⬇️
15pdf_bbcode_v3.0.zip5.8 MB⬇️

Implementing Mozilla's PDF Javascript Viewer [pdfjs 6.2.108] by using BBCode Tags

Written by Chipper (Andrew Egerszegi) and Claude.ai

Current Version: pdf_bbcode_v2.5  for Chiper's Dopetalk using a single master copy of pdfjs  v6.2.108 that lives in $Boarddir

Current Version: pdf_bbcode_v3.0  for Simple Machines using an embedded copy of pdfjs ]v6.2.108 that lives in $Themedir

Compatibility: SMF 2.0.x & SMF 2.1.x

Description and Notes

Rendered with a bundled, self-hosted copy of Mozilla's PDF.js viewer in an <iframe>

* Three ways to use the tag:


   * [pdf]https://example.com/file.pdf[/pdf]
    - Displays a locally stored pdf file in web root (eg. "/var/www/html/")   

    * [pdf=attach-nn]x[/pdf]
    - Displays the valid pdf attachment number and not the general attachment number.
           NB: The numbers start from 00
 
    * [pdf=autodisplay]x[/pdf]
    - Displays every PDF attached to this post automatically
   
   * [pdf=noautodisplay]x[/pdf]
    - (The DEFAULT) Do not display every PDF attached to this post automatically


Examples:

Display by URL to its webroot filename


Display by attachment id


Display every attachment automatically
[pdf=autodisplay]SELECTED: ON[/pdf]

DO NOT display every attachment automatically
[pdf=noautodisplay] DEFAULT: OFF [/pdf]


Display by URL to its webroot filename
📝 DEMO.md

PDF BBCode v3.0

Fixed

  • Black/404 viewer on [pdf=attach-NN] and [pdf]url[/pdf]: the inner PDF URL was being urlencode()'d before being passed to PDF.js's file= param. PDF.js 6.2.108 doesn't decode that value, so it tried to fetch a literal path containing %3F/%3D/%3B and got a 404.
  • Same bug, same fix, in the autodisplay path (pdf_display_patch.xml and pdf_display_patch_21.xml) — urlencode($attachment['href']) removed.
  • Removed schemeless() stripping on the inner PDF URL. PDF.js 6.2.108 needs an explicit http:/https: scheme to pick a fetch adapter — without it, "No available adapters." schemeless() is still used for the outer viewer.html iframe src, which was never broken.
  • 2.0.x install block was missing <require-dir name="pdfjs" destination="$themedir" /> entirely — added, matching the 2.1.x block.

Install location

pdfjs/ installs to $themedir (e.g. Themes/default/pdfjs), not $boarddir.

Notes

  • Live production was found running an unpatched, several-versions-behind PDFBBC.php despite package history showing v2.22 as reinstalled — several rounds of "the fix didn't work" were actually "the fix was never deployed." Worth checking the live file's VERSION const at the start of future debugging sessions.
  • Treat this as a full Package Manager uninstall + reinstall, not a hot-swap — the 2.0.x block now installs a directory it didn't before.


Display by URL to its webroot filename
[lmv]https://forum.drugs-and-users.org/sfm20/DEMO.md[/lmv]

Display by attachment id
[lmv=attach-01]x[/lmv]

Display every attachment automatically
[lmv=autodisplay]SELECTED: ON[/lmv]

DO NOT display every attachment automatically
[lmv=noautodisplay] DEFAULT: OFF [/lmv]
« Last Edit: Yesterday at 08:52:19 AM by Chip »
friendly
0
funny
0
informative
0
agree
0
disagree
0
like
0
dislike
0
No reactions
No reactions
No reactions
No reactions
No reactions
No reactions
No reactions
Our Discord Server invitation link is https://discord.gg/jB2qmRrxyD

Offline smfadmin

  • SMF (internal) Site
  • Administrator
  • Sr. Member
  • *****
  • Join Date: Dec 2014
  • Location: Management
  • Posts: 588
  • Reputation Power: 0
  • smfadmin has hidden their reputation power
  • Last Login:Yesterday at 09:01:19 PM
  • Supplied Install Member
Re: PDF BBCode Tag to Automatically Display All PDFs
« Reply #1 on: July 29, 2026, 09:56:29 AM »

Checkpoint: MD BBCode Mod — GFM Conformance Pass

Purpose: bring Andrew's SMF Markdown BBCode mod (MDParser.php/MDBBC.php) up to a level of GFM spec conformance good enough to satisfy SMF's lead dev, who recommended testing against the full GFM spec (https://github.github.com/gfm/) after reviewing the mod for possible official SMF inclusion.

Files / components

FileStatusUse it?
MDParser.php (this session's patched version, attached)Patched: emphasis rewrite, loose/tight lists, indented-code blank-line merging, link destination fixes, code span fix, bare-URL/www/email autolinkingYes — this is the current working version, supersedes the originally-uploaded copy
MDBBC.php (originally uploaded)Untouched this session — no changes were neededYes, unchanged
MD_SYNTAX_MANUAL.md (attached)Full table of every currently-supported syntax element + raw/rendered examples, generated from the actual current parserYes — hand this to anyone (including SM) who wants to see current scope
extract_spec.py (attached)One-time script: pulls cmark-gfm's test/spec.txt and converts it to spec.json (672 examples, tagged by section/extension)Only needed if spec.json (attached separately) is ever lost — otherwise skip straight to run_tests.php
spec.json (attached)Already-extracted output of extract_spec.py — the 672-example test suite itselfYes — drop it next to MDParser.php and run_tests.php, no re-fetch needed
run_tests.php (attached)Runs MDParser.php against every example in spec.json, writes results.jsonRe-run after every parser change
analyze.py (attached)Reads results.json, applies a "cosmetic-diff-tolerant" normalizer (strips our own CSS classes, rel= attribute, self-closing-tag style, tag-per-line formatting) to separate real bugs from harmless serialization differences; writes real_failures.json and prints per-section pass ratesRe-run after every run_tests.php run

Verified facts — don't re-check

  • The GFM spec's machine-readable test suite lives at test/spec.txt in github/cmark-gfm on GitHub (raw: raw.githubusercontent.com/github/cmark-gfm/master/test/spec.txt), in a literate format (fenced blocks marked `...`` example [extension-name] , input, a lone . line, expected HTML, closing fence). extract_spec.py parses this correctly — 672 examples extracted, matching the known canonical GFM spec size.
  • PHP is not preinstalled in this environment; apt-get install -y php-cli works (no sudo needed, container runs as root) and pulls PHP 8.3.
  • Raw pass rate (exact string match) is a bad metric here — many of the mod's own intentional additions (CSS classes md-code-block/md-table, the rel="noopener noreferrer nofollow" security hardening on links, HTML5-style non-self-closing tags) cosmetically differ from the reference renderer's output without being bugs. Always read the normalized pass rate from analyze.py, and treat real_failures.json (not raw results.json) as the list of genuine bugs.
  • Confirmed baseline at session start: 138/672 raw, 282/672 (42%) normalized.
  • Confirmed after this session's fixes: 200/672 raw, 396/672 (59%) normalized.
  • Confirmed ceiling: literal 672/672 is not a sensible goal. Reference-style links/link-reference-definitions and full raw-HTML-block parsing are deliberately out of scope (~100+ examples) — the latter because supporting it would conflict with the mod's "escape everything, selectively re-decode" security model, which the prior external security review specifically hardened. Realistic achievable ceiling is roughly 550–600/672 (~85-90%).
  • Confirmed via direct testing against the npm commonmark reference package: one spec example (__foo, __bar__, baz__) has an expected output in cmark-gfm's own spec.txt that disagrees with what the reference implementation's actual delimiter-stack algorithm produces (nested vs. flat <strong>). Traced this to the algorithm level, not a wasted rabbit hole — treat as a known, accepted gray area, do not re-derive.
  • Andrew's stated priority order (confirmed, his words): emphasis + list nesting first (highest-traffic, most complaint-prone), then links + blockquote laziness, then headings/tables (already solid), then fenced/indented code + thematic breaks/autolinks/escaping (lowest priority).
  • Andrew has separately built a syntax reference manual for the [md] tag on his own and confirmed it renders well — this may or may not be the same document as MD_SYNTAX_MANUAL.md above; worth asking rather than assuming they're the same artifact.
  • Forum BBC policy: all standard BBCode tags are disabled except [nobbc] (kept enabled/exempt as the literal-text escape hatch) and [md] itself. This is stated in MD_SYNTAX_MANUAL.md's header warning and in MDBBC.php's top doc-comment — check both stay in sync if the policy ever changes.

Open items (decisions, not blockers)

  • Base angle-bracket autolink (<scheme://...>) only recognizes http/https/ftp/ftps/mailto. CommonMark's actual rule allows any scheme matching [a-zA-Z][a-zA-Z0-9+.-]{1,31}:. Decision needed: is broadening this worth it for a forum (real schemes people might paste: irc://, magnet:, steam://), or is the current allowlist a deliberate security stance worth keeping as-is?
  • Link destinations don't yet balance parens ((foo(bar)) inside a bare URL) or do full percent-encoding of unsafe characters — only literal-space encoding is implemented. Decision needed: how much of this edge case is worth chasing given forum posts rarely paste raw unencoded URLs with parens.
  • Blockquote laziness (continuation lines without a leading >) is now fixed for the common case (paragraph continuation only, not headings/lists/fences/thematic breaks/indented code, and not after a blank line). Remaining edge case: laziness tracking inside an already-open non-paragraph block within a quote (e.g. an unclosed fence) isn't precise - low priority.
  • List "same list vs new list" rules fixed this session: a changed bullet character (-/*/+) or ordered delimiter style (. vs )) now correctly starts a new list; an ordered list can only interrupt a paragraph if it starts at 1.
  • Link destinations now do real percent-encoding (HTML entity decode, then percent-encode any byte outside the URL-safe set while preserving existing valid %XX sequences) and correctly balance parentheses via a recursive regex ([link](foo(and(bar))) works). Caution for future edits: adding a named recursive group inside an existing capturing group shifts the numeric index of every group after it — this caused a real regression this session (title text silently became a duplicate of the URL) until the shifted indices were corrected. Double-check group numbering with a quick preg_match test whenever the link/image regex structure changes again.
  • Link destinations still don't do full percent-encoding (backslash → %5C, HTML entities like &auml;%C3%A4, non-ASCII chars, quotes in a titleless destination) — only literal-space encoding is implemented. This is the largest remaining Links gap (roughly a dozen of the remaining ~53 failures).
  • Angle-bracket link destinations spanning a literal line break ([link](<foo\nbar>), which per spec should NOT be a valid link) aren't rejected, because paragraph-line-joining happens at the block level before this inline check ever sees the newline — a real but low-priority structural limitation.
  • Whether to reconcile/merge with Andrew's own separately-built syntax manual, or keep MD_SYNTAX_MANUAL.md as this session's independent version.

Next actual action

Run analyze.py's per-section breakdown on the current real_failures.json. Links is now largely down to reference-style-link failures (out of scope) plus a handful of exotic raw-HTML-mixed-with-brackets edge cases — List items (32/48) and Lists (13/26) are the next-best-value targets. Starting a fresh session should: install php-cli (apt-get install -y php-cli, no sudo needed), drop all six attached files in one directory, then run php run_tests.php && python3 analyze.py, and pick up from there.

« Last Edit: August 04, 2026, 02:27:24 PM by Chip »
friendly
0
funny
0
informative
0
agree
0
disagree
0
like
0
dislike
0
No reactions
No reactions
No reactions
No reactions
No reactions
No reactions
No reactions
measure twice, cut once

Offline smfadmin

  • SMF (internal) Site
  • Administrator
  • Sr. Member
  • *****
  • Join Date: Dec 2014
  • Location: Management
  • Posts: 588
  • Reputation Power: 0
  • smfadmin has hidden their reputation power
  • Last Login:Yesterday at 09:01:19 PM
  • Supplied Install Member
(No subject)
« Reply #2 on: August 12, 2026, 04:52:46 PM »
Topic bumped
friendly
0
funny
0
informative
0
agree
0
disagree
0
like
0
dislike
0
No reactions
No reactions
No reactions
No reactions
No reactions
No reactions
No reactions
measure twice, cut once

Offline Chip (OP)

  • Server Admin
  • Hero Member
  • *****
  • Administrator
  • *****
  • Join Date: Dec 2014
  • Location: Australia
  • Posts: 7304
  • Reputation Power: 0
  • Chip has hidden their reputation power
  • Gender: Male
  • Last Login:Yesterday at 10:48:36 PM
  • Deeply Confused Learner
  • Profession: IT Engineer now retired
Re: PDF BBCode Tag to Automatically Display All PDFs
« Reply #3 on: Yesterday at 08:03:08 AM »
No attachments on this post.
LISTATT TRACE — currentMsgId(): 49430, 0 rows in attachments table

Implementing Mozilla's PDF Javascript Viewer {PDF.js 6.2.108} by BBCode Tags
[
Written by Chipper (Andrew Egerszegi) and Claude.ai

Current Version: pdf_bbcode_v2.5  for Chiper's Dopetalk using a single master copy of pdfjs  6.2.108 that lives in $Boarddir

Current Version: pdf_bbcode_v3.0  for Simple Machines using an embedded copy of pdfjs v6.2.108 that lives in $Themedir

Compatibility: SMF 2.0.x & SMF 2.1.x

Description and Notes

Rendered with a bundled, self-hosted copy of Mozilla's PDF.js viewer in an <iframe>.

* Three ways to use the tag:


   * [pdf]https://example.com/file.pdf[/pdf]
    - Displays a locally stored pdf file in web root (eg. "/var/www/html/")   

    * [pdf=attach-nn]x[/pdf]
    - Displays the valid pdf attachment number and not the general attachment number.
           NB: The numbers start from 00
 
    * [pdf=autodisplay]x[/pdf]
    - Displays every PDF attached to this post automatically
   
   * [pdf=noautodisplay]x[/pdf]
    - (The DEFAULT) Do not display every PDF attached to this post automatically


[pdf=autodisplay]x[/pdf]

Examples:

Display by URL to its webroot filename


Display by attachment id
x

Display every attachment automatically

[pdf=autodisplay]SELECTED: ON[/pdf]

DO NOT display every attachment automatically
[pdf=noautodisplay] DEFAULT: OFF [/pdf]



[lmv=autodisplay] ON [/lmv]

lmv Examples:

Display by URL to its webroot filename
📝 DEMO.md

PDF BBCode v3.0

Fixed

  • Black/404 viewer on [pdf=attach-NN] and [pdf]url[/pdf]: the inner PDF URL was being urlencode()'d before being passed to PDF.js's file= param. PDF.js 6.2.108 doesn't decode that value, so it tried to fetch a literal path containing %3F/%3D/%3B and got a 404.
  • Same bug, same fix, in the autodisplay path (pdf_display_patch.xml and pdf_display_patch_21.xml) — urlencode($attachment['href']) removed.
  • Removed schemeless() stripping on the inner PDF URL. PDF.js 6.2.108 needs an explicit http:/https: scheme to pick a fetch adapter — without it, "No available adapters." schemeless() is still used for the outer viewer.html iframe src, which was never broken.
  • 2.0.x install block was missing <require-dir name="pdfjs" destination="$themedir" /> entirely — added, matching the 2.1.x block.

Install location

pdfjs/ installs to $themedir (e.g. Themes/default/pdfjs), not $boarddir.

Notes

  • Live production was found running an unpatched, several-versions-behind PDFBBC.php despite package history showing v2.22 as reinstalled — several rounds of "the fix didn't work" were actually "the fix was never deployed." Worth checking the live file's VERSION const at the start of future debugging sessions.
  • Treat this as a full Package Manager uninstall + reinstall, not a hot-swap — the 2.0.x block now installs a directory it didn't before.

📝 DEMO.md

PDF BBCode v3.0

Fixed

  • Black/404 viewer on [pdf=attach-NN] and [pdf]url[/pdf]: the inner PDF URL was being urlencode()'d before being passed to PDF.js's file= param. PDF.js 6.2.108 doesn't decode that value, so it tried to fetch a literal path containing %3F/%3D/%3B and got a 404.
  • Same bug, same fix, in the autodisplay path (pdf_display_patch.xml and pdf_display_patch_21.xml) — urlencode($attachment['href']) removed.
  • Removed schemeless() stripping on the inner PDF URL. PDF.js 6.2.108 needs an explicit http:/https: scheme to pick a fetch adapter — without it, "No available adapters." schemeless() is still used for the outer viewer.html iframe src, which was never broken.
  • 2.0.x install block was missing <require-dir name="pdfjs" destination="$themedir" /> entirely — added, matching the 2.1.x block.

Install location

pdfjs/ installs to $themedir (e.g. Themes/default/pdfjs), not $boarddir.

Notes

  • Live production was found running an unpatched, several-versions-behind PDFBBC.php despite package history showing v2.22 as reinstalled — several rounds of "the fix didn't work" were actually "the fix was never deployed." Worth checking the live file's VERSION const at the start of future debugging sessions.
  • Treat this as a full Package Manager uninstall + reinstall, not a hot-swap — the 2.0.x block now installs a directory it didn't before.


Display by attachment id
[lmv=attach-01]x[/lmv]

Display every attachment automatically
[lmv=autodisplay]SELECTED: ON[/lmv]

DO NOT display every attachment automatically
[lmv=noautodisplay] DEFAULT: OFF [/lmv]
« Last Edit: Yesterday at 08:45:59 AM by Chip »
friendly
0
funny
0
informative
0
agree
0
disagree
0
like
0
dislike
0
No reactions
No reactions
No reactions
No reactions
No reactions
No reactions
No reactions
Our Discord Server invitation link is https://discord.gg/jB2qmRrxyD

Tags:
 


dopetalk does not endorse any advertised product nor does it accept any liability for it's use or misuse





TERMS AND CONDITIONS

In no event will d&u or any person involved in creating, producing, or distributing site information be liable for any direct, indirect, incidental, punitive, special or consequential damages arising out of the use of or inability to use d&u. You agree to indemnify and hold harmless d&u, its domain founders, sponsors, maintainers, server administrators, volunteers and contributors from and against all liability, claims, damages, costs and expenses, including legal fees, that arise directly or indirectly from the use of any part of the d&u site.


TO USE THIS WEBSITE YOU MUST AGREE TO THE TERMS AND CONDITIONS ABOVE


Founded December 2014
SimplePortal 2.3.6 © 2008-2014, SimplePortal