| author | wenzelm | 
| Tue, 24 Sep 2024 21:24:44 +0200 | |
| changeset 80945 | 584828fa7a97 | 
| parent 78592 | fdfe9b91d96e | 
| child 82142 | 508a673c87ac | 
| permissions | -rw-r--r-- | 
| 76508 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 1 | /* Title: Pure/Tools/prismjs.scala | 
| 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 2 | Author: Makarius | 
| 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 3 | |
| 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 4 | Support for the Prism.js syntax highlighter -- via external Node.js process. | 
| 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 5 | */ | 
| 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 6 | |
| 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 7 | package isabelle | 
| 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 8 | |
| 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 9 | import scala.collection.mutable | 
| 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 10 | |
| 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 11 | |
| 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 12 | object Prismjs {
 | 
| 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 13 | /* component resources */ | 
| 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 14 | |
| 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 15 |   val HOME: Path = Path.explode("$ISABELLE_PRISMJS_HOME")
 | 
| 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 16 | |
| 76513 | 17 |   sealed case class Language(names: List[String]) {
 | 
| 18 | require(names.nonEmpty) | |
| 19 | ||
| 20 | def name: String = names.head | |
| 21 | def alias: List[String] = names.tail | |
| 22 | override def toString: String = name | |
| 23 | } | |
| 24 | ||
| 25 |   lazy val languages: List[Language] = {
 | |
| 76508 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 26 |     val components_path = HOME + Path.explode("components.json")
 | 
| 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 27 | val components_json = JSON.parse(File.read(components_path)) | 
| 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 28 |     JSON.value(components_json, "languages") match {
 | 
| 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 29 | case Some(JSON.Object(langs)) => | 
| 78592 | 30 |         (for (case (name, JSON.Object(info)) <- langs.iterator if name != "meta") yield {
 | 
| 76508 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 31 | val alias = | 
| 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 32 |             JSON.Value.List.unapply(info.getOrElse("alias", Nil), JSON.Value.String.unapply)
 | 
| 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 33 | .getOrElse(Nil) | 
| 76513 | 34 | Language(name :: alias) | 
| 76516 | 35 | }).toList.sortBy(_.name) | 
| 76508 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 36 |       case _ => error("Failed to determine languages from " + components_path)
 | 
| 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 37 | } | 
| 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 38 | } | 
| 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 39 | |
| 76513 | 40 | def check_language(name: String): Unit = | 
| 41 |     if (!languages.exists(_.names.contains(name))) error("Unknown language " + quote(name))
 | |
| 76508 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 42 | |
| 76513 | 43 | |
| 44 | /* generate JavaScript */ | |
| 76508 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 45 | |
| 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 46 | def prelude(lang: JS.Source): JS.Source = | 
| 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 47 | cat_lines(List( | 
| 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 48 | Nodejs.require_fs, | 
| 76510 | 49 |       Nodejs.require_path("const prismjs", HOME),
 | 
| 50 |       Nodejs.require_path("prismjs.load", HOME + Path.explode("components"), dir = true),
 | |
| 51 |       JS.function("prismjs.load", lang),
 | |
| 76508 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 52 | """ | 
| 76513 | 53 | function prismjs_encode(t) {
 | 
| 54 |   if (t instanceof prismjs.Token) {
 | |
| 55 | var types = [t.type] | |
| 56 |     if (Array.isArray(t.alias)) { for (a of t.alias) { types.push(a) } }
 | |
| 57 |     else if (t.alias !== undefined) { types.push(t.alias) }
 | |
| 58 |     return {"types": types, "content": prismjs_encode(t.content) }
 | |
| 59 | } | |
| 60 |   else if (Array.isArray(t)) { return t.map(prismjs_encode) }
 | |
| 76508 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 61 |   else { return t }
 | 
| 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 62 | } | 
| 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 63 | |
| 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 64 | function prismjs_tokenize(text, lang) {
 | 
| 76513 | 65 | return prismjs.tokenize(text, prismjs.languages[lang]).map(prismjs_encode) | 
| 76508 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 66 | } | 
| 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 67 | """)) | 
| 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 68 | |
| 76513 | 69 | def main(lang: JS.Source, input: Path, output: Path): JS.Source = | 
| 70 | Nodejs.write_file(output, | |
| 71 |       JS.json_print(JS.function("prismjs_tokenize", Nodejs.read_file(input), lang)))
 | |
| 72 | ||
| 76508 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 73 | |
| 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 74 | /* tokenize */ | 
| 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 75 | |
| 76513 | 76 |   sealed case class Token(types: List[String], content: Content) {
 | 
| 77 | def string: String = content.string | |
| 76514 
2615cf68f6f4
ML support for the Prism.js syntax highlighter -- via Isabelle/Scala;
 wenzelm parents: 
76513diff
changeset | 78 | def yxml: String = YXML.string_of_body(Encode.token(this)) | 
| 76513 | 79 | } | 
| 80 |   sealed abstract class Content { def string: String }
 | |
| 81 | case class Atom(string: String) extends Content | |
| 82 |   case class Nested(tokens: List[Token]) extends Content {
 | |
| 76514 
2615cf68f6f4
ML support for the Prism.js syntax highlighter -- via Isabelle/Scala;
 wenzelm parents: 
76513diff
changeset | 83 | def string: String = tokens.map(_.string).mkString | 
| 
2615cf68f6f4
ML support for the Prism.js syntax highlighter -- via Isabelle/Scala;
 wenzelm parents: 
76513diff
changeset | 84 | } | 
| 
2615cf68f6f4
ML support for the Prism.js syntax highlighter -- via Isabelle/Scala;
 wenzelm parents: 
76513diff
changeset | 85 | |
| 
2615cf68f6f4
ML support for the Prism.js syntax highlighter -- via Isabelle/Scala;
 wenzelm parents: 
76513diff
changeset | 86 |   object Encode {
 | 
| 
2615cf68f6f4
ML support for the Prism.js syntax highlighter -- via Isabelle/Scala;
 wenzelm parents: 
76513diff
changeset | 87 | import XML.Encode._ | 
| 
2615cf68f6f4
ML support for the Prism.js syntax highlighter -- via Isabelle/Scala;
 wenzelm parents: 
76513diff
changeset | 88 | def token(tok: Token): XML.Body = | 
| 
2615cf68f6f4
ML support for the Prism.js syntax highlighter -- via Isabelle/Scala;
 wenzelm parents: 
76513diff
changeset | 89 | pair(list(string), content)(tok.types, tok.content) | 
| 
2615cf68f6f4
ML support for the Prism.js syntax highlighter -- via Isabelle/Scala;
 wenzelm parents: 
76513diff
changeset | 90 |     def content: T[Content] = {
 | 
| 
2615cf68f6f4
ML support for the Prism.js syntax highlighter -- via Isabelle/Scala;
 wenzelm parents: 
76513diff
changeset | 91 | variant[Content](List( | 
| 
2615cf68f6f4
ML support for the Prism.js syntax highlighter -- via Isabelle/Scala;
 wenzelm parents: 
76513diff
changeset | 92 |         { case Atom(a) => (List(a), Nil) },
 | 
| 
2615cf68f6f4
ML support for the Prism.js syntax highlighter -- via Isabelle/Scala;
 wenzelm parents: 
76513diff
changeset | 93 |         { case Nested(a) => (Nil, list(token)(a)) }
 | 
| 
2615cf68f6f4
ML support for the Prism.js syntax highlighter -- via Isabelle/Scala;
 wenzelm parents: 
76513diff
changeset | 94 | )) | 
| 
2615cf68f6f4
ML support for the Prism.js syntax highlighter -- via Isabelle/Scala;
 wenzelm parents: 
76513diff
changeset | 95 | } | 
| 76513 | 96 | } | 
| 97 | ||
| 98 | def decode(json: JSON.T): Option[Token] = | |
| 99 | JSON.Value.String.unapply(json).map(string => Token(Nil, Atom(string))) orElse | |
| 100 |       (for {
 | |
| 101 | types <- JSON.strings(json, "types") | |
| 102 | content_json <- JSON.value(json, "content") | |
| 103 | content <- | |
| 104 | JSON.Value.String.unapply(content_json).map(Atom.apply) orElse | |
| 105 | JSON.Value.List.unapply(content_json, decode).map(Nested.apply) | |
| 106 | } yield Token(types, content)) | |
| 76508 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 107 | |
| 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 108 |   def tokenize(text: String, language: String): List[Token] = {
 | 
| 76513 | 109 | check_language(language) | 
| 76508 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 110 | |
| 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 111 | val json = | 
| 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 112 |       Isabelle_System.with_tmp_file("input", ext = "json") { input =>
 | 
| 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 113 |         Isabelle_System.with_tmp_file("output", ext = "json") { output =>
 | 
| 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 114 | File.write(input, text) | 
| 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 115 | val lang = JS.value(language) | 
| 76513 | 116 | Nodejs.execute(prelude(lang) + "\n" + main(lang, input, output)) | 
| 76508 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 117 | JSON.parse(File.read(output)) | 
| 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 118 | } | 
| 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 119 | } | 
| 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 120 | |
| 76513 | 121 |     JSON.Value.List.unapply(json, decode).getOrElse(error("Malformed JSON: " + json))
 | 
| 76508 
ecb9e6d29698
support for the Prism.js syntax highlighter -- via external Node.js process;
 wenzelm parents: diff
changeset | 122 | } | 
| 76514 
2615cf68f6f4
ML support for the Prism.js syntax highlighter -- via Isabelle/Scala;
 wenzelm parents: 
76513diff
changeset | 123 | |
| 
2615cf68f6f4
ML support for the Prism.js syntax highlighter -- via Isabelle/Scala;
 wenzelm parents: 
76513diff
changeset | 124 | |
| 
2615cf68f6f4
ML support for the Prism.js syntax highlighter -- via Isabelle/Scala;
 wenzelm parents: 
76513diff
changeset | 125 | /* Scala functions in ML */ | 
| 
2615cf68f6f4
ML support for the Prism.js syntax highlighter -- via Isabelle/Scala;
 wenzelm parents: 
76513diff
changeset | 126 | |
| 
2615cf68f6f4
ML support for the Prism.js syntax highlighter -- via Isabelle/Scala;
 wenzelm parents: 
76513diff
changeset | 127 |   object Languages extends Scala.Fun_Strings("Prismjs.languages") {
 | 
| 
2615cf68f6f4
ML support for the Prism.js syntax highlighter -- via Isabelle/Scala;
 wenzelm parents: 
76513diff
changeset | 128 | val here = Scala_Project.here | 
| 
2615cf68f6f4
ML support for the Prism.js syntax highlighter -- via Isabelle/Scala;
 wenzelm parents: 
76513diff
changeset | 129 | def apply(args: List[String]): List[String] = | 
| 
2615cf68f6f4
ML support for the Prism.js syntax highlighter -- via Isabelle/Scala;
 wenzelm parents: 
76513diff
changeset | 130 | languages.map(language => cat_lines(language.names)) | 
| 
2615cf68f6f4
ML support for the Prism.js syntax highlighter -- via Isabelle/Scala;
 wenzelm parents: 
76513diff
changeset | 131 | } | 
| 
2615cf68f6f4
ML support for the Prism.js syntax highlighter -- via Isabelle/Scala;
 wenzelm parents: 
76513diff
changeset | 132 | |
| 
2615cf68f6f4
ML support for the Prism.js syntax highlighter -- via Isabelle/Scala;
 wenzelm parents: 
76513diff
changeset | 133 |   object Tokenize extends Scala.Fun_Strings("Prismjs.tokenize", thread = true) {
 | 
| 
2615cf68f6f4
ML support for the Prism.js syntax highlighter -- via Isabelle/Scala;
 wenzelm parents: 
76513diff
changeset | 134 | val here = Scala_Project.here | 
| 
2615cf68f6f4
ML support for the Prism.js syntax highlighter -- via Isabelle/Scala;
 wenzelm parents: 
76513diff
changeset | 135 | def apply(args: List[String]): List[String] = | 
| 
2615cf68f6f4
ML support for the Prism.js syntax highlighter -- via Isabelle/Scala;
 wenzelm parents: 
76513diff
changeset | 136 |       args match {
 | 
| 
2615cf68f6f4
ML support for the Prism.js syntax highlighter -- via Isabelle/Scala;
 wenzelm parents: 
76513diff
changeset | 137 | case List(text, language) => tokenize(text, language).map(_.yxml) | 
| 
2615cf68f6f4
ML support for the Prism.js syntax highlighter -- via Isabelle/Scala;
 wenzelm parents: 
76513diff
changeset | 138 |         case _ => error("Bad arguments")
 | 
| 
2615cf68f6f4
ML support for the Prism.js syntax highlighter -- via Isabelle/Scala;
 wenzelm parents: 
76513diff
changeset | 139 | } | 
| 
2615cf68f6f4
ML support for the Prism.js syntax highlighter -- via Isabelle/Scala;
 wenzelm parents: 
76513diff
changeset | 140 | } | 
| 
2615cf68f6f4
ML support for the Prism.js syntax highlighter -- via Isabelle/Scala;
 wenzelm parents: 
76513diff
changeset | 141 | } |