Lesson 25 of 45 · Web pages

Pages and text

Most of a web page is text, and HTML has an element for every kind of text: a heading, a paragraph, a quotation, a piece of code, a date. In Salam you write them with plain readable names and the compiler turns them into the HTML tags. This lesson shows each one with an example you can run.

The shape of a page

A page: block holds everything on the page. Before the first element you can set things that belong to the page itself: title is the text on the browser tab, lang and dir say which language and which direction the text has, and background, color and the other style properties at that level paint the whole page. Everything else is an element. An element opens with its name and a colon and closes with end, and what goes between is attributes and child elements, written as name = value with no commas.

The text of an element is its content attribute. It is always plain text: a < or an & in it is shown as it is and never becomes markup, so text that comes from a user can never break the page. Put several words in one string, or build a string with + from constants and numbers.

web-text-article.salam
page:
    title = "A short article"
    global: selector = "body" font family = "system-ui, sans-serif" max width = "34rem" margin = "2rem auto" line height = 1.6 end
    heading group:
        h1: content = "Why we write pages in Salam" end
        paragraph:
            content = "Published "
            time: datetime = "2026-10-26" content = "26 October 2026" end
        end
    end
    paragraph: content = "A page is a tree of elements. Each element has a name, some attributes and sometimes children." end
    heading: size = 2 content = "One language" end
    paragraph: content = "The page and the program that serves it are written in the same language, so a name that is wrong is found while compiling." end
    line: end
    small: content = "Written for the Salam course." end
end

The preview above is the real page the compiler built. The global line is a style rule for the whole page, and you will meet it again in the CSS lessons; here it only gives the page a readable font and a comfortable width.

Headings

Headings give a page its outline. heading takes a size from 1 to 6, and h1 to h6 are the same thing under their HTML names. Use a single level 1 for the title of the page and then go down one level at a time: a level 3 belongs under a level 2, not directly under a level 1. Browsers draw the levels in decreasing sizes, but choose the level for its meaning and change the size with CSS. When a heading has a subtitle, wrap both in a heading group as the example above does.

Paragraphs, breaks and rules

paragraph is a block of text, and browsers leave space above and below it. Inside a paragraph, break starts a new line, which is right for an address or a poem and wrong as a way to add space, because empty space is a job for CSS. line draws a horizontal rule between two topics, and word break marks where a long word may be cut if it does not fit.

A paragraph can hold child elements next to its own content. The content text always comes first, and the children follow in the order you write them. So a sentence with a bold word in the middle is written as the first part in content, then the bold element, then a span with the rest. The span is a neutral container: it adds no meaning and no look of its own, which makes it the element for styling a few words.

Emphasis and inline text

Inline elements live inside a line of text. Several of them look alike in the browser and differ in meaning, and the meaning is what screen readers and search engines use. strong is important text and bold is only bold type. emphasis is stress, the word you say louder, and italic is a different voice, such as a foreign word. mark highlights what is relevant right now, strikethrough shows what is no longer true, and small is for small print. subscript and superscript raise and lower text for formulas. code, keyboard, sample and variable are the four ways to write about computers.

web-text-inline.salam
page:
    title = "Inline text"
    global: selector = "body" font family = "system-ui, sans-serif" margin = "1.5rem" line height = 1.7 end
    paragraph:
        content = "Water is H"
        subscript: content = "2" end
        span: content = "O and energy is E = mc" end
        superscript: content = "2" end
        span: content = ". " end
        strong: content = "Do not" end
        span: content = " drink the " end
        emphasis: content = "second" end
        span: content = " glass. Press " end
        keyboard: content = "Ctrl + S" end
        span: content = " to save, or call " end
        code: content = "save()" end
        span: content = " from your code. " end
        mark: content = "This part is highlighted." end
    end
end

Pick the element for what the text is, not for how it looks. Looks change in CSS in one place, but the meaning stays with the text, and a reader that cannot see your page, such as a screen reader, depends on it.

Quotations, code and preformatted text

quote is a short quotation inside a sentence and browsers add the quotation marks. block quote is a longer quotation set apart from the text. Both can take a cite attribute with the address of the source, and cite as an element names a work such as a book or a film. For a listing where every space and line break matters, use preformatted: it shows its text in a monospace font and keeps the layout exactly. Write a line break inside the string as \n.

