From ad397a05937dad678d72fb09e527b3de4729f1c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D0=B5=D0=BD=D1=86=D0=B0=20=D0=94=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=98=D0=B3=D0=BE=D1=80=D0=B5=D0=B2=D0=B8=D1=87?= Date: Wed, 8 Oct 2025 01:31:32 +0300 Subject: [PATCH 01/22] fixed bug in valid object detection --- src/resources/xmir-transformer.xsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/resources/xmir-transformer.xsl b/src/resources/xmir-transformer.xsl index ca20d3cf..10c183c5 100644 --- a/src/resources/xmir-transformer.xsl +++ b/src/resources/xmir-transformer.xsl @@ -6,7 +6,7 @@
- +
From 8b3bd0cac422593c7b419e3097130d8f9f353c33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D0=B5=D0=BD=D1=86=D0=B0=20=D0=94=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=98=D0=B3=D0=BE=D1=80=D0=B5=D0=B2=D0=B8=D1=87?= Date: Wed, 8 Oct 2025 01:58:20 +0300 Subject: [PATCH 02/22] Added test detection and removed tests from docs result --- src/resources/xmir-transformer.xsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/resources/xmir-transformer.xsl b/src/resources/xmir-transformer.xsl index 10c183c5..750f2a79 100644 --- a/src/resources/xmir-transformer.xsl +++ b/src/resources/xmir-transformer.xsl @@ -6,7 +6,7 @@
- +
From ab58091c9401eb1504d88208b5a71e12e435f805 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D0=B5=D0=BD=D1=86=D0=B0=20=D0=94=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=98=D0=B3=D0=BE=D1=80=D0=B5=D0=B2=D0=B8=D1=87?= Date: Wed, 8 Oct 2025 04:39:48 +0300 Subject: [PATCH 03/22] Stylized result HTMLs, added meta info to HTML(filename and creation time) --- src/commands/docs.js | 37 +++++++++++++++--------------- src/resources/xmir-transformer.xsl | 7 +++--- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/src/commands/docs.js b/src/commands/docs.js index 1fc83c7e..844a45ff 100644 --- a/src/commands/docs.js +++ b/src/commands/docs.js @@ -75,37 +75,38 @@ function createXmirHtmlBlock(xmir_path) { * @return {String} HTML of the package */ function generatePackageHtml(name, xmir_htmls, css_path) { - const title = `

Package ${name} documentation

`; + xmir_htmls = xmir_htmls.filter(item => item !== '
'); + const cur_date = new Date(); return ` + - ${title} - ${xmir_htmls.join('\n')} +
+
+ +
+ ${xmir_htmls.join('\n')} +
`; } /** * Wraps given html body + * @param {String} name - File name * @param {String} html - HTML body * @param {String} css_path - CSS file path * @return {String} Ready HTML */ -function wrapHtml(html, css_path) { - return ` - - - - - - - ${html} - - - `; +function wrapHtml(name, html, css_path) { + return generatePackageHtml(name, [html], css_path); } /** @@ -128,7 +129,7 @@ module.exports = async function(opts) { const xmir_html = createXmirHtmlBlock(xmir); const html_app = path.join(output, path.dirname(relative),`${name}.html`); fs.mkdirSync(path.dirname(html_app), {recursive: true}); - fs.writeFileSync(html_app, wrapHtml(xmir_html, css)); + fs.writeFileSync(html_app, wrapHtml(name, xmir_html, css)); const packages = path.dirname(relative).split(path.sep).join('.'); const html_package = path.join(output, `package_${packages}.html`); if (!(packages in packages_info)) { @@ -143,10 +144,10 @@ module.exports = async function(opts) { for (const package_name of Object.keys(packages_info)) { fs.mkdirSync(path.dirname(packages_info[package_name].path), {recursive: true}); fs.writeFileSync(packages_info[package_name].path, - generatePackageHtml(package_name, packages_info[package_name].xmir_htmls, css)); + generatePackageHtml(package_name + " package", packages_info[package_name].xmir_htmls, css)); } const packages = path.join(output, 'packages.html'); - fs.writeFileSync(packages, generatePackageHtml('', all_xmir_htmls, css)); + fs.writeFileSync(packages, generatePackageHtml('overall package', all_xmir_htmls, css)); console.info('Documentation generation completed in the %s directory', output); } catch (error) { console.error('Error generating documentation:', error); diff --git a/src/resources/xmir-transformer.xsl b/src/resources/xmir-transformer.xsl index 750f2a79..011bcb0e 100644 --- a/src/resources/xmir-transformer.xsl +++ b/src/resources/xmir-transformer.xsl @@ -4,8 +4,9 @@ * SPDX-License-Identifier: MIT --> + -
+
@@ -17,7 +18,7 @@ -

+

( @@ -33,7 +34,7 @@

-
+
From 98574463a5802849d106e5b0f35dfdc2725d4e5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D0=B5=D0=BD=D1=86=D0=B0=20=D0=94=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=98=D0=B3=D0=BE=D1=80=D0=B5=D0=B2=D0=B8=D1=87?= Date: Wed, 8 Oct 2025 05:11:08 +0300 Subject: [PATCH 04/22] lint fixes --- src/commands/docs.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/docs.js b/src/commands/docs.js index 844a45ff..f4ca744d 100644 --- a/src/commands/docs.js +++ b/src/commands/docs.js @@ -144,7 +144,7 @@ module.exports = async function(opts) { for (const package_name of Object.keys(packages_info)) { fs.mkdirSync(path.dirname(packages_info[package_name].path), {recursive: true}); fs.writeFileSync(packages_info[package_name].path, - generatePackageHtml(package_name + " package", packages_info[package_name].xmir_htmls, css)); + generatePackageHtml(`${package_name} package`, packages_info[package_name].xmir_htmls, css)); } const packages = path.join(output, 'packages.html'); fs.writeFileSync(packages, generatePackageHtml('overall package', all_xmir_htmls, css)); From 14f0fb2640b78597c8aedbbe73d30513ef496533 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D0=B5=D0=BD=D1=86=D0=B0=20=D0=94=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=98=D0=B3=D0=BE=D1=80=D0=B5=D0=B2=D0=B8=D1=87?= Date: Wed, 8 Oct 2025 15:30:41 +0300 Subject: [PATCH 05/22] Added test for tests generation in docs --- test/commands/test_docs.js | 22 +++++++++++++++ test/resources/test4.xmir | 56 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 test/resources/test4.xmir diff --git a/test/commands/test_docs.js b/test/commands/test_docs.js index 462e0c99..255bfd78 100644 --- a/test/commands/test_docs.js +++ b/test/commands/test_docs.js @@ -108,4 +108,26 @@ describe('docs', () => { assert(!test_content.includes('Not docs'), `Unnecessary comment found in ${test_html}`); done(); }); + /** + * Tests that the 'docs' command does not generate test to HTML. + * @param {Mocha.Done} done - Mocha callback signaling asynchronous completion + */ + it('does not generate tests to HTML', (done) => { + const sample = parsed; + fs.mkdirSync(sample, {recursive: true}); + const xmir = path.join(sample, 'test.xmir'); + fs.writeFileSync(xmir, fs.readFileSync(path.join(__dirname, '..', 'resources', 'test4.xmir')).toString()); + runSync([ + 'docs', + '--verbose', + '-s', path.resolve(home, 'src'), + '-t', home, + ]); + assert(fs.existsSync(docs), 'Expected the docs directory to be created but it is missing'); + const test_html = path.join(docs, 'test.html'); + assert(fs.existsSync(test_html), `Expected file ${test_html} but it was not created`); + const test_content = fs.readFileSync(test_html); + assert(!test_content.includes('Tests this comment is not in docs.'), `Unnecessary comment found in ${test_html}`); + done(); + }); }); diff --git a/test/resources/test4.xmir b/test/resources/test4.xmir new file mode 100644 index 00000000..23881e56 --- /dev/null +++ b/test/resources/test4.xmir @@ -0,0 +1,56 @@ + + + + # Says hello to Jeff. +[] &gt; app + # Tests this comment is not in docs. + [] +&gt; some-check + QQ.io.stdout &gt; @ + &quot;Test passed!&quot; + + + Says hello to Jeff. + Tests this comment is not in docs. + + + + + + + 54-65-73-74-20-70-61-73-73-65-64-21 + + + + + + + validate-before-stars + resolve-before-stars + wrap-method-calls + const-to-dataized + stars-to-tuples + vars-float-up + move-voids-up + validate-objects-count + build-fqns + expand-qqs + expand-aliases + resolve-aliases + add-default-package + roll-bases + cti-adds-errors + decorate + add-as-attributes-inside-application + st-hex + + \ No newline at end of file From f49ec01e78e8ce4562047c44a826cd1db871b144 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D0=B5=D0=BD=D1=86=D0=B0=20=D0=94=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=98=D0=B3=D0=BE=D1=80=D0=B5=D0=B2=D0=B8=D1=87?= Date: Wed, 8 Oct 2025 15:57:14 +0300 Subject: [PATCH 06/22] Added test for empty docblocks --- test/commands/test_docs.js | 25 +++++++++++++++++++ test/resources/test5.xmir | 49 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 test/resources/test5.xmir diff --git a/test/commands/test_docs.js b/test/commands/test_docs.js index 255bfd78..bae9ea04 100644 --- a/test/commands/test_docs.js +++ b/test/commands/test_docs.js @@ -130,4 +130,29 @@ describe('docs', () => { assert(!test_content.includes('Tests this comment is not in docs.'), `Unnecessary comment found in ${test_html}`); done(); }); + /** + * Tests that the 'docs' command does not generate comletely empty HTML for empty docblocks. + * @param {Mocha.Done} done - Mocha callback signaling asynchronous completion + */ + it('does not generate empty HTML for empty docblocks', (done) => { + const sample = parsed; + fs.mkdirSync(sample, {recursive: true}); + const xmir = path.join(sample, 'test.xmir'); + fs.writeFileSync(xmir, fs.readFileSync(path.join(__dirname, '..', 'resources', 'test5.xmir')).toString()); + runSync([ + 'docs', + '--verbose', + '-s', path.resolve(home, 'src'), + '-t', home, + ]); + assert(fs.existsSync(docs), 'Expected the docs directory to be created but it is missing'); + const test_html = path.join(docs, 'test.html'); + assert(fs.existsSync(test_html), `Expected file ${test_html} but it was not created`); + const cheerio = require('cheerio'); + const test_content = fs.readFileSync(test_html); + const test_html_processer = cheerio.load(test_content); + const test_text_content = test_html_processer('body').text().trim(); + assert(test_text_content.length > 0); + done(); + }); }); diff --git a/test/resources/test5.xmir b/test/resources/test5.xmir new file mode 100644 index 00000000..668cdbe3 --- /dev/null +++ b/test/resources/test5.xmir @@ -0,0 +1,49 @@ + + + + [args] &gt; app + QQ.io.stdout &gt; @ + &quot;Hello, world!\n&quot; + + + + + + + + 48-65-6C-6C-6F-2C-20-77-6F-72-6C-64-21-0A + + + + + + validate-before-stars + resolve-before-stars + wrap-method-calls + const-to-dataized + stars-to-tuples + vars-float-up + move-voids-up + validate-objects-count + build-fqns + expand-qqs + expand-aliases + resolve-aliases + add-default-package + roll-bases + cti-adds-errors + decorate + add-as-attributes-inside-application + st-hex + + \ No newline at end of file From c2c868d57b5dd044998258dc6d1064172d4610a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D0=B5=D0=BD=D1=86=D0=B0=20=D0=94=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=98=D0=B3=D0=BE=D1=80=D0=B5=D0=B2=D0=B8=D1=87?= Date: Wed, 8 Oct 2025 15:58:57 +0300 Subject: [PATCH 07/22] removed typos --- test/commands/test_docs.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/commands/test_docs.js b/test/commands/test_docs.js index bae9ea04..d7e58078 100644 --- a/test/commands/test_docs.js +++ b/test/commands/test_docs.js @@ -131,7 +131,7 @@ describe('docs', () => { done(); }); /** - * Tests that the 'docs' command does not generate comletely empty HTML for empty docblocks. + * Tests that the 'docs' command does not generate completely empty HTML for empty docblocks. * @param {Mocha.Done} done - Mocha callback signaling asynchronous completion */ it('does not generate empty HTML for empty docblocks', (done) => { @@ -150,8 +150,8 @@ describe('docs', () => { assert(fs.existsSync(test_html), `Expected file ${test_html} but it was not created`); const cheerio = require('cheerio'); const test_content = fs.readFileSync(test_html); - const test_html_processer = cheerio.load(test_content); - const test_text_content = test_html_processer('body').text().trim(); + const test_html_processor = cheerio.load(test_content); + const test_text_content = test_html_processor('body').text().trim(); assert(test_text_content.length > 0); done(); }); From b336f4fc5eb555690269b0b95d4a1890a4b9103a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D0=B5=D0=BD=D1=86=D0=B0=20=D0=94=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=98=D0=B3=D0=BE=D1=80=D0=B5=D0=B2=D0=B8=D1=87?= Date: Wed, 8 Oct 2025 16:19:02 +0300 Subject: [PATCH 08/22] Checking HTML content with regular expressions in empty html test --- test/commands/test_docs.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/commands/test_docs.js b/test/commands/test_docs.js index d7e58078..2fed252a 100644 --- a/test/commands/test_docs.js +++ b/test/commands/test_docs.js @@ -148,10 +148,9 @@ describe('docs', () => { assert(fs.existsSync(docs), 'Expected the docs directory to be created but it is missing'); const test_html = path.join(docs, 'test.html'); assert(fs.existsSync(test_html), `Expected file ${test_html} but it was not created`); - const cheerio = require('cheerio'); const test_content = fs.readFileSync(test_html); - const test_html_processor = cheerio.load(test_content); - const test_text_content = test_html_processor('body').text().trim(); + test_content.replace(/<[^>]*>/g, ''); + test_content.replace(/\s+/g, ''); assert(test_text_content.length > 0); done(); }); From f770bb2c86cae965ab97aa2f4682cd69e10bdf41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D0=B5=D0=BD=D1=86=D0=B0=20=D0=94=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=98=D0=B3=D0=BE=D1=80=D0=B5=D0=B2=D0=B8=D1=87?= Date: Wed, 8 Oct 2025 17:03:11 +0300 Subject: [PATCH 09/22] fixes --- test/commands/test_docs.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/commands/test_docs.js b/test/commands/test_docs.js index 2fed252a..4c5de9c1 100644 --- a/test/commands/test_docs.js +++ b/test/commands/test_docs.js @@ -148,10 +148,10 @@ describe('docs', () => { assert(fs.existsSync(docs), 'Expected the docs directory to be created but it is missing'); const test_html = path.join(docs, 'test.html'); assert(fs.existsSync(test_html), `Expected file ${test_html} but it was not created`); - const test_content = fs.readFileSync(test_html); - test_content.replace(/<[^>]*>/g, ''); - test_content.replace(/\s+/g, ''); - assert(test_text_content.length > 0); + const test_content = fs.readFileSync(test_html).toString(); + const text_only = test_content.replace(/<[^>]*>/g, '') + .replace(/\s+/g, ''); + assert(text_only.length > 0); done(); }); }); From b783c458ad2a9a5732e3716f27977fbf8ff281d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D0=B5=D0=BD=D1=86=D0=B0=20=D0=94=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=98=D0=B3=D0=BE=D1=80=D0=B5=D0=B2=D0=B8=D1=87?= Date: Wed, 8 Oct 2025 17:05:15 +0300 Subject: [PATCH 10/22] fixed lint --- test/commands/test_docs.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/commands/test_docs.js b/test/commands/test_docs.js index 4c5de9c1..c15c9e91 100644 --- a/test/commands/test_docs.js +++ b/test/commands/test_docs.js @@ -150,7 +150,7 @@ describe('docs', () => { assert(fs.existsSync(test_html), `Expected file ${test_html} but it was not created`); const test_content = fs.readFileSync(test_html).toString(); const text_only = test_content.replace(/<[^>]*>/g, '') - .replace(/\s+/g, ''); + .replace(/\s+/g, ''); assert(text_only.length > 0); done(); }); From 36ed0ac7070e7375f27695285a7dc4074ee40ae0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D0=B5=D0=BD=D1=86=D0=B0=20=D0=94=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=98=D0=B3=D0=BE=D1=80=D0=B5=D0=B2=D0=B8=D1=87?= Date: Thu, 9 Oct 2025 04:16:37 +0300 Subject: [PATCH 11/22] Added markdown support --- src/commands/docs.js | 21 ++++++++++++++++++++- src/resources/xmir-transformer.xsl | 4 ++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/commands/docs.js b/src/commands/docs.js index f4ca744d..61d26e1e 100644 --- a/src/commands/docs.js +++ b/src/commands/docs.js @@ -6,6 +6,8 @@ const fs = require('fs'); const path = require('path'); const SaxonJS = require('saxon-js'); +const { JSDOM } = require('jsdom'); +const marked = require('marked'); /** * Recursively reads all .xmir files from a directory. @@ -52,6 +54,23 @@ function transformDocument(xmir, xsl) { return html; } +/** + * Converts Markdown blocks in documentation to HTML + * @param {String} html - text of HTML file + * @return {String} HTML document + */ +function convertMarkdownToHtml(html) { + const dom = new JSDOM(html); + const doc = dom.window.document; + const description_elements = doc.querySelectorAll('div.object-desc'); + description_elements.forEach(desc => { + const markdown_text = desc.innerHTML; + const converted_html = marked.parse(markdown_text); + desc.innerHTML = converted_html; + }); + return doc.body.innerHTML; +} + /** * Creates documentation block from given XMIR * @param {String} xmir_path - path of XMIR @@ -61,7 +80,7 @@ function createXmirHtmlBlock(xmir_path) { try { const xmir = fs.readFileSync(xmir_path).toString(); const xsl = fs.readFileSync(path.join(__dirname, '..', 'resources', 'xmir-transformer.xsl')).toString(); - return transformDocument(xmir, xsl); + return convertMarkdownToHtml(transformDocument(xmir, xsl)); } catch(error) { throw new Error(`Error while applying XSL to XMIR: ${error.message}`, error); } diff --git a/src/resources/xmir-transformer.xsl b/src/resources/xmir-transformer.xsl index 011bcb0e..f07ab127 100644 --- a/src/resources/xmir-transformer.xsl +++ b/src/resources/xmir-transformer.xsl @@ -26,11 +26,11 @@ , )

-

+

-

+
From 352db4532ca757262cef7f5ef8fc551af9e3b391 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D0=B5=D0=BD=D1=86=D0=B0=20=D0=94=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=98=D0=B3=D0=BE=D1=80=D0=B5=D0=B2=D0=B8=D1=87?= Date: Thu, 9 Oct 2025 04:17:58 +0300 Subject: [PATCH 12/22] lint fixes --- src/commands/docs.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/commands/docs.js b/src/commands/docs.js index 61d26e1e..022bc1cb 100644 --- a/src/commands/docs.js +++ b/src/commands/docs.js @@ -64,9 +64,9 @@ function convertMarkdownToHtml(html) { const doc = dom.window.document; const description_elements = doc.querySelectorAll('div.object-desc'); description_elements.forEach(desc => { - const markdown_text = desc.innerHTML; - const converted_html = marked.parse(markdown_text); - desc.innerHTML = converted_html; + const markdown_text = desc.innerHTML; + const converted_html = marked.parse(markdown_text); + desc.innerHTML = converted_html; }); return doc.body.innerHTML; } From 9901d650f345d05c4cba3dca7e335c95725283dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D0=B5=D0=BD=D1=86=D0=B0=20=D0=94=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=98=D0=B3=D0=BE=D1=80=D0=B5=D0=B2=D0=B8=D1=87?= Date: Thu, 9 Oct 2025 05:11:31 +0300 Subject: [PATCH 13/22] Added markdown generation test --- test/commands/test_docs.js | 24 +++++++++++++++++ test/resources/test6.xmir | 55 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 test/resources/test6.xmir diff --git a/test/commands/test_docs.js b/test/commands/test_docs.js index c15c9e91..d26ce6ba 100644 --- a/test/commands/test_docs.js +++ b/test/commands/test_docs.js @@ -154,4 +154,28 @@ describe('docs', () => { assert(text_only.length > 0); done(); }); + /** + * Tests that the 'docs' command generates markdown correctly. + * @param {Mocha.Done} done - Mocha callback signaling asynchronous completion + */ + it('generates markdown correctly', (done) => { + const sample = parsed; + fs.mkdirSync(sample, {recursive: true}); + const xmir = path.join(sample, 'test.xmir'); + fs.writeFileSync(xmir, fs.readFileSync(path.join(__dirname, '..', 'resources', 'test6.xmir')).toString()); + runSync([ + 'docs', + '--verbose', + '-s', path.resolve(home, 'src'), + '-t', home, + ]); + assert(fs.existsSync(docs), 'Expected the docs directory to be created but it is missing'); + const test_html = path.join(docs, 'test.html'); + assert(fs.existsSync(test_html), `Expected file ${test_html} but it was not created`); + const test_content = fs.readFileSync(test_html); + assert(test_content.includes('Strong test'), `Markdown not processed correctly in ${test_html}`); + assert(test_content.includes('Code test'), `Markdown not processed correctly in ${test_html}`); + done(); + done(); + }); }); diff --git a/test/resources/test6.xmir b/test/resources/test6.xmir new file mode 100644 index 00000000..e409de40 --- /dev/null +++ b/test/resources/test6.xmir @@ -0,0 +1,55 @@ + + + + # **Strong test** +# `Code test` +[args] &gt; app + QQ.io.stdout &gt; @ + &quot;Test passed!&quot; + + + **Strong test**\n`Code test` + + + + + + + + 54-65-73-74-20-70-61-73-73-65-64-21 + + + + + + validate-before-stars + resolve-before-stars + wrap-method-calls + const-to-dataized + stars-to-tuples + vars-float-up + move-voids-up + validate-objects-count + build-fqns + expand-qqs + expand-aliases + resolve-aliases + add-default-package + roll-bases + cti-adds-errors + decorate + add-as-attributes-inside-application + st-hex + + +s \ No newline at end of file From 712f4ca94db95a6309138c3aa042d5635f348fce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D0=B5=D0=BD=D1=86=D0=B0=20=D0=94=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=98=D0=B3=D0=BE=D1=80=D0=B5=D0=B2=D0=B8=D1=87?= Date: Thu, 9 Oct 2025 13:41:50 +0300 Subject: [PATCH 14/22] Added cheerio implementation and support for markdown to html conversion --- package.json | 3 ++- src/commands/docs.js | 16 +++++++--------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 1ca0d856..5a214166 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,8 @@ "relative": "^3.0.2", "semver": "^7.7.2", "sync-request": "^6.1.0", - "xmlhttprequest": "^1.8.0" + "xmlhttprequest": "^1.8.0", + "cheerio": "^1.1.2" }, "description": "A collection of command line tools for EOLANG: compiling, parsing, transpiling to other languages, optimizing, and analyzing", "devDependencies": { diff --git a/src/commands/docs.js b/src/commands/docs.js index 022bc1cb..a5da8d4b 100644 --- a/src/commands/docs.js +++ b/src/commands/docs.js @@ -6,7 +6,7 @@ const fs = require('fs'); const path = require('path'); const SaxonJS = require('saxon-js'); -const { JSDOM } = require('jsdom'); +const cheerio = require('cheerio'); const marked = require('marked'); /** @@ -60,15 +60,13 @@ function transformDocument(xmir, xsl) { * @return {String} HTML document */ function convertMarkdownToHtml(html) { - const dom = new JSDOM(html); - const doc = dom.window.document; - const description_elements = doc.querySelectorAll('div.object-desc'); - description_elements.forEach(desc => { - const markdown_text = desc.innerHTML; + const parser = cheerio.load(html); + parser('div.object-desc').each(function() { + const markdown_text = parser(this).text(); const converted_html = marked.parse(markdown_text); - desc.innerHTML = converted_html; - }); - return doc.body.innerHTML; + parser(this).html(converted_html); + }); + return parser('body').html(); } /** From b4d68dd6c15e760d99d55d8e0ec86a2c28d0898e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D0=B5=D0=BD=D1=86=D0=B0=20=D0=94=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=98=D0=B3=D0=BE=D1=80=D0=B5=D0=B2=D0=B8=D1=87?= Date: Thu, 9 Oct 2025 13:46:01 +0300 Subject: [PATCH 15/22] Added marked to package.json --- package.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 5a214166..46587c57 100644 --- a/package.json +++ b/package.json @@ -6,16 +6,17 @@ "dependencies": { "@langchain/core": "^0.3.55", "@langchain/openai": "^0.6.0", + "cheerio": "^1.1.2", "colors": "^1.4.0", "commander": "^12.1.0", "eo2js": "^0.0.8", "fast-xml-parser": "^5.2.3", + "marked": "^16.4.0", "node": "^24.1.0", "relative": "^3.0.2", "semver": "^7.7.2", "sync-request": "^6.1.0", - "xmlhttprequest": "^1.8.0", - "cheerio": "^1.1.2" + "xmlhttprequest": "^1.8.0" }, "description": "A collection of command line tools for EOLANG: compiling, parsing, transpiling to other languages, optimizing, and analyzing", "devDependencies": { From 05fb9f5bb81f3f27e387c26b694be2037ba94d15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D0=B5=D0=BD=D1=86=D0=B0=20=D0=94=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=98=D0=B3=D0=BE=D1=80=D0=B5=D0=B2=D0=B8=D1=87?= Date: Thu, 9 Oct 2025 14:08:02 +0300 Subject: [PATCH 16/22] removed typo, added empty lines --- test/resources/test4.xmir | 2 +- test/resources/test5.xmir | 2 +- test/resources/test6.xmir | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/test/resources/test4.xmir b/test/resources/test4.xmir index 23881e56..44b95c8b 100644 --- a/test/resources/test4.xmir +++ b/test/resources/test4.xmir @@ -53,4 +53,4 @@ add-as-attributes-inside-application st-hex - \ No newline at end of file + diff --git a/test/resources/test5.xmir b/test/resources/test5.xmir index 668cdbe3..7757c120 100644 --- a/test/resources/test5.xmir +++ b/test/resources/test5.xmir @@ -46,4 +46,4 @@ add-as-attributes-inside-application st-hex - \ No newline at end of file + diff --git a/test/resources/test6.xmir b/test/resources/test6.xmir index e409de40..4eb35495 100644 --- a/test/resources/test6.xmir +++ b/test/resources/test6.xmir @@ -52,4 +52,3 @@ st-hex -s \ No newline at end of file From 6b964dcc60ad328158aeb9b76b7440b9d533ab70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D0=B5=D0=BD=D1=86=D0=B0=20=D0=94=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=98=D0=B3=D0=BE=D1=80=D0=B5=D0=B2=D0=B8=D1=87?= Date: Thu, 9 Oct 2025 14:21:46 +0300 Subject: [PATCH 17/22] removed typo --- test/commands/test_docs.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/commands/test_docs.js b/test/commands/test_docs.js index d26ce6ba..f3435ad3 100644 --- a/test/commands/test_docs.js +++ b/test/commands/test_docs.js @@ -176,6 +176,5 @@ describe('docs', () => { assert(test_content.includes('Strong test'), `Markdown not processed correctly in ${test_html}`); assert(test_content.includes('Code test'), `Markdown not processed correctly in ${test_html}`); done(); - done(); }); }); From 054846142ce06c8bd94acbf9f8cb399de3b1e216 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D0=B5=D0=BD=D1=86=D0=B0=20=D0=94=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=98=D0=B3=D0=BE=D1=80=D0=B5=D0=B2=D0=B8=D1=87?= Date: Thu, 9 Oct 2025 14:50:51 +0300 Subject: [PATCH 18/22] replaced cheerio module with jsdom --- package.json | 2 +- src/commands/docs.js | 16 +++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 46587c57..9351c9d5 100644 --- a/package.json +++ b/package.json @@ -6,11 +6,11 @@ "dependencies": { "@langchain/core": "^0.3.55", "@langchain/openai": "^0.6.0", - "cheerio": "^1.1.2", "colors": "^1.4.0", "commander": "^12.1.0", "eo2js": "^0.0.8", "fast-xml-parser": "^5.2.3", + "jsdom": "^27.0.0", "marked": "^16.4.0", "node": "^24.1.0", "relative": "^3.0.2", diff --git a/src/commands/docs.js b/src/commands/docs.js index a5da8d4b..022bc1cb 100644 --- a/src/commands/docs.js +++ b/src/commands/docs.js @@ -6,7 +6,7 @@ const fs = require('fs'); const path = require('path'); const SaxonJS = require('saxon-js'); -const cheerio = require('cheerio'); +const { JSDOM } = require('jsdom'); const marked = require('marked'); /** @@ -60,13 +60,15 @@ function transformDocument(xmir, xsl) { * @return {String} HTML document */ function convertMarkdownToHtml(html) { - const parser = cheerio.load(html); - parser('div.object-desc').each(function() { - const markdown_text = parser(this).text(); + const dom = new JSDOM(html); + const doc = dom.window.document; + const description_elements = doc.querySelectorAll('div.object-desc'); + description_elements.forEach(desc => { + const markdown_text = desc.innerHTML; const converted_html = marked.parse(markdown_text); - parser(this).html(converted_html); - }); - return parser('body').html(); + desc.innerHTML = converted_html; + }); + return doc.body.innerHTML; } /** From 42fedd5cecdc7b854ee3d8255aae80ff73cc3af0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D0=B5=D0=BD=D1=86=D0=B0=20=D0=94=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=98=D0=B3=D0=BE=D1=80=D0=B5=D0=B2=D0=B8=D1=87?= Date: Thu, 9 Oct 2025 15:41:22 +0300 Subject: [PATCH 19/22] Replaced jsdom with regular expressions --- src/commands/docs.js | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/commands/docs.js b/src/commands/docs.js index 022bc1cb..46c290d0 100644 --- a/src/commands/docs.js +++ b/src/commands/docs.js @@ -6,7 +6,6 @@ const fs = require('fs'); const path = require('path'); const SaxonJS = require('saxon-js'); -const { JSDOM } = require('jsdom'); const marked = require('marked'); /** @@ -60,15 +59,11 @@ function transformDocument(xmir, xsl) { * @return {String} HTML document */ function convertMarkdownToHtml(html) { - const dom = new JSDOM(html); - const doc = dom.window.document; - const description_elements = doc.querySelectorAll('div.object-desc'); - description_elements.forEach(desc => { - const markdown_text = desc.innerHTML; - const converted_html = marked.parse(markdown_text); - desc.innerHTML = converted_html; - }); - return doc.body.innerHTML; + const regex = /(]*>)([\s\S]*?)(<\/div>)/gi; + const converted_html = html.replace(regex, (match, opening_tag, content, closing_tag) => { + return `${opening_tag}${marked.parse(content)}${closing_tag}`; + }); + return converted_html; } /** From 211e60ca901cd680d78d68b148668a2958b5609e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D0=B5=D0=BD=D1=86=D0=B0=20=D0=94=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=98=D0=B3=D0=BE=D1=80=D0=B5=D0=B2=D0=B8=D1=87?= Date: Thu, 9 Oct 2025 15:58:49 +0300 Subject: [PATCH 20/22] added dynamic import of marked --- src/commands/docs.js | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/commands/docs.js b/src/commands/docs.js index 46c290d0..9c5d4633 100644 --- a/src/commands/docs.js +++ b/src/commands/docs.js @@ -6,7 +6,6 @@ const fs = require('fs'); const path = require('path'); const SaxonJS = require('saxon-js'); -const marked = require('marked'); /** * Recursively reads all .xmir files from a directory. @@ -58,11 +57,10 @@ function transformDocument(xmir, xsl) { * @param {String} html - text of HTML file * @return {String} HTML document */ -function convertMarkdownToHtml(html) { - const regex = /(]*>)([\s\S]*?)(<\/div>)/gi; - const converted_html = html.replace(regex, (match, opening_tag, content, closing_tag) => { - return `${opening_tag}${marked.parse(content)}${closing_tag}`; - }); +async function convertMarkdownToHtml(html) { + const { marked } = await import('marked'); + const regex = /(?]*>)(?[\s\S]*?)(?<\/div>)/gi; + const converted_html = html.replace(regex, (match, opening_tag, content, closing_tag) => `${opening_tag}${marked.parse(content)}${closing_tag}`); return converted_html; } @@ -71,11 +69,11 @@ function convertMarkdownToHtml(html) { * @param {String} xmir_path - path of XMIR * @return {String} HTML block */ -function createXmirHtmlBlock(xmir_path) { +async function createXmirHtmlBlock(xmir_path) { try { const xmir = fs.readFileSync(xmir_path).toString(); const xsl = fs.readFileSync(path.join(__dirname, '..', 'resources', 'xmir-transformer.xsl')).toString(); - return convertMarkdownToHtml(transformDocument(xmir, xsl)); + return await convertMarkdownToHtml(transformDocument(xmir, xsl)); } catch(error) { throw new Error(`Error while applying XSL to XMIR: ${error.message}`, error); } @@ -140,7 +138,7 @@ module.exports = async function(opts) { for (const xmir of xmirs) { const relative = path.relative(input, xmir); const name = path.parse(xmir).name; - const xmir_html = createXmirHtmlBlock(xmir); + const xmir_html = await createXmirHtmlBlock(xmir); const html_app = path.join(output, path.dirname(relative),`${name}.html`); fs.mkdirSync(path.dirname(html_app), {recursive: true}); fs.writeFileSync(html_app, wrapHtml(name, xmir_html, css)); From 1819bd1a4779bf7ecf9d47f1cd8ccaf6deb36c10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D0=B5=D0=BD=D1=86=D0=B0=20=D0=94=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=98=D0=B3=D0=BE=D1=80=D0=B5=D0=B2=D0=B8=D1=87?= Date: Thu, 9 Oct 2025 16:13:50 +0300 Subject: [PATCH 21/22] removed unnecessary dependencies from package.json --- package.json | 1 - src/commands/docs.js | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/package.json b/package.json index 9351c9d5..9031cb99 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,6 @@ "commander": "^12.1.0", "eo2js": "^0.0.8", "fast-xml-parser": "^5.2.3", - "jsdom": "^27.0.0", "marked": "^16.4.0", "node": "^24.1.0", "relative": "^3.0.2", diff --git a/src/commands/docs.js b/src/commands/docs.js index 9c5d4633..3c87670d 100644 --- a/src/commands/docs.js +++ b/src/commands/docs.js @@ -58,7 +58,7 @@ function transformDocument(xmir, xsl) { * @return {String} HTML document */ async function convertMarkdownToHtml(html) { - const { marked } = await import('marked'); + const { marked } = await import('marked'); // eslint-disable-line const regex = /(?]*>)(?[\s\S]*?)(?<\/div>)/gi; const converted_html = html.replace(regex, (match, opening_tag, content, closing_tag) => `${opening_tag}${marked.parse(content)}${closing_tag}`); return converted_html; From 7dc8ea0e576f26db337cb89e56dcd37c62b2f6ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D0=B5=D0=BD=D1=86=D0=B0=20=D0=94=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=98=D0=B3=D0=BE=D1=80=D0=B5=D0=B2=D0=B8=D1=87?= Date: Thu, 9 Oct 2025 16:25:24 +0300 Subject: [PATCH 22/22] using older version of marked --- package.json | 2 +- src/commands/docs.js | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 9031cb99..264ab744 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "commander": "^12.1.0", "eo2js": "^0.0.8", "fast-xml-parser": "^5.2.3", - "marked": "^16.4.0", + "marked": "^4.3.0", "node": "^24.1.0", "relative": "^3.0.2", "semver": "^7.7.2", diff --git a/src/commands/docs.js b/src/commands/docs.js index 3c87670d..1f5ba47d 100644 --- a/src/commands/docs.js +++ b/src/commands/docs.js @@ -6,6 +6,7 @@ const fs = require('fs'); const path = require('path'); const SaxonJS = require('saxon-js'); +const { marked } = require('marked'); /** * Recursively reads all .xmir files from a directory. @@ -57,8 +58,7 @@ function transformDocument(xmir, xsl) { * @param {String} html - text of HTML file * @return {String} HTML document */ -async function convertMarkdownToHtml(html) { - const { marked } = await import('marked'); // eslint-disable-line +function convertMarkdownToHtml(html) { const regex = /(?]*>)(?[\s\S]*?)(?<\/div>)/gi; const converted_html = html.replace(regex, (match, opening_tag, content, closing_tag) => `${opening_tag}${marked.parse(content)}${closing_tag}`); return converted_html; @@ -69,11 +69,11 @@ async function convertMarkdownToHtml(html) { * @param {String} xmir_path - path of XMIR * @return {String} HTML block */ -async function createXmirHtmlBlock(xmir_path) { +function createXmirHtmlBlock(xmir_path) { try { const xmir = fs.readFileSync(xmir_path).toString(); const xsl = fs.readFileSync(path.join(__dirname, '..', 'resources', 'xmir-transformer.xsl')).toString(); - return await convertMarkdownToHtml(transformDocument(xmir, xsl)); + return convertMarkdownToHtml(transformDocument(xmir, xsl)); } catch(error) { throw new Error(`Error while applying XSL to XMIR: ${error.message}`, error); } @@ -138,7 +138,7 @@ module.exports = async function(opts) { for (const xmir of xmirs) { const relative = path.relative(input, xmir); const name = path.parse(xmir).name; - const xmir_html = await createXmirHtmlBlock(xmir); + const xmir_html = createXmirHtmlBlock(xmir); const html_app = path.join(output, path.dirname(relative),`${name}.html`); fs.mkdirSync(path.dirname(html_app), {recursive: true}); fs.writeFileSync(html_app, wrapHtml(name, xmir_html, css));