RFC 2070

Internationalization of the Hypertext Markup Language

๐Ÿ“… published January 1997, from ietf

RFC 2070: Internationalization of the Hypertext Markup Language ๐ŸŒธ

  • Number: RFC 2070
  • Title: Internationalization of the Hypertext Markup Language
  • Written by: F. Yergeau (Alis Technologies), G. Nicol (Electronic Book Technologies), G. Adams (Spyglass), and M. Duerst (University of Zurich)
  • Group: Network Working Group
  • Category: Standards Track
  • Date: January 1997
  • Obsoletes / Updates: the title block doesn't list anything here ๐Ÿซถ

Status of This Memo ๐Ÿ“ฎ

okay so this bit is the official "here's what this doc is" part ๐Ÿ’… It says this is an Internet standards track protocol spec for the Internet community, and it's asking everyone to talk about it and send over ideas for making it better ๐Ÿซถ For the current standardization state and status of this protocol, go check the current edition of the "Internet Official Protocol Standards" (STD 1) ๐Ÿ“š And the distribution of this memo is unlimited, so share it with everyone bestie ๐ŸŒˆ

Abstract โœจ

HTML (the Hypertext Markup Language) is a markup language people use to make hypertext documents that are platform independent ๐Ÿ’– Early on, HTML on the World Wide Web was seriously held back because it relied on the ISO-8859-1 coded character set, which only really works for Western European languages ๐Ÿ˜ญ People still used HTML with other languages anyway, using other coded character sets or character encodings, but that came at the expense of interoperability ๐Ÿ’€

This document is all about fixing that: the internationalization (i18n, i followed by 18 letters followed by n) of HTML ๐ŸŒ It does this by extending the HTML specification and giving extra recommendations for doing internationalization properly ๐ŸŽ€ The biggest priority is making sure HTML stays a valid application of SGML, while also letting it be used with all the languages of the world ๐Ÿ‘‘

Table of Contents ๐Ÿ—‚๏ธ

   1.  Introduction .................................................. 2
     1.1. Scope ...................................................... 2
     1.2. Conformance ................................................ 3
   2. The document character set ..................................... 4
     2.1. Reference processing model ................................. 4
     2.2. The document character set ................................. 6
     2.3. Undisplayable characters ................................... 8

   3. The LANG attribute.............................................. 8
   4. Additional entities, attributes and elements ................... 9
     4.1. Full Latin-1 entity set .................................... 9
     4.2. Markup for language-dependent presentation ................ 10
   5. Forms ..........................................................16
     5.1. DTD additions ..............................................16
     5.2. Form submission ............................................17
   6. External character encoding issues .............................18
   7. HTML public text ...............................................20
     7.1. HTML DTD ...................................................20
     7.2. SGML declaration for HTML ..................................35
     7.3. ISO Latin 1 character entity set ...........................37
   8. Security Considerations.........................................40
   Bibliography ......................................................40
   Authors' Addresses ................................................43

1. Introduction ๐Ÿฆ‹

okay so HTML is a markup language for making platform independent hypertext docs ๐Ÿ’– At the start, it was super limited on the Web because it leaned on ISO-8859-1, which is only good for Western European languages ๐Ÿ™ˆ People got creative anyway and used HTML with other languages through a bunch of ad hoc extensions to the language [TAKADA], but the interop suffered ๐Ÿ˜ญ

This doc is here to make HTML properly internationalized โœจ It extends the HTML spec and gives extra recommendations for solid i18n support ๐ŸŒธ It's partly based on a paper one of the authors wrote about multilingualism on the WWW [NICOL] ๐Ÿ“ Same big rule as always: HTML has to remain a valid application of SGML while working with every language on earth ๐ŸŒˆ

The specific things it covers are: the SGML document character set used for HTML, the correct handling of the charset parameter tied to the text/html content type, and some extra elements and entities ๐Ÿ’…

1.1 Scope ๐Ÿ”ญ

HTML has been around for the World-Wide Web (WWW) global information initiative since 1990 ๐Ÿ•ฐ๏ธ This spec extends what HTML 2.0 (RFC 1866) can do, mainly by getting rid of the restriction to the ISO-8859-1 coded character set [ISO-8859] ๐ŸŽ‰

HTML is an application of ISO Standard 8879:1986, Information Processing Text and Office Systems -- Standard Generalized Markup Language (SGML) [ISO-8879] ๐Ÿงš The HTML Document Type Definition (DTD) is the formal definition of HTML syntax written in terms of SGML ๐Ÿ“ This spec amends the HTML 2.0 DTD so it can handle a character repertoire way bigger than ISO-8859-1, and it still stays SGML conformant ๐Ÿ’œ

Both the formal and the actual development of HTML are moving super fast ๐Ÿš€ The features in this doc are designed so they can (and should) be added to other forms of HTML too, not just the one described in RFC 1866 ๐Ÿ“ Wherever it's indicated, attributes introduced here should be extended to the appropriate elements โœจ

1.2 Conformance ๐Ÿ“‹

This spec slightly changes the conformance requirements for HTML documents and HTML user agents ๐ŸŽ€

1.2.1 Documents ๐Ÿ“„

All HTML 2.0 conforming documents stay conforming with this spec ๐Ÿ’– But the extensions here make valid some documents that wouldn't be HTML 2.0 conforming ๐Ÿ‘€ Those are the ones containing characters or character references outside the repertoire of ISO 8859-1, and the ones containing markup introduced in this doc ๐ŸŒˆ

1.2.2. User agents ๐Ÿ–ฅ๏ธ

On top of the requirements in RFC 1866, the following requirements are placed on HTML user agents ๐Ÿ’…

To ensure interoperability and proper support for at least ISO-8859-1 in an environment where character encoding schemes other than ISO-8859-1 are present, user agents MUST correctly interpret the charset parameter accompanying an HTML document received from the network. ๐Ÿ”ฅ

Furthermore, conforming user-agents MUST at least parse correctly all numeric character references within the range of ISO 10646-1 [ISO-10646]. ๐Ÿ‘‘

Conforming user-agents are required to apply the BIDI presentation algorithm if they display right-to-left characters. If there is no displayable right-to-left character in a document, there is no need to apply BIDI processing. ๐Ÿซถ


2. The document character set โœจ

2.1. Reference processing model โœจ

okay so this section is the big-picture model HTML uses, especially the SGML idea of a document character set ๐Ÿ’…. Real implementations can work very differently on the inside, but they should behave like this model to an outside observer ๐Ÿฆ‹.

Because there are tons of text encodings, SGML doesn't directly say how the abstract characters of an SGML document get turned into a sequence of octets (or sometimes bit groups of some other length than 8) in a real file. That's the external character encoding of the concrete document, and you should not mix it up with the document character set of the abstract HTML document ๐Ÿ™ˆ. SGML treats the characters as one set (a "character repertoire") plus a "code set" that gives each character an integer (a "character number"). The document character set declaration says what each character number represents [GOLD90, p. 451]. In most cases, an SGML DTD and every document that refers to it have one document character set, and all markup and data characters are part of that set.

HTML is an application of SGML, and it doesn't directly handle the external character encoding either. That job gets handed off to mechanisms outside HTML, like MIME as used by the HTTP protocol or by electronic mail ๐Ÿ“ฌ.

For the HTTP protocol [RFC2068], the external character encoding is indicated by the "charset" parameter of the "Content-Type" field in the header of an HTTP response. For example, to say the document is encoded in the "JUNET" encoding of Japanese [RFC1468], the header will contain this line:

Content-Type: text/html; charset=ISO-2022-JP

Quick fun fact: in MIME, "charset" is used to mean a character encoding, not just a coded character set like the name suggests ๐Ÿค“. A character encoding is a mapping (possibly many-to-one) of sequences of octets to sequences of characters taken from one or more character repertoires.

HTTP also gives clients a way to say which character encodings they can accept. Clients and servers are strongly requested to use these mechanisms so documents get transmitted and interpreted correctly ๐Ÿซถ. There are also extra things you can do to help with correct interpretation, even when a server or client isn't using these mechanisms yet, and those are described in section 6.

Similarly, if HTML documents are transferred by electronic mail, the external character encoding is defined by the "charset" parameter of the "Content-Type" MIME header field [RFC2045], and it defaults to US-ASCII when that parameter is missing.

Right now, no mechanisms are standardized for indicating the external character encoding of HTML documents that are transferred by FTP or accessed in distributed file systems ๐Ÿฅบ.

If some other way of transferring and storing HTML documents gets defined or becomes popular, it's advised to make similar provisions to clearly identify the character encoding being used, and/or to use a single default encoding that can represent the widest range of characters used in an international context ๐ŸŒˆ.

Whatever the external character encoding may be, the reference processing model translates it to the document character set specified in Section 2.2 before any processing specific to SGML/HTML happens. Here's how it looks:

 [resource]->[decoder]->[entity ]->[ SGML ]->[application]->[display]
                        [manager]  [parser]
                             ^          |
                             |          |
                             +----------+

The decoder is responsible for decoding the external representation of the resource into the document character set. The entity manager, the parser, and the application only deal with characters of the document character set. A display-oriented part of the application, or the display machinery itself, may then convert characters from the document character set into some other representation that's more suitable for its purpose. Either way, the entity manager, the parser, and the application are only using the HTML document character set when it comes to character semantics ๐Ÿงš.

An actual implementation may or may not choose to translate the document into some encoding of the document character set, as described above. The behaviour this reference processing model describes can be achieved in other ways too ๐Ÿ’œ. That said, this whole topic is well out of the scope of this specification, so if you want the details, go check out the SGML standard [ISO-8879] or one of the SGML handbooks [BRYAN88] [GOLD90] [VANH90] [SQ91].

The biggest takeaway from this reference processing model is that numeric character references are always resolved with respect to the fixed document character set. That means they point to the same characters no matter what external encoding was actually used ๐Ÿ‘‘. For an example, check out Section 2.2.

2.2. The document character set ๐Ÿ’–

The document character set, in the SGML sense, is the Universal Character Set (UCS) of ISO 10646:1993 [ISO-10646], as amended. Right now, it's code-by-code identical with the Unicode standard, version 1.1 [UNICODE] ๐ŸŒธ.

