//// Copyright (C) 2026 Fluxer Contributors //// //// This file is part of Fluxer. //// //// Fluxer is free software: you can redistribute it and/or modify //// it under the terms of the GNU Affero General Public License as published by //// the Free Software Foundation, either version 3 of the License, or //// (at your option) any later version. //// //// Fluxer is distributed in the hope that it will be useful, //// but WITHOUT ANY WARRANTY; without even the implied warranty of //// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //// GNU Affero General Public License for more details. //// //// You should have received a copy of the GNU Affero General Public License //// along with Fluxer. If not, see . import fluxer_marketing/help_center import fluxer_marketing/locale import fluxer_marketing/markdown_utils import fluxer_marketing/render_md import gleam/string import gleeunit import gleeunit/should pub fn main() { gleeunit.main() } fn empty_help_data() -> help_center.HelpCenterData { help_center.HelpCenterData(categories: [], all_articles: []) } fn without_anchor_style(html: String) -> String { html |> string.replace( " style=\"scroll-margin-top: var(--anchor-offset, 96px)\"", "", ) |> string.replace( " style=\"scroll-margin-top: var(--anchor-offset, 200px)\"", "", ) } pub fn render_simple_paragraph_test() { render_md.render( "Hello world!", "https://example.com", locale.EnUS, empty_help_data(), ) |> should.equal("

Hello world!

") } pub fn render_paragraph_with_line_breaks_test() { render_md.render( "Line one\nLine two", "https://example.com", locale.EnUS, empty_help_data(), ) |> should.equal("

Line one
Line two

") } pub fn render_multiple_paragraphs_test() { render_md.render( "First paragraph\n\nSecond paragraph", "https://example.com", locale.EnUS, empty_help_data(), ) |> should.equal("

First paragraph

\n\n

Second paragraph

") } pub fn render_header_followed_by_paragraph_without_blank_line_test() { render_md.render( "## Heading\nParagraph on next line", "https://example.com", locale.EnUS, empty_help_data(), ) |> without_anchor_style |> should.equal( "

Heading

\n\n

Paragraph on next line

", ) } pub fn render_header_followed_by_list_without_blank_line_test() { render_md.render( "## Table of contents\n- One\n- Two", "https://example.com", locale.EnUS, empty_help_data(), ) |> without_anchor_style |> should.equal( "

Table of contents

\n\n", ) } pub fn render_setext_header_followed_by_list_without_blank_line_test() { render_md.render( "Heading\n-----\n- First\n- Second", "https://example.com", locale.EnUS, empty_help_data(), ) |> without_anchor_style |> should.equal( "

Heading

\n\n", ) } pub fn render_h1_atx_test() { render_md.render( "# Heading 1", "https://example.com", locale.EnUS, empty_help_data(), ) |> should.equal( "

Heading 1

", ) } pub fn render_h2_atx_test() { render_md.render( "## Heading 2", "https://example.com", locale.EnUS, empty_help_data(), ) |> should.equal( "

Heading 2

", ) } pub fn render_h3_atx_test() { render_md.render( "### Heading 3", "https://example.com", locale.EnUS, empty_help_data(), ) |> should.equal( "

Heading 3

", ) } pub fn render_h6_atx_test() { render_md.render( "###### Heading 6", "https://example.com", locale.EnUS, empty_help_data(), ) |> should.equal( "
Heading 6
", ) } pub fn render_header_with_custom_id_test() { render_md.render( "## Heading with anchor {#custom-id}", "https://example.com", locale.EnUS, empty_help_data(), ) |> should.equal( "

Heading with anchor

", ) } pub fn render_arabic_header_with_custom_id_test() { render_md.render( "## مرحبًا بك في Fluxer {#welcome-to-fluxer}", "https://example.com", locale.Ar, empty_help_data(), ) |> should.equal( "

مرحبًا بك في Fluxer

", ) } pub fn render_numbered_heading_slug_test() { render_md.render( "## 16. Contact Us", "https://example.com", locale.EnUS, empty_help_data(), ) |> without_anchor_style |> should.equal("

16. Contact Us

