💾 Archived View for plot47.space › code › gemtext › gmi2html captured on 2022-07-16 at 14:09:11. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2022-03-01)

-=-=-=-=-=-=-

#!/usr/bin/awk -f

BEGIN {
  true = "true"
  false = "false"
  preformat_toggle = false
  preformat_start = false
  preformat_title = ""
  body_padding = "    "

  if (LANG == "") {
      LANG = "en"
  }

  if (TOC == "") {
    TOC = false
  }

  if (INLINE == "") {
    INLINE = true
  }

  delete TABLE_OF_CONTENTS

  if (TOC == true) {
    create_toc(ARGV[1], TABLE_OF_CONTENTS)
  }

  print "<!DOCTYPE html>"
  print "<html lang=\"" LANG "\">"
  print "  <head>"
  print "    <meta charset=\"utf-8\">"
  print "    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">"
  print "    <title>" basename(ARGV[1]) "</title>"
  print "    <style>"
  print embedded_css(CSS)
  print "    </style>"
  print "  </head>"
  print "  <body>"
}

function embedded_css(css_file, _embedded_css) {
  _embedded_css = "\
      html {\n\
        font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif;\n\
        font-weight: 400;\n\
        font-size: 16px;\n\
        -ms-text-size-adjust: 100%;\n\
        -webkit-text-size-adjust: 100%;\n\
        margin: 16px;\n\
      }\n\
\n\
      body {\n\
        line-height: 1.5rem;\n\
        max-width: 64em;\n\
        margin: auto;\n\
      }\n\
\n\
      h1, h2, h3, p, figure, blockquote, ul, li, a {\n\
        /* Don't break out */\n\
        overflow-wrap: break-word;\n\
        word-wrap: break-word;\n\
        margin-block-start: 0px;\n\
        margin-block-end: 0px;\n\
      }\n\
\n\
      h1, h2, h3 {\n\
        line-height: 1.5em;\n\
        font-weight: bold;\n\
      }\n\
\n\
      h1 {\n\
        font-size: 3em;\n\
      }\n\
\n\
      h2 {\n\
        font-size: 2em;\n\
      }\n\
\n\
      h3 {\n\
        font-size: 1.5em;\n\
      }\n\
\n\
      pre {\n\
        overflow-x: scroll;\n\
        background-color: rgb(245,245,245);\n\
        padding-left: 1em;\n\
        padding-right: 1em;\n\
        padding-top: 0.5em;\n\
        padding-bottom: 0.5em;\n\
        margin-top: 0px;\n\
        margin-bottom: 0px;\n\
        line-height: 1.3em;\n\
        font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace;\n\
      }\n\
\n\
      figure {\n\
        margin-inline-start: 0px;\n\
        margin-inline-end: 0px;\n\
      }\n\
\n\
      figcaption {\n\
        font-size: 0.75em;\n\
      }\n\
\n\
      blockquote:before, blockquote:after {\n\
        content: \"\";\n\
      }\n\
\n\
      blockquote {\n\
        border-left: 6px solid #ccc;\n\
        padding-left: 0.5em;\n\
        margin-top: 0px;\n\
        margin-bottom: 0px;\n\
        margin-left: 0.5em;\n\
      }\n\
\n\
      li {\n\
        padding-top: 0px;\n\
      }\n\
\n\
      a {\n\
        color: #33adff;\n\
        outline: 0 none;\n\
        text-decoration: none;\n\
      }\n\
\n\
      a:not([href^=\"#\"])::before {\n\
        content: \"\\2192\\00a0\";\n\
      }\n\
\n\
      img {\n\
        max-width: 100%;\n\
      }\n\
\n\
      /* Mobile view */\n\
      @media (max-width: 600px) {\n\
        body {\n\
          margin: 8px;\n\
        }\n\
      }\n\
\n\
      @media print {\n\
        a:not([href^=\"#\"]):not([data-noprint])::after {\n\
          content: \" (\" attr(href) \") \";\n\
        }\n\
      }"

  if (css_file != "") {
    _embedded_css = ""
    while (getline <css_file > 0) {
      if (_embedded_css == "") {
        _embedded_css = _embedded_css "      " $0
      } else {
        _embedded_css = _embedded_css "\n      " $0 
      }           
    }
    close(css_file)
  }

  return _embedded_css
}

function escape_html(s) {
  gsub(/&/,"\\&amp;",s)
  gsub(/</,"\\&lt;",s)
  gsub(/>/,"\\&gt;",s)
  return s
}