NOTE: Implementers should be aware that ISO 10646 gets amended from time to time ๐Ÿ‘€. Four amendments have been adopted since the initial 1993 publication, and none of them significantly affects this specification. A fifth amendment is under consideration, though, and it'll bring incompatible changes: 6556 Korean Hangul syllables that are allocated between code positions 3400 and 4DFF (hexadecimal) will be moved to new positions (and 4516 new syllables will be added), which makes references to the old positions invalid ๐Ÿ˜ญ. The Unicode consortium has already adopted a matching amendment for the upcoming Unicode 2.0, so adoption of DAM 5 is considered likely, and implementers should probably consider the old code positions as already invalid. Even with this one-time change, the relevant standard bodies have committed to never changing any allocated code position in the future ๐Ÿซถ. If you want to encode Korean Hangul no matter what happens with these changes, you can use the conjoining Hangul Jamo in the range 1110-11F9.

Adopting this document character set means changing the SGML declaration that was specified in the HTML 2.0 specification (section 9.5 of [RFC1866]) ๐Ÿ”ง. The change is to remove the first BASESET specification and its accompanying DESCSET declaration, and replace them with the following declaration:

  BASESET "ISO Registration Number 177//CHARSET
           ISO/IEC 10646-1:1993 UCS-4 with implementation level 3
           //ESC 2/5 2/15 4/6"
  DESCSET  0   9     UNUSED
           9   2     9
           11  2     UNUSED
           13  1     13
           14  18    UNUSED
           32  95    32
           127 1     UNUSED
           128 32    UNUSED
           160 2147483486 160

Making UCS the document character set doesn't break any expression, construct, or document that conforms to HTML 2.0 โœ…. It does make some constructs conforming that weren't admissible in HTML 2.0 ๐Ÿ’…. One consequence is that data characters outside the repertoire of ISO-8859-1, but within the repertoire of UCS-4, become valid SGML characters ๐ŸŒ. Another is that the upper limit of the range of numeric character references is extended from 255 to 2147483645, so И is a valid reference to a "CYRILLIC CAPITAL LETTER I" ๐Ÿ‡ท๐Ÿ‡บ. [ERCS] is a good source of information on Unicode and SGML, although its scope and technical content differ a lot from this specification.

NOTE: Just like HTML 2.0's own SGML declaration, the declaration above specifies character numbers 128 to 159 (80 to 9F hex) as UNUSED. That means numeric character references in that range (for example, ’) are illegal in HTML ๐Ÿ™…. Neither ISO 8859-1 nor ISO 10646 contains characters in that range, because it's reserved for control characters.

Another change from the HTML 2.0 SGML declaration was made because the authors' true intent didn't seem to be expressed by the original ๐Ÿค”. The syntax character set declaration was changed from ISO 646.IRV:1983 to the newer ISO 646.IRV:1991. Only the latter is identical with US-ASCII. In principle, this introduces an incompatibility with HTML 2.0, but in practice it should improve interoperability by (i) having the SGML declaration say what everyone already thinks it says, and (ii) making the syntax character set a proper subset of the document character set ๐ŸŽ€. The characters that differ between the two versions of ISO 646.IRV aren't actually used to express HTML syntax, so nothing breaks there ๐Ÿ’•.

ISO 10646-1:1993 is the most encompassing character set that currently exists, and there's no other character set that could take its place as the document character set for HTML ๐ŸŒŸ. If, for some specific application, there's a need to use characters outside this standard, it should be done by avoiding any conflicts with present or future versions of ISO 10646. In other words, you assign those characters to a private zone of the UCS-4 coding space [ISO-10646 section 11] ๐Ÿ”’. Keep in mind that this kind of use will be highly unportable, and in many cases it's better to use inline bitmaps instead ๐Ÿ–ผ๏ธ.

2.3. Undisplayable characters ๐Ÿ™ˆ

With the document character set being the full ISO 10646, there's no way to avoid the possibility that a character can't be displayed because the right resources (fonts) aren't available. There are lots of different things that could be done in that case, so this document doesn't prescribe any specific behaviour ๐Ÿคท. Depending on the implementation, this might also be handled by the underlying display system instead of the application itself. Still, the following considerations may help:

  • A clearly visible, but unobtrusive, behaviour should be preferred. Some documents may contain lots of characters that can't be rendered, so showing an alert for each one is not the right move ๐Ÿ™…โ€โ™€๏ธ.
  • If a numeric representation of the missing character is given, its hexadecimal (not decimal) form is to be preferred, because that's the form used in character set standards [ERCS] ๐Ÿ”ขโœจ.

3. The LANG attribute โœจ

okay so language tags are lowkey the cheat code for how a page looks ๐Ÿ’… they can steer glyph disambiguation (when the character encoding alone can't pick the right glyph ๐Ÿ‘€), quotation marks, hyphenation, ligatures, spacing, voice synthesis, and more ๐ŸŽ€ and even apart from rendering, language markup is super useful as content markup for stuff like classification and searching ๐Ÿ”

since literally any text can be assigned a language, almost every HTML element admits the LANG attribute ๐Ÿ’– the DTD shows this, and the only elements in this version of HTML without it are BR, HR, BASE, NEXTID, and META. any new element in later versions of HTML is also meant to admit LANG, unless there's a really good reason not to ๐Ÿฆ‹

the LANG attribute takes a language tag that names a natural language spoken, written, or otherwise conveyed by humans to share information with other humans. computer languages are explicitly excluded ๐Ÿ™…โ€โ™€๏ธ

the syntax and registry of HTML language tags is the same as the one defined by [RFC1766]. in short, a language tag is made of one or more parts: a primary language tag, plus a possibly empty series of subtags ๐ŸŒธ

language-tag  = primary-tag *( "-" subtag )
primary-tag   = 1*8ALPHA
subtag        = 1*8ALPHA

whitespace isn't allowed inside the tag, and all tags are case-insensitive. the namespace of language tags is administered by the IANA. some example tags are en, en-US, en-cockney, i-cherokee, and x-pig-latin ๐Ÿงš

here's the big twist ๐Ÿคฏ in HTML, a language tag is not a single token like in [RFC1766]. it's a hierarchy! ๐ŸŒณ so a user agent that adjusts rendering by language should consider that it has a match when a language tag in a style sheet entry matches the initial portion of an element's language tag. an exact match should be preferred. this means an element marked en-US can trigger styles for US-English (en-US) or for 'plain' or 'international' English (en), in that order of preference โœจ

NOTE -- using the language tag as a hierarchy does not imply that all languages with a common prefix will be understood by those fluent in one or more of those languages; it simply allows the user to request this commonality when it is true for that user.
ngl this note is so important bestie ๐Ÿ˜ญ a shared prefix doesn't mean you can read it. it just lets the user ask for that similarity when it's actually true for them ๐Ÿซถ

the LANG attribute can affect how elements render ๐ŸŽจ for any element, its own LANG value overrides the LANG value of any enclosing element, and also the value (if any) of the HTTP Content-Language header. if none of these are set, a suitable default should be used to control rendering. that default could come from user preferences, automatic context analysis, or the user's locale ๐ŸŒ


4. Additional entities, attributes and elements ๐ŸŽ€

4.1. Full Latin-1 entity set

following the suggestion in section 14 of [RFC1866], the Latin-1 entity set gets extended to cover the whole right part of ISO-8859-1 (every code position with the high-order bit set) ๐Ÿ‡ซ๐Ÿ‡ท this includes the already super commonly used  , ©, and ®. the entity names come from the appendices of SGML [ISO-8879]. you'll find a list in section 7.3 of this spec ๐Ÿ“‹

4.2. Markup for language-dependent presentation

4.2.1. Overview

so some languages need extra entities and elements to be presented correctly (no matter what the formatting looks like) ๐Ÿ’… the main features covered are:

  • markup of bidirectional text, meaning text where left-to-right and right-to-left scripts get mixed ๐Ÿ”„
  • control of cursive joining behaviour in places where the default isn't appropriate โœ๏ธ
  • language-dependent rendering of short (in-line) quotations ๐Ÿ’ฌ
  • better justification control for languages where it really matters ๐Ÿ“
  • superscripts and subscripts for languages where they show up as part of normal text ๐Ÿ”ข

some of these features need barely any extra support, while others need more. the additional features get introduced below with only brief comments, and the explanations for cursive joining and bidirectional text come later ๐Ÿฆ‹ for both of those, this document follows [UNICODE] in two ways: i) character semantics, where they apply, are identical to [UNICODE], and ii) where functionality moves up into HTML as a higher-level protocol, it's done in a way that makes it straightforward to convert to the lower-level mechanisms defined in [UNICODE] ๐Ÿ’œ

4.2.2. List of entities, elements, and attributes

first up, a generic container is needed to carry the LANG and DIR attributes in cases where no other element fits. that's the SPAN element, introduced just for that ๐Ÿงš

a set of named character entities gets added for bidirectional rendering and cursive joining control:

<!ENTITY zwnj CDATA "&#8204;"--=zero width non-joiner-->
<!ENTITY zwj  CDATA "&#8205;"--=zero width joiner-->
<!ENTITY lrm  CDATA "&#8206;"--=left-to-right mark-->
<!ENTITY rlm  CDATA "&#8207;"--=right-to-left mark-->

you can use these entities in place of the matching formatting characters whenever it's convenient, like when you want to make keyboard entry easier or when a formatting character isn't available in the document's character encoding ๐Ÿ’–

next, there's a DIR attribute, restricted to the values LTR (left-to-right) and RTL (right-to-left), for indicating directionality in bidirectional text (see 4.2.4 below for the details) โžก๏ธโฌ…๏ธ since any text and lots of other elements (like tables) can logically be given a directionality, all elements except BR, HR, BASE, NEXTID, and META admit this attribute ๐Ÿ™Œ the DTD reflects that, and any new element in later HTML versions is also meant to admit DIR, unless there's a good reason not to ๐Ÿซถ

there's also a new phrase-level element called BDO (BIDI Override) ๐Ÿ”€ it requires the DIR attribute to say whether the override is left-to-right or right-to-left. this element is required for bidirectional text control, and you can read the full explanation in section 4.2.4 ๐Ÿ“–

the phrase-level element Q lets short quotations render differently depending on language and platform capability ๐Ÿ’ฌ as the examples below show (kinda poorly, because Internet specs are limited to a certain character set ๐Ÿ˜…), the quotation marks around the quote are the main thing affected:

