tkhtml(n)

πŸ“¦
version 7.44.0 Β· 3 versions
, in nixos 26.05, nixpkgs unstable

πŸŽ€ tkhtml(n) β€” NAME πŸŽ€

Okay bestie, so tkhtml is literally the widget that renders html documents. That’s the whole vibe. πŸ’…βœ¨


🌸 SYNOPSIS 🌸

html pathName ?options?

πŸ¦‹ STANDARD OPTIONS πŸ¦‹

These are the standard options in the mix, no cap:

  • -height β€” standard option listed for this widget. πŸŽ€
  • -width β€” standard option listed for this widget. 🌸
  • -xscrollcommand β€” standard option listed for this widget. πŸ¦‹
  • -xscrollincrement β€” standard option listed for this widget. ✨
  • -yscrollcommand β€” standard option listed for this widget. πŸ’–
  • -yscrollincrement β€” standard option listed for this widget. πŸ’«

πŸ’– WIDGET-SPECIFIC OPTIONS πŸ’–

  • -defaultstyle β€” Command-Line Name: -defaultstyle; Database Name: defaultstyle; Database Class: Defaultstyle.

This option sets the default style-sheet for the widget. The option value should be the entire text of the default style-sheet, or an empty string, in which case a built-in default stylesheet (for HTML) is used. πŸŽ€

At the moment, this option is not very useful. 😭 The default stylesheet defines things that are β€œbuilt-in” to the document β€” for example the behaviour of <p> or <img> tags in html. The idea behind making it flexible is to allow Tkhtml to display anything that looks roughly like an XML document. But it will not work at the moment because of other assumptions the implementation makes about the set of valid tags. πŸ’€
  • -imagecmd β€” Command-Line Name: -imagecmd; Database Name: imagecmd; Database Class: Imagecmd.

As well as for replacing entire document nodes (i.e. <img>), images are used in several other contexts in CSS formatted documents, for example as list markers or backgrounds. πŸ–ΌοΈβœ¨ If the -imagecmd option is not set to an empty string (the default), then each time an image URI is encountered in the document, it is appended to the -imagecmd script and the resulting list evaluated. πŸ‘‘

The command should return either an empty string, the name of a Tk image, or a list of exactly two elements, the name of a Tk image and a script. If the result is an empty string, then no image can be displayed. If the result is a Tk image name, then the image is displayed in the widget. When the image is no longer required, it is deleted. If the result of the command is a list containing a Tk image name and a script, then instead of deleting the image when it is no longer required, the script is evaluated. 🫢

If the size or content of the image are modified while it is in use the widget display is updated automatically. πŸ”₯

  • -logcmd β€” Command-Line Name: -logcmd; Database Name: logcmd; Database Class: Logcmd.

This option is used for internally debugging the widget. πŸ› οΈπŸ‘€


🌈 DESCRIPTION 🌈

The [html] command creates a new window (given by the pathName argument) and makes it into an html widget. The html command returns its pathName argument. πŸͺ„

At the time this command is invoked, there must not exist a window named pathName, but pathName's parent must exist. 🚨

πŸ’… WIDGET COMMAND πŸ’…

okay so [html] creates a new Tcl command whose name is pathName, and that command is your whole remote control for the widget, bestie. You can use it to invoke all these operations, no cap:

πŸŽ€ pathName bbox nodeHandle

If node nodeHandle generates content, this command returns a list of four integers that define the bounding-box of the generated content, relative to the top-left hand corner of the rendered document. The first two integers are the x and y coordinates of the top-left corner of the bounding-box; the later two are the x and y coordinates of the bottom-right corner of the same box. If the node does not generate content, then an empty string is returned. πŸ’–

πŸŽ€ pathName cget option

Returns the current value of the configuration option given by option. Option may have any of the values accepted by the [html] command. simple, iconic, periodt ✨

πŸŽ€ pathName configure ?option? ?value?

