HTML Renderer (Emacs)

 


Emacs: A non-intrusive browser

An Elisp implementation of HTML rendering using SVG. The browser functionality is an extension of eww. For Javascript, you can use either NodeJS or QuickJS as a JS interpreter.

Developer Note: The entry point is shr-render.

 

Table

Colspan example

Rowspan example


Sample Table

<html>
  <body>
    <table border="1">
      <tr bgcolor="#9acd32">
        <th style="text-align:left">Title</th>
        <th style="text-align:left">Artist</th>
      </tr>
      <tr>
        <td>Empire Burlesque</td>
        <td>Bob Dylan</td>
      </tr>
    </table>
  </body>
</html>  

 

CSS Support


 Limited CSS support for following attributes - padding, margin, margin-left, margin-top, border, color, background, background-color, display, width, height, clear, text-align, font, font-size, font-style, font-weight.

Minimal CSS

head {display: none}
body {margin: 8; font-size: 14;}
b {font-weight: bold}
em, i {font-style: italic}
a, em, i, b {display: inline}
hr {height: 1; border: 1; color: grey}
h1, h2, h3, p, ul, li {display: block}
input, button {display: flex; margin: 5; padding: 5; border: 1;}
button {background-color: #adb1b8;}
a {color: blue}

// Break table
table {display: table}
tr {display: table-row}

// Less used tags
center {display: block; text-align: center;}
big, tt, font {display: inline}

 

Caching

Static resources like images, JS and CSS are cached by url package based on HTTP 304 (Not Modified) status. Cache expiry is controlled by url-cache-expire-time.

This function might be useful in other scenarios. Use (url-fetch-from-cache url) to retrieve the object.

(defun fetch (url)
  (let* ((site (url-generic-parse-url url))
         (buf (get-buffer-create (url-cache-create-filename url))))
    (with-current-buffer buf
      (setq url-current-object site))
    (if (not (url-is-cached url))
        (url-queue-retrieve
         url 'jit--image-fetched
         (list buf)
         t
         (not (shr--use-cookies-p url shr-base))))
    ))

 

Masonry

Pictures look best when their aspect ratios are maintained. If you are viewing a collection of pictures in a regular grid layout, this results in some jarring whitespace. Masonry layout, like below, provides a more tight fitting view.



<style>
  .grid {
  display: masonry;
  column-count: 3;
  }
</style>
<h1>Masonry</h1>

<div class="grid">
  <div class="grid-item">
    <img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/82/orange-tree.jpg" />
  </div>
  <div class="grid-item">
    <img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/82/submerged.jpg" />
  </div>
  <div class="grid-item">
    <img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/82/look-out.jpg" />
  </div>
  <div class="grid-item">
    <img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/82/one-world-trade.jpg" />
  </div>
  <div class="grid-item">
    <img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/82/drizzle.jpg" />
  </div>
  <div class="grid-item">
    <img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/82/cat-nose.jpg" />
  </div>
  <div class="grid-item">
    <img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/82/contrail.jpg" />
  </div>
  <div class="grid-item">
    <img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/82/golden-hour.jpg" />
  </div>
  <div class="grid-item">
    <img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/82/flight-formation.jpg" />
  </div>
</div>



Lessons Learnt

  • To improve HTML page load performance and to reduce jitters, provide the dimensions for image as much as possible. This takes out any guess work, reflow (causes for jitters) or the need to fetch image for finding the dimensions (cause for delays).
  • Margin is the space between elements. First reading of Box model might lead you to believe that margins are additive. However, margin collapse ensures that they don't add up.
  • For constant border in table layout, cells must overlap. In contrast, blocks normally don't overlap and are separated by margin.
  • In librsvg, 50% of border lies outside the box definition. This is especially important when you're drawing boxes with thick borders.
  • Most elements in an HTML page are not rendered - they simply act as a container. Generally speaking, if they don't have a border or background, they need not be drawn. However, they are very important from CSS perspective.
  • CSS plays an important role in sizing the elements. Hence it must be loaded before layout calculations.


Code

References


Comments

Popular posts from this blog

GNU Emacs as a Comic Book Reader

Mozilla Readability in GNU Emacs