"a quotation in English", `another, slightly better one', ,,a
quotation in German'', << a quotation in French >>

the contents of the Q element don't include quotation marks. those have to be added by the rendering process โœจ

NOTE -- Q elements can be nested. Many languages use different quotation styles for outer and inner quotations, and this should be respected by user-agents implementing this element.
NOTE -- minimal support for the Q element is to surround the contents with some kind of quotes, like the plain ASCII double quotes. it's really easy to implement, and not showing any visible quotes can change how the text's meaning comes across, so user-agent implementors are strongly requested to provide at least this minimal level of support ๐Ÿ™

many languages need superscript text for proper rendering ๐Ÿ”ข for example, the French "Mlle Dupont" should have "lle" in superscript. the SUP element, plus its sibling SUB for subscript text, get introduced to allow proper markup of this. SUP and SUB contents are restricted to PCDATA to avoid nesting problems ๐Ÿ™…โ€โ™€๏ธ

finally, text justification matters way more in many languages than in Western ones, so it gets its own markup ๐Ÿ“ the ALIGN attribute, with the values LEFT, RIGHT, CENTER, and JUSTIFY, is added to the elements where it makes sense: the block-like P, HR, H1 to H6, OL, UL, DIR, MENU, LI, BLOCKQUOTE, and ADDRESS ๐ŸŽ€ if a user-agent chooses LEFT as the default for blocks of left-to-right directionality, it should use RIGHT for blocks of right-to-left directionality ๐Ÿ”„

NOTE -- [RFC1866] section 4.2.2 says an HTML user agent should treat an end of line as a word space, except in preformatted text. this should be interpreted in the context of the script being processed, because the way words are separated in writing depends on the script. for some scripts (e.g. Latin), a word space is just a space. in other scripts (e.g. Thai) it's a zero-width word separator, and in yet others (e.g. Japanese) it's nothing at all, i.e. totally ignored ๐Ÿ™ˆ
NOTE -- the SOFT HYPHEN character (U+00AD) needs special attention from user-agent implementers ๐Ÿฆ‹ it's present in many character sets (including the whole ISO 8859 series and, of course, ISO 10646), and it can always be included with the reference &shy;. its meaning is different from a plain HYPHEN: it marks a point in a word where a line break is allowed. if the line does break there, a hyphen must be displayed at the end of the first line. if not, the character is not displayed at all. in operations like searching and sorting, it must always be ignored ๐Ÿšซ

in the DTD, the LANG and DIR attributes are grouped together in a parameter entity called attrs ๐Ÿง to match [RFC1942], the ID and CLASS attributes are also included in attrs. the ID and CLASS attributes are required for use with style sheets, and [RFC1942] defines them like this:

ID      Used to define a document-wide identifier. This can be used
        for naming positions within documents as the destination of a
        hypertext link. It may also be used by style sheets for
        rendering an element in a unique style. An ID attribute value is
        an SGML NAME token. NAME tokens are formed by an initial
        letter followed by letters, digits, "-" and "." characters. The
        letters are restricted to A-Z and a-z.

CLASS   A space separated list of SGML NAME tokens. CLASS names
        specify that the element belongs to the corresponding named
        classes. It allows authors to distinguish different roles
        played by the same tag. The classes may be used by style
        sheets to provide different renderings as appropriate to
        these roles.

4.2.3. Cursive joining behaviour

sometimes markup is needed to force cursive joining in places where it wouldn't normally happen, or to block it where it normally would ๐Ÿช„

the zero-width joiner and non-joiner (&zwj; and &zwnj;) are used to control cursive joining behaviour ๐Ÿ’ซ for example, ARABIC LETTER HEH is used on its own to abbreviate "Hijri" (the Islamic calendrical system) ๐ŸŒ™ but the initial form of the letter is what's wanted, because the isolated form of HEH looks like the digit five as used in Arabic script ๐Ÿ˜ณ so you follow the HEH with a zero-width joiner, whose only job is to provide context. in Persian texts, there are cases where a letter that would normally join a following letter in a cursive connection doesn't. that's where a zero-width non-joiner comes in ๐Ÿฆข

4.2.4. Bidirectional text โœจ

okay so some languages get written left to right ๐Ÿ“–, and others go right to left ๐Ÿ”„. When both directions show up in the same text, that's bidirectional text (BIDI for short) ๐Ÿฆ‹. BIDI text needs markup in special situations where the direction of some characters is ambiguous and has to be sorted out. Without that markup, the text can end up looking so mixed up that nothing you render actually matches what it means ๐Ÿ’€. Plain text can carry BIDI markup too, using special-purpose formatting characters ๐Ÿ’….

HTML can do this as well. It supports the five BIDI-related formatting characters (202A - 202E) from ISO 10646 ๐ŸŒธ. It also gives you equivalent SGML markup as an alternative ๐ŸŽ€.

BIDI is a whole complicated thing ๐Ÿ˜ญ. Turning logical text into display order has to follow the algorithm and character properties in [UNICODE] โœจ. I'm only going to explain as much here as you need to get why these features exist and what they exactly mean ๐Ÿงš.

The Unicode BIDI algorithm assumes every character is stored in logical order, which is the order people normally type it and the order the sounds are normally spoken in ๐Ÿซถ. To make logical-order text render properly, the algorithm gives each character a directionality property. For example, Latin letters are left-to-right, and Arabic and Hebrew characters are right-to-left ๐ŸŒˆ.

The left-to-right and right-to-left marks (&lrm; and &rlm;) are how you tell neutral characters which way to go ๐Ÿ™ˆ. Say a double quote sits between an Arabic letter and a Latin letter. Its direction is genuinely ambiguous ๐Ÿ˜ต. If you add a directional mark on one side so the quote is surrounded by characters with only one directionality, the ambiguity goes away โœจ. These marks act kind of like zero width spaces that have a directional property, but no word or line break property ๐Ÿ’œ.

Nested embeddings of opposite-direction text runs are another case where the characters' implicit direction isn't enough, so you need markup ๐Ÿ”ฅ. That happens with nested quotations, or when you paste text from one BIDI context into another ๐Ÿ‘€. It's also often useful to set the base direction of a whole block of text ๐Ÿ“. That's what the DIR attribute is for ๐Ÿ‘‘.

On block-type elements, the DIR attribute sets the base directionality of the text in that block. If it's left out, the block inherits it from its parent element ๐Ÿฆ‹. The default directionality of the whole HTML document is left-to-right ๐Ÿ’–.

On inline elements, DIR starts a new embedding level, which I'll explain in a sec ๐ŸŽ€. If you leave it off, the inline element does not start a new embedding level ๐Ÿ™ƒ.

NOTE -- the PRE, XMP and LISTING elements admit the DIR attribute. Their contents should not be considered as preformatted with respect to bidirectional layout, but the BIDI algorithm should be applied to each line of text. ๐ŸŒธ

Here's an example where you need embedding, and what it actually does ๐Ÿงš. Imagine these latin (uppercase) and arabic (lowercase) letters stored with these embeddings:

<SPAN DIR=LTR> AB <SPAN DIR=RTL> xy <SPAN DIR=LTR> CD </SPAN> zw
</SPAN> EF </SPAN>

With those embeddings you get this rendering, where the [] show the direction changes ๐Ÿซถ:

[ AB [ wz [ CD ] yx ] EF ]

But without this markup, and with a base direction of LTR, you get this instead ๐Ÿ˜ญ:

[ AB [ yx ] CD [ wz ] EF ]

Notice how yx is on the left and wz is on the right in the second one? With the embedding levels, it's the other way around, which is the whole point ๐Ÿ’…. Without embedding markup you only get two levels at most: a base directional level and a single counterflow directional level ๐Ÿ”„.

The DIR attribute on inline elements is equivalent to the formatting characters LEFT-TO-RIGHT EMBEDDING (202A) and RIGHT-TO-LEFT EMBEDDING (202B) from ISO 10646 ๐ŸŒˆ. The element's end tag is equivalent to the POP DIRECTIONAL FORMATTING (202C) character ๐ŸŽ€.

Directional override, which BDO provides, handles those weird short bits of text where the direction just can't be worked out from context ๐Ÿ™ˆ. For example, it can force left-to-right (or right-to-left) display of part numbers made of Latin letters, digits and Hebrew letters ๐Ÿ”ข.

BDO forces every character inside it to the direction given by DIR, no matter what their intrinsic directional properties are ๐Ÿ‘‘. It's equivalent to using the LEFT-TO-RIGHT OVERRIDE (202D) or RIGHT-TO-LEFT OVERRIDE (202E) characters from ISO 10646 ๐Ÿ’–. Again, the end tag is equivalent to the POP DIRECTIONAL FORMATTING (202C) character โœจ.

NOTE -- authors and authoring software writers should be aware that conflicts can arise if the DIR attribute is used on inline elements (including BDO) concurrently with the use of the corresponding ISO 10646 formatting characters. ๐Ÿšจ
Preferably one or the other should be used exclusively; the markup method is better able to guarantee document structural integrity, and alleviates some problems when editing bidirectional HTML text with a simple text editor, but some software may be more apt at using the 10646 characters. If both methods are used, great care should be exercised to insure proper nesting of markup and directional embedding or override; otherwise, rendering results are undefined. ๐Ÿ’€

5. Forms ๐Ÿ’…

5.1. DTD additions

It's totally natural to expect people to type in any language in forms ๐ŸŒ, since forms are basically one of the only ways to get user input ๐Ÿ“. This is mostly a UI thing, but some stuff should be spelled out at the HTML level so it guides behaviour and keeps things interoperable ๐Ÿซถ.

To make sure everything works fully together, the user agent (and the user) needs to know which character encoding(s) the server handling the form can accept once the form is submitted ๐Ÿ”. That info comes from the ACCEPT-CHARSET attribute on the INPUT and TEXTAREA elements โœจ. It's modeled on the HTTP Accept-Charset header (see [HTTP-1.1]), and it holds a space and/or comma delimited list of character sets the server is okay with ๐ŸŽ€. A user agent may want to let the user know what's in this attribute, or limit what they can type to the character repertoires of the listed sets ๐Ÿฆ‹.

NOTE -- The list of character sets is to be interpreted as an EXCLUSIVE-OR list; the server announces that it is ready to accept any ONE of these character encoding schemes for each part of a multipart entity. The client may perform character encoding translation to satisfy the server if necessary. ๐Ÿงš
NOTE -- The default value for the ACCEPT-CHARSET attribute of an INPUT or TEXTAREA element is the reserved value "UNKNOWN". A user agent may interpret that value as the character encoding scheme that was used to transmit the document containing that element. ๐ŸŒธ

5.2. Form submission

The HTML 2.0 form submission mechanism is based on the application/x-www-form-urlencoded media type ๐Ÿ“ฎ. Honestly it's kind of akward ๐Ÿ˜ฌ when it comes to internationalization. URLs are restricted to ASCII characters, so it's clunky even for ISO-8859-1 text ๐Ÿ™ƒ. Section 2.2 of [RFC1738] says octets can be encoded with the %HH notation ๐Ÿ”ข. But text submitted from a form is made of characters, not octets ๐Ÿซ . Without a character encoding scheme specified, the %HH notation doesn't have a well-defined meaning ๐Ÿ’€.

The best solution is to use the multipart/form-data media type described in [RFC1867] with the POST method for form submission ๐Ÿ‘‘. This encapsulates the value part of each name-value pair in a body-part of a multipart MIME body, which gets sent as the HTTP entity โœจ. Each body part can be labeled with an appropriate Content-Type, including, if needed, a charset parameter that specifies the character encoding scheme ๐ŸŒˆ. The DTD changes needed to support this form submission method are already included in the DTD in this specification ๐ŸŽ€.

A less satisfying solution is to add a MIME charset parameter to the application/x-www-form-urlencoded media type specifier sent with a POST method form submission ๐Ÿฅบ. The understanding there is that the URL encoding of [RFC1738] gets applied on top of the specified character encoding, kind of like an implicit Content-Transfer-Encoding ๐Ÿฆ‹.

One problem with both of those solutions is that current browsers don't generally let bookmarks specify the POST method ๐Ÿ˜ค. That should be improved ๐Ÿ”ง. On the flip side, the GET method could send the form data in the body instead of the URL ๐Ÿค”. Nothing in the protocol seems to stop it, but no implementations appear to exist right now ๐Ÿ™ˆ.

How the user agent figures out the encoding of the text the user typed is outside the scope of this specification ๐Ÿ’….

NOTE -- Designers of forms and their handling scripts should be aware of an important caveat: when the default value of a field (the VALUE attribute) is returned upon form submission (i.e. the user did not modify this value), it cannot be guaranteed to be transmitted as a sequence of octets identical to that in the source document -- only as a possibly different but valid encoding of the same sequence of text elements. This may be true even if the encoding of the document containing the form and that used for submission are the same. ๐Ÿšจ
Differences can occur when a sequence of characters can be represented by various sequences of octets, and also when a composite sequence (a base character plus one or more combining diacritics) can be represented by either a different but equivalent composite sequence or by a fully precomposed character. For instance, the UCS-2 sequence 00EA+0323 (LATIN SMALL LETTER E WITH CIRCUMFLEX ACCENT + COMBINING DOT BELOW) may be transformed into 1EC7 (LATIN SMALL LETTER E WITH CIRCUMFLEX ACCENT AND DOT BELOW), into 0065+0302+0323 (LATIN SMALL LETTER E + COMBINING CIRCUMFLEX ACCENT + COMBINING DOT BELOW), as well as into other equivalent composite sequences. ๐Ÿงโœจ

6. External character encoding issues โœจ

okay so, to read a text doc properly you need to know its character encoding, bestie ๐Ÿค“. The problem is that current HTTP servers usually don't send a charset parameter in the Content-Type header ๐Ÿ˜ญ. That's bad behaviour, and it's honestly enabled by browsers that treat a media type as unrecognized when they get a charset parameter ๐Ÿ’€. User agent implementors are strongly encouraged to make their software tolerant of this parameter, even if they can't use it yet ๐Ÿซถ. Proper labelling is highly desirable, but there are some preventive measures that cut down the damage when it's missing ๐Ÿฆ‹:

In the case where a document is accessed from a hyperlink in an origin HTML document, a CHARSET attribute is added to the attribute list of elements with link semantics (A and LINK), specifically by adding it to the linkExtraAttributes entity. The value of that attribute is to be considered a hint to the User Agent as to the character encoding scheme used by the resource pointed to by the hyperlink. It should be the appropriate value of the MIME charset parameter for that resource ๐ŸŒธ.

In any document, you can include an indication of the encoding scheme like this, as early as possible within the HEAD of the document โœจ:

 <META HTTP-EQUIV="Content-Type"
  CONTENT="text/html; charset=ISO-2022-JP">

This isn't foolproof ๐Ÿ™ˆ, but it works if the encoding scheme is such that ASCII-valued octets stand for ASCII characters only, at least until the META element gets parsed. Also, there are better ways for a server to get encoding info than this unreliable META thing. See [NICOL2] for some details and a proposal ๐Ÿ’œ.

For definiteness, the "charset" parameter received from the source of the document should be considered the most authoritative ๐Ÿ‘‘. After that, in order of preference, comes the contents of a META element like the one above, and finally the CHARSET parameter of the anchor that was followed (if any) ๐Ÿ“.

When HTML text is sent directly in UCS-2 or UCS-4 form, the question of byte order comes up: does the high-order byte of each multi-byte character come first or last? ๐Ÿค” For definiteness, this specification recommends that UCS-2 and UCS-4 be transmitted in big-endian byte order (high order byte first). That matches the established network byte order for two- and four-byte quantities, the ISO 10646 requirement and Unicode recommendation for serialized text data, and RFC 1641 ๐Ÿงš. To maximize the chances of proper interpretation, it's recommended that documents sent as UCS-2 or UCS-4 always begin with a ZERO-WIDTH NON-BREAKING SPACE character (hexadecimal FEFF or 0000FEFF). When byte-reversed, that becomes the number FFFE or FFFE0000, a character that's guaranteed to never be assigned. So if a user-agent receives an FFFE as the first octets of a text, it knows the bytes have to be reversed for the rest of the text ๐Ÿ”ฅ.

There are so-called UCS Transformation Formats that can be used to transmit UCS data, in addition to UCS-2 and UCS-4 ๐Ÿ’…. UTF-7 [RFC1642] and UTF-8 [UTF-8] have really good properties (no byte-ordering problem, different flavours of ASCII compatibility) that make them worth a look, especially for sending multilingual text ๐ŸŒˆ. Another encoding scheme, MNEM [RFC1345], also has interesting properties and can transmit the full UCS โœจ. The UTF-1 transformation format of ISO 10646:1993 (registered by IANA as ISO-10646-UTF-1) has been removed from ISO 10646 by amendment 4, so it should not be used ๐Ÿ’€.


7. HTML Public Text

7.1. HTML DTD

This section has a DTD for HTML, based on the HTML 2.0 DTD of RFC 1866. It also includes the file upload changes from RFC 1867, plus the changes that come from this document ๐ŸŽ€.

 <!--    html.dtd

         Document Type Definition for the HyperText Markup Language,
         extended for internationalisation (HTML DTD)

         Last revised: 96/08/07

      Authors: Daniel W. Connolly <connolly@w3.org>
                  Francois Yergeau <yergeau@alis.com>
      See Also:
        http://www.w3.org/hypertext/WWW/MarkUp/MarkUp.html
 -->

 <!ENTITY % HTML.Version
         "-//IETF//DTD HTML i18n//EN"

         -- Typical usage:

             <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML i18n//EN">
             <html>
             ...
             </html>
         --
         >


 <!--============ Feature Test Entities ========================-->

 <!ENTITY % HTML.Recommended "IGNORE"
      -- Certain features of the language are necessary for
         compatibility with widespread usage, but they may
         compromise the structural integrity of a document.
         This feature test entity enables a more prescriptive
         document type definition that eliminates
         those features.
      -->

 <![ %HTML.Recommended [
         <!ENTITY % HTML.Deprecated "IGNORE">
 ]]>
 <!ENTITY % HTML.Deprecated "INCLUDE"
      -- Certain features of the language are necessary for
         compatibility with earlier versions of the specification,
         but they tend to be used and implemented inconsistently,
         and their use is deprecated. This feature test entity
         enables a document type definition that eliminates
         these features.
      -->

 <!ENTITY % HTML.Highlighting "INCLUDE"
      -- Use this feature test entity to validate that a
         document uses no highlighting tags, which may be
         ignored on minimal implementations.
      -->

 <!ENTITY % HTML.Forms "INCLUDE"
         -- Use this feature test entity to validate that a document
            contains no forms, which may not be supported in minimal
            implementations
         -->

 <!--============== Imported Names ==============================-->

 <!ENTITY % Content-Type "CDATA"
         -- meaning an internet media type
            (aka MIME content type, as per RFC2045)
         -->

 <!ENTITY % HTTP-Method "GET | POST"
         -- as per HTTP specification, RFC2068
         -->

 <!--========= DTD "Macros" =====================-->

 <!ENTITY % heading "H1|H2|H3|H4|H5|H6">

 <!ENTITY % list " UL | OL | DIR | MENU " >

 <!ENTITY % attrs -- common attributes for elements --
          "LANG  NAME      #IMPLIED  -- RFC 1766 language tag --
           DIR  (ltr|rtl)  #IMPLIED  -- text directionnality --
           ID      ID      #IMPLIED  -- element identifier
                                        (from RFC1942) --
           CLASS   NAMES   #IMPLIED  -- for subclassing elements
                                        (from RFC1942) --">

 <!ENTITY % just -- an attribute for text justification --
          "ALIGN  (left|right|center|justify)  #IMPLIED"
          -- default is left for ltr paragraphs, right for rtl -- >

 <!--======= Character mnemonic entities =================-->

 <!ENTITY % ISOlat1 PUBLIC
   "ISO 8879-1986//ENTITIES Added Latin 1//EN//HTML">
 %ISOlat1;

 <!ENTITY amp CDATA "&#38;"     -- ampersand          -->
 <!ENTITY gt CDATA "&#62;"      -- greater than       -->
 <!ENTITY lt CDATA "&#60;"      -- less than          -->
 <!ENTITY quot CDATA "&#34;"    -- double quote       -->

 <!--Entities for language-dependent presentation (BIDI and
     contextual analysis) -->
 <!ENTITY zwnj CDATA "&#8204;"-- zero width non-joiner-->
 <!ENTITY zwj  CDATA "&#8205;"-- zero width joiner-->
 <!ENTITY lrm  CDATA "&#8206;"-- left-to-right mark-->
 <!ENTITY rlm  CDATA "&#8207;"-- right-to-left mark-->


 <!--========= SGML Document Access (SDA) Parameter Entities =====-->

 <!-- HTML contains SGML Document Access (SDA) fixed attributes
 in support of easy transformation to the International Committee
 for Accessible Document Design (ICADD) DTD
       "-//EC-USA-CDA/ICADD//DTD ICADD22//EN".
 ICADD applications are designed to support usable access to
 structured information by print-impaired individuals through
 Braille, large print and voice synthesis.  For more information on
 SDA & ICADD:
         - ISO 12083:1993, Annex A.8, Facilities for Braille,
        large print and computer voice
         - ICADD ListServ
        <ICADD%ASUACAD.BITNET@ARIZVM1.ccit.arizona.edu>
         - Usenet news group bit.listserv.easi
         - Recording for the Blind, +1 800 221 4792
 -->

 <!ENTITY % SDAFORM  "SDAFORM  CDATA  #FIXED"
        -- one to one mapping        -->
 <!ENTITY % SDARULE  "SDARULE  CDATA  #FIXED"
        -- context-sensitive mapping -->
 <!ENTITY % SDAPREF  "SDAPREF  CDATA  #FIXED"
        -- generated text prefix     -->
 <!ENTITY % SDASUFF  "SDASUFF  CDATA  #FIXED"
        -- generated text suffix     -->
 <!ENTITY % SDASUSP  "SDASUSP  NAME   #FIXED"

        -- suspend transform process -->


 <!--========== Text Markup =====================-->

 <![ %HTML.Highlighting [

 <!ENTITY % font " TT | B | I ">

 <!ENTITY % phrase "EM | STRONG | CODE | SAMP | KBD | VAR | CITE ">

 <!ENTITY % text "#PCDATA|A|IMG|BR|%phrase|%font|SPAN|Q|BDO|SUP|SUB">

 <!ELEMENT (%font;|%phrase) - - (%text)*>
 <!ATTLIST ( TT | CODE | SAMP | KBD | VAR )
         %attrs;
         %SDAFORM; "Lit"
         >

 <!ATTLIST ( B | STRONG )
         %attrs;
         %SDAFORM; "B"
         >
 <!ATTLIST ( I | EM | CITE )
         %attrs;
         %SDAFORM; "It"
         >

 <!-- <TT>       Typewriter text                         -->
 <!-- <B>        Bold text                               -->
 <!-- <I>        Italic text                             -->

 <!-- <EM>       Emphasized phrase                       -->
 <!-- <STRONG>   Strong emphasis                         -->
 <!-- <CODE>     Source code phrase                      -->
 <!-- <SAMP>     Sample text or characters               -->
 <!-- <KBD>      Keyboard phrase, e.g. user input        -->
 <!-- <VAR>      Variable phrase or substitutable        -->
 <!-- <CITE>     Name or title of cited work             -->

 <!ENTITY % pre.content "#PCDATA|A|HR|BR|%font|%phrase|SPAN|BDO">

 ]]>

 <!ENTITY % text "#PCDATA|A|IMG|BR|SPAN|Q|BDO|SUP|SUB">

 <!ELEMENT BR    - O EMPTY>
 <!ATTLIST BR

         %SDAPREF; "&#RE;"
         >

 <!-- <BR>       Line break      -->

 <!ELEMENT SPAN - - (%text)*>
 <!ATTLIST SPAN
         %attrs;
         %SDAFORM; "other #Attlist"
 >

 <!-- <SPAN>             Generic inline container  -->
 <!-- <SPAN DIR=...>     New counterflow embedding -->
 <!-- <SPAN LANG="...">  Language of contents      -->

 <!ELEMENT Q - - (%text)*>
 <!ATTLIST Q
         %attrs;
         %SDAPREF; '"'
         %SDASUFF; '"'
         >

 <!-- <Q>         Short quotation              -->
 <!-- <Q LANG=xx> Language of quotation is xx  -->
 <!-- <Q DIR=...> New conterflow embedding     -->

 <!ELEMENT BDO - - (%text)+>
 <!ATTLIST BDO
         LANG   NAME      #IMPLIED
         DIR    (ltr|rtl) #REQUIRED
         ID     ID        #IMPLIED
         CLASS  NAMES     #IMPLIED
         %SDAPREF "Bidi Override #Attval(DIR): "
         %SDASUFF "End Bidi"
         >

 <!-- <BDO DIR=...>   Override directionality of text to value of DIR -->
 <!-- <BDO LANG=...>  Language of contents                            -->

 <!ELEMENT (SUP|SUB) - - (#PCDATA)>
 <!ATTLIST (SUP)
         %attrs;
         %SDAPREF "Superscript(#content)"
         >
 <!ATTLIST (SUB)
         %attrs;
         %SDAPREF "Subscript(#content)"
         >

okay bestie, the DTD is about to get SO good ๐Ÿ’– the link markup is up first ๐Ÿ”—

   <!-- <SUP>      Superscript              -->
   <!-- <SUB>      Subscript                -->

   <!--========= Link Markup ======================-->

   <!ENTITY % linkType "NAMES">

   <!ENTITY % linkExtraAttributes
           "REL %linkType #IMPLIED
           REV %linkType #IMPLIED
           URN CDATA #IMPLIED
           TITLE CDATA #IMPLIED
           METHODS NAMES #IMPLIED
           CHARSET NAME #IMPLIED
           ">

   <![ %HTML.Recommended [
           <!ENTITY % A.content   "(%text)*"

           -- <H1><a name="xxx">Heading</a></H1>
                   is preferred to
              <a name="xxx"><H1>Heading</H1></a>
           -->
   ]]>

   <!ENTITY % A.content   "(%heading|%text)*">

   <!ELEMENT A     - - %A.content -(A)>
   <!ATTLIST A
           %attrs;
           HREF CDATA #IMPLIED
           NAME CDATA #IMPLIED
           %linkExtraAttributes;
           %SDAPREF; "<Anchor: #AttList>"
           >
   <!-- <A>       Anchor; source/destination of link -->
   <!-- <A NAME="..."> Name of this anchor           -->
   <!-- <A HREF="..."> Address of link destination        -->
   <!-- <A URN="...">  Permanent address of destination   -->
   <!-- <A REL=...>    Relationship to destination        -->
   <!-- <A REV=...>    Relationship of destination to this     -->
   <!-- <A TITLE="...">     Title of destination (advisory)         -->
   <!-- <A METHODS="...">   Operations on destination (advisory)    -->
   <!-- <A CHARSET="...">   Charset of destination (advisory)  -->
   <!-- <A LANG="...">     Language of contents btw <A> and </A>   -->
   <!-- <A DIR=...>        Contents is a new counterflow embedding -->

ngl the <A> element is giving main character energy ๐Ÿ‘‘ it's the star of the link markup, no notes

now the images ๐Ÿ–ผ๏ธ IMG is an empty element, so it's all attributes and no body, very minimalist, I love a clean aesthetic ๐Ÿฆ‹

   <!--========== Images ==========================-->
   <!ELEMENT IMG    - O EMPTY>
   <!ATTLIST IMG
           %attrs;
           SRC CDATA  #REQUIRED
           ALT CDATA #IMPLIED
           ALIGN (top|middle|bottom) #IMPLIED
           ISMAP (ISMAP) #IMPLIED
           %SDAPREF; "<Fig><?SDATrans Img: #AttList>#AttVal(Alt)</Fig>"
           >

   <!-- <IMG>              Image; icon, glyph or illustration      -->
   <!-- <IMG SRC="...">    Address of image object                 -->
   <!-- <IMG ALT="...">    Textual alternative                     -->
   <!-- <IMG ALIGN=...>    Position relative to text               -->
   <!-- <IMG LANG=...>     Image contains "text" in that language  -->
   <!-- <IMG DIR=...>      Inline image acts as a RTL or LTR
                           embedding w/r to BIDI algorithm         -->
   <!-- <IMG ISMAP>        Each pixel can be a link                -->

   <!--========== Paragraphs=======================-->

   <!ELEMENT P     - O (%text)*>
   <!ATTLIST P
           %attrs;
           %just;
           %SDAFORM; "Para"
           >

   <!-- <P>             Paragraph                           -->
   <!-- <P LANG="...">  Language of paragraph text          -->
   <!-- <P DIR=...>     Base directionality of paragraph    -->
   <!-- <P ALIGN=...>   Paragraph alignment (justification) -->

   <!--========== Headings, Titles, Sections ===============-->

   <!ELEMENT HR    - O EMPTY>
   <!ATTLIST HR
           %just;
           %SDAPREF; "&#RE;&#RE;"
           >

   <!-- <HR>       Horizontal rule -->

   <!ELEMENT ( %heading )  - -  (%text;)*>
   <!ATTLIST H1
           %attrs;
           %just;
           %SDAFORM; "H1"
           >
   <!ATTLIST H2
           %attrs;
           %just;
           %SDAFORM; "H2"
           >
   <!ATTLIST H3
           %attrs;
           %just;
           %SDAFORM; "H3"
           >
   <!ATTLIST H4
           %attrs;
           %just;
           %SDAFORM; "H4"
           >
   <!ATTLIST H5
           %attrs;
           %just;
           %SDAFORM; "H5"
           >
   <!ATTLIST H6
           %attrs;
           %just;
           %SDAFORM; "H6"
           >

   <!-- <H1>       Heading, level 1 -->
   <!-- <H2>       Heading, level 2 -->
   <!-- <H3>       Heading, level 3 -->
   <!-- <H4>       Heading, level 4 -->
   <!-- <H5>       Heading, level 5 -->
   <!-- <H6>       Heading, level 6 -->


   <!--========== Text Flows ======================-->

   <![ %HTML.Forms [
           <!ENTITY % block.forms "BLOCKQUOTE | FORM | ISINDEX">
   ]]>

   <!ENTITY % block.forms "BLOCKQUOTE">

   <![ %HTML.Deprecated [
           <!ENTITY % preformatted "PRE | XMP | LISTING">
   ]]>

   <!ENTITY % preformatted "PRE">
   <!ENTITY % block "P | %list | DL
           | %preformatted
           | %block.forms">

   <!ENTITY % flow "(%text|%block)*">

   <!ENTITY % pre.content "#PCDATA | A | HR | BR | SPAN | BDO">
   <!ELEMENT PRE - - (%pre.content)*>
   <!ATTLIST PRE
           %attrs;
           WIDTH NUMBER #implied
           %SDAFORM; "Lit"
           >

   <!-- <PRE>              Preformatted text                    -->
   <!-- <PRE WIDTH=...>    Maximum characters per line          -->
   <!-- <PRE DIR=...>      Base direction of preformatted block -->
   <!-- <PRE LANG=...>     Language of contents                 -->

   <![ %HTML.Deprecated [

   <!ENTITY % literal "CDATA"
           -- historical, non-conforming parsing mode where
              the only markup signal is the end tag
              in full
           -->

   <!ELEMENT (XMP|LISTING) - -  %literal>
   <!ATTLIST XMP
           %attrs;
           %SDAFORM; "Lit"
           %SDAPREF; "Example:&#RE;"
           >
   <!ATTLIST LISTING
           %attrs;
           %SDAFORM; "Lit"
           %SDAPREF; "Listing:&#RE;"
           >

   <!-- <XMP>              Example section         -->
   <!-- <LISTING>          Computer listing        -->

   <!ELEMENT PLAINTEXT - O %literal>
   <!-- <PLAINTEXT>        Plain text passage      -->

   <!ATTLIST PLAINTEXT
           %attrs;
           %SDAFORM; "Lit"
           >
   ]]>

the deprecated bits are wrapped up in their own little ]]> blankets ๐Ÿงธ very cosy, very careful of them

lists are next and they're SO organised ๐Ÿ“‹ definition lists, ordered, unordered, directory, menu... the whole gang ๐Ÿ“

   <!--========== Lists ==================-->

   <!ELEMENT DL    - -  (DT | DD)+>
   <!ATTLIST DL
           %attrs;
           COMPACT (COMPACT) #IMPLIED
           %SDAFORM; "List"
           %SDAPREF; "Definition List:"
           >

   <!ELEMENT DT    - O (%text)*>
   <!ATTLIST DT
           %attrs;
           %SDAFORM; "Term"
           >

   <!ELEMENT DD    - O %flow>
   <!ATTLIST DD
           %attrs;
           %SDAFORM; "LItem"
           >

   <!-- <DL>               Definition list, or glossary    -->
   <!-- <DL COMPACT>       Compact style list              -->
   <!-- <DT>               Term in definition list         -->
   <!-- <DD>               Definition of term              -->

   <!ELEMENT (OL|UL) - -  (LI)+>
   <!ATTLIST OL
           %attrs;
           %just;
           COMPACT (COMPACT) #IMPLIED
           %SDAFORM; "List"
           >
   <!ATTLIST UL
           %attrs;
           %just;
           COMPACT (COMPACT) #IMPLIED
           %SDAFORM; "List"
           >
   <!-- <UL>               Unordered list                  -->
   <!-- <UL COMPACT>       Compact list style              -->
   <!-- <OL>               Ordered, or numbered list       -->
   <!-- <OL COMPACT>       Compact list style              -->
   <!ELEMENT (DIR|MENU) - -  (LI)+ -(%block)>
   <!ATTLIST DIR
           %attrs;
           %just;
           COMPACT (COMPACT) #IMPLIED
           %SDAFORM; "List"
           %SDAPREF; "<LHead>Directory</LHead>"
           >
   <!ATTLIST MENU
           %attrs;
           %just;
           COMPACT (COMPACT) #IMPLIED
           %SDAFORM; "List"
           %SDAPREF; "<LHead>Menu</LHead>"
           >

   <!-- <DIR>              Directory list                  -->
   <!-- <DIR COMPACT>      Compact list style              -->
   <!-- <MENU>             Menu list                       -->
   <!-- <MENU COMPACT>     Compact list style              -->

   <!ELEMENT LI    - O %flow>
   <!ATTLIST LI
           %attrs;
           %just;
           %SDAFORM; "LItem"
           >

   <!-- <LI>               List item                       -->

   <!--========== Document Body ===================-->

   <![ %HTML.Recommended [
        <!ENTITY % body.content "(%heading|%block|HR|ADDRESS|IMG)*"
        -- <h1>Heading</h1>
           <p>Text ...
             is preferred to
           <h1>Heading</h1>
           Text ...
        -->
   ]]>

   <!ENTITY % body.content "(%heading | %text | %block |
                        HR | ADDRESS)*">

   <!ELEMENT BODY O O  %body.content>
   <!ATTLIST BODY
           %attrs;
           >

   <!-- <BODY>          Document body                -->
   <!-- <BODY DIR=...>  Base direction of whole body -->
   <!-- <BODY LANG=...> Language of contents         -->

   <!ELEMENT BLOCKQUOTE - - %body.content>
   <!ATTLIST BLOCKQUOTE
           %attrs;
           %just;
           %SDAFORM; "BQ"
           >

   <!-- <BLOCKQUOTE>       Quoted passage  -->

   <!ELEMENT ADDRESS - - (%text|P)*>
   <!ATTLIST  ADDRESS
           %attrs;
           %just;
           %SDAFORM; "Lit"
           %SDAPREF; "Address:&#RE;"
           >

   <!-- <ADDRESS> Address, signature, or byline -->


   <!--======= Forms ====================-->

   <![ %HTML.Forms [

   <!ELEMENT FORM - - %body.content -(FORM) +(INPUT|SELECT|TEXTAREA)>
   <!ATTLIST FORM
           %attrs;
           ACTION CDATA #IMPLIED
           METHOD (%HTTP-Method) GET
           ENCTYPE %Content-Type; "application/x-www-form-urlencoded"
           %SDAPREF; "<Para>Form:</Para>"
           %SDASUFF; "<Para>Form End.</Para>"
           >

   <!-- <FORM>                     Fill-out or data-entry form     -->
   <!-- <FORM ACTION="...">        Address for completed form      -->
   <!-- <FORM METHOD=...>          Method of submitting form       -->
   <!-- <FORM ENCTYPE="...">       Representation of form data     -->
   <!-- <FORM DIR=...>             Base direction of form          -->
   <!-- <FORM LANG=...>            Language of contents            -->

   <!ENTITY % InputType "(TEXT | PASSWORD | CHECKBOX |

                           RADIO | SUBMIT | RESET |
                           IMAGE | HIDDEN | FILE )">
   <!ELEMENT INPUT - O EMPTY>
   <!ATTLIST INPUT
           %attrs;
        TYPE %InputType TEXT
        NAME CDATA #IMPLIED
        VALUE CDATA #IMPLIED
        SRC CDATA #IMPLIED
        CHECKED (CHECKED) #IMPLIED
        SIZE CDATA #IMPLIED
        MAXLENGTH NUMBER #IMPLIED
        ALIGN (top|middle|bottom) #IMPLIED
           ACCEPT CDATA #IMPLIED --list of content types --
           ACCEPT-CHARSET CDATA #IMPLIED --list of charsets accepted --
           %SDAPREF; "Input: "
        >

   <!-- <INPUT>               Form input datum        -->
   <!-- <INPUT TYPE=...>           Type of input interaction    -->
   <!-- <INPUT NAME=...>           Name of form datum           -->
   <!-- <INPUT VALUE="...">   Default/initial/selected value -->
   <!-- <INPUT SRC="...">          Address of image        -->
   <!-- <INPUT CHECKED>            Initial state is "on"        -->
   <!-- <INPUT SIZE=...>           Field size hint         -->
   <!-- <INPUT MAXLENGTH=...>      Data length maximum          -->
   <!-- <INPUT ALIGN=...>          Image alignment         -->
   <!-- <INPUT ACCEPT="...">         List of desired media types    -->
   <!-- <INPUT ACCEPT-CHARSET="..."> List of acceptable charsets    -->

   <!ELEMENT SELECT - - (OPTION+) -(INPUT|SELECT|TEXTAREA)>
   <!ATTLIST SELECT
           %attrs;
           NAME CDATA #REQUIRED
           SIZE NUMBER #IMPLIED
           MULTIPLE (MULTIPLE) #IMPLIED
           %SDAFORM; "List"
           %SDAPREF;
           "<LHead>Select #AttVal(Multiple)</LHead>"
        >

   <!-- <SELECT>            Selection of option(s)        -->
   <!-- <SELECT NAME=...>        Name of form datum       -->
   <!-- <SELECT SIZE=...>        Options displayed at a time   -->
   <!-- <SELECT MULTIPLE>        Multiple selections allowed   -->

   <!ELEMENT OPTION - O (#PCDATA)*>
   <!ATTLIST OPTION

the form stuff is where it gets spicy ๐ŸŒˆ INPUT has so many little attributes, it's like a whole makeup bag ๐Ÿ’…

           %attrs;
           SELECTED (SELECTED) #IMPLIED
           VALUE CDATA #IMPLIED
           %SDAFORM; "LItem"
           %SDAPREF;
           "Option: #AttVal(Value) #AttVal(Selected)"
        >

   <!-- <OPTION>            A selection option       -->
   <!-- <OPTION SELECTED>        Initial state            -->
   <!-- <OPTION VALUE="...">     Form datum value for this option-->

   <!ELEMENT TEXTAREA - - (#PCDATA)* -(INPUT|SELECT|TEXTAREA)>
   <!ATTLIST TEXTAREA
           %attrs;
           NAME CDATA #REQUIRED
           ROWS NUMBER #REQUIRED
           COLS NUMBER #REQUIRED
           ACCEPT-CHARSET CDATA #IMPLIED -- list of charsets accepted --
           %SDAFORM; "Para"
           %SDAPREF; "Input Text -- #AttVal(Name): "
           >

   <!-- <TEXTAREA>               An area for text input        -->
   <!-- <TEXTAREA NAME=...> Name of form datum       -->
   <!-- <TEXTAREA ROWS=...> Height of area           -->
   <!-- <TEXTAREA COLS=...> Width of area            -->

   ]]>


   <!--======= Document Head ======================-->

   <![ %HTML.Recommended [
        <!ENTITY % head.extra "">
   ]]>
   <!ENTITY % head.extra "& NEXTID?">

   <!ENTITY % head.content "TITLE & ISINDEX? & BASE? %head.extra">

   <!ELEMENT HEAD O O  (%head.content) +(META|LINK)>
   <!ATTLIST HEAD
           %attrs;           >

   <!-- <HEAD>     Document head   -->

   <!ELEMENT TITLE - -  (#PCDATA)*  -(META|LINK)>
   <!ATTLIST TITLE

           %attrs;
           %SDAFORM; "Ti"    >

   <!-- <TITLE>    Title of document -->

   <!ELEMENT LINK - O EMPTY>
   <!ATTLIST LINK
           %attrs;
           HREF CDATA #REQUIRED
           %linkExtraAttributes;
           %SDAPREF; "Linked to : #AttVal (TITLE) (URN) (HREF)>"    >

   <!-- <LINK>         Link from this document            -->
   <!-- <LINK HREF="...">   Address of link destination        -->
   <!-- <LINK URN="...">    Lasting name of destination        -->
   <!-- <LINK REL=...> Relationship to destination        -->
   <!-- <LINK REV=...> Relationship of destination to this     -->
   <!-- <LINK TITLE="...">  Title of destination (advisory)         -->
   <!-- <LINK CHARSET="..."> Charset of destination (advisory)      -->
   <!-- <LINK METHODS="..."> Operations allowed (advisory)          -->

   <!ELEMENT ISINDEX - O EMPTY>
   <!ATTLIST ISINDEX
           %attrs;
           %SDAPREF;
      "<Para>[Document is indexed/searchable.]</Para>">

   <!-- <ISINDEX>          Document is a searchable index          -->

   <!ELEMENT BASE - O EMPTY>
   <!ATTLIST BASE
           HREF CDATA #REQUIRED     >

   <!-- <BASE>             Base context document                   -->
   <!-- <BASE HREF="...">  Address for this document               -->

   <!ELEMENT NEXTID - O EMPTY>
   <!ATTLIST NEXTID
           N CDATA #REQUIRED     >

   <!-- <NEXTID>       Next ID to use for link name       -->
   <!-- <NEXTID N=...> Next ID to use for link name       -->

   <!ELEMENT META - O EMPTY>
   <!ATTLIST META
           HTTP-EQUIV  NAME    #IMPLIED
           NAME        NAME    #IMPLIED
           CONTENT     CDATA   #REQUIRED    >

   <!-- <META>                     Generic Meta-information        -->
   <!-- <META HTTP-EQUIV=...>      HTTP response header name       -->
   <!-- <META NAME=...>          Meta-information name           -->
   <!-- <META CONTENT="...">       Associated information          -->

   <!--======= Document Structure =================-->

   <![ %HTML.Deprecated [
           <!ENTITY % html.content "HEAD, BODY, PLAINTEXT?">
   ]]>
   <!ENTITY % html.content "HEAD, BODY">

   <!ELEMENT HTML O O  (%html.content)>
   <!ENTITY % version.attr "VERSION CDATA #FIXED '%HTML.Version;'">

   <!ATTLIST HTML
           %attrs;
           %version.attr;
           %SDAFORM; "Book"
           >

   <!-- <HTML>              HTML Document  -->

7.2. SGML Declaration for HTML โœจ

Okay bestie, we've made it to the SGML declaration ๐Ÿงš It's the setup that tells the parser what character set and syntax to expect, so every single line here matters ๐Ÿ’…

   <!SGML  "ISO 8879:1986"
   --
        SGML Declaration for HyperText Markup Language version 2.x
           (HTML 2.x = HTML 2.0 + i18n).

   --

   CHARSET
            BASESET  "ISO Registration Number 177//CHARSET
                      ISO/IEC 10646-1:1993 UCS-4 with
                      implementation level 3//ESC 2/5 2/15 4/6"
            DESCSET  0   9     UNUSED
                     9   2     9
                     11  2     UNUSED
                     13  1     13
                     14  18    UNUSED
                     32  95    32
                     127 1     UNUSED
                     128 32    UNUSED
                     160 2147483486 160
   --
       In ISO 10646, the positions with hexadecimal
       values 0000D800 - 0000DFFF, used in the UTF-16
       encoding of UCS-4, are reserved, as well as the last
       two code values in each plane of UCS-4, i.e. all
       values of the hexadecimal form xxxxFFFE or xxxxFFFF.
       These code values or the corresponding numeric
       character references must not be included when
       generating a new HTML document, and they should be
       ignored if encountered when processing a HTML
       document.
   --

   CAPACITY        SGMLREF
                   TOTALCAP        150000
                   GRPCAP          150000
             ENTCAP         150000

   SCOPE    DOCUMENT

   SYNTAX
            SHUNCHAR CONTROLS 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
              17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 127

            BASESET  "ISO 646IRV:1991//CHARSET
                      International Reference Version
                      (IRV)//ESC 2/8 4/2"
            DESCSET  0 128 0

            FUNCTION
                     RE            13
                     RS            10
                     SPACE         32
                     TAB SEPCHAR    9

            NAMING   LCNMSTRT ""
                     UCNMSTRT ""
                     LCNMCHAR ".-"
                     UCNMCHAR ".-"
                     NAMECASE GENERAL YES
                              ENTITY  NO
            DELIM    GENERAL  SGMLREF
                     SHORTREF SGMLREF
            NAMES    SGMLREF
            QUANTITY SGMLREF
                     ATTSPLEN 2100
                     LITLEN   1024
                     NAMELEN  72    -- somewhat arbitrary; taken from
                                   internet line length conventions --
                     PILEN    1024
                     TAGLVL   100
                     TAGLEN   2100
                     GRPGTCNT 150
                     GRPCNT   64

   FEATURES
     MINIMIZE
       DATATAG  NO
       OMITTAG  YES
       RANK     NO
       SHORTTAG YES
     LINK
       SIMPLE   NO
       IMPLICIT NO
       EXPLICIT NO
     OTHER
       CONCUR   NO
       SUBDOC   NO
       FORMAL   YES
     APPINFO    "SDA"  -- conforming SGML Document Access application
                 --
   >

7.3. ISO Latin 1 entity set โœจ

okay so this next bit is the whole ISO Latin 1 entity set ๐Ÿ’… It's a list of every character in the Added Latin 1 set, and for each one you get its name, how to write it, and what it actually is. The list comes from ISO Standard 8879:1986//ENTITIES Added Latin 1//EN ๐ŸŽ€ HTML takes that entire entity set and also adds entities for every character still missing from the right-hand part of ISO-8859-1, so nothing gets left out ๐Ÿซถ

    <!-- (C) International Organization for Standardization 1986
         Permission to copy in any form is granted for use with
         conforming SGML systems and applications as defined in
         ISO 8879, provided this notice is included in all copies.
      -->
    <!-- Character entity set. Typical invocation:
         <!ENTITY % ISOlat1 PUBLIC
           "ISO 8879-1986//ENTITIES Added Latin 1//EN//HTML">
         %ISOlat1;
      -->
    <!ENTITY nbsp   CDATA "&#160;" -- no-break space -->
    <!ENTITY iexcl  CDATA "&#161;" -- inverted exclamation mark -->
    <!ENTITY cent   CDATA "&#162;" -- cent sign -->
    <!ENTITY pound  CDATA "&#163;" -- pound sterling sign -->
    <!ENTITY curren CDATA "&#164;" -- general currency sign -->
    <!ENTITY yen    CDATA "&#165;" -- yen sign -->
    <!ENTITY brvbar CDATA "&#166;" -- broken (vertical) bar -->
    <!ENTITY sect   CDATA "&#167;" -- section sign -->
    <!ENTITY uml    CDATA "&#168;" -- umlaut (dieresis) -->
    <!ENTITY copy   CDATA "&#169;" -- copyright sign -->
    <!ENTITY ordf   CDATA "&#170;" -- ordinal indicator, feminine -->
    <!ENTITY laquo  CDATA "&#171;" -- angle quotation mark, left -->
    <!ENTITY not    CDATA "&#172;" -- not sign -->
    <!ENTITY shy    CDATA "&#173;" -- soft hyphen -->
    <!ENTITY reg    CDATA "&#174;" -- registered sign -->
    <!ENTITY macr   CDATA "&#175;" -- macron -->
    <!ENTITY deg    CDATA "&#176;" -- degree sign -->
    <!ENTITY plusmn CDATA "&#177;" -- plus-or-minus sign -->
    <!ENTITY sup2   CDATA "&#178;" -- superscript two -->
    <!ENTITY sup3   CDATA "&#179;" -- superscript three -->
    <!ENTITY acute  CDATA "&#180;" -- acute accent -->
    <!ENTITY micro  CDATA "&#181;" -- micro sign -->
    <!ENTITY para   CDATA "&#182;" -- pilcrow (paragraph sign) -->
    <!ENTITY middot CDATA "&#183;" -- middle dot -->
    <!ENTITY cedil  CDATA "&#184;" -- cedilla -->
    <!ENTITY sup1   CDATA "&#185;" -- superscript one -->
    <!ENTITY ordm   CDATA "&#186;" -- ordinal indicator, masculine -->
    <!ENTITY raquo  CDATA "&#187;" -- angle quotation mark, right -->
    <!ENTITY frac14 CDATA "&#188;" -- fraction one-quarter -->
    <!ENTITY frac12 CDATA "&#189;" -- fraction one-half -->
    <!ENTITY frac34 CDATA "&#190;" -- fraction three-quarters -->
    <!ENTITY iquest CDATA "&#191;" -- inverted question mark -->
    <!ENTITY Agrave CDATA "&#192;" -- capital A, grave accent -->
    <!ENTITY Aacute CDATA "&#193;" -- capital A, acute accent -->
    <!ENTITY Acirc  CDATA "&#194;" -- capital A, circumflex accent -->
    <!ENTITY Atilde CDATA "&#195;" -- capital A, tilde -->
    <!ENTITY Auml   CDATA "&#196;" -- capital A, dieresis or umlaut -->
    <!ENTITY Aring  CDATA "&#197;" -- capital A, ring -->
    <!ENTITY AElig  CDATA "&#198;" -- capital AE diphthong (ligature) -->
    <!ENTITY Ccedil CDATA "&#199;" -- capital C, cedilla -->
    <!ENTITY Egrave CDATA "&#200;" -- capital E, grave accent -->
    <!ENTITY Eacute CDATA "&#201;" -- capital E, acute accent -->
    <!ENTITY Ecirc  CDATA "&#202;" -- capital E, circumflex accent -->
    <!ENTITY Euml   CDATA "&#203;" -- capital E, dieresis or umlaut -->
    <!ENTITY Igrave CDATA "&#204;" -- capital I, grave accent -->
    <!ENTITY Iacute CDATA "&#205;" -- capital I, acute accent -->
    <!ENTITY Icirc  CDATA "&#206;" -- capital I, circumflex accent -->
    <!ENTITY Iuml   CDATA "&#207;" -- capital I, dieresis or umlaut -->
    <!ENTITY ETH    CDATA "&#208;" -- capital Eth, Icelandic -->
    <!ENTITY Ntilde CDATA "&#209;" -- capital N, tilde -->
    <!ENTITY Ograve CDATA "&#210;" -- capital O, grave accent -->
    <!ENTITY Oacute CDATA "&#211;" -- capital O, acute accent -->
    <!ENTITY Ocirc  CDATA "&#212;" -- capital O, circumflex accent -->
    <!ENTITY Otilde CDATA "&#213;" -- capital O, tilde -->
    <!ENTITY Ouml   CDATA "&#214;" -- capital O, dieresis or umlaut -->
    <!ENTITY times  CDATA "&#215;" -- multiply sign -->
    <!ENTITY Oslash CDATA "&#216;" -- capital O, slash -->
    <!ENTITY Ugrave CDATA "&#217;" -- capital U, grave accent -->
    <!ENTITY Uacute CDATA "&#218;" -- capital U, acute accent -->
    <!ENTITY Ucirc  CDATA "&#219;" -- capital U, circumflex accent -->
    <!ENTITY Uuml   CDATA "&#220;" -- capital U, dieresis or umlaut -->
    <!ENTITY Yacute CDATA "&#221;" -- capital Y, acute accent -->
    <!ENTITY THORN  CDATA "&#222;" -- capital Thorn, Icelandic -->
    <!ENTITY szlig  CDATA "&#223;" -- small sharp s, German (sz ligature) -->
    <!ENTITY agrave CDATA "&#224;" -- small a, grave accent -->
    <!ENTITY aacute CDATA "&#225;" -- small a, acute accent -->
    <!ENTITY acirc  CDATA "&#226;" -- small a, circumflex accent -->
    <!ENTITY atilde CDATA "&#227;" -- small a, tilde -->
    <!ENTITY auml   CDATA "&#228;" -- small a, dieresis or umlaut -->
    <!ENTITY aring  CDATA "&#229;" -- small a, ring -->
    <!ENTITY aelig  CDATA "&#230;" -- small ae diphthong (ligature) -->
    <!ENTITY ccedil CDATA "&#231;" -- small c, cedilla -->
    <!ENTITY egrave CDATA "&#232;" -- small e, grave accent -->
    <!ENTITY eacute CDATA "&#233;" -- small e, acute accent -->
    <!ENTITY ecirc  CDATA "&#234;" -- small e, circumflex accent -->
    <!ENTITY euml   CDATA "&#235;" -- small e, dieresis or umlaut -->
    <!ENTITY igrave CDATA "&#236;" -- small i, grave accent -->
    <!ENTITY iacute CDATA "&#237;" -- small i, acute accent -->
    <!ENTITY icirc  CDATA "&#238;" -- small i, circumflex accent -->
    <!ENTITY iuml   CDATA "&#239;" -- small i, dieresis or umlaut -->
    <!ENTITY eth    CDATA "&#240;" -- small eth, Icelandic -->
    <!ENTITY ntilde CDATA "&#241;" -- small n, tilde -->
    <!ENTITY ograve CDATA "&#242;" -- small o, grave accent -->
    <!ENTITY oacute CDATA "&#243;" -- small o, acute accent -->
    <!ENTITY ocirc  CDATA "&#244;" -- small o, circumflex accent -->
    <!ENTITY otilde CDATA "&#245;" -- small o, tilde -->
    <!ENTITY ouml   CDATA "&#246;" -- small o, dieresis or umlaut -->
    <!ENTITY divide CDATA "&#247;" -- divide sign -->
    <!ENTITY oslash CDATA "&#248;" -- small o, slash -->
    <!ENTITY ugrave CDATA "&#249;" -- small u, grave accent -->
    <!ENTITY uacute CDATA "&#250;" -- small u, acute accent -->
    <!ENTITY ucirc  CDATA "&#251;" -- small u, circumflex accent -->
    <!ENTITY uuml   CDATA "&#252;" -- small u, dieresis or umlaut -->
    <!ENTITY yacute CDATA "&#253;" -- small y, acute accent -->
    <!ENTITY thorn  CDATA "&#254;" -- small thorn, Icelandic -->
    <!ENTITY yuml   CDATA "&#255;" -- small y, dieresis or umlaut -->

8. Security Considerations ๐Ÿ”’

okay bestie, security time, and it's serious but still giving ๐Ÿ’€ Anchors, embedded images, and literally every other element that carries a URI as a parameter can end up dereferencing that URI because a user poked at something. When that happens, the security considerations of [RFC1738] apply ๐Ÿ”

Next up, forms. The two big methods for sending form requests, HTTP and SMTP, are both widely deployed, but they give you little assurance of confidentiality ๐Ÿ˜ญ So if you're an information provider asking for sensitive stuff through a form, especially with a `PASSWORD' type input field (see section 8.1.2 in [RFC1866]), you need to be aware of that lack of confidentiality and make sure your users are aware of it too ๐Ÿซถ๐Ÿ”ฅ