Query or modify the configuration options of the widget. If no option is specified, returns a list describing all of the available options for pathName (see Tk_ConfigureInfo for information on the format of this list). If option is specified with no value, then the command returns a list describing the one named option (this list will be identical to the corresponding sublist of the value returned if no option is specified). If one or more option-value pairs are specified, then the command modifies the given widget option(s) to have the given value(s); in this case the command returns an empty string. Option may have any of the values accepted by the [html] command. πŸ’…

πŸŽ€ pathName handler type tag script

This command is used to define "handler" scripts β€” Tcl callback scripts that are invoked by the widget when document elements of specified types are encountered. The widget supports two types of handler scripts: "node" and "script". The type parameter to this command must take one of these two values.

For a "node" handler script, whenever a document element having the specified tag type (e.g. "p" or "link") is encountered during parsing, then the node handle for the node is appended to script and the resulting list evaluated as a Tcl command. See the section "NODE COMMAND" for details of how a node handle may be used to query and manipulate a document node. πŸ¦‹

If the handler script is a "script" handler, whenever a document node of type tag is parsed, then the text that appears between the start and end tags of the node is appended to script and the resulting list evaluated as a Tcl command.

Handler callbacks are always made from within [pathName parse] commands. The callback for a given node is made as soon as the node is completely parsed. This can happen because an implicit or explicit closing tag is parsed, or because there is no more document data and the -final switch was passed to the [pathName parse] command.

TODO: Return values of handler scripts? If an exception occurs in a handler script?

πŸŽ€ pathName image

This command returns the name of a new Tk image containing the rendered document. Where Tk widgets would be mapped in a live display, the image contains blank space. πŸŽ€

The returned image should be deleted when the script has finished with it, for example:

set img [.html image]
# ... Use $img ...
image delete $img

This command is included mainly for automated testing and should be used with care, as large documents can result in very large images that take a long time to create and use vast amounts of memory. 😭

Currently this command is not available on windows. On that platform an empty string is always returned.

πŸŽ€ pathName node ? ?-index? x y?

This command is used to retrieve one or more document node handles from the current document. If the x and y parameters are omitted, then the handle returned is the root-node of the document, or an empty string if the document has no root-node (i.e. an empty document).

If the x and y arguments are present, then a list of node handles is returned. The list contains one handle for each node that generates content currently located at viewport coordinates (x, y). Usually this is only a single node, but floating boxes and other overlapped content can cause this command to return more than one node. If no content is located at the specified coordinates or the widget window is not mapped, then an empty string is returned. 🌸

If the -index option is specified along with the x and y coordinates, then instead of a list of node handles, a list of two elements is returned. The first element of the list is the node-handle associated with the generated text closest to the specified (x, y) coordinates. The second list value is an index into the text obtainable by [nodeHandle text] for the character closest to coordinates (x, y). The index may be used with the [pathName select] commands.

The document node can be queried and manipulated using the interface described in the "NODE COMMAND" section.

πŸŽ€ pathName parse ?-final? html-text

Append extra text to the end of the (possibly empty) document currently stored by the widget. πŸ’œ

If the -final option is present, this indicates that the supplied text is the last of the document. Any subsequent call to [pathName parse] before a call to [pathName reset] will raise an error. do not test this unless you're ready for drama 😭

πŸŽ€ pathName reset

This is used to clear the internal contents of the widget prior to parsing a new document. The widget is reset such that the document tree is empty (as if no calls to [pathName parse] had ever been made) and no stylesheets except the default stylesheet are loaded (as if no invocations of [pathName style] had occurred). ✨

πŸŽ€ pathName select commands

The selection commands look like this, bestie:

  • pathName select clear
  • pathName select from ?nodeHandle ?index? ?
  • pathName select to ?nodeHandle ?index? ?
  • pathName select span

The [pathName select] commands are used to query and manipulate the widget selection.

TODO: Describe these commands.

πŸŽ€ pathName style ?options? stylesheet-text

