From 2f46954b652c12ff7a63600faea08dfd10133ce0 Mon Sep 17 00:00:00 2001 From: Heat Hamilton Date: Tue, 7 Jan 2025 17:21:35 -0500 Subject: [PATCH 1/2] Added function to collect code list items; added tests --- .../collect-code-list-items.mjs | 74 +++++++++++++++++++ .../collect-code-list-items.test.mjs | 73 ++++++++++++++++++ 2 files changed, 147 insertions(+) create mode 100644 scripts/algolia/transform-mdx-to-algolia-record/code-list-items/collect-code-list-items.mjs create mode 100644 scripts/algolia/transform-mdx-to-algolia-record/code-list-items/collect-code-list-items.test.mjs diff --git a/scripts/algolia/transform-mdx-to-algolia-record/code-list-items/collect-code-list-items.mjs b/scripts/algolia/transform-mdx-to-algolia-record/code-list-items/collect-code-list-items.mjs new file mode 100644 index 0000000000..8c1a9da1f4 --- /dev/null +++ b/scripts/algolia/transform-mdx-to-algolia-record/code-list-items/collect-code-list-items.mjs @@ -0,0 +1,74 @@ +import remark from 'remark' +import visit from 'unist-util-visit' +import is from 'unist-util-is' + +/** + * A remark plugin that finds
  • nodes that start with inline code, + * and extracts the inline code's text content. + * + * Text content for each inline code item is pushed to the provided + * `collector` variable, which is required for the plugin to function. + */ +const codeListItemCollector = ({ collector }) => { + return function transformer(tree) { + visit(tree, 'listItem', (node) => { + // If the list node has no children, skip it + if (!node.children) { + return + } + // We expect the child node to be a paragraph, with nested children. + const childNode = node.children[0] + if (!isParagraph(childNode) || !childNode.children) { + return + } + // We expect the nested child to be an inline code node. + const nestedChild = childNode.children[0] + if (!isInlineCode(nestedChild)) { + return + } + // If we have found
  • , then we extract the text. + collector.push(nestedChild.value) + }) + } +} + +/** + * Given some MDX content, + * find all

  • nodes that start with inline code, and + * Return an array of text values for all those bits of inline code lists. + * + * For context, in many MDX documents, we list parameters or options as + * lists, with each items starting with . The text content of those + * elements often represents relatively important parameters or options. + * Being able to extract the text means we can do things like search index it. + */ +export async function collectCodeListItems(content) { + const codeListItems = [] + + /** + * Run remark using the extraction plugin, + * then return the collected array of `codeListItems` + */ + return remark() + .use(codeListItemCollector, { collector: codeListItems }) + .process(content) + .then(() => { + return codeListItems + }) +} + +/** + * unist-util-is for `paragraph` nodes, + * with a type guard so we don't have to cast types. + */ +function isParagraph(node) { + return is(node, 'paragraph') +} + +/** + * unist-util-is for `inlineCode` nodes, + * with a type guard so we don't have to cast types. + */ +function isInlineCode(node) { + return is(node, 'inlineCode') +} diff --git a/scripts/algolia/transform-mdx-to-algolia-record/code-list-items/collect-code-list-items.test.mjs b/scripts/algolia/transform-mdx-to-algolia-record/code-list-items/collect-code-list-items.test.mjs new file mode 100644 index 0000000000..002b4ccb58 --- /dev/null +++ b/scripts/algolia/transform-mdx-to-algolia-record/code-list-items/collect-code-list-items.test.mjs @@ -0,0 +1,73 @@ +import { describe, test, expect } from 'vitest' +import { collectCodeListItems } from './collect-code-list-items.mjs' + +describe('collectCodeListItems', () => { + test('should collect content from list items that start with inline code', async () => { + const mdxContent = `# Setting Up Logging for HTTP Transactions + +The recommended logging helper for SDK is built on top of [terraform-plugin-log](/terraform/plugin/log). This lets you leverage the features from our structured logging framework without having to write an entire implementation of \`http.RoundTripper\`. + +There are two functions inside \`helper/logging\` that target a specific logging setup for your provider. Refer to [“Writing Log Output”](/terraform/plugin/log/writing) for details. + +- \`NewLoggingHTTPTransport(transport http.RoundTripper)\`: Use this method when you want logging against the \`tflog\` Provider root logger. +- \`NewSubsystemLoggingHTTPTransport(subsystem string, transport http.RoundTripper)\`: Use this method when you want logging against a \`tflog\` Provider [Subsystem logger](/terraform/plugin/log/writing#subsystems). The \`subsystem\` string you use with \`NewSubsystemLoggingHTTPTransport()\` must match the [pre-created subsystem logger name](/terraform/plugin/log/writing#create-subsystems). + +To set up HTTP transport, you must create the HTTP Client to use the new transport and then add logging configuration to the HTTP request context.` + + const result = await collectCodeListItems(mdxContent) + expect(result).toEqual([ + 'NewLoggingHTTPTransport(transport http.RoundTripper)', + 'NewSubsystemLoggingHTTPTransport(subsystem string, transport http.RoundTripper)', + ]) + expect(result).not.toContain('NewSubsystemLoggingHTTPTransport()') + }) + + test('should return an empty array if no list items start with inline code', async () => { + const mdxContent = ` +- [AWS](/terraform/enterprise/cost-estimation/aws) +- [GCP](/terraform/enterprise/cost-estimation/gcp) +- [Azure](/terraform/enterprise/cost-estimation/azure)` + + const result = await collectCodeListItems(mdxContent) + expect(result).toEqual([]) + }) + + test('should return an empty array for nested list items that do not start with inline code, but contain inline code', async () => { + const mdxContent = `### 2021-06-8 + +- Updated [Registry Module APIs](/terraform/enterprise/api-docs/private-registry/modules). + - added \`registry_name\` scoped APIs. + - added \`organization_name\` scoped APIs.` + const result = await collectCodeListItems(mdxContent) + expect(result).toEqual([]) + }) + + test('should handle nested list items that start with inline code', async () => { + const mdxContent = `### 2021-06-8 + +- Updated [Registry Module APIs](/terraform/enterprise/api-docs/private-registry/modules). + - added \`registry_name\` scoped APIs. + - added \`organization_name\` scoped APIs. + - added [Module List API](/terraform/enterprise/api-docs/private-registry/modules#list-registry-modules-for-an-organization). + - updated [Module Delete APIs](/terraform/enterprise/api-docs/private-registry/modules#delete-a-module) (see deprecation note below). + - **CLOUD**: added public registry module related APIs. +- **DEPRECATION**: The following [Registry Module APIs](/terraform/enterprise/api-docs/private-registry/modules) have been replaced with newer apis and will be removed in the future. + - The following endpoints to delete modules are replaced with [Module Delete APIs](/terraform/enterprise/api-docs/private-registry/modules#delete-a-module) + - \`POST /registry-modules/actions/delete/:organization_name/:name/:provider/:version\` replaced with \`DELETE /organizations/:organization_name/registry-modules/:registry_name/:namespace/:name/:provider/:version\` + - \`POST /registry-modules/actions/delete/:organization_name/:name/:provider\` replaced with \`DELETE /organizations/:organization_name/registry-modules/:registry_name/:namespace/:name/:provider\` + - \`POST /registry-modules/actions/delete/:organization_name/:name\` replaced with \`DELETE /organizations/:organization_name/registry-modules/:registry_name/:namespace/:name\` + - \`POST /registry-modules\` replaced with [\`POST /organizations/:organization_name/registry-modules/vcs\`](/terraform/enterprise/api-docs/private-registry/modules#publish-a-private-module-from-a-vcs) + - \`POST /registry-modules/:organization_name/:name/:provider/versions\` replaced with [\`POST /organizations/:organization_name/registry-modules/:registry_name/:namespace/:name/:provider/versions\`](/terraform/enterprise/api-docs/private-registry/modules#create-a-module-version) + - \`GET /registry-modules/show/:organization_name/:name/:provider\` replaced with [\`GET /organizations/:organization_name/registry-modules/:registry_name/:namespace/:name/:provider\`](/terraform/enterprise/api-docs/private-registry/modules#get-a-module)` + + const result = await collectCodeListItems(mdxContent) + expect(result).toEqual([ + 'POST /registry-modules/actions/delete/:organization_name/:name/:provider/:version', + 'POST /registry-modules/actions/delete/:organization_name/:name/:provider', + 'POST /registry-modules/actions/delete/:organization_name/:name', + 'POST /registry-modules', + 'POST /registry-modules/:organization_name/:name/:provider/versions', + 'GET /registry-modules/show/:organization_name/:name/:provider', + ]) + }) +}) From 0a370cc33310b775fdabcd34b72e6e3e874e4d32 Mon Sep 17 00:00:00 2001 From: Heat Hamilton Date: Wed, 8 Jan 2025 11:16:37 -0500 Subject: [PATCH 2/2] Moved isParagraph and isInlineCode to codeListItemCollector function --- .../collect-code-list-items.mjs | 29 +++++++++---------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/scripts/algolia/transform-mdx-to-algolia-record/code-list-items/collect-code-list-items.mjs b/scripts/algolia/transform-mdx-to-algolia-record/code-list-items/collect-code-list-items.mjs index 8c1a9da1f4..42e6feb0ac 100644 --- a/scripts/algolia/transform-mdx-to-algolia-record/code-list-items/collect-code-list-items.mjs +++ b/scripts/algolia/transform-mdx-to-algolia-record/code-list-items/collect-code-list-items.mjs @@ -10,6 +10,19 @@ import is from 'unist-util-is' * `collector` variable, which is required for the plugin to function. */ const codeListItemCollector = ({ collector }) => { + /** + * unist-util-is for `paragraph` nodes + */ + function isParagraph(node) { + return is(node, 'paragraph') + } + + /** + * unist-util-is for `inlineCode` nodes + */ + function isInlineCode(node) { + return is(node, 'inlineCode') + } return function transformer(tree) { visit(tree, 'listItem', (node) => { // If the list node has no children, skip it @@ -56,19 +69,3 @@ export async function collectCodeListItems(content) { return codeListItems }) } - -/** - * unist-util-is for `paragraph` nodes, - * with a type guard so we don't have to cast types. - */ -function isParagraph(node) { - return is(node, 'paragraph') -} - -/** - * unist-util-is for `inlineCode` nodes, - * with a type guard so we don't have to cast types. - */ -function isInlineCode(node) { - return is(node, 'inlineCode') -}