Bibliography โœจ

okay bestie, these are all the sources this spec leans on ๐Ÿ“š every single one is listed below, exactly as written, so you can go find them ๐Ÿ”

[BRYAN88]      M. Bryan, "SGML -- An Author's Guide to the Standard
               Generalized Markup Language", Addison-Wesley, Reading,
               1988.

[ERCS]         Extended Reference Concrete Syntax for SGML.
               <http://www.sgmlopen.org/sgml/docs/ercs/ercs-
               home.html>

[GOLD90]       C. F. Goldfarb, "The SGML Handbook", Y. Rubinsky, Ed.,
               Oxford University Press, 1990.

[HTTP-1.1]     Fielding, R., Gettys, J., Mogul, J., Frystyk, H.,
               and T. Berners-Lee, "Hypertext Transfer Protocol --
               HTTP/1.1", RFC 2068, January 1997.

[ISO-639]      ISO 639:1988. International standard -- Code for the
               representation of the names of languages.  Technical
               content in <http://www.sil.org/sgml/iso639a.html>

[ISO-8859]     ISO 8859.  International standard -- Information pro-
               cessing -- 8-bit single-byte coded graphic character
               sets -- Part 1: Latin alphabet No. 1 (1987) -- Part 2:
               Latin alphabet No. 2 (1987) -- Part 3: Latin alphabet
               No. 3 (1988) -- Part 4: Latin alphabet No. 4 (1988) --
               Part 5: Latin/Cyrillic alphabet (1988) -- Part 6:
               Latin/Arabic alphabet (1987) -- Part : Latin/Greek
               alphabet (1987) -- Part 8: Latin/Hebrew alphabet
               (1988) -- Part 9: Latin alphabet No. 5 (1989) -- Part
               10: Latin alphabet No. 6 (1992)