") } pub fn render_heading_with_punctuation_slug_test() { render_md.render( "### 9. Disclaimers, Limitation of Liability, and Indemnification", "https://example.com", locale.EnUS, empty_help_data(), ) |> without_anchor_style |> should.equal( "

9. Disclaimers, Limitation of Liability, and Indemnification

", ) } pub fn render_h1_setext_test() { render_md.render( "Heading 1\n=========", "https://example.com", locale.EnUS, empty_help_data(), ) |> should.equal( "

Heading 1

", ) } pub fn render_h2_setext_test() { render_md.render( "Heading 2\n---------", "https://example.com", locale.EnUS, empty_help_data(), ) |> should.equal( "

Heading 2

", ) } pub fn render_horizontal_rule_test() { render_md.render("---", "https://example.com", locale.EnUS, empty_help_data()) |> should.equal("
") } pub fn render_unordered_list_test() { render_md.render( "- Item 1\n- Item 2\n- Item 3", "https://example.com", locale.EnUS, empty_help_data(), ) |> should.equal( "", ) } pub fn render_ordered_list_test() { render_md.render( "1. Item 1\n2. Item 2\n3. Item 3", "https://example.com", locale.EnUS, empty_help_data(), ) |> should.equal( "
    \n
  1. Item 1
  2. \n
  3. Item 2
  4. \n
  5. Item 3
  6. \n
", ) } pub fn render_mixed_list_markers_test() { render_md.render( "* Item 1\n+ Item 2\n- Item 3", "https://example.com", locale.EnUS, empty_help_data(), ) |> should.equal( "", ) } pub fn render_list_with_continuation_test() { render_md.render( "- Item 1\n continuation\n- Item 2", "https://example.com", locale.EnUS, empty_help_data(), ) |> should.equal("") } pub fn render_list_continuation_with_link_test() { let markdown = "- **Request a data export:** Request a full export of your account data\n See [Exporting your account data](/help/en-us/articles/1445731738851475456-exporting-your-account-data) for current limits and details." let expected = "" render_md.render( markdown, "https://example.com", locale.EnUS, empty_help_data(), ) |> without_anchor_style |> should.equal(expected) } pub fn render_list_continuation_with_article_shortcut_test() { let article = help_center.HelpArticle( title: "Exporting your account data", description: "Export data", category: "account-settings", category_title: "Account Settings", category_icon: "gear", order: 1, slug: "exporting-your-account-data", snowflake_id: "111", content: "", ) let help_data = help_center.HelpCenterData(categories: [], all_articles: [article]) let markdown = "- **Request a data export:** Request a full export of your account data\n See <% article 111 %> for current limits and details." let expected = "" render_md.render(markdown, "https://example.com", locale.EnUS, help_data) |> should.equal(expected) } pub fn render_bold_text_test() { render_md.render( "This is **bold** text", "https://example.com", locale.EnUS, empty_help_data(), ) |> should.equal("

This is bold text

") } pub fn render_link_test() { render_md.render( "Visit [Google](https://google.com)", "https://example.com", locale.EnUS, empty_help_data(), ) |> should.equal( "

Visit Google

", ) } pub fn render_link_with_relative_url_test() { render_md.render( "Go to [home](/)", "https://example.com", locale.EnUS, empty_help_data(), ) |> should.equal( "

Go to home

", ) } pub fn render_relative_link_with_trailing_slash_base_test() { render_md.render( "Read our [privacy policy](/privacy).", "https://example.com/", locale.EnUS, empty_help_data(), ) |> should.equal( "

Read our privacy policy.

", ) } pub fn render_relative_link_preserves_absolute_test() { render_md.render( "See [docs](https://docs.example.com/help).", "https://example.com", locale.EnUS, empty_help_data(), ) |> should.equal( "

See docs.

", ) } pub fn render_bold_and_link_test() { render_md.render( "This is **bold** and [linked](http://example.com)", "https://example.com", locale.EnUS, empty_help_data(), ) |> should.equal( "

This is bold and linked

", ) } pub fn render_html_escaping_test() { render_md.render( "This has