web-text-quote.salam
page:
    title = "Quotes and code"
    global: selector = "body" font family = "system-ui, sans-serif" margin = "1.5rem" end
    block quote:
        cite = "https://example.com/essay"
        content = "Everything should be made as simple as possible, but no simpler."
    end
    paragraph:
        content = "From "
        cite: content = "an essay on design" end
        span: content = ", as she put it: " end
        quote: content = "start small" end
        span: content = "." end
    end
    preformatted:
        content = "func main:\n    println \"Hello\"\nend"
        background = "#f3f4f6"
        padding = "12px"
        border radius = "8px"
    end
end

Edits, dates and abbreviations

deleted and inserted show what was taken out and what was put in, and both accept a datetime and a cite. time holds a date or a time in words for people and in a fixed format in its datetime for programs, and data does the same for any other value. An abbreviation keeps its full form in title, and definition marks the word that a sentence defines.

web-text-edits.salam
page:
    title = "Edits and abbreviations"
    global: selector = "body" font family = "system-ui, sans-serif" margin = "1.5rem" line height = 1.7 end
    paragraph:
        content = "The meeting moved from "
        deleted: datetime = "2026-10-26" content = "Monday" end
        span: content = " to " end
        inserted: datetime = "2026-10-26" content = "Tuesday" end
        span: content = "." end
    end
    paragraph:
        definition: content = "Salam" end
        span: content = " is written in " end
        abbreviation: title = "Cascading Style Sheets" content = "CSS" end
        span: content = " and " end
        abbreviation: title = "HyperText Markup Language" content = "HTML" end
        span: content = " for you." end
    end
    paragraph:
        content = "Price: "
        strikethrough: content = "$20" end
        span: content = " " end
        data: value = "15" content = "$15" end
    end
end

Mixed directions and ruby

A page in English often contains a Persian name, and a Persian page often contains an English one. Browsers decide the order of such text by a standard algorithm that usually works, but a name at the edge of a sentence can still pull the punctuation to the wrong side. Wrap a piece of text of unknown direction in isolate and it is laid out on its own, without affecting its neighbours. direction override is the blunt tool: it forces one direction whatever the characters say. ruby places a small annotation, usually a pronunciation, above the base text.

web-text-direction.salam
page:
    title = "Mixed directions"
    global: selector = "body" font family = "system-ui, sans-serif" margin = "1.5rem" line height = 1.8 end
    paragraph:
        content = "Comment from "
        isolate: content = "محمد" end
        span: content = " and from " end
        isolate: content = "Sara" end
        span: content = "." end
    end
    paragraph:
        content = "Forced: "
        direction override: dir = "rtl" content = "abc 123" end
    end
    paragraph:
        ruby:
            content = "東京"
            ruby text: content = "Tōkyō" end
        end
    end
end

Reference: every text element

Each element below is shown with a short example. Wherever an element has attributes of its own they are listed under it, and the attributes that every element has are in the lesson on the head and global attributes. The examples are checked by the compiler, so you can paste any of them inside a page: block. Persian names work in any file, and the Persian lessons use them.

heading (Persian: سرتیتر; HTML: <h1>)

A heading. The size attribute chooses the level, from 1 (the largest and most important) to 6. Search engines and screen readers build the outline of your page from its headings, so use one level 1 per page and do not skip levels.

heading: size = 2 content = "Our story" end
AttributeWhat it doesExample
size
اندازه
The heading level as a whole number from 1 to 6. Without it the heading is level 1, and a number outside the range is cut to the nearest level, so 7 gives a level 6. [int]heading: size = 3 content = "Opening hours" end

h1 (HTML: <h1>)

A level 1 heading written with its HTML name. heading with size = 1 produces exactly the same tag.

h1: content = "Welcome" end

h2 (HTML: <h2>)

A level 2 heading, used for the main sections under the page title.

h2: content = "Features" end

h3 (HTML: <h3>)

A level 3 heading, used for subsections of a level 2 section.

h3: content = "Speed" end

h4 (HTML: <h4>)

A level 4 heading.

h4: content = "Benchmarks" end

h5 (HTML: <h5>)

A level 5 heading.

h5: content = "Method" end

h6 (HTML: <h6>)

A level 6 heading, the smallest of the six.

h6: content = "Footnote" end

heading group (Persian: گروه سرتیتر; HTML: <hgroup>)

Groups a heading with its subtitle or tagline so they count as one heading in the outline.

heading group:
    h1: content = "Salam" end
    paragraph: content = "A language for the web and beyond" end
end

paragraph (Persian: پاراگراف; HTML: <p>)

A paragraph of text. It is the element you will use most. Browsers put space above and below it.

paragraph: content = "Salam compiles to fast native code." end

span (Persian: تکه; HTML: <span>)