Add a stylesheet to the widget's internal configuration. The stylesheet-text argument should contain the text of a complete stylesheet. Incremental parsing of stylesheets is not supported, although of course multiple stylesheets may be added to a single widget. πŸŽ€

The following options are supported:

  • -id <stylesheet-id> β€” default value "author"
  • -importcmd <script> β€” default value ""
  • -urlcmd <script> β€” default value ""

The value of the -id option determines the priority taken by the style-sheet when assigning property values to document nodes (see chapter 6 of the CSS specification for more detail on this process). The first part of the style-sheet id must be one of the strings "agent", "user" or "author". Following this, a style-sheet id may contain any text. πŸ‘‘

When comparing two style-ids to determine which stylesheet takes priority, the widget uses the following approach: If the initial strings of the two style-id values are not identical, then "user" takes precedence over "author", and "author" takes precedence over "agent". Otherwise, the lexicographically largest style-id value takes precedence. For more detail on why this seemingly odd approach is taken, please refer to the "STYLESHEET LOADING" below. 🧚

The -importcmd option is used to provide a handler script for @import directives encountered within the stylesheet text. Each time an @import directive is encountered, if the -importcmd option is set to other than an empty string, the URI to be imported is appended to the option value and the resulting list evaluated as a Tcl script. The return value of the script is ignored. If the script raises an error, then it is propagated up the call-chain to the [pathName style] caller. 🌈

The -urlcmd option is used to supply a script to translate "url(...)" CSS attribute values. If this option is not set to "", each time a url() value is encountered the URI is appended to the value of -urlcmd and the resulting script evaluated. The return value is stored as the URL in the parsed stylesheet. πŸ¦‹

πŸŽ€ pathName xview ?options?

This command is used to query or adjust the horizontal position of the viewport relative to the document layout. It is identical to the [pathName xview] command implemented by the canvas and text widgets. πŸ’–

πŸŽ€ pathName yview ?options?

This command is used to query or adjust the vertical position of the viewport relative to the document layout. It is identical to the [pathName yview] command implemented by the canvas and text widgets. πŸ’–

πŸ’… NODE COMMAND πŸ’…

okay so bestie, there are several interfaces a script can use to get a β€œnode handle.” Each node handle is a Tcl command you can use to poke at the document node it represents. A node handle stays valid from the moment you get it until the next call to [pathName reset] β€” that’s its little expiry window ✨

You use that handle to query and manipulate the document node through these subcommands:

🫢 nodeHandle attr ?attribute?

If the attribute argument is there, you get back the value of that named html attribute β€” or an empty string if the attribute you asked for doesn’t exist. If attribute is not there, you get a key-value list of the node’s defined attributes, in the form you can hand straight to [array set].

# Html code for node
<p class="normal" id="second" style="color : red">

# Value returned by [nodeHandle attr]
{class normal id second style {color : red}}

# Value returned by [nodeHandle attr class]
normal

🌸 nodeHandle child index

Returns the node handle for the *index*’th child of the node. Children are numbered from zero upward, bestie β€” zero-indexed like a true icon πŸ‘‘

πŸ¦‹ nodeHandle nChild

Returns how many children the node has.

πŸŽ€ nodeHandle parent

Returns the node handle for the node’s parent. If the node has no parent (i.e. it’s the document root), you get an empty string.

πŸ‘‘ nodeHandle replace ? ?options? newValue?

This command sets and gets the name of the replacement object for the node, if there is one. If the newValue argument is present, it sets the node’s replacement object name and returns the new value. If newValue is not present, it returns the current value.

A node’s replacement object can be set to the name of a Tk window or to an empty string. If it’s an empty string (the default and usual case), the node renders normally. If it’s set to the name of a Tk window, that Tk window gets mapped into the widget in place of any other content β€” for example, to implement form elements or plugins.

The following options are supported:

  • -deletecmd <script> β€” default: "destroy <window>"
  • -configurecmd <script> β€” default: ""

