title: Convert attributed string, to, "simple" tagged html
body: <p>I want to convert an NSAttributedString, to html like this:</p>
  
  <pre><code>This is a &lt;i&gt;string&lt;/i&gt; with some &lt;b&gt;simple&lt;/b&gt; &lt;i&gt;&lt;b&gt;html&lt;/b&gt;&lt;/i&gt; tags in it.
  </code></pre>
  
  <p>Unfortunately if you use apple's built-in system it generates verbose css-based html.  (Example below for reference.)</p>
  
  <p>So how to generate simple tagged html from an NSAttributedString?</p>
  
  <p>I wrote a very verbose, fragile call to do it, which is a poor solution.</p>
  
  <pre><code>func simpleTagStyle(fromNSAttributedString att: NSAttributedString)-&gt;String {
  
      // verbose, fragile solution
  
      // essentially, iterate all the attribute ranges in the attString
      // make a note of what style they are, bold italic etc
      // (totally ignore any not of interest to us)
      // then basically get the plain string, and munge it for those ranges.
      // be careful with the annoying "multiple attribute" case
      // (an alternative would be to repeatedly munge out attributed ranges
      // one by one until there are none left.)
  
      let rangeAll = NSRange(location: 0, length: att.length)
  
      // make a note of all of the ranges of bold/italic
      // (use a tuple to remember which is which)
      var allBlocks: [(NSRange, String)] = []
  
      att.enumerateAttribute(
          NSFontAttributeName,
          in: rangeAll,
          options: .longestEffectiveRangeNotRequired
          )
              { value, range, stop in
  
              handler: if let font = value as? UIFont {
  
                  let b = font.fontDescriptor.symbolicTraits.contains(.traitBold)
                  let i = font.fontDescriptor.symbolicTraits.contains(.traitItalic)
  
                  if b &amp;&amp; i {
                      allBlocks.append( (range, "bolditalic") )
                      break handler   // take care not to duplicate
                  }
  
                  if b {
                      allBlocks.append( (range, "bold") )
                      break handler
                  }
  
                  if i {
                      allBlocks.append( (range, "italic") )
                      break handler
                  }
              }
  
          }
  
      // traverse those backwards and munge away
  
      var plainString = att.string
  
      for oneBlock in allBlocks.reversed() {
  
          let r = oneBlock.0.range(for: plainString)!
  
          let w = plainString.substring(with: r)
  
          if oneBlock.1 == "bolditalic" {
              plainString.replaceSubrange(r, with: "&lt;b&gt;&lt;i&gt;" + w + "&lt;/i&gt;&lt;/b&gt;")
          }
  
          if oneBlock.1 == "bold" {
              plainString.replaceSubrange(r, with: "&lt;b&gt;" + w + "&lt;/b&gt;")
          }
  
          if oneBlock.1 == "italic" {
              plainString.replaceSubrange(r, with: "&lt;i&gt;" + w + "&lt;/i&gt;")
          }
  
      }
  
      return plainString
  }
  </code></pre>
  
  <hr>
  
  <p>So here's how to use Apple's built in system, which unfortunately generates full-on CSS etc.</p>
  
  <pre><code>x = ... your NSAttributedText
  var resultHtmlText = ""
  do {
  
      let r = NSRange(location: 0, length: x.length)
      let att = [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType]
  
      let d = try x.data(from: r, documentAttributes: att)
  
      if let h = String(data: d, encoding: .utf8) {
          resultHtmlText = h
      }
  }
  catch {
      print("utterly failed to convert to html!!! \n&gt;\(x)&lt;\n")
  }
  print(resultHtmlText)
  </code></pre>
  
  <p>Example output....</p>
  
  <pre><code>&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"&gt;
  &lt;html&gt;
  &lt;head&gt;
  &lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8"&gt;
  &lt;meta http-equiv="Content-Style-Type" content="text/css"&gt;
  &lt;title&gt;&lt;/title&gt;
  &lt;meta name="Generator" content="Cocoa HTML Writer"&gt;
  &lt;style type="text/css"&gt;
  p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px 'Some Font'}
  span.s1 {font-family: 'SomeFont-ItalicOrWhatever'; font-weight: normal; font-style: normal; font-size: 14.00pt}
  span.s2 {font-family: 'SomeFont-SemiboldItalic'; font-weight: bold; font-style: italic; font-size: 14.00pt}
  &lt;/style&gt;
  &lt;/head&gt;
  &lt;body&gt;
  &lt;p class="p1"&gt;&lt;span class="s1"&gt;So, &lt;/span&gt;&lt;span class="s2"&gt;here is&lt;/span&gt;&lt;span class="s1"&gt; some&lt;/span&gt; stuff&lt;/p&gt;
  &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>