A neutral inline container with no meaning of its own. Use it to style or script a few words inside a line of text.

paragraph:
    content = "The total is "
    span: content = "42" color = "crimson" end
end

break (Persian: شکست; HTML: <br>)

A line break inside a paragraph. It is a void element, so it takes no content. Use it for poems and addresses, not to add vertical space.

paragraph:
    content = "First line"
    break: end
    span: content = "Second line" end
end

Void element, it cannot have children

line (Persian: خط; HTML: <hr>)

A thematic break, drawn as a horizontal rule. It marks a change of topic between paragraphs.

line: end

Void element, it cannot have children

word break (Persian: شکست واژه; HTML: <wbr>)

Marks a place where the browser may break a very long word if it needs to. It is invisible otherwise.

paragraph:
    content = "super"
    word break: end
    span: content = "cali" end
    word break: end
    span: content = "fragilistic" end
end

Void element, it cannot have children

bold (Persian: پررنگ; HTML: <b>)

Draws attention to text with bold type without saying it is important, such as a product name in a review.

paragraph:
    content = "Try the "
    bold: content = "Pro" end
    span: content = " plan." end
end

strong (Persian: قوی; HTML: <strong>)

Text of strong importance. Browsers show it in bold and screen readers may stress it.

paragraph:
    strong: content = "Warning:" end
    span: content = " this cannot be undone." end
end

italic (Persian: کج; HTML: <i>)

Text set apart from its surroundings in tone or voice, such as a technical term or a thought. Browsers show it in italics.

paragraph:
    content = "The word "
    italic: content = "salam" end
    span: content = " means peace." end
end

emphasis (Persian: تاکید; HTML: <em>)

Stress emphasis, the word you would say louder. Browsers show it in italics and screen readers stress it.

paragraph:
    content = "I said "
    emphasis: content = "never" end
    span: content = "." end
end

underline (Persian: زیرخط; HTML: <u>)

Text with an unarticulated annotation, such as a misspelling mark. Do not use it for links, because readers expect underlined text to be clickable.

paragraph:
    content = "Check the "
    underline: content = "speling" end
    span: content = " here." end
end

strikethrough (Persian: خط خورده; HTML: <s>)

Text that is no longer accurate or relevant, drawn with a line through it, such as an old price.

paragraph:
    strikethrough: content = "$20" end
    span: content = " $15 today" end
end

small (Persian: ریز; HTML: <small>)

Side comments and small print, such as copyright lines and legal notes. Browsers show it one size smaller.

small: content = "Prices include VAT." end

mark (Persian: برجسته; HTML: <mark>)

Highlights text because it is relevant right now, like a search match. Browsers paint it with a yellow background.

paragraph:
    content = "Results for "
    mark: content = "salam" end
    span: content = ": 12 pages" end
end

subscript (Persian: زیرنویس; HTML: <sub>)

Text set lower than the line, as in chemical formulas.

paragraph:
    content = "H"
    subscript: content = "2" end
    span: content = "O" end
end

superscript (Persian: بالانویس; HTML: <sup>)

Text set higher than the line, as in exponents and footnote marks.

paragraph:
    content = "E = mc"
    superscript: content = "2" end
end

code (Persian: کد; HTML: <code>)

A short piece of computer code inside text. Browsers use a monospace font.

paragraph:
    content = "Call "
    code: content = "println" end
    span: content = " to print." end
end

keyboard (Persian: صفحه کلید; HTML: <kbd>)

Text the user types, usually a key or a shortcut.

paragraph:
    content = "Press "
    keyboard: content = "Ctrl + S" end
    span: content = " to save." end
end

sample (Persian: نمونه خروجی; HTML: <samp>)

Sample output from a program, shown in a monospace font.

paragraph:
    content = "The program printed "
    sample: content = "Hello, World" end
end

variable (Persian: متغیر; HTML: <var>)

The name of a variable in a formula or in programming text. Browsers show it in italics.

paragraph:
    content = "The area is "
    variable: content = "w" end
    span: content = " times " end
    variable: content = "h" end
end

abbreviation (Persian: کوته‌نوشت; HTML: <abbr>)

An abbreviation or acronym. Put the full form in title so it shows when the pointer rests on it.

abbreviation: title = "HyperText Markup Language" content = "HTML" end

definition (Persian: تعریف; HTML: <dfn>)

The term being defined in a sentence that defines it.

paragraph:
    definition: content = "Salam" end
    span: content = " is a compiled language with a built in page language." end
end

cite (Persian: نام اثر; HTML: <cite>)