When a replacement object is no longer being used by the widget (e.g. because the node has been deleted or [pathName reset] is invoked), the value of the -deletecmd option is evaluated as a Tcl script.

If -configurecmd is not set to an empty string (empty is the default), then each time the node’s CSS properties are recalculated, a serialized array is appended to the value of the -configurecmd option and the result is evaluated as a Tcl command. The script should update the replacement object’s appearance where appropriate to reflect the property values. The format of the appended argument is {p1 v1 p2 v2 ... pN vN} where the pX values are property names (i.e. "background-color") and the vX values are property values (i.e. "#CCCCCC"). The CSS properties that currently may be present in the array are listed below. More may be added in the future.

  • background-color
  • color
  • font
  • selected

The value of the "font" property, if present in the serialized array, is not set to the value of the corresponding CSS property. Instead it’s set to the name of a Tk font determined by combining the various font-related CSS properties. Unless they are set to "transparent", the two color values are guaranteed to parse as Tk colors. The "selected" property is either true or false, depending on whether or not the replaced object is part of the selection or not. Whether an object is part of the selection is governed by previous calls to the [pathName select] command.

The -configurecmd callback is always executed at least once between the [nodeHandle replace] command and when the replaced object is mapped into the widget display.

🌈 nodeHandle tag

Returns the name of the Html tag that generated this document node (i.e. "p" or "link"), or an empty string if the node is a text node.

πŸ“ nodeHandle text

If the node is a "text" node, returns the string contained by the node. If the node is not a "text" node, returns an empty string.

TODO: Add the "write" part of the DOM compatible interface to this section.

✨ STYLESHEET LOADING ✨

okay so bestie, quick vibe check: apart from the default stylesheet that is always loaded (peep the description of the -defaultstyle option above πŸ‘€), a script may configure the widget with extra style information in the form of CSS stylesheet documents. And these are complete stylesheet documents β€” it is not possible to incrementally parse stylesheets as it is HTML document files β€” and they are passed to the widget using the [pathName style] command. πŸ’…

As well as any stylesheets specified by the application, stylesheets may be included in HTML documents by document authors in several ways:

  • Embedded in the document itself, using a <style> tag. To handle this case an application script must register a "script" type handler for <style> tags using the [pathName handler] command. The handler command should call [pathName style] to configure the widget with the stylesheet text.
  • Linked from the document, using a <link> tag. To handle this case the application script should register a "node" type handler for <link> tags.
  • Linked from another stylesheet, using the @import directive. To handle this, an application needs to configure the widget -importcommand option.

here's the example code, bestie β€” exact vibes:

# Implementations of application callbacks to load
# stylesheets from the various sources enumerated above.
# ".html" is the name of the applications tkhtml widget.
# The variable $document contains an entire HTML document.
# The pseudo-code <LOAD URI CONTENTS> is used to indicate
# code to load and return the content located at $URI.

proc script_handler {tagcontents} {
    incr ::stylecount
    set id "author.[format %.4d $::stylecount]"
    set handler "import_handler $id"
    .html style -id $id.9999 -importcmd $handler $tagcontents
}

proc link_handler {node} {
    if {[node attr rel] == "stylesheet"} {
     set URI [node attr href]
     set stylesheet [<LOAD URI CONTENTS>]

     incr ::stylecount
     set id "author.[format %.4d $::stylecount]"
     set handler "import_handler $id"
     .html style -id $id.9999 -importcmd $handler $stylesheet
    }
}

proc import_handler {parentid URI} {
    set stylesheet [<LOAD URI CONTENTS>]

    incr ::stylecount
    set id "$parentid.[format %.4d $::stylecount]"
    set handler "import_handler $id"
    .html style -id $id.9999 -importcmd $handler $stylesheet
}

set ::stylecount 0

