diff --git a/lib/node_modules/@stdlib/_tools/remark/plugins/remark-lint-html-section-structure/README.md b/lib/node_modules/@stdlib/_tools/remark/plugins/remark-lint-html-section-structure/README.md
new file mode 100644
index 000000000000..211e1f1fd261
--- /dev/null
+++ b/lib/node_modules/@stdlib/_tools/remark/plugins/remark-lint-html-section-structure/README.md
@@ -0,0 +1,109 @@
+
+
+# remark-lint-html-section-structure
+
+> [remark][remark] plugin to lint HTML section structure in README files.
+
+
+
+This plugin validates the HTML section structure in README files, ensuring that:
+
+1. Each opening `` tag has a corresponding `` closing tag.
+2. Each opening `` tag has a corresponding closing comment ``.
+3. There is an empty line between the closing `` tag and the closing comment ``.
+
+
+
+
+
+
+
+## Usage
+
+```javascript
+var sectionStructure = require( '@stdlib/_tools/remark/plugins/remark-lint-html-section-structure' );
+```
+
+### sectionStructure()
+
+Plugin to lint HTML section structure in README files.
+
+```javascript
+var remark = require( 'remark' );
+
+remark().use( sectionStructure );
+```
+
+
+
+
+
+
+
+## Examples
+
+```javascript
+var remark = require( 'remark' );
+var report = require( 'vfile-reporter' );
+var sectionStructure = require( '@stdlib/_tools/remark/plugins/remark-lint-html-section-structure' );
+
+// Create a markdown file with HTML sections:
+var markdown = [
+ '# Title',
+ '',
+ '',
+ '',
+ '## Usage',
+ '',
+ '```javascript',
+ 'var foo = require( \'foo\' );',
+ '```',
+ '',
+ '',
+ '',
+ '',
+ ''
+].join( '\n' );
+
+// Lint using the plugin:
+remark()
+ .use( sectionStructure )
+ .process( markdown, onDone );
+
+function onDone( error, file ) {
+ if ( error ) {
+ throw error;
+ }
+ console.log( report( file ) );
+}
+```
+
+
+
+
+
+
+
+[remark]: https://github.com/remarkjs/remark
+
+
+
+
diff --git a/lib/node_modules/@stdlib/_tools/remark/plugins/remark-lint-html-section-structure/examples/index.js b/lib/node_modules/@stdlib/_tools/remark/plugins/remark-lint-html-section-structure/examples/index.js
new file mode 100644
index 000000000000..9c7ebb50b242
--- /dev/null
+++ b/lib/node_modules/@stdlib/_tools/remark/plugins/remark-lint-html-section-structure/examples/index.js
@@ -0,0 +1,59 @@
+/**
+* @license Apache-2.0
+*
+* Copyright (c) 2025 The Stdlib Authors.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+'use strict';
+
+var remark = require( 'remark' );
+var report = require( 'vfile-reporter' );
+var linter = require( './../lib' );
+
+// Create a markdown file with both valid and invalid HTML sections:
+var markdown = [
+ '# Title',
+ '',
+ '',
+ '',
+ '## Usage',
+ '',
+ '```javascript',
+ 'var foo = require( \'foo\' );',
+ '```',
+ '',
+ '',
+ '',
+ ''
+].join( '\n' );
+
+// Lint using the plugin:
+remark()
+ .use( linter )
+ .process( markdown, done );
+
+/**
+* Callback invoked upon processing a Markdown file.
+*
+* @private
+* @param {Error|null} error - error object
+* @param {VFile} file - virtual file
+*/
+function done( error, file ) {
+ if ( error ) {
+ throw error;
+ }
+ console.log( report( file ) );
+}
diff --git a/lib/node_modules/@stdlib/_tools/remark/plugins/remark-lint-html-section-structure/lib/index.js b/lib/node_modules/@stdlib/_tools/remark/plugins/remark-lint-html-section-structure/lib/index.js
new file mode 100644
index 000000000000..493beec0be5c
--- /dev/null
+++ b/lib/node_modules/@stdlib/_tools/remark/plugins/remark-lint-html-section-structure/lib/index.js
@@ -0,0 +1,50 @@
+/**
+* @license Apache-2.0
+*
+* Copyright (c) 2025 The Stdlib Authors.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+'use strict';
+
+/**
+* remark lint plugin for validating HTML section structure in README files.
+*
+* @module @stdlib/_tools/remark/plugins/remark-lint-html-section-structure
+*
+* @example
+* var remark = require( 'remark' );
+* var lint = require( '@stdlib/_tools/remark/plugins/remark-lint-html-section-structure' );
+*
+* var str = '# Title\n\n';
+*
+* function done( error, file ) {
+* var i;
+* if ( error ) {
+* throw error;
+* }
+* for ( i = 0; i < file.messages.length; i++ ) {
+* console.error( file.messages[ i ].message );
+* }
+* }
+*/
+
+// MODULES //
+
+var main = require( './main.js' );
+
+
+// EXPORTS //
+
+module.exports = main;
diff --git a/lib/node_modules/@stdlib/_tools/remark/plugins/remark-lint-html-section-structure/lib/main.js b/lib/node_modules/@stdlib/_tools/remark/plugins/remark-lint-html-section-structure/lib/main.js
new file mode 100644
index 000000000000..9163f5f4cc2c
--- /dev/null
+++ b/lib/node_modules/@stdlib/_tools/remark/plugins/remark-lint-html-section-structure/lib/main.js
@@ -0,0 +1,367 @@
+/**
+* @license Apache-2.0
+*
+* Copyright (c) 2025 The Stdlib Authors.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+'use strict';
+
+// MODULES //
+
+var logger = require( 'debug' );
+var rule = require( 'unified-lint-rule' );
+var visit = require( 'unist-util-visit' );
+var replace = require( '@stdlib/string/replace' );
+var trim = require( '@stdlib/string/trim' );
+
+
+// VARIABLES //
+
+var debug = logger( 'remark-lint-html-section-structure' );
+var RE_SECTION_START = //;
+var RE_SECTION_END = /<\/section>$/;
+var RE_SECTION_END_WITH_COMMENT = /<\/section>\s*/;
+var RE_END_COMMENT_SIMPLE = //;
+var RE_END_COMMENT = /^\s*/;
+var RE_EMPTY_LINES = /(\r?\n)\s*(\r?\n)/;
+var htmlSectionStructureRule;
+
+
+// FUNCTIONS //
+
+/**
+* Creates a position string from a node's position.
+*
+* @private
+* @param {Object} node - AST node
+* @returns {string} position string in format "line:column"
+*/
+function formatPosition( node ) {
+ return node.position.start.line + ':' + node.position.start.column;
+}
+
+/**
+* Reports an error message.
+*
+* @private
+* @param {Object} file - virtual file
+* @param {Object} node - AST node to attach message to
+* @param {string} message - error message
+* @param {string} errorCode - error code identifier
+*/
+function reportErr( file, node, message, errorCode ) {
+ var fullMsg = formatPosition( node ) + ' error ' + message + ' ' + errorCode;
+ debug( fullMsg );
+ file.message( fullMsg, node );
+}
+
+/**
+* Extracts comment class name from a node.
+*
+* @private
+* @param {Object} node - AST node containing comment
+* @param {RegExp} matchRegex - regular expression for matching comment
+* @param {RegExp} simpleMatchRegex - alternative regular expression for matching comment
+* @returns {(string|null)} extracted class name or null if no match
+*/
+function extractCommentClass( node, matchRegex, simpleMatchRegex ) {
+ var simpleMatch;
+ var match;
+
+ match = matchRegex.exec( node.value );
+ if ( match ) {
+ return match[ 1 ];
+ }
+
+ simpleMatch = simpleMatchRegex.exec( node.value );
+ if ( simpleMatch ) {
+ return trim( simpleMatch[ 1 ] );
+ }
+
+ return null;
+}
+
+/**
+* Validates that the class name in a comment matches the section class.
+*
+* @private
+* @param {Object} file - virtual file
+* @param {Object} node - node containing the comment
+* @param {string} cClass - class name extracted from comment
+* @param {string} sClass - class name from section
+* @param {string} errMsg - error message to use if validation fails
+* @param {string} errCode - error code to use if validation fails
+* @returns {boolean} boolean indicating whether the comment class matches the section class
+*/
+function checkCommentClass( file, node, cClass, sClass, errMsg, errCode ) {
+ if ( sClass && cClass !== sClass ) {
+ debug( 'Mismatched section class in comment: expected %s, got %s', sClass, cClass );
+ errMsg = replace( errMsg, '%s1', sClass );
+ errMsg = replace( errMsg, '%s2', cClass );
+ reportErr( file, node, errMsg, errCode );
+ return false;
+ }
+ return true;
+}
+
+/**
+* Validates if there is sufficient whitespace between nodes.
+*
+* @private
+* @param {Object} endNode - end section node
+* @param {Object} commentNode - comment node
+* @returns {boolean} boolean indicating whether there is sufficient whitespace between nodes
+*/
+function hasValidWhitespace( endNode, commentNode ) {
+ var lineGap = commentNode.position.start.line - endNode.position.end.line;
+ debug( 'Gap between section end and comment: %d lines', lineGap );
+
+ // We require at least 2 lines of gap for an empty line:
+ return lineGap >= 2;
+}
+
+/**
+* Checks if a text node contains proper empty line.
+*
+* @private
+* @param {Object} node - text node to check
+* @returns {boolean} boolean indicating whether the node contains proper empty line
+*/
+function hasEmptyLine( node ) {
+ var value;
+
+ if ( node.type !== 'text' ) {
+ return false;
+ }
+
+ value = node.value;
+
+ // Look for at least two consecutive newlines (representing an empty line):
+ return RE_EMPTY_LINES.test( value );
+}
+
+
+// MAIN //
+
+/**
+* Validates HTML section structure in README files.
+*
+* @private
+* @param {Node} tree - abstract syntax tree (AST)
+* @param {File} file - virtual file
+* @param {Object} options - options
+* @param {Callback} clbk - callback to invoke upon completion
+* @returns {void}
+*/
+function linter( tree, file, options, clbk ) {
+ var rootSections;
+ var sectionStack;
+ var structure;
+ var positions;
+ var className;
+ var errCode;
+ var msg;
+ var i;
+
+ debug( 'Linting file: %s', file.path || '' );
+
+ sectionStack = [];
+ rootSections = [];
+ structure = [];
+ positions = {};
+
+ visit( tree, 'html', visitor );
+
+ debug( 'Final section stack length: %d', sectionStack.length );
+
+ if ( sectionStack.length > 0 ) {
+ debug( 'Found unclosed sections: %d', sectionStack.length );
+ for ( i = 0; i < sectionStack.length; i++ ) {
+ className = sectionStack[ i ].className || '[no class specified]';
+ msg = 'Unclosed section tag. Missing closing tag for section with class="' + className + '". Add a closing tag to fix.';
+ errCode = 'unclosed-section';
+ reportErr( file, sectionStack[ i ], msg, errCode );
+ }
+ }
+
+ debug( 'Finished linting: %s', file.path || '' );
+ return clbk();
+
+ /**
+ * Callback invoked upon finding a matching node.
+ *
+ * @private
+ * @param {Object} node - AST node
+ * @param {number} index - position of `node` in `parent`
+ * @param {Object} parent - parent AST node
+ * @returns {void}
+ */
+ function visitor( node, index, parent ) {
+ var combinedMatch;
+ var commentClass;
+ var sectionMatch;
+ var commentNode;
+ var nextNode;
+ var endMatch;
+ var current;
+ var match;
+ var data;
+
+ // Store position for tracking purposes:
+ if ( node.position ) {
+ positions[ node.position.start.line ] = node;
+ }
+
+ // Check if this is a combined section end with comment on the same line (which is an error):
+ combinedMatch = RE_SECTION_END_WITH_COMMENT.exec( node.value );
+ if ( combinedMatch ) {
+ debug( 'Found combined section end with comment: %s', node.value );
+ msg = 'Missing empty line between closing section tag and comment. There should be an empty line between and ';
+ errCode = 'missing-empty-line';
+ reportErr( file, node, msg, errCode );
+
+ // Make sure to pop the section stack for this case - otherwise we'll get "unclosed section" errors:
+ if ( sectionStack.length > 0 ) {
+ debug( 'Popping section stack for combined section end+comment' );
+ sectionStack.pop();
+ }
+ return;
+ }
+
+ // Check if this is a section start tag:
+ sectionMatch = RE_SECTION_START.exec( node.value );
+ if ( sectionMatch ) {
+ debug( 'Found a section start tag with class: %s', sectionMatch[1] || '[none]' );
+
+ data = {
+ 'node': node,
+ 'className': sectionMatch[1] || '',
+ 'position': node.position,
+ 'children': [],
+ 'index': index,
+ 'parent': parent
+ };
+
+ if ( sectionStack.length === 0 ) {
+ // This is a root level section...
+ rootSections.push( data );
+ structure.push( data );
+ } else {
+ // This is a nested section, add to parent's children:
+ sectionStack[ sectionStack.length - 1 ].children.push( data );
+ }
+
+ sectionStack.push( data );
+ return;
+ }
+
+ // Check if this is a section end tag:
+ endMatch = RE_SECTION_END.exec( node.value );
+ if ( endMatch ) {
+ debug( 'Found a section end tag' );
+
+ if ( sectionStack.length === 0 ) {
+ debug( 'Orphaned section end tag found' );
+ msg = 'Orphaned section closing tag. Found without a matching opening tag. Remove this tag or add a corresponding opening tag.';
+ errCode = 'orphaned-section-end';
+ reportErr( file, node, msg, errCode );
+ return;
+ }
+
+ // Special handling for direct closing tag followed by a comment (no text node between)...
+ if ( index + 1 < parent.children.length ) {
+ nextNode = parent.children[ index + 1 ];
+
+ // Look at the next node to check if it's a comment:
+ if ( nextNode.type === 'html' ) {
+ // Check if the next node is a comment but NOT on the same line
+ commentClass = extractCommentClass( nextNode, RE_END_COMMENT, RE_END_COMMENT_SIMPLE );
+
+ if ( commentClass ) {
+ // Check if there are at least 2 line breaks between them:
+ if ( !hasValidWhitespace( node, nextNode ) ) {
+ msg = 'Missing proper empty line after closing section tag. There should be an empty line between and the closing comment.';
+ errCode = 'missing-empty-line-after-section';
+ reportErr( file, node, msg, errCode );
+ }
+
+ // Verify the comment matches the class name:
+ current = sectionStack[sectionStack.length - 1];
+ msg = 'Mismatched section class in closing comment. Opening tag has class="%s1" but closing comment is . They should match.';
+ errCode = 'mismatched-section-class';
+ checkCommentClass( file, nextNode, commentClass, current.className, msg, errCode );
+
+ // Pop the section stack before returning:
+ sectionStack.pop();
+ return;
+ }
+ }
+ }
+
+ // Standard handling for other cases with whitespace between section end and comment...
+ if ( index + 2 < parent.children.length ) {
+ nextNode = parent.children[ index + 1 ];
+ commentNode = parent.children[ index + 2 ];
+
+ // Check if the next node is a proper whitespace with empty line:
+ if ( !hasEmptyLine( nextNode ) ) {
+ debug( 'Invalid whitespace after section end' );
+ msg = 'Missing proper empty line after closing section tag. There should be an empty line between and the closing comment.';
+ errCode = 'missing-empty-line-after-section';
+ reportErr( file, node, msg, errCode );
+ }
+
+ // Check if the following node is the expected comment:
+ if ( commentNode.type === 'html' ) {
+ match = RE_END_COMMENT.exec( commentNode.value );
+ if ( match ) {
+ current = sectionStack[ sectionStack.length - 1 ];
+ msg = 'Mismatched section class in closing comment. Opening tag has class="%s1" but closing comment is . They should match.';
+ errCode = 'mismatched-section-class';
+ checkCommentClass( file, commentNode, match[1], current.className, msg, errCode );
+ } else {
+ // The HTML node exists but it's not a proper closing comment...
+ debug( 'Invalid closing comment format' );
+ msg = 'Invalid section closing comment format. Expected ';
+ errCode = 'invalid-closing-comment';
+ reportErr( file, commentNode, msg, errCode );
+ }
+ } else {
+ // The node after whitespace is not an HTML node (comment)...
+ debug( 'Node after whitespace is not an HTML comment' );
+ msg = 'Missing section closing comment. Section closing tag should be followed by comment.';
+ errCode = 'missing-section-comment';
+ reportErr( file, node, msg, errCode );
+ }
+ } else {
+ // There's not enough nodes after the section closing tag...
+ debug( 'Not enough nodes after section end' );
+ msg = 'Missing section closing comment. Section closing tag should be followed by comment on a separate line.';
+ errCode = 'missing-section-comment';
+ reportErr( file, node, msg, errCode );
+ }
+
+ // Pop the section stack:
+ sectionStack.pop();
+ }
+ }
+}
+
+htmlSectionStructureRule = rule( 'remark-lint:html-section-structure', linter );
+
+
+// EXPORTS //
+
+module.exports = htmlSectionStructureRule;
diff --git a/lib/node_modules/@stdlib/_tools/remark/plugins/remark-lint-html-section-structure/package.json b/lib/node_modules/@stdlib/_tools/remark/plugins/remark-lint-html-section-structure/package.json
new file mode 100644
index 000000000000..ce16e5213092
--- /dev/null
+++ b/lib/node_modules/@stdlib/_tools/remark/plugins/remark-lint-html-section-structure/package.json
@@ -0,0 +1,52 @@
+{
+ "name": "@stdlib/_tools/remark/plugins/remark-lint-html-section-structure",
+ "version": "0.0.0",
+ "description": "remark lint plugin for validating HTML section structure in README files.",
+ "license": "Apache-2.0",
+ "author": {
+ "name": "The Stdlib Authors",
+ "url": "https://github.com/stdlib-js/stdlib/graphs/contributors"
+ },
+ "contributors": [
+ {
+ "name": "The Stdlib Authors",
+ "url": "https://github.com/stdlib-js/stdlib/graphs/contributors"
+ }
+ ],
+ "main": "./lib",
+ "directories": {
+ "example": "./examples",
+ "lib": "./lib",
+ "test": "./test"
+ },
+ "scripts": {},
+ "homepage": "https://github.com/stdlib-js/stdlib",
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/stdlib-js/stdlib.git"
+ },
+ "bugs": {
+ "url": "https://github.com/stdlib-js/stdlib/issues"
+ },
+ "dependencies": {},
+ "devDependencies": {},
+ "engines": {
+ "node": ">=6.0.0",
+ "npm": ">2.7.0"
+ },
+ "keywords": [
+ "stdlib",
+ "tools",
+ "lint",
+ "linter",
+ "markdown",
+ "md",
+ "remark",
+ "remark-plugin",
+ "plugin",
+ "html",
+ "section",
+ "structure",
+ "validate"
+ ]
+}
diff --git a/lib/node_modules/@stdlib/_tools/remark/plugins/remark-lint-html-section-structure/test/fixtures/mismatched_class.md.txt b/lib/node_modules/@stdlib/_tools/remark/plugins/remark-lint-html-section-structure/test/fixtures/mismatched_class.md.txt
new file mode 100644
index 000000000000..0969fd2f3162
--- /dev/null
+++ b/lib/node_modules/@stdlib/_tools/remark/plugins/remark-lint-html-section-structure/test/fixtures/mismatched_class.md.txt
@@ -0,0 +1,13 @@
+# Example
+
+
+
+## Usage
+
+```javascript
+var foo = require( 'foo' );
+```
+
+
+
+
diff --git a/lib/node_modules/@stdlib/_tools/remark/plugins/remark-lint-html-section-structure/test/fixtures/missing_empty_line.md.txt b/lib/node_modules/@stdlib/_tools/remark/plugins/remark-lint-html-section-structure/test/fixtures/missing_empty_line.md.txt
new file mode 100644
index 000000000000..7d0ae4fdda0a
--- /dev/null
+++ b/lib/node_modules/@stdlib/_tools/remark/plugins/remark-lint-html-section-structure/test/fixtures/missing_empty_line.md.txt
@@ -0,0 +1,11 @@
+# Example
+
+
+
+## Usage
+
+```javascript
+var foo = require( 'foo' );
+```
+
+
diff --git a/lib/node_modules/@stdlib/_tools/remark/plugins/remark-lint-html-section-structure/test/fixtures/missing_section_comment.md.txt b/lib/node_modules/@stdlib/_tools/remark/plugins/remark-lint-html-section-structure/test/fixtures/missing_section_comment.md.txt
new file mode 100644
index 000000000000..e11fe286f97a
--- /dev/null
+++ b/lib/node_modules/@stdlib/_tools/remark/plugins/remark-lint-html-section-structure/test/fixtures/missing_section_comment.md.txt
@@ -0,0 +1,11 @@
+# Example
+
+
+
+## Usage
+
+```javascript
+var foo = require( 'foo' );
+```
+
+
diff --git a/lib/node_modules/@stdlib/_tools/remark/plugins/remark-lint-html-section-structure/test/fixtures/orphaned_section_end.md.txt b/lib/node_modules/@stdlib/_tools/remark/plugins/remark-lint-html-section-structure/test/fixtures/orphaned_section_end.md.txt
new file mode 100644
index 000000000000..dd57b6e2c341
--- /dev/null
+++ b/lib/node_modules/@stdlib/_tools/remark/plugins/remark-lint-html-section-structure/test/fixtures/orphaned_section_end.md.txt
@@ -0,0 +1,7 @@
+# Example
+
+Some content...
+
+
+
+
diff --git a/lib/node_modules/@stdlib/_tools/remark/plugins/remark-lint-html-section-structure/test/fixtures/unclosed_section.md.txt b/lib/node_modules/@stdlib/_tools/remark/plugins/remark-lint-html-section-structure/test/fixtures/unclosed_section.md.txt
new file mode 100644
index 000000000000..ba96db797a11
--- /dev/null
+++ b/lib/node_modules/@stdlib/_tools/remark/plugins/remark-lint-html-section-structure/test/fixtures/unclosed_section.md.txt
@@ -0,0 +1,11 @@
+# Example
+
+
+
+## Usage
+
+```javascript
+var foo = require( 'foo' );
+```
+
+
diff --git a/lib/node_modules/@stdlib/_tools/remark/plugins/remark-lint-html-section-structure/test/fixtures/valid.md.txt b/lib/node_modules/@stdlib/_tools/remark/plugins/remark-lint-html-section-structure/test/fixtures/valid.md.txt
new file mode 100644
index 000000000000..8b913517f299
--- /dev/null
+++ b/lib/node_modules/@stdlib/_tools/remark/plugins/remark-lint-html-section-structure/test/fixtures/valid.md.txt
@@ -0,0 +1,13 @@
+# Example
+
+
+
+## Usage
+
+```javascript
+var foo = require( 'foo' );
+```
+
+
+
+
diff --git a/lib/node_modules/@stdlib/_tools/remark/plugins/remark-lint-html-section-structure/test/fixtures/valid_multiple.md.txt b/lib/node_modules/@stdlib/_tools/remark/plugins/remark-lint-html-section-structure/test/fixtures/valid_multiple.md.txt
new file mode 100644
index 000000000000..50197c4418de
--- /dev/null
+++ b/lib/node_modules/@stdlib/_tools/remark/plugins/remark-lint-html-section-structure/test/fixtures/valid_multiple.md.txt
@@ -0,0 +1,37 @@
+# Example
+
+
+
+## Usage
+
+```javascript
+var foo = require( 'foo' );
+```
+
+
+
+
+
+
+
+## Examples
+
+```javascript
+var foo = require( 'foo' );
+
+// Usage example
+foo();
+```
+
+
+
+
+
+
+
+[npm-image]: https://img.shields.io/npm/v/example.svg
+[npm-url]: https://npmjs.org/package/example
+
+
+
+
diff --git a/lib/node_modules/@stdlib/_tools/remark/plugins/remark-lint-html-section-structure/test/fixtures/valid_nested.md.txt b/lib/node_modules/@stdlib/_tools/remark/plugins/remark-lint-html-section-structure/test/fixtures/valid_nested.md.txt
new file mode 100644
index 000000000000..693d42afe65c
--- /dev/null
+++ b/lib/node_modules/@stdlib/_tools/remark/plugins/remark-lint-html-section-structure/test/fixtures/valid_nested.md.txt
@@ -0,0 +1,93 @@
+# Example
+
+
+
+## Usage
+
+```javascript
+var foo = require( 'foo' );
+```
+
+
+
+
+
+
+
+## Examples
+
+```javascript
+var foo = require( 'foo' );
+// Example
+```
+
+
+
+
+
+
+
+## C APIs
+
+
+
+### Introduction
+
+This section contains C API documentation.
+
+
+
+
+
+
+
+### Usage
+
+```c
+#include "foo.h"
+```
+
+
+
+
+
+
+
+### Notes
+
+Some implementation notes...
+
+
+
+
+
+
+
+### Examples
+
+```c
+// C example
+#include "foo.h"
+
+int main() {
+ foo();
+ return 0;
+}
+```
+
+
+
+
+
+
+
+
+
+
+
+[npm-image]: https://img.shields.io/npm/v/example.svg
+[npm-url]: https://npmjs.org/package/example
+
+
+
+
diff --git a/lib/node_modules/@stdlib/_tools/remark/plugins/remark-lint-html-section-structure/test/fixtures/valid_no_sections.md.txt b/lib/node_modules/@stdlib/_tools/remark/plugins/remark-lint-html-section-structure/test/fixtures/valid_no_sections.md.txt
new file mode 100644
index 000000000000..ec6828393c75
--- /dev/null
+++ b/lib/node_modules/@stdlib/_tools/remark/plugins/remark-lint-html-section-structure/test/fixtures/valid_no_sections.md.txt
@@ -0,0 +1,10 @@
+# Title
+
+## Heading 2
+
+This is a regular markdown file with no HTML sections.
+
+* List item 1
+* List item 2
+
+Some more text.
diff --git a/lib/node_modules/@stdlib/_tools/remark/plugins/remark-lint-html-section-structure/test/test.js b/lib/node_modules/@stdlib/_tools/remark/plugins/remark-lint-html-section-structure/test/test.js
new file mode 100644
index 000000000000..6f0e4ad2889d
--- /dev/null
+++ b/lib/node_modules/@stdlib/_tools/remark/plugins/remark-lint-html-section-structure/test/test.js
@@ -0,0 +1,217 @@
+/**
+* @license Apache-2.0
+*
+* Copyright (c) 2025 The Stdlib Authors.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+'use strict';
+
+// MODULES //
+
+var join = require( 'path' ).join;
+var tape = require( 'tape' );
+var remark = require( 'remark' );
+var readSync = require( 'to-vfile' ).readSync; // eslint-disable-line node/no-sync
+var isArray = require( '@stdlib/assert/is-array' );
+var IS_BROWSER = require( '@stdlib/assert/is-browser' );
+var lint = require( './../lib' );
+
+
+// VARIABLES //
+
+var opts = {
+ 'skip': IS_BROWSER
+};
+
+
+// TESTS //
+
+tape( 'main export is a function', function test( t ) {
+ t.ok( true, __filename );
+ t.strictEqual( typeof lint, 'function', 'main export is a function' );
+ t.end();
+});
+
+tape( 'the plugin successfully lints valid Markdown not containing any HTML sections', opts, function test( t ) {
+ var fpath = join( __dirname, 'fixtures', 'valid_no_sections.md.txt' );
+ var file = readSync( fpath, 'utf8' );
+
+ remark().use( lint ).process( file, done );
+
+ function done( error, file ) {
+ if ( error ) {
+ t.fail( error.message );
+ } else {
+ t.strictEqual( isArray( file.messages ), true, 'is an array' );
+ t.strictEqual( file.messages.length, 0, 'is empty array' );
+ }
+ t.end();
+ }
+});
+
+tape( 'the plugin successfully lints valid Markdown not containing any HTML sections (string)', opts, function test( t ) {
+ remark().use( lint ).process( '# Beep\n\n## Boop\n', done );
+
+ function done( error, file ) {
+ if ( error ) {
+ t.fail( error.message );
+ } else {
+ t.strictEqual( isArray( file.messages ), true, 'is an array' );
+ t.strictEqual( file.messages.length, 0, 'is empty array' );
+ }
+ t.end();
+ }
+});
+
+tape( 'the plugin successfully lints a valid HTML section structure', opts, function test( t ) {
+ var fpath = join( __dirname, 'fixtures', 'valid.md.txt' );
+ var file = readSync( fpath, 'utf8' );
+
+ remark().use( lint ).process( file, done );
+
+ function done( error, file ) {
+ if ( error ) {
+ t.fail( error.message );
+ } else {
+ t.strictEqual( isArray( file.messages ), true, 'is an array' );
+ t.strictEqual( file.messages.length, 0, 'is empty array' );
+ }
+ t.end();
+ }
+});
+
+tape( 'the plugin successfully lints valid HTML section structure (multiple sections)', opts, function test( t ) {
+ var fpath = join( __dirname, 'fixtures', 'valid_multiple.md.txt' );
+ var file = readSync( fpath, 'utf8' );
+
+ remark().use( lint ).process( file, done );
+
+ function done( error, file ) {
+ if ( error ) {
+ t.fail( error.message );
+ } else {
+ t.strictEqual( isArray( file.messages ), true, 'is an array' );
+ t.strictEqual( file.messages.length, 0, 'is empty array' );
+ }
+ t.end();
+ }
+});
+
+tape( 'the plugin successfully lints valid HTML section structure (nested sections)', opts, function test( t ) {
+ var fpath = join( __dirname, 'fixtures', 'valid_nested.md.txt' );
+ var file = readSync( fpath, 'utf8' );
+
+ remark().use( lint ).process( file, done );
+
+ function done( error, file ) {
+ if ( error ) {
+ t.fail( error.message );
+ } else {
+ t.strictEqual( isArray( file.messages ), true, 'is an array' );
+ t.strictEqual( file.messages.length, 0, 'is empty array' );
+ }
+ t.end();
+ }
+});
+
+tape( 'the plugin returns a lint error if a section is missing a closing tag', opts, function test( t ) {
+ var fpath = join( __dirname, 'fixtures', 'unclosed_section.md.txt' );
+ var file = readSync( fpath, 'utf8' );
+
+ remark().use( lint ).process( file, done );
+
+ function done( error, file ) {
+ if ( error ) {
+ t.fail( error.message );
+ } else {
+ t.strictEqual( isArray( file.messages ), true, 'is an array' );
+ t.strictEqual( file.messages.length, 1, 'contains lint error' );
+ t.pass( file.messages[ 0 ] );
+ }
+ t.end();
+ }
+});
+
+tape( 'the plugin returns a lint error if a section closing tag is missing a comment', opts, function test( t ) {
+ var fpath = join( __dirname, 'fixtures', 'missing_section_comment.md.txt' );
+ var file = readSync( fpath, 'utf8' );
+
+ remark().use( lint ).process( file, done );
+
+ function done( error, file ) {
+ if ( error ) {
+ t.fail( error.message );
+ } else {
+ t.strictEqual( isArray( file.messages ), true, 'is an array' );
+ t.strictEqual( file.messages.length, 1, 'contains lint error' );
+ t.pass( file.messages[ 0 ] );
+ }
+ t.end();
+ }
+});
+
+tape( 'the plugin returns a lint error if a section closing comment does not match the class', opts, function test( t ) {
+ var fpath = join( __dirname, 'fixtures', 'mismatched_class.md.txt' );
+ var file = readSync( fpath, 'utf8' );
+
+ remark().use( lint ).process( file, done );
+
+ function done( error, file ) {
+ if ( error ) {
+ t.fail( error.message );
+ } else {
+ t.strictEqual( isArray( file.messages ), true, 'is an array' );
+ t.strictEqual( file.messages.length, 1, 'contains lint error' );
+ t.pass( file.messages[ 0 ] );
+ }
+ t.end();
+ }
+});
+
+tape( 'the plugin returns a lint error if a section end tag has no matching opening tag', opts, function test( t ) {
+ var fpath = join( __dirname, 'fixtures', 'orphaned_section_end.md.txt' );
+ var file = readSync( fpath, 'utf8' );
+
+ remark().use( lint ).process( file, done );
+
+ function done( error, file ) {
+ if ( error ) {
+ t.fail( error.message );
+ } else {
+ t.strictEqual( isArray( file.messages ), true, 'is an array' );
+ t.strictEqual( file.messages.length, 1, 'contains lint error' );
+ t.pass( file.messages[ 0 ] );
+ }
+ t.end();
+ }
+});
+
+tape( 'the plugin returns a lint error if a section is missing an empty line between closing tag and comment', opts, function test( t ) {
+ var fpath = join( __dirname, 'fixtures', 'missing_empty_line.md.txt' );
+ var file = readSync( fpath, 'utf8' );
+
+ remark().use( lint ).process( file, done );
+
+ function done( error, file ) {
+ if ( error ) {
+ t.fail( error.message );
+ } else {
+ t.strictEqual( isArray( file.messages ), true, 'is an array' );
+ t.strictEqual( file.messages.length, 1, 'contains lint error' );
+ t.pass( file.messages[ 0 ] );
+ }
+ t.end();
+ }
+});