The title of a creative work, such as a book, a film or a paper. It is not for the name of a person.

paragraph:
    content = "I loved "
    cite: content = "The Little Prince" end
    span: content = "." end
end

quote (Persian: نقل قول; HTML: <q>)

A short quotation that stays inside a paragraph. Browsers put quotation marks around it.

paragraph:
    content = "She said "
    quote: content = "see you soon" end
    span: content = " and left." end
end
AttributeWhat it doesExample
cite
منبع نقل
The address of the page the quotation comes from. It is not shown, but tools can read it. [url]quote: cite = "https://example.com/talk" content = "less is more" end

block quote (Persian: نقل قول بلند; HTML: <blockquote>)

A longer quotation set apart from the text around it, usually indented.

block quote:
    content = "Simplicity is the ultimate sophistication."
end
AttributeWhat it doesExample
cite
منبع نقل
The address of the source of the quotation. [url]block quote: cite = "https://example.com/essay" content = "Make it simple." end

preformatted (Persian: پیش‌قالب; HTML: <pre>)

Text that keeps its spaces and line breaks exactly, shown in a monospace font. It is the right choice for code listings and ASCII art.

preformatted: content = "line one\n    line two" end

time (Persian: زمان; HTML: <time>)

A date or a time. The readable text can be anything, and datetime gives the exact value for programs.

time: datetime = "2026-10-26" content = "26 October 2026" end
AttributeWhat it doesExample
datetime
زمان دقیق
The machine readable date or time, such as 2026-10-26 or 2026-10-26T09:30. [datetime]time: datetime = "2026-10-26T09:30" content = "9:30 in the morning" end

data (Persian: داده; HTML: <data>)

Links readable text to a value a program can use, such as a product number. value is required.

data: value = "4021" content = "Green tea" end

Required: value

AttributeWhat it doesExample
value
مقدار
The machine readable value. It is required. [string]data: value = "7" content = "seven" end

deleted (Persian: حذف شده; HTML: <del>)

Text that was removed from a document. Browsers draw it with a line through it.

paragraph:
    content = "Meet at "
    deleted: content = "5 pm" end
    inserted: content = "6 pm" end
end
AttributeWhat it doesExample
cite
منبع نقل
The address of a page that explains why the text was removed. [url]deleted: cite = "https://example.com/changes" content = "old text" end
datetime
زمان دقیق
When the text was removed, as a date or a date and time. [datetime]deleted: datetime = "2026-10-26" content = "old text" end

inserted (Persian: افزوده; HTML: <ins>)

Text that was added to a document. Browsers underline it.

inserted: content = "New in this version" end
AttributeWhat it doesExample
cite
منبع نقل
The address of a page that explains why the text was added. [url]inserted: cite = "https://example.com/changes" content = "new text" end
datetime
زمان دقیق
When the text was added, as a date or a date and time. [datetime]inserted: datetime = "2026-10-26T09:30" content = "new text" end

ruby (Persian: آوانما; HTML: <ruby>)

Annotation for East Asian and other scripts, a small pronunciation guide shown above or beside the base text. It holds the base text plus ruby text elements.

ruby:
    content = "漢"
    ruby text: content = "han" end
end

ruby text (Persian: متن آوانما; HTML: <rt>)

The small annotation text of a ruby.

ruby:
    content = "東京"
    ruby text: content = "Tōkyō" end
end

Only inside: ruby

ruby parenthesis (Persian: پرانتز آوانما; HTML: <rp>)

Parentheses shown only by browsers that cannot draw ruby, so the annotation still reads as 漢(han).

ruby:
    content = "漢"
    ruby parenthesis: content = "(" end
    ruby text: content = "han" end
    ruby parenthesis: content = ")" end
end

Only inside: ruby

isolate (Persian: جداساز جهت; HTML: <bdi>)

Isolates a piece of text from the direction of the text around it. It is the safe way to put a name of unknown direction, such as a user name, inside a sentence.

paragraph:
    content = "User "
    isolate: content = "محمد" end
    span: content = " left a comment." end
end

direction override (Persian: جهت اجباری; HTML: <bdo>)

Forces the direction of its text, ignoring what the characters say. dir is required.

direction override: dir = "rtl" content = "abc 123" end

Required: dir

Try it yourself

  • Write a recipe page with a level 1 title, an ordered list of steps and a time for the cooking time.
  • Take the article above and add a block quote with a cite and a mark on the sentence you want people to notice.
  • Change a strong to a bold and a bold to a strong. Does the page look different? What would a screen reader do?