[ISO-8879]     ISO 8879:1986. International standard -- Information
               processing -- Text and office systems -- Standard gen-
               eralized markup language (SGML).

[ISO-10646]    ISO/IEC 10646-1:1993. International standard -- Infor-
               mation technology -- Universal multiple-octet coded
               character Sset (UCS) -- Part 1: Architecture and basic
               multilingual plane.

[NICOL]        G.T. Nicol, "The Multilingual World Wide Web",
               Electronic Book Technologies, 1995,
               <http://www.ebt.com/docs/multling.html>

[NICOL2]       G.T. Nicol, "MIME Header Supplemented File Type", Work
               in Progress, EBT, October 1995.

[RFC1345]      Simonsen, K., "Character Mnemonics & Character Sets",
               RFC 1345, Rationel Almen Planlaegning, June 1992.

[RFC1468]      Murai, J., Crispin M., and E. van der Poel,
               "Japanese Character Encoding for Internet Messages",
               RFC 1468, Keio University, Panda Programming, June
               1993.

[RFC2045]      Freed, N., and N. Borenstein, "Multipurpose Internet
               Mail Extensions (MIME) Part One: Format of Internet
               Message Bodies", RFC 2045, Innosoft, First Virtual,
               November 1996.

[RFC1641]      Goldsmith, D., and M.Davis, "Using Unicode with MIME",
               RFC 1641, Taligent inc., July 1994.