function escape_attribute(s) {
  escape_html(s)
  gsub(/"/,"\\&quot;",s)
  return s
}

function basename(file, _a1, _a2, _n1) {
  _n1 = split(file, _a1, "/")
  split(_a1[_n1], _a2, ".")
  return _a2[1]
}

function is_image(url, _suffix) {
  sub(/^[ \t]+/,"",url)
  sub(/[ \t]+$/,"",url)
  
  _suffix = tolower(substr(url,length(url)-3))
  if (_suffix == ".png" || _suffix == ".jpg") {
    return true
  } else {
    return false
  }
}

function print_heading(type, heading, _id) {
  heading = create_heading(heading)
  
  if (TOC == true) {
    _id = " id=\"" create_id(heading) "\""
  } else {
    _id = ""
  }

  if (TOC == true) {
    print body_padding "<" type _id "><a href=\"#\">" escape_html(heading) "</a></" type  ">"
  } else {
    print body_padding "<" type _id ">" escape_html(heading) "</" type  ">"
  }
}

function create_heading(string) {
    sub(/^(###|##|#)[ \t]*/,"",string)
    sub(/^[ \t]+/,"",string)
    sub(/[ \t]+$/,"",string)
    
    return string
}

function create_id(string) {
    sub(/^[ \t]+/,"",string)
    sub(/[ \t]+$/,"",string)

    gsub(/[ \t]/,"-",string)
    gsub(/[^0-9a-zA-Z\-]/,"",string)
    return tolower(string)
}

function create_toc(file, toc, _preformat_toggle, _toc_count) {
  _preformat_toggle = false
  _toc_count = 0

  while (getline <file > 0) {
    if ($0 ~ /^```/) {
      if (_preformat_toggle == false) {
        _preformat_toggle = true
      } else {
        _preformat_toggle = false
      }
    } else if ($0 ~ /^(###|##|#)[ \t]*/ && _preformat_toggle == false) {
      toc[++_toc_count] = $0
    }
  }
  toc["size"] = _toc_count
  close(file)
}

function print_toc(toc, _level, _heading, _id, _indent, _size, _i) {
  _size = toc["size"]
  for (_i = 1; _i <= _size; _i++) {
    _heading = toc[_i]

    if (_heading ~ /^###/) {
      _level = 3
    } else if (_heading ~ /^##[ \t]*/) {
      _level = 2
    } else if (_heading ~ /^#[ \t]*/) {
      _level = 1
    }

    _heading = create_heading(_heading)
    _id = create_id(_heading)

    _indent = ""
    if (_level == 1) {
      _indent = "→ "
    } else if (_level == 2) {
      _indent = "→ → "
    } else if (_level == 3) {
      _indent = "→ → → "
    }
    print body_padding "<p><a href=\"#" _id "\">" escape_html(_indent _heading) "</a></p>"
  }
  print body_padding "<p><br></p>"
}

/^=>[ \t]*/ && preformat_toggle == false {
  sub(/^=>[ \t]*/, "")
  url = ""
  link_name = ""
  if (match($0,/[ \t]+/)) {
    url = substr($0,0,RSTART-1)
    link_name = substr($0,RSTART+RLENGTH)
    data_attribute = "" 
  } else {
    url = $0
    link_name = $0
    data_attribute = "data-noprint "
  }
  if (INLINE == true && is_image(url) == true) {
    print body_padding "<p><img src=\"" url "\" alt=\"" escape_html(link_name) "\"></p>"
  } else {
    print body_padding "<p><a " data_attribute "href=\"" url "\">" escape_html(link_name) "</a></p>"
  }
  next
}

/^```/ && preformat_toggle == false {
  preformat_toggle = true
  preformat_start = true

  sub(/^```[ \t]*/, "")
  sub(/[ \t]+$/,"")
  if ($0 != "") {
    preformat_title = $0
    if (preformat_title == "TOC" && TOC == true) {
      print_toc(TABLE_OF_CONTENTS)
    }
  }
  
  next
}

/^```/ && preformat_toggle == true {
  preformat_toggle = false

  if (preformat_start == true) { 
    preformat_start = false
  } else {
    print "</pre>"
    if (preformat_title != "") {
      print body_padding "  <figcaption id=\"" create_id(preformat_title) "\">"
      print body_padding "    " escape_attribute(preformat_title)
      print body_padding "  </figcaption>"
      print body_padding "</figure>"
    }
  }

  preformat_title = ""

  next
}

/^###/ && preformat_toggle == false {
  print_heading("h3", $0)
  next
}

/^##[ \t]*/ && preformat_toggle == false {
  print_heading("h2", $0)
  next
}

/^#[ \t]*/ && preformat_toggle == false {
  print_heading("h1", $0)
  next
}

/^\* / && preformat_toggle == false {
  sub(/^\* /, "")
  print body_padding "<ul><li>" escape_html($0) "</li></ul>"
  next
}

/^>/ && preformat_toggle == false {
  sub(/^>/, "")
  print body_padding "<blockquote>" escape_html($0) "</blockquote>"
  next
}

{
  if (preformat_toggle == true) {
    if (preformat_start == true) {
      preformat_start = false
      if (preformat_title == "") {
        print body_padding "<pre>"
      } else {
        print body_padding "<figure role=\"figure\" aria-labelledby=\"" create_id(preformat_title) "\">"
        print body_padding "  <pre>"
      }
    }
    print escape_html($0)
  } else {
    if ($0 ~ /^[ \t]*$/) {
      print body_padding "<p><br></p>"
    } else {
      print body_padding "<p>" escape_html($0) "</p>"
    }
  }
}

END {
  print "  <body>"
  print "</html>"
}