The complicated part of the example code above is the generation of stylesheet-ids β€” the values passed to the -id option of the [.html style] command. Stylesheet-ids are used to determine the precedence of each stylesheet passed to the widget, and the role it plays in the CSS cascade algorithm used to assign properties to document nodes. The first part of each stylesheet-id, which must be either "user", "author" or "agent", determines the role the stylesheet plays in the cascade algorithm. In general, author stylesheets take precedence over user stylesheets which take precedence over agent stylesheets. An author stylesheet is one supplied or linked by the author of the document. A user stylesheet is supplied by the user of the viewing application, possibly by configuring a preferences dialog or similar. An agent stylesheet is supplied by the viewing application, for example the default stylesheet configured using the -defaultstyle option.

The stylesheet id mechanism is designed so that the cascade can be correctly implemented even when the various stylesheets are passed to the widget asynchronously and out of order (as may be the case if they are being downloaded from a network server or servers). ✨

#
# Contents of HTML document
#

<html><head>
    <link rel="stylesheet" href="A.css">
    <style>
     @import uri("B.css")
     @import uri("C.css")
     ... rules ...
    </style>
    <link rel="stylesheet" href="D.css">

#
# Contents of B.css
#

@import "E.css"

In the example above, the stylesheet documents A.css, B.css, C.css, D.css, E.css and the stylesheet embedded in the <style> tag are all author stylesheets. CSS states that the relative precedences of the stylesheets in this case is governed by the following rules:

  • Linked, embedded or imported stylesheets take precedence over stylesheets linked, embedded or imported earlier in the same document or stylesheet.
  • Rules specified in a stylesheet take precedence over rules specified in imported stylesheets.

Applying the above two rules to the example documents indicates that the order of the stylesheets from least to most important is: A.css, E.css, B.css, C.css, embedded <stylesheet>, D.css. For the widget to implement the cascade correctly, the stylesheet-ids passed to the six [pathName style] commands must sort lexicographically in the same order as the stylesheet precedence determined by the above two rules. The example code above shows one approach to this. Using the example code, stylesheets would be associated with stylesheet-ids as follows:

  • A.css β†’ author.0001.9999
  • <embedded style> β†’ author.0002.9999
  • B.css β†’ author.0002.0003.9999
  • E.css β†’ author.0002.0003.0004.9999
  • C.css β†’ author.0002.0005.9999
  • D.css β†’ author.0006.9999

Entries are specified in the above list in the order in which the calls to [html style] would be made. Of course, the example code fails if 10000 or more individual stylesheet documents are loaded. More inventive solutions that avoid this kind of limitation are possible. 🫢

Other factors, namely rule specificity and the !IMPORTANT directive are involved in determining the precedence of individual stylesheet rules. These are completely encapsulated by the widget, so are not described here. For complete details of the CSS cascade algorithm, refer to [1].


πŸ“₯ INCREMENTAL DOCUMENT LOADING πŸ“₯

This section discusses the widget API in the context of loading a document incrementally, for example from a network server. We assume both remote stylesheets and image files are retrieved as well as the document. πŸ‘€

Before a new document (html file) is loaded, any previous document should be purged from memory using the [pathName reset] command. The portion of the new document that is read is passed to the widget using the [pathName parse] command. As new chunks of the document are downloaded, they should also be passed to [pathName parse]. When the final chunk of the document file is passed to the [pathName parse] command the -final option should be specified. This ensures node-handler callbacks (see the description of the [pathname handler] command above) are made for tags that are closed implicitly by the end of the document. πŸ’–

The widget display is updated in an idle callback scheduled after each invocation of the [pathName parse] command.

TODO: Finish this section. 😭

🧚 HTML SPECIFIC PROCESSING 🧚

TODO: Detail implicit opening and closing tag rules here. LATER: If only I could figure them out... πŸ’€

πŸ“š REFERENCES πŸ“š

  • [1] CSS2 specification.

okay bye bestie, this was the tkhtml(n) page, dated Sat Feb 25 06:44:47 PM ICT 2006 β€” catch you in the next manpage πŸ’…βœ¨πŸŽ€

πŸ“¦ where this page comes from