diff --git a/.github/scripts/docs-lint/index.mjs b/.github/scripts/docs-lint/index.mjs index 8bce140b..dd735c43 100644 --- a/.github/scripts/docs-lint/index.mjs +++ b/.github/scripts/docs-lint/index.mjs @@ -22,8 +22,9 @@ import remarkGfm from 'remark-gfm' import { Reporter, printReport } from './lib/report.mjs' import * as tables from './rules/tables.mjs' +import * as links from './rules/links.mjs' -const RULES = [tables] +const RULES = [tables, links] const SYNC_PATHS = [ 'docs/**/*.md', diff --git a/.github/scripts/docs-lint/rules/links.mjs b/.github/scripts/docs-lint/rules/links.mjs new file mode 100644 index 00000000..069c39ed --- /dev/null +++ b/.github/scripts/docs-lint/rules/links.mjs @@ -0,0 +1,51 @@ +/** + * Link rules for docs-lint. + * + * Rules and severity: + * error confluence-html-link + * Link target matches Confluence-export filename pattern + * `_.html` (e.g. `children_1608551.html`). These are + * dead artifacts from the original Confluence-to-Markdown migration. + * Either the link should be repointed at the current in-repo doc, or + * the target should be hosted somewhere that still resolves. + * + * Detects both relative (`children_1608551.html`) and absolute + * (`/.../children_1608551.html`) forms. Also catches external URLs to + * the `sdkdocs-archive.staging.web.roku.com` Confluence-archive host. + */ + +import { visit } from 'unist-util-visit'; + +export const id = 'links'; + +// `_.html` pattern, anywhere in the URL path. Trailing +// `#anchor` is tolerated by the parser; we test against just the path. +const CONFLUENCE_EXPORT_RE = /[^\s/]+_\d+\.html(\?[^#\s]*)?(#\S*)?$/i; +const CONFLUENCE_ARCHIVE_HOST_RE = /^https?:\/\/sdkdocs-archive\.staging\.web\.roku\.com\//i; + +function isConfluenceLink(url) { + if (!url) return false; + if (CONFLUENCE_ARCHIVE_HOST_RE.test(url)) return true; + // Strip query + hash, then test the path portion + const pathPart = url.split('#')[0].split('?')[0]; + // Skip true external URLs (already handled by archive-host check above) + if (/^https?:\/\//i.test(url) && !CONFLUENCE_ARCHIVE_HOST_RE.test(url)) return false; + // mailto / tel / doc:slug -- skip + if (/^(mailto|tel|doc):/i.test(url)) return false; + return CONFLUENCE_EXPORT_RE.test(pathPart); +} + +export function check({ file, mdast, reporter }) { + visit(mdast, (node) => { + if (node.type !== 'link' && node.type !== 'image' && node.type !== 'definition') return; + if (!isConfluenceLink(node.url)) return; + reporter.add({ + file, + line: node.position?.start.line, + col: node.position?.start.column ?? 1, + rule: 'confluence-html-link', + severity: 'error', + message: `Confluence-export link target \`${node.url}\` -- the original Confluence page is gone; repoint at the current in-repo doc`, + }); + }); +} diff --git a/docs/DEVELOPER/core-concepts/xml-components/component-initialization-order.md b/docs/DEVELOPER/core-concepts/xml-components/component-initialization-order.md index 579b4f85..da3ae7e4 100644 --- a/docs/DEVELOPER/core-concepts/xml-components/component-initialization-order.md +++ b/docs/DEVELOPER/core-concepts/xml-components/component-initialization-order.md @@ -15,17 +15,17 @@ next: Instances of components defined in an XML file follow a well-defined initialization order when they are created. -1. The [**\**](children_1608551.html) element nodes defined +1. The [**\**](/docs/references/scenegraph/xml-elements/children.md) element nodes defined in XML markup are created, and their fields are set to their initial values, either to a default value, or to the value specified in the XML markup. -2. The **[\](interface_1608549.html)** element fields of +2. The **[\](/docs/references/scenegraph/xml-elements/interface.md)** element fields of the XML component are created, and their initial values are set, either to a default value, or to the value specified by the `value` attribute. -3. The [**\**](script_1608550.html) element `init()` function +3. The [**\**](/docs/references/scenegraph/xml-elements/script.md) element `init()` function is called, and all initializations contained in the function are performed. @@ -55,7 +55,7 @@ using **`createObject()`** or **`createChild()`**. This means that a component object may not have been completely constructed immediately after those calls. For certain nodes that may rely on dynamically-downloaded content to construct the node, such as -[**PosterGrid**](PosterGrid_1607203.html), subsequent object function +[**PosterGrid**](/docs/references/scenegraph/list-and-grid-nodes/postergrid.md), subsequent object function calls may return an object reference to an unconstructed object. ## Parenting and the Focus Chain @@ -63,8 +63,8 @@ calls may return an object reference to an unconstructed object. For nodes that are defined in the **\** XML markup of the component file, the parent node is set after the node is created, and **`init()`** is called. This has implications for the focus chain (see -[**Remote Control Events**](Remote-Control-Events_1607636.html)), which -must end at a node derived from **[Scene](Scene_1607315.html)**. Until +[**Remote Control Events**](../scenegraph-xml/remote-control-events.md)), which +must end at a node derived from **[Scene](/docs/references/scenegraph/scene.md)**. Until the newly-created node is parented to a node that is either derived from **Scene**, or parented to a node in a focus chain that ends on a node derived from **Scene**, you will not be able to set remote control focus diff --git a/docs/DEVELOPER/core-concepts/xml-components/scenegraph-compilation.md b/docs/DEVELOPER/core-concepts/xml-components/scenegraph-compilation.md index 3663fe6e..6c7e3a3b 100644 --- a/docs/DEVELOPER/core-concepts/xml-components/scenegraph-compilation.md +++ b/docs/DEVELOPER/core-concepts/xml-components/scenegraph-compilation.md @@ -21,17 +21,17 @@ BrightScript files in the `pkg:/components` directory are compiled in the same way as BrightScript files in the `pkg:/source` directory. The SceneGraph component files are compiled by creating a list of component names for the application, based on the `name` attribute of -the [**\**](component_1608292.html) element of each file. +the [**\**](/docs/references/scenegraph/xml-elements/component.md) element of each file. These component names are checked for validity as instances of the components are created in the application. This check is *case-sensitive*: the component name to be created must *exactly* match a name in the component name list, *including* case. The application begins to create instances of SceneGraph components starting with a component extended from a scene node class (either -[**Scene**](Scene_1607315.html) or -[**OverhangPanelSetScene**](OverhangPanelSetScene_1613108.html)). See +[**Scene**](/docs/references/scenegraph/scene.md) or +[**OverhangPanelSetScene**](/docs/references/scenegraph/sliding-panels-nodes/overhangpanelsetscene.md)). See [**Component Initialization -Order**](Component-Initialization-Order_1611697.html) for a description +Order**](component-initialization-order.md) for a description of the process that creates component instances. diff --git a/docs/REFERENCES/brightscript/interfaces/ifpath.md b/docs/REFERENCES/brightscript/interfaces/ifpath.md index c143d9e8..33e79a6c 100644 --- a/docs/REFERENCES/brightscript/interfaces/ifpath.md +++ b/docs/REFERENCES/brightscript/interfaces/ifpath.md @@ -71,7 +71,7 @@ A flag indicating whether the current path is valid. #### Description -Returns an [roAssociativeArray](https://sdkdocs-archive.staging.web.roku.com/roAssociativeArray_1611481.html) containing keys for the parent directories, extensions, and file name in the file path. +Returns an [roAssociativeArray](/docs/references/brightscript/components/roassociativearray.md) containing keys for the parent directories, extensions, and file name in the file path. #### Return Value