packages feed

skylighting-format-blaze-html (empty) → 0.1

raw patch · 4 files changed

+288/−0 lines, 4 filesdep +basedep +blaze-htmldep +containers

Dependencies added: base, blaze-html, containers, skylighting-core, text

Files

+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2016-2018, John MacFarlane.+All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are+met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * The names of the contributors may not be used to endorse or+      promote products derived from this software without specific+      prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,5 @@+# skylighting-format-ansi++This package provides functions to render syntax-highlighting+as ANSI text.+
+ skylighting-format-blaze-html.cabal view
@@ -0,0 +1,37 @@+name:                skylighting-format-blaze-html+version:             0.1+synopsis:            HTML formatter for skylighting syntax highlighting library+description:         This module allows tokens produced by skylighting-core+                     to be rendered as HTML.+homepage:            https://github.com/jgm/skylighting+license:             BSD3+license-file:        LICENSE+author:              John MacFarlane+maintainer:          jgm@berkeley.edu+copyright:           (C) 2016-2022 John MacFarlane+category:            Text+build-type:          Simple+extra-source-files:  README.md++cabal-version:       >=1.10++source-repository head+  type:              git+  location:          https://github.com/jgm/skylighting.git++library+  exposed-modules:     Skylighting.Format.HTML+  other-extensions:    CPP+  build-depends:       base >= 4.8 && < 5.0,+                       skylighting-core,+                       text,+                       containers,+                       blaze-html >= 0.5+  hs-source-dirs:      src+  ghc-prof-options:    -fprof-auto-exported+  default-language:    Haskell2010+  ghc-options:         -Wall+  if impl(ghc >= 8.4)+    ghc-options:       -fhide-source-paths+  if impl(ghc >= 8.10)+    ghc-options:      -Wunused-packages
+ src/Skylighting/Format/HTML.hs view
@@ -0,0 +1,216 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE NoOverloadedStrings #-}+module Skylighting.Format.HTML (+      formatHtmlInline+    , formatHtmlBlock+    , styleToCss+    ) where++import Data.List (intersperse, sort)+import qualified Data.Map as Map+import qualified Data.Text as Text+import Skylighting.Types+import Text.Blaze.Html+import qualified Text.Blaze.Html5 as H+import qualified Text.Blaze.Html5.Attributes as A+import Data.String (fromString)+#if !MIN_VERSION_base(4,11,0)+import Data.Semigroup+#endif++-- | Format tokens using HTML spans inside @code@ tags. For example,+-- A @KeywordTok@ is rendered as a span with class @kw@.+-- Short class names correspond to 'TokenType's as follows:+-- 'KeywordTok'        = @kw@,+-- 'DataTypeTok'       = @dt@,+-- 'DecValTok'         = @dv@,+-- 'BaseNTok'          = @bn@,+-- 'FloatTok'          = @fl@,+-- 'CharTok'           = @ch@,+-- 'StringTok'         = @st@,+-- 'CommentTok'        = @co@,+-- 'OtherTok'          = @ot@,+-- 'AlertTok'          = @al@,+-- 'FunctionTok'       = @fu@,+-- 'RegionMarkerTok'   = @re@,+-- 'ErrorTok'          = @er@,+-- 'ConstantTok'       = @cn@,+-- 'SpecialCharTok'    = @sc@,+-- 'VerbatimStringTok' = @vs@,+-- 'SpecialStringTok'  = @ss@,+-- 'ImportTok'         = @im@,+-- 'DocumentationTok'  = @do@,+-- 'AnnotationTok'     = @an@,+-- 'CommentVarTok'     = @cv@,+-- 'VariableTok'       = @va@,+-- 'ControlFlowTok'    = @cf@,+-- 'OperatorTok'       = @op@,+-- 'BuiltInTok'        = @bu@,+-- 'ExtensionTok'      = @ex@,+-- 'PreprocessorTok'   = @pp@,+-- 'AttributeTok'      = @at@,+-- 'InformationTok'    = @in@,+-- 'WarningTok'        = @wa@.+-- A 'NormalTok' is not marked up at all.+formatHtmlInline :: FormatOptions -> [SourceLine] -> Html+formatHtmlInline opts = wrapCode opts+                      . mconcat . intersperse (toHtml "\n")+                      . map (mapM_ (tokenToHtml opts))++-- | Format tokens as an HTML @pre@ block. Each line is wrapped in an a+-- element with the class ‘source-line’. If line numbering+-- is selected, the surrounding pre is given the class ‘numberSource’,+-- and the resulting html will display line numbers thanks to the included+-- CSS.  See the documentation for 'formatHtmlInline' for information about how+-- tokens are encoded.+formatHtmlBlock :: FormatOptions -> [SourceLine] -> Html+formatHtmlBlock opts ls =+  H.div ! A.class_ (toValue "sourceCode") $+  H.pre ! A.class_ (toValue $ Text.unwords classes)+        $ wrapCode opts+        $ mconcat . intersperse (toHtml "\n")+        $ zipWith (sourceLineToHtml opts) [startNum..] ls+  where  classes = Text.pack "sourceCode" :+                   [Text.pack "numberSource" | numberLines opts] +++                   [x | x <- containerClasses opts+                      , x /= Text.pack "sourceCode"]+         startNum = LineNo $ startNumber opts++wrapCode :: FormatOptions -> Html -> Html+wrapCode opts h = H.code ! A.class_ (toValue $ Text.unwords+                                             $ Text.pack "sourceCode"+                                               : codeClasses opts)+                         !? (startZero /= 0, A.style (toValue counterOverride))+                         $ h+  where  counterOverride = "counter-reset: source-line " <> show startZero <> ";"+         startZero = startNumber opts - 1++-- | Each line of source is wrapped in an (inline-block) anchor that makes+-- subsequent per-line processing (e.g. adding line numnbers) possible.+sourceLineToHtml :: FormatOptions -> LineNo -> SourceLine -> Html+sourceLineToHtml opts lno cont =+  H.span ! A.id lineNum+         $ do+           H.a ! A.href lineRef+               ! (if numberLines opts+                     then mempty+                     else customAttribute (fromString "aria-hidden")+                           (fromString "true")) -- see jgm/pandoc#6352+               ! (if numberLines opts+                     then mempty+                     else customAttribute (fromString "tabindex")+                           (fromString "-1"))+               $ mempty+           mapM_ (tokenToHtml opts) cont+  where  lineNum = toValue prefixedLineNo+         lineRef = toValue ('#':prefixedLineNo)+         prefixedLineNo = Text.unpack (lineIdPrefix opts) <> show (lineNo lno)++tokenToHtml :: FormatOptions -> Token -> Html+tokenToHtml _ (NormalTok, txt)  = toHtml txt+tokenToHtml opts (toktype, txt) =+  if titleAttributes opts+     then sp ! A.title (toValue $ show toktype)+     else sp+   where sp = H.span ! A.class_ (toValue $ short toktype) $ toHtml txt++short :: TokenType -> String+short KeywordTok        = "kw"+short DataTypeTok       = "dt"+short DecValTok         = "dv"+short BaseNTok          = "bn"+short FloatTok          = "fl"+short CharTok           = "ch"+short StringTok         = "st"+short CommentTok        = "co"+short OtherTok          = "ot"+short AlertTok          = "al"+short FunctionTok       = "fu"+short RegionMarkerTok   = "re"+short ErrorTok          = "er"+short ConstantTok       = "cn"+short SpecialCharTok    = "sc"+short VerbatimStringTok = "vs"+short SpecialStringTok  = "ss"+short ImportTok         = "im"+short DocumentationTok  = "do"+short AnnotationTok     = "an"+short CommentVarTok     = "cv"+short VariableTok       = "va"+short ControlFlowTok    = "cf"+short OperatorTok       = "op"+short BuiltInTok        = "bu"+short ExtensionTok      = "ex"+short PreprocessorTok   = "pp"+short AttributeTok      = "at"+short InformationTok    = "in"+short WarningTok        = "wa"+short NormalTok         = ""++-- | Returns CSS for styling highlighted code according to the given style.+styleToCss :: Style -> String+styleToCss f = unlines $+  divspec ++ numberspec ++ colorspec ++ linkspec +++    sort (map toCss (Map.toList (tokenStyles f)))+   where colorspec = pure . unwords $ [+            "div.sourceCode\n  {"+          , maybe "" (\c -> "color: "            ++ fromColor c ++ ";") (defaultColor f)+          , maybe "" (\c -> "background-color: " ++ fromColor c ++ ";") (backgroundColor f)+          , "}"+          ]+         numberspec = [+            "pre.numberSource code"+          , "  { counter-reset: source-line 0; }"+          , "pre.numberSource code > span"+          , "  { position: relative; left: -4em; counter-increment: source-line; }"+          , "pre.numberSource code > span > a:first-child::before"+          , "  { content: counter(source-line);"+          , "    position: relative; left: -1em; text-align: right; vertical-align: baseline;"+          , "    border: none; display: inline-block;"+          , "    -webkit-touch-callout: none; -webkit-user-select: none;"+          , "    -khtml-user-select: none; -moz-user-select: none;"+          , "    -ms-user-select: none; user-select: none;"+          , "    padding: 0 4px; width: 4em;"+          , maybe "" (\c -> "    background-color: " ++ fromColor c ++ ";\n")+              (lineNumberBackgroundColor f) +++            maybe "" (\c -> "    color: " ++ fromColor c ++ ";\n")+              (lineNumberColor f) +++            "  }"+          , "pre.numberSource { margin-left: 3em; " +++              maybe "" (\c -> "border-left: 1px solid " ++ fromColor c ++ "; ") (lineNumberColor f) +++              " padding-left: 4px; }"+          ]+         divspec = [+            "pre > code.sourceCode { white-space: pre; position: relative; }" -- position relative needed for relative contents+          , "pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }"+          , "pre > code.sourceCode > span:empty { height: 1.2em; }" -- correct empty line height+          , ".sourceCode { overflow: visible; }" -- needed for line numbers+          , "code.sourceCode > span { color: inherit; text-decoration: inherit; }"+          , "div.sourceCode { margin: 1em 0; }" -- Collapse neighbours correctly+          , "pre.sourceCode { margin: 0; }" -- Collapse neighbours correctly+          , "@media screen {"+          , "div.sourceCode { overflow: auto; }" -- do not overflow on screen+          , "}"+          , "@media print {"+          , "pre > code.sourceCode { white-space: pre-wrap; }"+          , "pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }"+          , "}"+          ]+         linkspec = [ "@media screen {"+          , "pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }"+          , "}"+          ]++toCss :: (TokenType, TokenStyle) -> String+toCss (t,tf) = "code span" ++ (if null (short t) then "" else ('.' : short t)) ++ " { "+                ++ colorspec ++ backgroundspec ++ weightspec ++ stylespec+                ++ decorationspec ++ "} /* " ++ showTokenType t ++ " */"+  where colorspec = maybe "" (\col -> "color: " ++ fromColor col ++ "; ") $ tokenColor tf+        backgroundspec = maybe "" (\col -> "background-color: " ++ fromColor col ++ "; ") $ tokenBackground tf+        weightspec = if tokenBold tf then "font-weight: bold; " else ""+        stylespec  = if tokenItalic tf then "font-style: italic; " else ""+        decorationspec = if tokenUnderline tf then "text-decoration: underline; " else ""+        showTokenType t' = case reverse (show t') of+                             'k':'o':'T':xs -> reverse xs+                             _              -> ""+