[RFC1642]      Goldsmith, D., and M. Davis, "UTF-7: A Mail-safe
               Transformation Format of Unicode", RFC 1642, Taligent,
               Inc., July 1994.

[RFC1738]      Berners-Lee, T., Masinter, L., and M. McCahill,
               "Uniform Resource Locators (URL)", RFC 1738, CERN,
               Xerox PARC, University of Minnesota, October 1994.

[RFC1766]      Alverstrand, H., "Tags for the Identification of
               Languages", RFC 1766, UNINETT, March 1995.

[RFC1866]      Berners-Lee, T., and D. Connolly, "Hypertext Markup
               Language - 2.0", RFC 1866, MIT/W3C, November 1995.

[RFC1867]      Nebel, E., and L. Masinter, "Form-based File Upload
               in HTML", RFC 1867, Xerox Corporation, November 1995.

[RFC1942]      Raggett, D., "HTML Tables", RFC 1942, W3C, May 1996.

[RFC2068]      Fielding, R., Gettys, J., Mogul, J., Frystyk, H.,
               and T. Berners-Lee, "Hypertext Transfer Protocol --
               HTTP/1.1", RFC 2068, January 1997.

[SQ91]         SoftQuad, "The SGML Primer", 3rd ed., SoftQuad Inc.,
               1991.

