packages feed

skylighting-format-typst (empty) → 0.1

raw patch · 4 files changed

+183/−0 lines, 4 filesdep +basedep +containersdep +skylighting-core

Dependencies added: base, 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-typst++This package provides functions to render syntax-highlighting+as typst.+
+ skylighting-format-typst.cabal view
@@ -0,0 +1,36 @@+name:                skylighting-format-typst+version:             0.1+synopsis:            Typst formatter for skylighting syntax highlighting library+description:         This module allows tokens produced by skylighting-core+                     to be rendered as Typst.+homepage:            https://github.com/jgm/skylighting+license:             BSD3+license-file:        LICENSE+author:              John MacFarlane+maintainer:          jgm@berkeley.edu+copyright:           (C) 2024 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.Typst+  other-extensions:    CPP+  build-depends:       base >= 4.8 && < 5.0,+                       skylighting-core,+                       text,+                       containers+  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/Typst.hs view
@@ -0,0 +1,112 @@+{-# LANGUAGE CPP                 #-}+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE ScopedTypeVariables #-}+module Skylighting.Format.Typst (+         formatTypstInline+       , formatTypstBlock+       , styleToTypst+       ) where++import Control.Monad (mplus)+import Data.List (sort)+import qualified Data.Map as Map+import Data.Text (Text)+import qualified Data.Text as Text+import Skylighting.Types+import qualified Data.Map as M+import Data.Maybe (fromMaybe)+#if !MIN_VERSION_base(4,11,0)+import Data.Semigroup+#endif++-- | Formats tokens as Typst using custom commands inside+-- @|@ characters. Assumes that @|@ is defined as a short verbatim+-- command by the macros produced by 'styleToTypst'.+-- A @KeywordTok@ is rendered using @\\KeywordTok{..}@, and so on.+formatTypstInline :: FormatOptions -> [SourceLine] -> Text+formatTypstInline _opts = Text.intercalate newline . map sourceLineToTypst++newline :: Text+newline =  "#EndLine()\n"++sourceLineToTypst :: SourceLine -> Text+sourceLineToTypst = mconcat . map tokenToTypst++tokenToTypst :: Token -> Text+tokenToTypst (toktype, txt) =+  "#" <> Text.pack (show toktype) <> "(" <> doubleQuoted txt <> ");"++doubleQuoted :: Text -> Text+doubleQuoted t = "\"" <> escape t <> "\""+ where+  escape = Text.concatMap escapeChar+  escapeChar '\\' = "\\\\"+  escapeChar '"' = "\\\""+  escapeChar c = Text.singleton c++-- Typst++-- | Format tokens as a Typst @Highlighting@ environment inside a+-- Skylighting block that can be styled. @Skylighting@ is+-- defined by the macros produced by 'styleToTypst'.+formatTypstBlock :: FormatOptions -> [SourceLine] -> Text+formatTypstBlock opts ls =+  "#Skylighting(" <>+  (if numberLines opts+       then "number: true, start: " <> Text.pack (show (startNumber opts)) <> ", "+       else "") <>+  "(" <> -- an array+  Text.intercalate "\n" (map (\ln -> "[" <> formatTypstInline opts [ln] <> "],") ls)+  <> "));"++-- | Converts a 'Style' to a set of Typst macro definitions,+-- which should be placed in the document's preamble.+styleToTypst :: Style -> Text+styleToTypst f =+  Text.unlines $+  [ "/* Function definitions for syntax highlighting generated by skylighting: */"+  , "#let EndLine() = raw(\"\\n\")"+  , "#let Skylighting(fill: none, number: false, start: 1, sourcelines) = {"+  , "   let blocks = []"+  , "   let lnum = start - 1"+  , "   let bgcolor = " <> maybe "none" toTypstColor (backgroundColor f)+  , "   for ln in sourcelines {"+  , "     if number {"+  , "       lnum = lnum + 1"+  , "       blocks = blocks + box(width: if start + sourcelines.len() > 999 { 30pt } else { 24pt }, text(" <> lineNumberFill <> "[ #lnum ]))"+  , "     }"+  , "     blocks = blocks + ln + EndLine()"+  , "   }"+  , "   block(fill: bgcolor, blocks)"+  , "}"+  ] <>+  sort (map (macrodef (defaultColor f) (Map.toList (tokenStyles f)))+         (enumFromTo KeywordTok NormalTok))+ where+   toTypstColor c = "rgb(" <> Text.pack (show (fromColor c :: String)) <> ")"+   lineNumberFill = case lineNumberColor f of+                      Nothing -> ""+                      Just c -> "fill: " <> toTypstColor c <> ", "++macrodef :: Maybe Color -> [(TokenType, TokenStyle)] -> TokenType -> Text+macrodef defaultcol tokstyles' tokt =+  "#let " <> Text.pack (show tokt) <> "(s) = " <> (ul . bg . textstyle) ("raw(s)")+ where tokstyles = M.fromList tokstyles'+       tokf = fromMaybe defStyle $ M.lookup tokt tokstyles+       ul x = if tokenUnderline tokf+                 then "underline(" <> x <> ")"+                 else x+       bg x = case tokenBackground tokf of+                   Nothing        -> x+                   Just _c -> x -- TODO?+       textstyle x = "text(" <> bf <> it <> co <> x <> ")"+       it = if tokenItalic tokf+               then "style: \"italic\","+               else ""+       bf = if tokenBold tokf+               then "weight: \"bold\","+               else ""+       co = case tokenColor tokf `mplus` defaultcol of+                 Just c -> "fill: rgb(" <>+                   Text.pack (show (fromColor c :: String)) <> "),"+                 Nothing -> ""