Summary
Symbol-page Tech Notes are filled by replacing the header cell (MarkdownToNotebook.wl, symbolNotebook, line 3966):
If[ rt =!= {} && paclet =!= "",
nb = nb /. tns : Cell[_, "TechNotesSection", ___] :> techNotesGroup[tns, rt, paclet]
]
with techNotesGroup (line 2760) wrapping the matched cell into a fresh group:
techNotesGroup[header_Cell, entries_List, paclet_String] := Cell[CellGroupData[
Prepend[tutorialLinkCell[#, paclet] & /@ entries, header], Open]]
Its comment (line ~2734) states the premise: the Symbol template "ships the TechNotesSection header as a bare cell rather than a group with a placeholder inside."
That premise is false on this installation. FunctionBaseTemplateExt.nb (loaded via docTemplate, from $InstallationDirectory/AddOns/Applications/DocumentationTools/FrontEnd/TextResources/) ships the header INSIDE an existing group:
CellGroupData[{ Cell[_, "TechNotesSection"], Cell[_, "Tutorials"] }, ...]
HEAD's own comment agrees (line 3846): "the XXXX placeholder the template ships inside the TechNotesSection group."
Effect
Because /. matches the inner Cell[_, "TechNotesSection", ___] (the header inside the existing group), techNotesGroup wraps that header into a new group, producing a group nested directly inside the original group. The result is a CellGroupData whose head cell is itself a Cell[CellGroupData[...]], i.e. an outer section with no heading cell at its own level.
Measured on a built Symbol page with RelatedTutorials set:
|
working tree |
HEAD (486a861) |
| TechNotesSection-bearing groups |
2 |
1 |
malformed CellGroupData[{Cell[CellGroupData[..]], ...}] |
1 |
0 |
| group shape |
{{GROUP, {TechNotesSection, Tutorials}}} nested |
{TechNotesSection, Tutorials} flat |
HEAD produces the correct flat group; the working tree produces a double-nested, malformed one.
Repro
sym.md:
---
Title: FooBar
Template: Symbol
Name: FooBar
Paclet: My`Pac`
Context: My`Pac`
RelatedTutorials:
- Getting Started
- [Advanced Topics](AdvancedGuide)
---
## Usage
`FooBar[x]` returns a thing.
Get[".../MarkdownToNotebook.wl"];
nb = MarkdownToNotebook["sym.md", "Evaluate" -> False];
Length @ Cases[nb, CellGroupData[{Cell[CellGroupData[__], ___], ___}, ___], Infinity] (* 1, should be 0 *)
Which change introduced it
The uncommitted merge kept the local techNotesGroup / tutorialLinkCell implementation in place of upstream's techNoteContent + fillDocCells[nb, "Tutorials", ...]. fillDocCells fills the Tutorials placeholder inside the existing group and yields the correct flat structure; the wrap approach does not, given the actual template shape.
Fix options
- Revert to the
fillDocCells[nb, "Tutorials", ...] approach (fills the placeholder in the group the template already ships), or
- Match and replace the whole group
Cell[CellGroupData[{Cell[_, "TechNotesSection", ___], ___}, ___], ___] and rebuild it flat, rather than matching only the inner header cell.
Note
Correctness depends on the installed DocumentationTools template. On the current install the template ships a group, so the wrap approach is wrong. If a future template ships a bare TechNotesSection cell, the premise (and the wrap approach) would hold; the code should not silently assume one shape.
Severity
Medium-high: every Symbol page with RelatedTutorials builds a malformed TechNotesSection group.
Summary
Symbol-page Tech Notes are filled by replacing the header cell (MarkdownToNotebook.wl,
symbolNotebook, line 3966):with
techNotesGroup(line 2760) wrapping the matched cell into a fresh group:Its comment (line ~2734) states the premise: the Symbol template "ships the TechNotesSection header as a bare cell rather than a group with a placeholder inside."
That premise is false on this installation.
FunctionBaseTemplateExt.nb(loaded viadocTemplate, from$InstallationDirectory/AddOns/Applications/DocumentationTools/FrontEnd/TextResources/) ships the header INSIDE an existing group:HEAD's own comment agrees (line 3846): "the XXXX placeholder the template ships inside the TechNotesSection group."
Effect
Because
/.matches the innerCell[_, "TechNotesSection", ___](the header inside the existing group),techNotesGroupwraps that header into a new group, producing a group nested directly inside the original group. The result is aCellGroupDatawhose head cell is itself aCell[CellGroupData[...]], i.e. an outer section with no heading cell at its own level.Measured on a built Symbol page with
RelatedTutorialsset:CellGroupData[{Cell[CellGroupData[..]], ...}]{{GROUP, {TechNotesSection, Tutorials}}}nested{TechNotesSection, Tutorials}flatHEAD produces the correct flat group; the working tree produces a double-nested, malformed one.
Repro
sym.md:Which change introduced it
The uncommitted merge kept the local
techNotesGroup/tutorialLinkCellimplementation in place of upstream'stechNoteContent+fillDocCells[nb, "Tutorials", ...].fillDocCellsfills theTutorialsplaceholder inside the existing group and yields the correct flat structure; the wrap approach does not, given the actual template shape.Fix options
fillDocCells[nb, "Tutorials", ...]approach (fills the placeholder in the group the template already ships), orCell[CellGroupData[{Cell[_, "TechNotesSection", ___], ___}, ___], ___]and rebuild it flat, rather than matching only the inner header cell.Note
Correctness depends on the installed DocumentationTools template. On the current install the template ships a group, so the wrap approach is wrong. If a future template ships a bare
TechNotesSectioncell, the premise (and the wrap approach) would hold; the code should not silently assume one shape.Severity
Medium-high: every Symbol page with
RelatedTutorialsbuilds a malformed TechNotesSection group.