[TAKADA]       Toshihiro Takada, "Multilingual Information Exchange
               through the World-Wide Web", Computer Networks and
               ISDN Systems, Vol. 27, No. 2, Nov. 1994 , p. 235-241.

[TEI]          TEI Guidelines for Electronic Text Encoding and Inter-
               change.  <http://etext.virgina.edu/TEI.html>

[UNICODE]      The Unicode Consortium, "The Unicode Standard --
               Worldwide Character Encoding -- Version 1.0", Addison-
               Wesley, Volume 1, 1991, Volume 2, 1992, and Technical
               Report #4, 1993.  The BIDI algorithm is in appendix A
               of volume 1, with corrections in appendix D of volume
               2.

[UTF-8]        ISO/IEC 10646-1:1993 AMENDMENT 2 (1996). UCS Transfor-
               mation Format 8 (UTF-8).

[VANH90]       E. van Hervijnen, "Practical SGML", Kluwer Academicq
               Publishers Group, Norwell and Dordrecht, 1990.

Authors' Addresses ๐Ÿซถ

and here are the people who wrote it, the whole squad ๐Ÿ’œ contact details are copied exactly as they appear in the original ๐ŸŒธ

Frangois Yergeau
Alis Technologies
100, boul. Alexis-Nihon, bureau 600
Montrial  QC  H4M 2P2
Canada

Tel: +1 (514) 747-2547
Fax: +1 (514) 747-2561
EMail: fyergeau@alis.com


Gavin Thomas Nicol
Electronic Book Technologies, Japan
1-29-9 Tsurumaki,
Setagaya-ku,
Tokyo
Japan

Tel: +81-3-3230-8161
Fax: +81-3-3230-8163
EMail: gtn@ebt.com, gtn@twics.co.jp


Glenn Adams
Spyglass
118 Magazine Street
Cambridge, MA 02139
U.S.A.

Tel: +1 (617) 864-5524
Fax: +1 (617) 864-4965
EMail: glenn@spyglass.com


Martin J. Duerst
Multimedia-Laboratory
Department of Computer Science
University of Zurich
Winterthurerstrasse 190
CH-8057 Zurich
Switzerland

Tel: +41 1 257 43 16
Fax: +41 1 363 00 35
EMail: mduerst@ifi.unizh.ch

that's the whole RFC, we made it!! ๐ŸŒˆโœจ ๐Ÿ’…

๐Ÿ“ฆ where this page comes from