mirror of
https://github.com/Micke-K/IntuneManagement.git
synced 2026-09-28 10:55:38 +02:00
IntuneManagement 4.0.0-beta1
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
# Atlassian (Confluence) documentation output
|
||||
|
||||
[`Internal/Documentation/OutputProviders/DocumentationOutputAtlassian.ps1`](../Internal/Documentation/OutputProviders/DocumentationOutputAtlassian.ps1)
|
||||
|
||||
Emits Confluence **storage format** (XHTML plus `<ac:*>` macros) for a documentation
|
||||
run: paste it into a page's *Rich Text -> Source* view, or POST it to the Confluence
|
||||
REST API as `representation=storage`. Structurally it mirrors the HTML provider
|
||||
(BasicInfo / FilteredSettings / ComplianceActions / ApplicabilityRules / Assignments /
|
||||
CustomTables plus a per-run table of contents); only the markup differs.
|
||||
|
||||
Select it with `-OutputFormat atlassian`.
|
||||
|
||||
| Option (`$Options.Outputs.atlassian`) | Default | Meaning |
|
||||
| --- | --- | --- |
|
||||
| `AtlassianDocumentName` | `%MyDocuments%\%Organization%-%Date%.html` | Output path. Supports `Expand-FileName` tokens. |
|
||||
| `AtlassianDocumentFileType` | `Full` | `Full` = one file; `Object` = one file per policy plus a TOC index file. |
|
||||
| `AtlassianTitleProperty` | `Intune documentation` | `<h1>` of the index page. |
|
||||
| `AtlassianOpenFile` | `$true` | Launch the file with the OS default handler. Set `$false` for CI. |
|
||||
|
||||
## Heading anchors (a consumer contract)
|
||||
|
||||
Every heading is emitted with an inline anchor macro:
|
||||
|
||||
```xml
|
||||
<h4 id='section-42'><ac:structured-macro ac:name='anchor' ac:schema-version='1'><ac:parameter ac:name=''>section-42</ac:parameter></ac:structured-macro>Contoso Reader</h4>
|
||||
```
|
||||
|
||||
The anchor name has appeared as literal `<!--#section-N-->` text downstream of the
|
||||
generated file. The source of that rewrite is still unproven: the publishing runbook
|
||||
parses the body with mshtml before POSTing, and Confluence also transforms storage
|
||||
format. The inline placement remains the known baseline until those paths are measured
|
||||
separately.
|
||||
|
||||
Three properties are guaranteed, and downstream tooling depends on them:
|
||||
|
||||
1. **The `anchor` macro carries the link target.** Confluence discards author-specified
|
||||
`id=` attributes when it converts storage format to ADF, so `#section-42` can only
|
||||
resolve to an anchor macro or to Confluence's own heading-text-derived anchor.
|
||||
2. **`id=` always equals the macro name, byte for byte.** Confluence strips it, but
|
||||
automation that parses the *generated file* before publishing reads the anchor from
|
||||
it - for example to walk an assignment table cell back to its policy heading and
|
||||
build a deep link into the published page.
|
||||
3. **The table of contents links these names, never the heading text.** Anchor names
|
||||
contain no character that came from tenant data.
|
||||
|
||||
**Naming scheme (breaking-change surface):** `section-N` for every heading, numbered
|
||||
in emission order over the whole run. `section-N` is unique across a run even in
|
||||
`Object` mode, because the counter is reset only in
|
||||
`Invoke-AtlassianPreProcessItems`. Numbering is *not contiguous within the TOC*: a
|
||||
heading consumes a number whenever it is written to the document, including the
|
||||
level-6 table captions that the TOC's level cap (4) filters out and the `-SkipTOC`
|
||||
script captions it never lists. Do not assume contiguity - and do not reconstruct the
|
||||
numbers by counting TOC entries.
|
||||
|
||||
`table-N` is reserved for the `-ToT` caption form of `Add-AtlassianHeader`, which no
|
||||
call site in this provider uses: table captions here are plain level-6 headings, as
|
||||
in the HTML provider. Only the Markdown provider passes `-ToT` (and so is the only
|
||||
output with visible `Table N.` numbering). Enabling it for Atlassian would change
|
||||
rendered captions, so it belongs with the HTML provider as one formatting decision
|
||||
rather than a port detail.
|
||||
|
||||
The scheme is positional, so inserting one policy shifts every later anchor: links a
|
||||
user saved from an earlier run of a scheduled export therefore move. A content-derived
|
||||
scheme (`policy-<objectId>` from the Graph GUID) would be stable and is the natural
|
||||
follow-up; it needs `Add-AtlassianHeader` to accept an explicit anchor from
|
||||
`Invoke-AtlassianProcessItem`, with the positional counter kept as the fallback for
|
||||
headers that have no natural identifier.
|
||||
|
||||
**Deployment ordering:** update the module wherever the export runs *before* a consumer
|
||||
switches to reading `id=` / linking `#section-N`, or its links will point at anchors
|
||||
that do not exist yet.
|
||||
|
||||
## Markup constraints
|
||||
|
||||
- **Single-quote every attribute.** Consumers JSON-escape the document body before a
|
||||
Confluence client serialises it again; a double-quoted attribute arrives as
|
||||
`ac:name=\"anchor\"` and breaks the macro. Every macro in the provider follows this,
|
||||
so the body survives a JSON round-trip byte-identically.
|
||||
- **Storage format is strict XML** and declares only the five XML built-in entities.
|
||||
Use numeric references (` `, never ` `), close every macro, and escape
|
||||
text that comes from the tenant - `Get-AtlassianXmlText` for headings, TOC labels,
|
||||
the title and the document-info lines; `Set-AtlassianText` for table cell values
|
||||
(it also wraps XML-looking values in a `code` macro and long text in an `expand`).
|
||||
A single bare `&` in a policy name invalidates the whole page body, not one heading,
|
||||
and Confluence rejects the upload.
|
||||
- **In `Object` mode the TOC's `href` carries a file name derived from a policy
|
||||
name.** `Get-AtlassianObjectFileName` strips only path-invalid characters, so `&`,
|
||||
`'` and `#` survive into it. `Get-AtlassianHref` percent-encodes the file-name
|
||||
component (never the `#` that introduces the fragment) and then XML-escapes the
|
||||
result; use it rather than interpolating a file name into an attribute.
|
||||
|
||||
## Change history
|
||||
|
||||
Unreleased (part of 4.0, no shipped version has the earlier behaviour):
|
||||
|
||||
- Table of contents entries link the anchor macro each heading emits. They used to
|
||||
target a fragment re-derived from the heading text, so duplicate policy names all
|
||||
jumped to the first occurrence and characters other than a plain space (`.`, `(`,
|
||||
`)`, `:`, `&`, `+`, `,`, U+00A0) leaked into the href unencoded.
|
||||
- Headings carry an inline `anchor` macro; previously they carried only an `id=` that
|
||||
Confluence discards, which nothing could link to. The *shape* of an anchor name is
|
||||
unchanged (`section-N`), so a consumer reading `id=` needs no update. A provisional
|
||||
preceding-paragraph placement was reverted before release because its downstream
|
||||
behavior and blank-line cost had not been measured.
|
||||
- A heading kept out of the TOC now consumes an anchor number. It used to reuse the
|
||||
next listed heading's number, so a document containing script captions (Detection
|
||||
script, Requirement scripts) emitted two `section-N` anchors with one name and the
|
||||
TOC entry landed on the caption. This shifts the numbers in such documents: another
|
||||
reason to read `id=` rather than compute `section-N` from a position.
|
||||
- Object-mode `href` file names are percent-encoded. A policy name containing `&`
|
||||
or `'` used to produce a malformed body, and one containing `#` a link to the wrong
|
||||
fragment.
|
||||
- In the `-ToT` caption path (present but unused, see above) the `Table N. ` prefix
|
||||
moved from the id to the visible text, where the Markdown provider puts it.
|
||||
- Heading text, TOC labels, the title and the document-info lines are XML-escaped.
|
||||
- Confluence keeps generating its own text-derived anchors, so externally saved
|
||||
`#Policy-Name` links still resolve.
|
||||
|
||||
The three guarantees above are covered by the project's own test suite.
|
||||
Reference in New Issue
Block a user