| 1 | # always use LF line endings | |
| 2 | ||
| 3 | # ALL FILES: | |
| 4 | # Normalize line endings to LF on checkin and | |
| 5 | # prevent conversion to CRLF when the file is checked out. | |
| 6 | ||
| 7 | * text eol=lf | |
| 8 | ||
| 9 | ||
| 10 | # BINARY FILES: | |
| 11 | # Disable line ending normalize on checkin. | |
| 12 | ||
| 13 | *.blend binary | |
| 14 | ||
| 15 | *.bin binary | |
| 16 | *.bmp binary | |
| 17 | *.eps binary | |
| 18 | *.exe binary | |
| 19 | *.gif binary | |
| 20 | *.ico binary | |
| 21 | *.jar binary | |
| 22 | *.jpg binary | |
| 23 | *.mng binary | |
| 24 | *.png binary | |
| 25 | *.zip binary | |
| 26 | *.otf binary | |
| 27 | *.ttf binary | |
| 28 | ||
| 1 | 29 |
| 1 | dist | |
| 2 | *.bin | |
| 3 | *.exe | |
| 4 | *.app | |
| 5 | /*.jar | |
| 6 | build | |
| 7 | .gradle | |
| 8 | video | |
| 9 | .settings | |
| 10 | .classpath | |
| 11 | .idea | |
| 12 | count/ | |
| 13 | themes/ | |
| 14 | quotes/ | |
| 15 | tex/ | |
| 16 | spell/ | |
| 17 | keenwrite.build_artifacts.txt | |
| 18 | todo | |
| 19 | tokens/ | |
| 1 | 20 |
| 1 | # Introduction | |
| 2 | ||
| 3 | This document describes how to build the application and platform binaries. | |
| 4 | ||
| 5 | # Requirements | |
| 6 | ||
| 7 | Download and install the following software packages: | |
| 1 | 8 | |
| 9 | * [JDK 22](https://bell-sw.com/pages/downloads) (Full JDK + JavaFX) | |
| 10 | * [Gradle 8.9](https5 |
| 1 | # License | |
| 2 | ||
| 3 | Copyright 2023 White Magic Software, Ltd. | |
| 4 | ||
| 5 | All rights reserved. | |
| 6 | ||
| 7 | Redistribution and use in source and binary forms, with or without | |
| 8 | modification, are permitted provided that the following conditions are met: | |
| 9 | ||
| 10 | * Redistributions of source | |
| 11 | disclaimer. | |
| 12 | ||
| 13 | * | |
| 14 | disclaimer in the | |
| 15 | ||
| 16 | INCLUDING, BUT NOT | |
| 17 | ||
| 18 | A PARTICULAR PURPOSE ARE | |
| 19 | ||
| 20 | ||
| 21 | ||
| 22 | THEORY OF LIABILITY, | |
| 1 | 23 |
| 1 | setwd( v$application$r$working$directory ) | |
| 2 | ||
| 3 | # To reference additional R variables in documents, define them such as: | |
| 4 | # assign( "variable", v$key$name, envir = .GlobalEnv ) | |
| 5 | ||
| 6 | source( "pluralize.R" ) | |
| 7 | source( "possessive.R" ) | |
| 8 | source( "conversion.R" ) | |
| 9 | source( "csv.R" ) | |
| 10 | ||
| 1 | 11 |
| 1 | ||
| 1 | # ----------------------------------------------------------------------------- | |
| 2 | # Copyright 2020, White Magic Software, Ltd. | |
| 3 | # | |
| 4 | # Permission is hereby granted, free of charge, to any person obtaining | |
| 5 | # a copy of this software and associated documentation ounds the given value to the nearest integer. | |
| 6 | # | |
| 7 | # @param n The value roundround.intformat( round( n |
| 1 | # ----------------------------------------------------------------------------- | |
| 2 | # Copyright 2020, White Magic Software, Ltd. | |
| 3 | # | |
| 4 | # Permission is hereby granted, free of charge, to any person obtaining | |
| 5 | # a copy of this software and associated documentation , caption = ""Use pandoc syntax for table captions. | |
| 6 | if( caption != "" ) { | |
| 7 | caption <- paste( '\n[', caption, ']\n', sep='' ) | |
| 8 | } | |
| 9 | ||
| 10 | # Crsep='' | |
| 11 | ), | |
| 12 | '|', | |
| 13 | caption, | |
| 14 | sep='' | |
| 15 | ) | |
| 16 | } | |
| 17 | ||
| 1 | 18 |
| 1 | # TODO: Finish the implementation | |
| 2 | ||
| 3 | # ----------------------------------------------------------------------------- | |
| 4 | # Converts an integer value into English words. Negative numbers are prefixed | |
| 5 | # with the word minus. This is useful for very large numbers. | |
| 6 | # | |
| 7 | # See https://english.stackexchange.com/a/111837/22099 | |
| 8 | # | |
| 9 | # @param n Any integer value, including zero, and negative numbers. | |
| 10 | # ----------------------------------------------------------------------------- | |
| 11 | to.words <- function( n ) { | |
| 12 | s <- 'zero'; | |
| 13 | ||
| 14 | if( n > 0 ) { | |
| 15 | s <- to.words.nz( n ); | |
| 16 | } | |
| 17 | else if( n < 0 ) { | |
| 18 | s <- paste0( 'minus ', to.words.nz( -n ) ); | |
| 19 | } | |
| 20 | ||
| 21 | s | |
| 22 | } | |
| 23 | ||
| 24 | # ----------------------------------------------------------------------------- | |
| 25 | # Converts a non-zero number into English words. | |
| 26 | # ----------------------------------------------------------------------------- | |
| 27 | to.words.nz <- function( n ) { | |
| 28 | scales <- c( | |
| 29 | "thousand", "million", "billion", "trillion", "quadrillion", | |
| 30 | "quintillion", "sextillion", "septillion", "octillion", "nonillion", | |
| 31 | "decillion", "undecillion", "duodecillion", "tredecillion", | |
| 32 | "quattuordecillion", "quindecillion", "sexdecillion", "septendecillion", | |
| 33 | "octodecillion", "novemdecillion", "vigintillion", "centillion", | |
| 34 | "quadrillion", "quitillion", "sextillion" | |
| 35 | ); | |
| 36 | ||
| 37 | i <- 0; | |
| 38 | s <- ""; | |
| 39 | ||
| 40 | while( n > 0 ) { | |
| 41 | if( !(n %% 1000 == 0) ) { | |
| 42 | j <- if( n < 100 ) "," else ""; | |
| 43 | s <- paste( to.words.help( n %% 1000 ), scales[ i ], j, s ); | |
| 44 | } | |
| 45 | ||
| 46 | n <- floor( n / 1000 ); | |
| 47 | i <- i + 1; | |
| 48 | } | |
| 49 | ||
| 50 | s | |
| 51 | } | |
| 52 | ||
| 53 | to.words.help <- function( n ) { | |
| 54 | low <- c( | |
| 55 | "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", | |
| 56 | "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", | |
| 57 | "seventeen", "eighteen", "nineteen" | |
| 58 | ); | |
| 59 | ||
| 60 | tens <- c( | |
| 61 | "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety" | |
| 62 | ); | |
| 63 | ||
| 64 | if( n < 20 ) { | |
| 65 | s <- low[ n ]; | |
| 66 | } | |
| 67 | else if( n < 100 ) { | |
| 68 | d <- n %% 10; | |
| 69 | j <- if( d > 0 ) "-" else ""; | |
| 70 | s <- paste0( tens[ (n / 10) - 1 ], j, to.words.help( d ) ); | |
| 71 | } | |
| 72 | else { | |
| 73 | d <- (n / 100); | |
| 74 | r <- (n %% 100); | |
| 75 | j <- if( r > 0 ) "and" else ""; | |
| 76 | s <- paste( low[ d ], "hundred", j, to.words.help( r ) ); | |
| 77 | } | |
| 78 | ||
| 79 | s | |
| 80 | } | |
| 81 | ||
| 1 | 82 |
| 1 | ||
| 1 | # ----------------------------------------------------------------------------- | |
| 2 | # Copyright 2021 Robin Gertenbach. | |
| 3 | # | |
| 4 | # Copyright 2021 White Magic Software, Ltd. | |
| 5 | # | |
| 6 | # Permission is hereby granted, free of charge, to any person obtaining | |
| 7 | # a copy of this so |
| 1 | ||
| 1 | # ----------------------------------------------------------------------------- | |
| 2 | # Copyright 2020, White Magic Software, Ltd. | |
| 3 | # | |
| 4 | # Permission is hereby granted, free of charge, to any person obtaining | |
| 5 | # a copy of this software and associated documentation madj<- 'his<- 'hishers<- |
| 1 | #  | |
| 2 | ||
| 3 | A free, open-source, cross-platform desktop Markdown editor that can produce beautifully typeset PDFs. | |
| 4 | ||
| 5 | ## Download | |
| 6 | ||
| 7 | Visit [KeenWrite.com](https://keenwrite.com/) for downloads. | |
| 8 | ||
| 9 | ## Run | |
| 1 | 10 | |
| 11 | Note that the first time the a2 |
| 1 | #  | |
| 2 | ||
| 3 | 智能写入是一个文本编辑器,它使用插值字符串引用外部定义的值。 | |
| 4 | ||
| 5 | ## 下载 | |
| 6 | ||
| 7 | [KeenWrite.com](https://keenwrite.com/) | |
| 8 | ||
| 9 | ## 跑 | |
| 10 | ||
| 11 | 在第一次运行期间,应用程序将自身解压到本地目录中。随后的启动会更快。 | |
| 12 | ||
| 13 | ### Windows | |
| 14 | ||
| 15 | 双击应用程序以启动。您必须授予应用程序运行权限。 | |
| 16 | ||
| 17 | 升级时,删除以下目录: | |
| 18 | ||
| 19 | C:\Users\%USERNAME%\AppData\Local\warp\packages\keenwrite.exe | |
| 20 | ||
| 21 | ### Linux | |
| 22 | ||
| 23 | 执行以下命令: | |
| 24 | ||
| 25 | ``` bash | |
| 26 | chmod +x keenwrite.bin | |
| 27 | ./keenwrite.bin | |
| 28 | ``` | |
| 29 | ||
| 30 | ### MacOS | |
| 31 | ||
| 32 | 执行以下命令: | |
| 33 | ||
| 34 | ``` bash | |
| 35 | chmod +x keenwrite.app | |
| 36 | ./keenwrite.app | |
| 37 | ``` | |
| 38 | ||
| 39 | ### Java | |
| 40 | ||
| 41 | 使用Java,首先按照以下一次性设置步骤进行操作: | |
| 42 | ||
| 43 | 1. 下载Java Runtime Environment(JRE)的*完整版本*,[JRE 21](https://bell-sw.com/pages/downloads)。 | |
| 44 | * 需要BellSoft的*完整版本*中捆绑的JavaFX。 | |
| 45 | 1. 安装JRE(将JRE的`bin`目录包含在`PATH`环境变量中)。 | |
| 46 | 1. 打开一个新的终端。 | |
| 47 | 1. 验证安装:`java -version` | |
| 48 | 1. 下载[keenwrite.jar](https://keenwrite.com/downloads/keenwrite.jar)。 | |
| 49 | 1. 下载[keenwrite.sh](https://gitlab.com/DaveJarvis/KeenWrite/-/raw/main/keenwrite.sh?inline=false)。 | |
| 50 | 1. 将`.jar`和`.sh`文件放置在同一个目录中。 | |
| 51 | 1. 使`keenwrite.sh`可执行:`chmod +x keenwrite.sh` | |
| 52 | ||
| 53 | 按以下方式启动应用程序: | |
| 54 | ||
| 55 | 1. 打开一个新的终端。 | |
| 56 | 1. 切换到`.jar`和`.sh`目录。 | |
| 57 | 1. 运行:`./keenwrite.sh` | |
| 58 | ||
| 59 | 应用程序已启动。 | |
| 60 | ||
| 61 | ## 特征 | |
| 62 | ||
| 63 | * 用户定义的插值字符串 | |
| 64 | * 带变量替换的实时预览 | |
| 65 | * 基于变量值自动完成变量名 | |
| 66 | * 独立于操作系统 | |
| 67 | * 打字时拼写检查 | |
| 68 | * 使用TeX的子集编写数学公式 | |
| 69 | * 嵌入R语句 | |
| 70 | ||
| 71 | ## Typesetting | |
| 72 | ||
| 73 | 排版到 PDF 文件需要以下內容: | |
| 74 | ||
| 75 | * [Theme Pack](https://gitlab.com/DaveJarvis/keenwrite-themes/-/releases/permalink/latest/downloads/theme-pack.zip) | |
| 76 | * [ConTeXt](https://wiki.contextgarden.net/Installation) | |
| 77 | ||
| 78 | ## 软件使用 | |
| 79 | ||
| 80 | 有關使用該應用程序的信息,請參[閱詳細文檔](docs/README.md)。 | |
| 81 | ||
| 82 | ## 截图 | |
| 83 | ||
| 84 |  | |
| 85 | ||
| 86 |  | |
| 87 | ||
| 88 |  | |
| 89 | ||
| 90 | ||
| 91 | ## 软件许可证 | |
| 92 | ||
| 93 | This software is licensed under the [BSD 2-Clause License](LICENSE.md) and | |
| 94 | based on [Markdown-Writer-FX](licenses/MARKDOWN-WRITER-FX.md). | |
| 95 | ||
| 1 | 96 |
| 1 | <?xml version="1.0" encoding="UTF-8"?> | |
| 2 | <FindBugsFilter> | |
| 3 | <Match> | |
| 4 | <Or> | |
| 5 | <Bug code="EI, EI2, CT, RV, PI" /> | |
| 6 | </Or> | |
| 7 | </Match> | |
| 8 | ||
| 9 | <Match class="com.keenwrite.preview.HighQualityRenderingHints"> | |
| 10 | <Method name="initializeRenderingHints" /> | |
| 11 | <Bug code="WMI" /> | |
| 12 | </Match> | |
| 13 | ||
| 14 | <Match class="com.keenwrite.processors.html.HtmlPreviewProcessor"> | |
| 15 | <Method name="<init>" /> | |
| 16 | <Bug code="ST" /> | |
| 17 | </Match> | |
| 18 | </FindBugsFilter> | |
| 1 | 19 |
| 1 | //file:noinspection SpellCheckingInspection | |
| 1 | 2 | |
| 3 | buildscript { | |
| 4 | repositories { | |
| 5 | mavenCentral() | |
| 6 | maven { | |
| 7 | url "https://plugins.gradle.org/m2/" | |
| 8 | } | |
| 9 | } | |
| 10 | dependencies { | |
| 11 | classpath 'org.owasp:dependency-check-gradle:10.0.3' | |
| 12 | classpath "com.22 | |
| 13 | targetCompatibility = 22'21' |
| 1 | token.txt | |
| 1 | 2 |
| 1 | # ######################################################################## | |
| 2 | # | |
| 3 | # Copyright 2022 White Magic Software, Ltd. | |
| 4 | # | |
| 5 | # Creates a container image that can run ConTeXt to typeset documents. | |
| 6 | # | |
| 7 | # ######################################################################## | |
| 8 | ||
| 9 | LABEL org.opencontainers.image.description Configures a typesetting system. | |
| 10 | ||
| 11 | FROM alpine:latest | |
| 12 | ENV ENV="/etc/profile" | |
| 13 | ENV PROFILE=/etc/profile | |
| 14 | ||
| 15 | ENV INSTALL_DIR=/opt | |
| 16 | ENV SOURCE_DIR=/root/source | |
| 17 | ENV TARGET_DIR=/root/target | |
| 18 | ENV IMAGES_DIR=/root/images | |
| 19 | ENV THEMES_DIR=/root/themes | |
| 20 | ENV CACHES_DIR=/root/caches | |
| 21 | ENV FONTS_DIR=/usr/share/fonts/user | |
| 22 | ENV DOWNLOAD_DIR=/root | |
| 23 | ||
| 24 | ENV CONTEXT_HOME=$INSTALL_DIR/context | |
| 25 | ||
| 26 | # ######################################################################## | |
| 27 | # | |
| 28 | # Download all required dependencies | |
| 29 | # | |
| 30 | # ######################################################################## | |
| 31 | WORKDIR $DOWNLOAD_DIR | |
| 32 | ||
| 33 | # Many fonts may be downloaded using Google's download URL. Example: | |
| 34 | # https://fonts.google.com/download?family=Roboto%20Mono | |
| 35 | ||
| 36 | # Fonts are repacked with minimal file set, flat directory, and license. | |
| 37 | ADD "https://fonts.keenwrite.com/download/andada-pro.zip" ./ | |
| 38 | ADD "https://fonts.keenwrite.com/download/archivo-narrow.zip" ./ | |
| 39 | ADD "https://fonts.keenwrite.com/download/carlito.zip" ./ | |
| 40 | ADD "https://fonts.keenwrite.com/download/courier-prime.zip" ./ | |
| 41 | ADD "https://fonts.keenwrite.com/download/inconsolata.zip" ./ | |
| 42 | ADD "https://fonts.keenwrite.com/download/libre-baskerville.zip" ./ | |
| 43 | ADD "https://fonts.keenwrite.com/download/niconne.zip" ./ | |
| 44 | ADD "https://fonts.keenwrite.com/download/nunito.zip" ./ | |
| 45 | ADD "https://fonts.keenwrite.com/download/open-sans-emoji.zip" ./ | |
| 46 | ADD "https://fonts.keenwrite.com/download/pt-mono.zip" ./ | |
| 47 | ADD "https://fonts.keenwrite.com/download/pt-sans.zip" ./ | |
| 48 | ADD "https://fonts.keenwrite.com/download/pt-serif.zip" ./ | |
| 49 | ADD "https://fonts.keenwrite.com/download/roboto.zip" ./ | |
| 50 | ADD "https://fonts.keenwrite.com/download/roboto-mono.zip" ./ | |
| 51 | ADD "https://fonts.keenwrite.com/download/source-serif-4.zip" ./ | |
| 52 | ADD "https://fonts.keenwrite.com/download/underwood.zip" ./ | |
| 53 | ||
| 54 | # Typesetting software | |
| 55 | ADD "http://lmtx.pragma-ade.nl/install-lmtx/context-linuxmusl.zip" "context.zip" | |
| 56 | ||
| 57 | # ######################################################################## | |
| 58 | # | |
| 59 | # Install components, modules, configure system, remove unnecessary files | |
| 60 | # | |
| 61 | # ######################################################################## | |
| 62 | WORKDIR $CONTEXT_HOME | |
| 63 | ||
| 64 | RUN \ | |
| 65 | apk add -t py3-cssselect && \ | |
| 66 | apk add -t py3-lxml && \ | |
| 67 | apk add -t py3-numpy && \ | |
| 68 | apk --update --no-cache \ | |
| 69 | add ca-certificates curl fontconfig inkscape rsync && \ | |
| 70 | mkdir -p \ | |
| 71 | "$FONTS_DIR" \ | |
| 72 | "$INSTALL_DIR" \ | |
| 73 | "$TARGET_DIR" \ | |
| 74 | "$SOURCE_DIR" \ | |
| 75 | "$THEMES_DIR" \ | |
| 76 | "$IMAGES_DIR" \ | |
| 77 | "$CACHES_DIR" && \ | |
| 78 | echo "export CONTEXT_HOME=\"$CONTEXT_HOME\"" >> $PROFILE && \ | |
| 79 | echo "export PATH=\"\$PATH:\$CONTEXT_HOME/tex/texmf-linuxmusl/bin\"" >> $PROFILE && \ | |
| 80 | echo "export OSFONTDIR=\"/usr/share/fonts//\"" >> $PROFILE && \ | |
| 81 | echo "PS1='\\u@typesetter:\\w\\$ '" >> $PROFILE && \ | |
| 82 | unzip -d $CONTEXT_HOME $DOWNLOAD_DIR/context.zip && \ | |
| 83 | unzip -j -o -d $FONTS_DIR $DOWNLOAD_DIR/andada-pro.zip "*.otf" && \ | |
| 84 | unzip -j -o -d $FONTS_DIR $DOWNLOAD_DIR/archivo-narrow.zip "*.otf" && \ | |
| 85 | unzip -j -o -d $FONTS_DIR $DOWNLOAD_DIR/carlito.zip "*.ttf" && \ | |
| 86 | unzip -j -o -d $FONTS_DIR $DOWNLOAD_DIR/courier-prime.zip "*.ttf" && \ | |
| 87 | unzip -j -o -d $FONTS_DIR $DOWNLOAD_DIR/libre-baskerville.zip "*.ttf" && \ | |
| 88 | unzip -j -o -d $FONTS_DIR $DOWNLOAD_DIR/inconsolata.zip "*.ttf" && \ | |
| 89 | unzip -j -o -d $FONTS_DIR $DOWNLOAD_DIR/niconne.zip "*.ttf" && \ | |
| 90 | unzip -j -o -d $FONTS_DIR $DOWNLOAD_DIR/nunito.zip "*.ttf" && \ | |
| 91 | unzip -j -o -d $FONTS_DIR $DOWNLOAD_DIR/open-sans-emoji.zip "*.ttf" && \ | |
| 92 | unzip -j -o -d $FONTS_DIR $DOWNLOAD_DIR/pt-mono.zip "*.ttf" && \ | |
| 93 | unzip -j -o -d $FONTS_DIR $DOWNLOAD_DIR/pt-sans.zip "*.ttf" && \ | |
| 94 | unzip -j -o -d $FONTS_DIR $DOWNLOAD_DIR/pt-serif.zip "*.ttf" && \ | |
| 95 | unzip -j -o -d $FONTS_DIR $DOWNLOAD_DIR/roboto.zip "*.ttf" && \ | |
| 96 | unzip -j -o -d $FONTS_DIR $DOWNLOAD_DIR/roboto-mono.zip "*.ttf" && \ | |
| 97 | unzip -j -o -d $FONTS_DIR $DOWNLOAD_DIR/source-serif-4.zip "*.otf" && \ | |
| 98 | unzip -j -o -d $FONTS_DIR $DOWNLOAD_DIR/underwood.zip "*.ttf" && \ | |
| 99 | fc-cache -f -v && \ | |
| 100 | mkdir -p tex && \ | |
| 101 | sh install.sh && \ | |
| 102 | rm -rf \ | |
| 103 | "modules" \ | |
| 104 | "/var/cache" \ | |
| 105 | "/usr/share/icons" \ | |
| 106 | "/opt/context/tex/texmf-context/source" \ | |
| 107 | $DOWNLOAD_DIR/*.zip \ | |
| 108 | $CONTEXT_HOME/tex/texmf-modules/doc \ | |
| 109 | $CONTEXT_HOME/tex/texmf-context/doc && \ | |
| 110 | mkdir -p $CONTEXT_HOME/tex/texmf-fonts/tex/context/user && \ | |
| 111 | ln -s $CONTEXT_HOME/tex/texmf-fonts/tex/context/user $HOME/fonts && \ | |
| 112 | source $PROFILE && \ | |
| 113 | mtxrun --generate && \ | |
| 114 | find \ | |
| 115 | /usr/share/inkscape \ | |
| 116 | -type f -not -iname \*.xml -exec rm {} \; && \ | |
| 117 | find \ | |
| 118 | $CONTEXT_HOME \ | |
| 119 | -type f \ | |
| 120 | \( -iname \*.pdf -o -iname \*.txt -o -iname \*.log \) \ | |
| 121 | -exec rm {} \; | |
| 122 | ||
| 123 | # ######################################################################## | |
| 124 | # | |
| 125 | # Ensure login goes to the target directory. ConTeXt prefers to export to | |
| 126 | # the current working directory. | |
| 127 | # | |
| 128 | # ######################################################################## | |
| 129 | WORKDIR $TARGET_DIR | |
| 130 | ||
| 1 | 131 |
| 1 | # Overview | |
| 2 | ||
| 3 | This document describes how to maintain the containerized typesetting system. | |
| 4 | The container is built locally then deployed to a web server capable of | |
| 5 | serving static web pages. | |
| 6 | ||
| 7 | ## Installation wizard | |
| 1 | 8 | |
| 9 | The installation wizard is responsible for --build --export |
| 1 | #!/usr/bin/env bash | |
| 2 | ||
| 3 | # --------------------------------------------------------------------------- | |
| 4 | # Copyright 2022 White Magic Software, Ltd. | |
| 5 | # | |
| 6 | # This script manages the container configured to run ConTeXt. | |
| 7 | # --------------------------------------------------------------------------- | |
| 8 | ||
| 9 | source ../scripts/build-template | |
| 10 | ||
| 11 | # Reads the value of a property from a properties file. | |
| 12 | # | |
| 13 | # $1 - The key name to obtain. | |
| 14 | function property { | |
| 15 | grep "^${1}" "${PROPERTIES}" | cut -d'=' -f2 | |
| 16 | } | |
| 17 | ||
| 18 | readonly BUILD_DIR=build | |
| 19 | readonly PROPERTIES="${SCRIPT_DIR}/../src/main/resources/com/keenwrite/messages.properties" | |
| 20 | ||
| 21 | readonly CONTAINER_EXE=podman | |
| 22 | readonly CONTAINER_SHORTNAME=$(property Wizard.typesetter.container.image.name) | |
| 23 | readonly CONTAINER_VERSION=$(property Wizard.typesetter.container.image.version) | |
| 24 | readonly CONTAINER_NETWORK=host | |
| 25 | readonly CONTAINER_FILE="${CONTAINER_SHORTNAME}-${CONTAINER_VERSION}" | |
| 26 | readonly CONTAINER_ARCHIVE_FILE="${CONTAINER_FILE}.tar" | |
| 27 | readonly CONTAINER_ARCHIVE_PATH="${BUILD_DIR}/${CONTAINER_ARCHIVE_FILE}" | |
| 28 | readonly CONTAINER_COMPRESSED_FILE="${CONTAINER_ARCHIVE_FILE}.gz" | |
| 29 | readonly CONTAINER_COMPRESSED_PATH="${BUILD_DIR}/${CONTAINER_ARCHIVE_FILE}.gz" | |
| 30 | readonly CONTAINER_IMAGE_FILE="${BUILD_DIR}/${CONTAINER_FILE}" | |
| 31 | readonly CONTAINER_DIR_SOURCE="/root/source" | |
| 32 | readonly CONTAINER_DIR_TARGET="/root/target" | |
| 33 | readonly CONTAINER_DIR_IMAGES="/root/images" | |
| 34 | readonly CONTAINER_DIR_FONTS="/root/fonts" | |
| 35 | ||
| 36 | ARG_CONTAINER_NAME="${CONTAINER_SHORTNAME}:${CONTAINER_VERSION}" | |
| 37 | ARG_CONTAINER_COMMAND="context --version" | |
| 38 | ARG_MOUNTPOINT_SOURCE="" | |
| 39 | ARG_MOUNTPOINT_TARGET="." | |
| 40 | ARG_MOUNTPOINT_IMAGES="" | |
| 41 | ARG_MOUNTPOINT_FONTS="${HOME}/.fonts" | |
| 42 | ||
| 43 | DEPENDENCIES=( | |
| 44 | "podman,https://podman.io" | |
| 45 | "tar,https://www.gnu.org/software/tar" | |
| 46 | "bzip2,https://gitlab.com/bzip2/bzip2" | |
| 47 | ) | |
| 48 | ||
| 49 | ARGUMENTS+=( | |
| 50 | "b,build,Build container" | |
| 51 | "c,connect,Connect to container" | |
| 52 | "d,delete,Remove all containers" | |
| 53 | "s,source,Set mount point for input document (before typesetting)" | |
| 54 | "t,target,Set mount point for output file (after typesetting)" | |
| 55 | "i,images,Set mount point for image files (to typeset)" | |
| 56 | "f,fonts,Set mount point for font files (during typesetting)" | |
| 57 | "l,load,Load container (${CONTAINER_COMPRESSED_PATH})" | |
| 58 | "p,publish,Publish the container" | |
| 59 | "r,run,Run a command in the container (\"${ARG_CONTAINER_COMMAND}\")" | |
| 60 | "x,export,Save container (${CONTAINER_COMPRESSED_PATH})" | |
| 61 | ) | |
| 62 | ||
| 63 | # --------------------------------------------------------------------------- | |
| 64 | # Manages the container. | |
| 65 | # --------------------------------------------------------------------------- | |
| 66 | execute() { | |
| 67 | $do_delete | |
| 68 | $do_build | |
| 69 | $do_publish | |
| 70 | $do_export | |
| 71 | $do_load | |
| 72 | $do_execute | |
| 73 | $do_connect | |
| 74 | ||
| 75 | return 1 | |
| 76 | } | |
| 77 | ||
| 78 | # --------------------------------------------------------------------------- | |
| 79 | # Deletes all containers. | |
| 80 | # --------------------------------------------------------------------------- | |
| 81 | utile_delete() { | |
| 82 | $log "Deleting all containers" | |
| 83 | ||
| 84 | ${CONTAINER_EXE} rmi --all --force > /dev/null | |
| 85 | ||
| 86 | $log "Containers deleted" | |
| 87 | } | |
| 88 | ||
| 89 | # --------------------------------------------------------------------------- | |
| 90 | # Builds the container file in the current working directory. | |
| 91 | # --------------------------------------------------------------------------- | |
| 92 | utile_build() { | |
| 93 | $log "Building container version ${CONTAINER_VERSION}" | |
| 94 | ||
| 95 | # Show what commands are run while building, but not the commands' output. | |
| 96 | ${CONTAINER_EXE} build \ | |
| 97 | --network="${CONTAINER_NETWORK}" \ | |
| 98 | --squash \ | |
| 99 | -t "${ARG_CONTAINER_NAME}" . | \ | |
| 100 | grep ^STEP | |
| 101 | } | |
| 102 | ||
| 103 | # --------------------------------------------------------------------------- | |
| 104 | # Publishes the container to the repository. | |
| 105 | # --------------------------------------------------------------------------- | |
| 106 | utile_publish() { | |
| 107 | local -r TOKEN_FILE="token.txt" | |
| 108 | ||
| 109 | if [[ -f "${TOKEN_FILE}" ]]; then | |
| 110 | local -r repository=$(cat ${TOKEN_FILE}) | |
| 111 | local -r remote_file="${CONTAINER_SHORTNAME}:${CONTAINER_VERSION}" | |
| 112 | local -r remote_path="${repository}/${remote_file}" | |
| 113 | ||
| 114 | $log "Publishing ${CONTAINER_IMAGE_FILE} to ${remote_path}" | |
| 115 | ||
| 116 | # Path to the repository. | |
| 117 | scp -q "${CONTAINER_IMAGE_FILE}" "${remote_path}" | |
| 118 | else | |
| 119 | error "Create ${TOKEN_FILE} with publish credentials" | |
| 120 | fi | |
| 121 | } | |
| 122 | ||
| 123 | # --------------------------------------------------------------------------- | |
| 124 | # Creates the command-line option for a read-only mountpoint. | |
| 125 | # | |
| 126 | # $1 - The host directory. | |
| 127 | # $2 - The guest (container) directory. | |
| 128 | # $3 - The file system permissions (set to 1 for read-write). | |
| 129 | # --------------------------------------------------------------------------- | |
| 130 | get_mountpoint() { | |
| 131 | local result="" | |
| 132 | local binding="ro" | |
| 133 | ||
| 134 | if [ ! -z "${3+x}" ]; then | |
| 135 | binding="Z" | |
| 136 | fi | |
| 137 | ||
| 138 | if [ ! -z "${1}" ]; then | |
| 139 | result="-v ${1}:${2}:${binding}" | |
| 140 | fi | |
| 141 | ||
| 142 | echo "${result}" | |
| 143 | } | |
| 144 | ||
| 145 | get_mountpoint_source() { | |
| 146 | echo $(get_mountpoint "${ARG_MOUNTPOINT_SOURCE}" "${CONTAINER_DIR_SOURCE}") | |
| 147 | } | |
| 148 | ||
| 149 | get_mountpoint_target() { | |
| 150 | echo $(get_mountpoint "${ARG_MOUNTPOINT_TARGET}" "${CONTAINER_DIR_TARGET}" 1) | |
| 151 | } | |
| 152 | ||
| 153 | get_mountpoint_images() { | |
| 154 | echo $(get_mountpoint "${ARG_MOUNTPOINT_IMAGES}" "${CONTAINER_DIR_IMAGES}") | |
| 155 | } | |
| 156 | ||
| 157 | get_mountpoint_fonts() { | |
| 158 | echo $(get_mountpoint "${ARG_MOUNTPOINT_FONTS}" "${CONTAINER_DIR_FONTS}") | |
| 159 | } | |
| 160 | ||
| 161 | # --------------------------------------------------------------------------- | |
| 162 | # Connects to the container. | |
| 163 | # --------------------------------------------------------------------------- | |
| 164 | utile_connect() { | |
| 165 | $log "Connecting to container" | |
| 166 | ||
| 167 | declare -r mount_source=$(get_mountpoint_source) | |
| 168 | declare -r mount_target=$(get_mountpoint_target) | |
| 169 | declare -r mount_images=$(get_mountpoint_images) | |
| 170 | declare -r mount_fonts=$(get_mountpoint_fonts) | |
| 171 | ||
| 172 | $log "mount_source = '${mount_source}'" | |
| 173 | $log "mount_target = '${mount_target}'" | |
| 174 | $log "mount_images = '${mount_images}'" | |
| 175 | $log "mount_fonts = '${mount_fonts}'" | |
| 176 | ||
| 177 | ${CONTAINER_EXE} run \ | |
| 178 | --network="${CONTAINER_NETWORK}" \ | |
| 179 | --rm \ | |
| 180 | -it \ | |
| 181 | ${mount_source} \ | |
| 182 | ${mount_target} \ | |
| 183 | ${mount_images} \ | |
| 184 | ${mount_fonts} \ | |
| 185 | "${ARG_CONTAINER_NAME}" | |
| 186 | } | |
| 187 | ||
| 188 | # --------------------------------------------------------------------------- | |
| 189 | # Runs a command in the container. | |
| 190 | # | |
| 191 | # Examples: | |
| 192 | # | |
| 193 | # ./manage.sh -r "ls /" | |
| 194 | # ./manage.sh -r "context --version" | |
| 195 | # --------------------------------------------------------------------------- | |
| 196 | utile_execute() { | |
| 197 | $log "Running \"${ARG_CONTAINER_COMMAND}\":" | |
| 198 | ||
| 199 | ${CONTAINER_EXE} run \ | |
| 200 | --network=${CONTAINER_NETWORK} \ | |
| 201 | --rm \ | |
| 202 | -i \ | |
| 203 | -t "${ARG_CONTAINER_NAME}" \ | |
| 204 | /bin/sh --login -c "${ARG_CONTAINER_COMMAND}" | |
| 205 | } | |
| 206 | ||
| 207 | # --------------------------------------------------------------------------- | |
| 208 | # Saves the container to a file. | |
| 209 | # --------------------------------------------------------------------------- | |
| 210 | utile_export() { | |
| 211 | if [[ -f "${CONTAINER_COMPRESSED_PATH}" ]]; then | |
| 212 | warning "${CONTAINER_COMPRESSED_PATH} exists, delete before saving." | |
| 213 | else | |
| 214 | $log "Saving ${CONTAINER_SHORTNAME} image" | |
| 215 | ||
| 216 | mkdir -p "${BUILD_DIR}" | |
| 217 | ||
| 218 | ${CONTAINER_EXE} save \ | |
| 219 | --quiet \ | |
| 220 | -o "${BUILD_DIR}/${CONTAINER_ARCHIVE_FILE}" \ | |
| 221 | "${ARG_CONTAINER_NAME}" | |
| 222 | ||
| 223 | $log "Compressing to ${CONTAINER_COMPRESSED_PATH}" | |
| 224 | gzip "${CONTAINER_ARCHIVE_PATH}" | |
| 225 | ||
| 226 | $log "Renaming to ${CONTAINER_IMAGE_FILE}" | |
| 227 | mv "${CONTAINER_COMPRESSED_PATH}" "${CONTAINER_IMAGE_FILE}" | |
| 228 | ||
| 229 | $log "Saved ${CONTAINER_IMAGE_FILE} image" | |
| 230 | fi | |
| 231 | } | |
| 232 | ||
| 233 | # --------------------------------------------------------------------------- | |
| 234 | # Loads the container from a file. | |
| 235 | # --------------------------------------------------------------------------- | |
| 236 | utile_load() { | |
| 237 | if [[ -f "${CONTAINER_COMPRESSED_PATH}" ]]; then | |
| 238 | $log "Loading ${CONTAINER_SHORTNAME} from ${CONTAINER_COMPRESSED_PATH}" | |
| 239 | ||
| 240 | ${CONTAINER_EXE} load \ | |
| 241 | --quiet \ | |
| 242 | -i "${CONTAINER_COMPRESSED_PATH}" | |
| 243 | ||
| 244 | $log "Loaded ${CONTAINER_SHORTNAME} image" | |
| 245 | else | |
| 246 | warning "Missing ${CONTAINER_COMPRESSED_PATH}; use build followed by save" | |
| 247 | fi | |
| 248 | } | |
| 249 | ||
| 250 | argument() { | |
| 251 | local consume=1 | |
| 252 | ||
| 253 | case "$1" in | |
| 254 | -b|--build) | |
| 255 | do_build=utile_build | |
| 256 | ;; | |
| 257 | -c|--connect) | |
| 258 | do_connect=utile_connect | |
| 259 | ;; | |
| 260 | -d|--delete) | |
| 261 | do_delete=utile_delete | |
| 262 | ;; | |
| 263 | -l|--load) | |
| 264 | do_load=utile_load | |
| 265 | ;; | |
| 266 | -i|--images) | |
| 267 | if [ ! -z "${2+x}" ]; then | |
| 268 | ARG_MOUNTPOINT_IMAGES="$2" | |
| 269 | consume=2 | |
| 270 | fi | |
| 271 | ;; | |
| 272 | -t|--target) | |
| 273 | if [ ! -z "${2+x}" ]; then | |
| 274 | ARG_MOUNTPOINT_TARGET="$2" | |
| 275 | consume=2 | |
| 276 | fi | |
| 277 | ;; | |
| 278 | -p|--publish) | |
| 279 | do_publish=utile_publish | |
| 280 | ;; | |
| 281 | -r|--run) | |
| 282 | do_execute=utile_execute | |
| 283 | ||
| 284 | if [ ! -z "${2+x}" ]; then | |
| 285 | ARG_CONTAINER_COMMAND="$2" | |
| 286 | consume=2 | |
| 287 | fi | |
| 288 | ;; | |
| 289 | -s|--source) | |
| 290 | if [ ! -z "${2+x}" ]; then | |
| 291 | ARG_MOUNTPOINT_SOURCE="$2" | |
| 292 | consume=2 | |
| 293 | fi | |
| 294 | ;; | |
| 295 | -x|--export) | |
| 296 | do_export=utile_export | |
| 297 | ;; | |
| 298 | esac | |
| 299 | ||
| 300 | return ${consume} | |
| 301 | } | |
| 302 | ||
| 303 | do_build=: | |
| 304 | do_connect=: | |
| 305 | do_delete=: | |
| 306 | do_execute=: | |
| 307 | do_load=: | |
| 308 | do_publish=: | |
| 309 | do_export=: | |
| 310 | ||
| 311 | main "$@" | |
| 312 | ||
| 1 | 313 |
| 1 | # Documentation | |
| 2 | ||
| 3 | The following documents have additional details about using the editor: | |
| 4 | ||
| 5 | * [cmd.md](cmd.md) -- Command-line argument usage | |
| 6 | * [div.md](div.md) -- Syntax for annotated text (fenced divs) | |
| 7 | * [i18n.md](i18n.md) -- Internationalization features | |
| 8 | * [r.md](r.md) -- R functions within R Markdown documents | |
| 9 | * [samples](samples) -- Example documents | |
| 10 | * [skins.md](skins.md) -- User interface customization | |
| 11 | * [svg.md](svg.md) -- Resolve issues with some SVG files | |
| 12 | * [metadata.md](metadata.md) -- Document metadata | |
| 13 | * [references.md](references.md) -- Captions and cross-references | |
| 14 | * [typesetting.md](typesetting.md) -- Document typesetting | |
| 15 | * [variables.md](variables.md) -- Variable definitions and interpolation | |
| 16 | ||
| 17 | # Contributions | |
| 18 | ||
| 19 | * [credits.md](credits.md) -- Thanks to authors of contributing projects | |
| 20 | * [licenses](licenses) -- Third-party licenses | |
| 21 | ||
| 1 | 22 |
| 1 | # Command-line arguments | |
| 2 | ||
| 3 | The application may be run from the command-line to convert Markdown and | |
| 4 | R Markdown files to a variety of output formats. Without specifying any | |
| 5 | command-line arguments, the application will launch a graphical user interface. | |
| 6 | ||
| 7 | ## Common arguments | |
| 8 | ||
| 9 | The most common command-line arguments to use include: | |
| 10 | ||
| 11 | * `-h` -- displays all command-line arguments, then exits. | |
| 12 | * `-i` -- sets the input file name, must be a full path. | |
| 13 | * `-o` -- sets the output file name, can be a relative path. | |
| 14 | * `-s` -- sets a variable name and value at build time (dynamic data). | |
| 15 | ||
| 16 | ## Example usage | |
| 17 | ||
| 18 | On Linux, simple usages include: | |
| 19 | ||
| 20 | keenwrite.bin -i $HOME/document/01.md -o document.xhtml | |
| 21 | ||
| 22 | keenwrite.bin -i $HOME/document/01.md -o document.md \ | |
| 23 | -v $HOME/document/variables.yaml | |
| 24 | ||
| 25 | That command will convert `01.md` into the respective file formats. In | |
| 26 | the first case, it will become an HTML page. In the second case, it will | |
| 27 | become a Markdown document with all variables interpolated and replaced. | |
| 28 | ||
| 29 | A more complex example follows: | |
| 30 | ||
| 31 | keenwrite.bin -i $HOME/document/01.Rmd -o document.pdf \ | |
| 32 | --image-dir=$HOME/document/images -v $HOME/document/variables.yaml \ | |
| 33 | --metadata="title={{book.title}}" --metadata="author={{book.author}}" \ | |
| 34 | --r-dir=$HOME/document/r --r-script=$HOME/document/r/bootstrap.R \ | |
| 35 | --theme-dir=$HOME/document/themes/boschet | |
| 36 | ||
| 37 | That command will convert `01.Rmd` to `document.pdf` and replace the metadata | |
| 38 | using values from the variable definitions file. | |
| 39 | ||
| 40 | Directory names containing spaces must be quoted. For example, on Windows: | |
| 41 | ||
| 42 | keenwrite.bin -i "C:\Users\My Documents\01.Rmd" -o document.pdf | |
| 43 | ||
| 1 | 44 |
| 1 | # Credits | |
| 2 | ||
| 3 | Using libraries from: | |
| 4 | ||
| 5 | * Tomas Mikula: [RichTextFX](https://github.com/TomasMikula/RichTextFX), [WellBehavedFX](https://github.com/TomasMikula/WellBehavedFX), [Flowless](https://github.com/TomasMikula/Flowless), and [UndoFX](https://github.com/TomasMikula/UndoFX) | |
| 6 | * Jens Deters: [FontAwesomeFX](https://bitbucket.org/Jerady/fontawesomefx) | |
| 7 | * Dieter Holz: [PreferencesFX](https://github.com/dlsc-software-consulting-gmbh/PreferencesFX) | |
| 8 | * David Croft: [File Preferences](http://www.davidc.net/programming/java/java-preferences-using-file-backing-store) | |
| 9 | * Alex Bertram: [Renjin](https://www.renjin.org/) | |
| 10 | * Vladimir Schneider: [flexmark](https://github.com/vsch/flexmark-java) | |
| 11 | * Alberto Fernández, Shy Shalom, Kohei Taketa: [juniversalchardet](https://github.com/takscape/juniversalchardet) | |
| 12 | * Morten Nobel-Jørgensen: [Java Image Scaling](https://github.com/mortennobel/java-image-scaling) | |
| 13 | ||
| 14 | Inspired by: | |
| 15 | ||
| 16 | * Karl Tauber: [Markdown Writer FX](https://github.com/JFormDesigner/markdown-writer-fx) | |
| 1 | 17 |
| 1 | From https://github.com/greenrobot/EventBus#r8-proguard | |
| 2 | ||
| 3 | -keepattributes *Annotation* | |
| 4 | -keepclassmembers class * { | |
| 5 | @org.greenrobot.eventbus.Subscribe <methods>; | |
| 6 | } | |
| 7 | -keep enum org.greenrobot.eventbus.ThreadMode { *; } | |
| 8 | ||
| 1 | 9 |
| 1 | # Introduction | |
| 2 | ||
| 3 | From a high level, the application architecture for converting Markdown documents is captured in the following figure: | |
| 4 | ||
| 5 | ``` diagram-graphviz | |
| 6 | digraph { | |
| 7 | node [fontname = "Noto Sans" fontsize=6 height=.25 penwidth=.5]; | |
| 8 | edge [fontname = "Noto Sans" fontsize=6 penwidth=.5 arrowsize=.5]; | |
| 9 | node [shape=box color="{{keenwrite.palette.primary.light}}" fontcolor="{{keenwrite.palette.primary.dark}}"] | |
| 10 | edge [color="{{keenwrite.palette.grayscale.light}}" fontcolor="{{keenwrite.palette.grayscale.dark}}"] | |
| 11 | ||
| 12 | {{keenwrite.classes.processors.variable.definition}} -> {{keenwrite.classes.processors.markdown}} [xlabel="{{keenwrite.graph.label.chain.next}} "] | |
| 13 | {{keenwrite.classes.processors.markdown}} -> {{keenwrite.classes.processors.preview}} [xlabel="{{keenwrite.graph.label.chain.next}} "] | |
| 14 | {{keenwrite.classes.processors.markdown}} -> Extensions [label=" contains"] | |
| 15 | ||
| 16 | Extensions -> FencedBlockExtension | |
| 17 | Extensions -> CaretExtension | |
| 18 | Extensions -> ImageLinkExtension | |
| 19 | Extensions -> TeXExtension | |
| 20 | } | |
| 21 | ``` | |
| 22 | ||
| 23 | An extension is an addition to the Markdown parser, flexmark-java, that is used when converting the document's abstract syntax tree into an HTML document. The {{keenwrite.classes.processors.markdown}} contains both prepackaged and custom extensions. | |
| 1 | 24 |
| 1 | --- | |
| 2 | keenwrite: | |
| 3 | classes: | |
| 4 | processors: | |
| 5 | markdown: MarkdownProcessor | |
| 6 | variable: | |
| 7 | definition: DefinitionProcessor | |
| 8 | preview: PreviewProcessor | |
| 9 | palette: | |
| 10 | primary: | |
| 11 | light: '#51a9cf' | |
| 12 | dark: '#126d95' | |
| 13 | secondary: | |
| 14 | light: '#ec706a' | |
| 15 | dark: '#7e252f' | |
| 16 | accent: | |
| 17 | light: '#76A786' | |
| 18 | dark: '#385742' | |
| 19 | grayscale: | |
| 20 | light: '#bac2c5' | |
| 21 | dark: '#394343' | |
| 22 | graph: | |
| 23 | label: | |
| 24 | chain: | |
| 25 | next: successor | |
| 1 | 26 |
| 1 | # Fenced divs | |
| 2 | ||
| 3 | This section describes the syntax to generate HTML `div` elements. The | |
| 4 | syntax is known as a _fenced div_. | |
| 5 | ||
| 6 | # Basic syntax | |
| 7 | ||
| 8 | A fenced div has the following basic syntax: | |
| 9 | ||
| 10 | ``` markdown | |
| 11 | ::: name | |
| 12 | Content | |
| 13 | ::: | |
| 14 | ``` | |
| 1 | 15 | |
| 16 | To start a fenced div, begin a lss |
| 1 | # Internationalization | |
| 2 | ||
| 3 | The application supports internationalization (I18N). There are multiple | |
| 4 | components to editing and previewing internationalized text documents. | |
| 5 | These include: | |
| 6 | ||
| 7 | * Fonts | |
| 8 | * Language | |
| 9 | ||
| 10 | Both fonts and language must be set for non-Latin-based text. | |
| 11 | ||
| 12 | # Fonts | |
| 13 | ||
| 14 | The text editors and preview panel have independent font settings. For | |
| 15 | all Chinese, Japanese, and Korean (CJK) fonts, you may have to type in | |
| 16 | the font family name directly. | |
| 17 | ||
| 18 | For example, CJK font families for the editor have the following names: | |
| 19 | ||
| 20 | * **Noto Sans CJK KR** --- Korean font | |
| 21 | * **Noto Sans CJK JP** --- Japanese font | |
| 22 | * **Noto Sans CJK HN** --- Chinese font | |
| 23 | * **Noto Sans CJK SC** --- Simplified Chinese font | |
| 24 | ||
| 25 | While CJK font families for the preview have the following names: | |
| 26 | ||
| 27 | * **Noto Serif CJK KR** --- Korean font | |
| 28 | * **Noto Serif CJK JP** --- Japanese font | |
| 29 | * **Noto Serif CJK HN** --- Chinese font | |
| 30 | * **Noto Serif CJK SC** --- Simplified Chinese font | |
| 31 | ||
| 32 | ## Editor | |
| 33 | ||
| 34 | Complete the following steps to change the editor font: | |
| 35 | ||
| 36 | 1. Click **Edit → Preferences**. | |
| 37 | 1. Click **Fonts**. | |
| 38 | 1. Click **Change** under **Editor Font**. | |
| 39 | 1. Find the font name by typing or scrolling. | |
| 40 | 1. Click the desired font family. | |
| 41 | 1. Click **OK**. | |
| 42 | 1. Click **Apply**. | |
| 43 | ||
| 44 | The text editor font is changed. | |
| 45 | ||
| 46 | Note the following: | |
| 47 | ||
| 48 | * The font must be installed in the system for this to work. | |
| 49 | * You may have to edit the font name if it cannot be selected from the list. | |
| 50 | * Setting the editor font also sets the statistics panel font. | |
| 51 | ||
| 52 | ## Preview | |
| 53 | ||
| 54 | The preview panel uses regular and monospace fonts. | |
| 55 | ||
| 56 | ### Regular | |
| 57 | ||
| 58 | Complete the following steps to change the regular preview font: | |
| 59 | ||
| 60 | 1. Click **Edit → Preferences**. | |
| 61 | 1. Click **Fonts**. | |
| 62 | 1. Click **Change** under **Preview Font** for the **Preview pane font name**. | |
| 63 | 1. Find the font name by typing or scrolling. | |
| 64 | 1. Click the desired font family. | |
| 65 | 1. Click **OK**. | |
| 66 | 1. Click **Apply**. | |
| 67 | ||
| 68 | The regular preview font is changed. | |
| 69 | ||
| 70 | ### Monospace | |
| 71 | ||
| 72 | Complete the following steps to change the monospace preview font: | |
| 73 | ||
| 74 | 1. Click **Edit → Preferences**. | |
| 75 | 1. Click **Fonts**. | |
| 76 | 1. Click **Change** under **Preview Font** for the **Monospace font name**. | |
| 77 | 1. Find the font name by typing or scrolling. | |
| 78 | 1. Click the desired font family. | |
| 79 | 1. Click **OK**. | |
| 80 | 1. Click **Apply**. | |
| 81 | ||
| 82 | The monospace font is changed. | |
| 83 | ||
| 84 | # Language | |
| 85 | ||
| 86 | Language settings control the locale that the application uses. When using | |
| 87 | a CJK font, for example, the application must also be instructed to use | |
| 88 | a particular locale. Change the locale as follows: | |
| 89 | ||
| 90 | 1. Click **Edit → Preferences**. | |
| 91 | 1. Click **Language**. | |
| 92 | 1. Select a value for **Locale**. | |
| 93 | 1. Click **Apply**. | |
| 94 | ||
| 95 | The language is set. | |
| 96 | ||
| 1 | 97 |
| 1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> | |
| 2 | <svg | |
| 3 | xmlns:dc="http://purl.org/dc/elements/1.1/" | |
| 4 | xmlns:cc="http://creativecommons.org/ns#" | |
| 5 | xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | |
| 6 | xmlns:svg="http://www.w3.org/2000/svg" | |
| 7 | xmlns="http://www.w3.org/2000/svg" | |
| 8 | xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | |
| 9 | xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | |
| 10 | inkscape:export-ydpi="150.0097" | |
| 11 | inkscape:export-xdpi="150.0097" | |
| 12 | sodipodi:docname="architecture.svg" | |
| 13 | viewBox="0 0 764.4414 811.46748" | |
| 14 | height="811.46747" | |
| 15 | width="764.44141" | |
| 16 | id="svg4610" | |
| 17 | version="1.2" | |
| 18 | inkscape:version="1.0 (4035a4fb49, 2020-05-01)"> | |
| 19 | <metadata | |
| 20 | id="metadata4616"> | |
| 21 | <rdf:RDF> | |
| 22 | <cc:Work | |
| 23 | rdf:about=""> | |
| 24 | <dc:format>image/svg+xml</dc:format> | |
| 25 | <dc:type | |
| 26 | rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | |
| 27 | <dc:title /> | |
| 28 | </cc:Work> | |
| 29 | </rdf:RDF> | |
| 30 | </metadata> | |
| 31 | <defs | |
| 32 | id="defs4614"> | |
| 33 | <marker | |
| 34 | inkscape:stockid="Arrow1Mend" | |
| 35 | orient="auto" | |
| 36 | refY="0" | |
| 37 | refX="0" | |
| 38 | id="marker10933" | |
| 39 | style="overflow:visible" | |
| 40 | inkscape:isstock="true"> | |
| 41 | <path | |
| 42 | id="path10931" | |
| 43 | d="M 0,0 5,-5 -12.5,0 5,5 Z" | |
| 44 | style="fill:#05556e;fill-opacity:1;fill-rule:evenodd;stroke:#05556e;stroke-width:1.00000003pt;stroke-opacity:1" | |
| 45 | transform="matrix(-0.4,0,0,-0.4,-4,0)" | |
| 46 | inkscape:connector-curvature="0" /> | |
| 47 | </marker> | |
| 48 | <marker | |
| 49 | inkscape:stockid="Arrow1Mend" | |
| 50 | orient="auto" | |
| 51 | refY="0" | |
| 52 | refX="0" | |
| 53 | id="marker9893" | |
| 54 | style="overflow:visible" | |
| 55 | inkscape:isstock="true"> | |
| 56 | <path | |
| 57 | id="path9891" | |
| 58 | d="M 0,0 5,-5 -12.5,0 5,5 Z" | |
| 59 | style="fill:#05556e;fill-opacity:1;fill-rule:evenodd;stroke:#05556e;stroke-width:1.00000003pt;stroke-opacity:1" | |
| 60 | transform="matrix(-0.4,0,0,-0.4,-4,0)" | |
| 61 | inkscape:connector-curvature="0" /> | |
| 62 | </marker> | |
| 63 | <marker | |
| 64 | inkscape:collect="always" | |
| 65 | inkscape:isstock="true" | |
| 66 | style="overflow:visible" | |
| 67 | id="marker9767" | |
| 68 | refX="0" | |
| 69 | refY="0" | |
| 70 | orient="auto" | |
| 71 | inkscape:stockid="Arrow1Mend"> | |
| 72 | <path | |
| 73 | inkscape:connector-curvature="0" | |
| 74 | transform="matrix(-0.4,0,0,-0.4,-4,0)" | |
| 75 | style="fill:#05556e;fill-opacity:1;fill-rule:evenodd;stroke:#05556e;stroke-width:1.00000003pt;stroke-opacity:1" | |
| 76 | d="M 0,0 5,-5 -12.5,0 5,5 Z" | |
| 77 | id="path9765" /> | |
| 78 | </marker> | |
| 79 | <marker | |
| 80 | inkscape:collect="always" | |
| 81 | inkscape:stockid="Arrow1Mend" | |
| 82 | orient="auto" | |
| 83 | refY="0" | |
| 84 | refX="0" | |
| 85 | id="marker9761" | |
| 86 | style="overflow:visible" | |
| 87 | inkscape:isstock="true"> | |
| 88 | <path | |
| 89 | id="path9759" | |
| 90 | d="M 0,0 5,-5 -12.5,0 5,5 Z" | |
| 91 | style="fill:#05556e;fill-opacity:1;fill-rule:evenodd;stroke:#05556e;stroke-width:1.00000003pt;stroke-opacity:1" | |
| 92 | transform="matrix(-0.4,0,0,-0.4,-4,0)" | |
| 93 | inkscape:connector-curvature="0" /> | |
| 94 | </marker> | |
| 95 | <marker | |
| 96 | inkscape:isstock="true" | |
| 97 | style="overflow:visible" | |
| 98 | id="marker9750" | |
| 99 | refX="0" | |
| 100 | refY="0" | |
| 101 | orient="auto" | |
| 102 | inkscape:stockid="Arrow1Mend"> | |
| 103 | <path | |
| 104 | inkscape:connector-curvature="0" | |
| 105 | transform="matrix(-0.4,0,0,-0.4,-4,0)" | |
| 106 | style="fill:#05556e;fill-opacity:1;fill-rule:evenodd;stroke:#05556e;stroke-width:1.00000003pt;stroke-opacity:1" | |
| 107 | d="M 0,0 5,-5 -12.5,0 5,5 Z" | |
| 108 | id="path9748" /> | |
| 109 | </marker> | |
| 110 | <marker | |
| 111 | inkscape:isstock="true" | |
| 112 | style="overflow:visible" | |
| 113 | id="marker9715" | |
| 114 | refX="0" | |
| 115 | refY="0" | |
| 116 | orient="auto" | |
| 117 | inkscape:stockid="Arrow1Mend"> | |
| 118 | <path | |
| 119 | inkscape:connector-curvature="0" | |
| 120 | transform="matrix(-0.4,0,0,-0.4,-4,0)" | |
| 121 | style="fill:#05556e;fill-opacity:1;fill-rule:evenodd;stroke:#05556e;stroke-width:1.00000003pt;stroke-opacity:1" | |
| 122 | d="M 0,0 5,-5 -12.5,0 5,5 Z" | |
| 123 | id="path9713" /> | |
| 124 | </marker> | |
| 125 | <marker | |
| 126 | inkscape:collect="always" | |
| 127 | inkscape:stockid="Arrow1Mend" | |
| 128 | orient="auto" | |
| 129 | refY="0" | |
| 130 | refX="0" | |
| 131 | id="marker9685" | |
| 132 | style="overflow:visible" | |
| 133 | inkscape:isstock="true"> | |
| 134 | <path | |
| 135 | id="path9683" | |
| 136 | d="M 0,0 5,-5 -12.5,0 5,5 Z" | |
| 137 | style="fill:#05556e;fill-opacity:1;fill-rule:evenodd;stroke:#05556e;stroke-width:1.00000003pt;stroke-opacity:1" | |
| 138 | transform="matrix(-0.4,0,0,-0.4,-4,0)" | |
| 139 | inkscape:connector-curvature="0" /> | |
| 140 | </marker> | |
| 141 | <marker | |
| 142 | inkscape:collect="always" | |
| 143 | inkscape:stockid="Arrow1Mend" | |
| 144 | orient="auto" | |
| 145 | refY="0" | |
| 146 | refX="0" | |
| 147 | id="marker9679" | |
| 148 | style="overflow:visible" | |
| 149 | inkscape:isstock="true"> | |
| 150 | <path | |
| 151 | id="path9677" | |
| 152 | d="M 0,0 5,-5 -12.5,0 5,5 Z" | |
| 153 | style="fill:#05556e;fill-opacity:1;fill-rule:evenodd;stroke:#05556e;stroke-width:1.00000003pt;stroke-opacity:1" | |
| 154 | transform="matrix(-0.4,0,0,-0.4,-4,0)" | |
| 155 | inkscape:connector-curvature="0" /> | |
| 156 | </marker> | |
| 157 | <marker | |
| 158 | inkscape:collect="always" | |
| 159 | inkscape:isstock="true" | |
| 160 | style="overflow:visible" | |
| 161 | id="marker9640" | |
| 162 | refX="0" | |
| 163 | refY="0" | |
| 164 | orient="auto" | |
| 165 | inkscape:stockid="Arrow1Mend"> | |
| 166 | <path | |
| 167 | inkscape:connector-curvature="0" | |
| 168 | transform="matrix(-0.4,0,0,-0.4,-4,0)" | |
| 169 | style="fill:#05556e;fill-opacity:1;fill-rule:evenodd;stroke:#05556e;stroke-width:1.00000003pt;stroke-opacity:1" | |
| 170 | d="M 0,0 5,-5 -12.5,0 5,5 Z" | |
| 171 | id="path9638" /> | |
| 172 | </marker> | |
| 173 | <marker | |
| 174 | inkscape:collect="always" | |
| 175 | inkscape:isstock="true" | |
| 176 | style="overflow:visible" | |
| 177 | id="marker9513" | |
| 178 | refX="0" | |
| 179 | refY="0" | |
| 180 | orient="auto" | |
| 181 | inkscape:stockid="Arrow1Mend"> | |
| 182 | <path | |
| 183 | inkscape:connector-curvature="0" | |
| 184 | transform="matrix(-0.4,0,0,-0.4,-4,0)" | |
| 185 | style="fill:#05556e;fill-opacity:1;fill-rule:evenodd;stroke:#05556e;stroke-width:1.00000003pt;stroke-opacity:1" | |
| 186 | d="M 0,0 5,-5 -12.5,0 5,5 Z" | |
| 187 | id="path9511" /> | |
| 188 | </marker> | |
| 189 | <marker | |
| 190 | inkscape:stockid="Arrow1Mend" | |
| 191 | orient="auto" | |
| 192 | refY="0" | |
| 193 | refX="0" | |
| 194 | id="marker9509" | |
| 195 | style="overflow:visible" | |
| 196 | inkscape:isstock="true"> | |
| 197 | <path | |
| 198 | id="path9507" | |
| 199 | d="M 0,0 5,-5 -12.5,0 5,5 Z" | |
| 200 | style="fill:#05556e;fill-opacity:1;fill-rule:evenodd;stroke:#05556e;stroke-width:1.00000003pt;stroke-opacity:1" | |
| 201 | transform="matrix(-0.4,0,0,-0.4,-4,0)" | |
| 202 | inkscape:connector-curvature="0" /> | |
| 203 | </marker> | |
| 204 | <marker | |
| 205 | inkscape:isstock="true" | |
| 206 | style="overflow:visible" | |
| 207 | id="marker9505" | |
| 208 | refX="0" | |
| 209 | refY="0" | |
| 210 | orient="auto" | |
| 211 | inkscape:stockid="Arrow1Mend"> | |
| 212 | <path | |
| 213 | inkscape:connector-curvature="0" | |
| 214 | transform="matrix(-0.4,0,0,-0.4,-4,0)" | |
| 215 | style="fill:#05556e;fill-opacity:1;fill-rule:evenodd;stroke:#05556e;stroke-width:1.00000003pt;stroke-opacity:1" | |
| 216 | d="M 0,0 5,-5 -12.5,0 5,5 Z" | |
| 217 | id="path9503" /> | |
| 218 | </marker> | |
| 219 | <marker | |
| 220 | inkscape:collect="always" | |
| 221 | inkscape:stockid="Arrow1Mend" | |
| 222 | orient="auto" | |
| 223 | refY="0" | |
| 224 | refX="0" | |
| 225 | id="marker9479" | |
| 226 | style="overflow:visible" | |
| 227 | inkscape:isstock="true"> | |
| 228 | <path | |
| 229 | id="path9477" | |
| 230 | d="M 0,0 5,-5 -12.5,0 5,5 Z" | |
| 231 | style="fill:#05556e;fill-opacity:1;fill-rule:evenodd;stroke:#05556e;stroke-width:1.00000003pt;stroke-opacity:1" | |
| 232 | transform="matrix(-0.4,0,0,-0.4,-4,0)" | |
| 233 | inkscape:connector-curvature="0" /> | |
| 234 | </marker> | |
| 235 | <clipPath | |
| 236 | id="ID000001"> | |
| 237 | <rect | |
| 238 | id="rect6" | |
| 239 | height="961.125" | |
| 240 | width="1381.6169" | |
| 241 | y="-43.688" | |
| 242 | x="-62.683998" /> | |
| 243 | </clipPath> | |
| 244 | <filter | |
| 245 | id="filter2842" | |
| 246 | inkscape:label="Drop Shadow" | |
| 247 | style="color-interpolation-filters:sRGB;"> | |
| 248 | <feFlood | |
| 249 | id="feFlood2832" | |
| 250 | result="flood" | |
| 251 | flood-color="rgb(0,0,0)" | |
| 252 | flood-opacity="0.498039" /> | |
| 253 | <feComposite | |
| 254 | id="feComposite2834" | |
| 255 | result="composite1" | |
| 256 | operator="in" | |
| 257 | in2="SourceGraphic" | |
| 258 | in="flood" /> | |
| 259 | <feGaussianBlur | |
| 260 | id="feGaussianBlur2836" | |
| 261 | result="blur" | |
| 262 | stdDeviation="2" | |
| 263 | in="composite1" /> | |
| 264 | <feOffset | |
| 265 | id="feOffset2838" | |
| 266 | result="offset" | |
| 267 | dy="3" | |
| 268 | dx="3" /> | |
| 269 | <feComposite | |
| 270 | id="feComposite2840" | |
| 271 | result="composite2" | |
| 272 | operator="over" | |
| 273 | in2="offset" | |
| 274 | in="SourceGraphic" /> | |
| 275 | </filter> | |
| 276 | <filter | |
| 277 | id="filter2854" | |
| 278 | inkscape:label="Drop Shadow" | |
| 279 | style="color-interpolation-filters:sRGB;"> | |
| 280 | <feFlood | |
| 281 | id="feFlood2844" | |
| 282 | result="flood" | |
| 283 | flood-color="rgb(0,0,0)" | |
| 284 | flood-opacity="0.498039" /> | |
| 285 | <feComposite | |
| 286 | id="feComposite2846" | |
| 287 | result="composite1" | |
| 288 | operator="in" | |
| 289 | in2="SourceGraphic" | |
| 290 | in="flood" /> | |
| 291 | <feGaussianBlur | |
| 292 | id="feGaussianBlur2848" | |
| 293 | result="blur" | |
| 294 | stdDeviation="2" | |
| 295 | in="composite1" /> | |
| 296 | <feOffset | |
| 297 | id="feOffset2850" | |
| 298 | result="offset" | |
| 299 | dy="3" | |
| 300 | dx="3" /> | |
| 301 | <feComposite | |
| 302 | id="feComposite2852" | |
| 303 | result="composite2" | |
| 304 | operator="over" | |
| 305 | in2="offset" | |
| 306 | in="SourceGraphic" /> | |
| 307 | </filter> | |
| 308 | <filter | |
| 309 | id="filter2866" | |
| 310 | inkscape:label="Drop Shadow" | |
| 311 | style="color-interpolation-filters:sRGB;"> | |
| 312 | <feFlood | |
| 313 | id="feFlood2856" | |
| 314 | result="flood" | |
| 315 | flood-color="rgb(0,0,0)" | |
| 316 | flood-opacity="0.498039" /> | |
| 317 | <feComposite | |
| 318 | id="feComposite2858" | |
| 319 | result="composite1" | |
| 320 | operator="in" | |
| 321 | in2="SourceGraphic" | |
| 322 | in="flood" /> | |
| 323 | <feGaussianBlur | |
| 324 | id="feGaussianBlur2860" | |
| 325 | result="blur" | |
| 326 | stdDeviation="2" | |
| 327 | in="composite1" /> | |
| 328 | <feOffset | |
| 329 | id="feOffset2862" | |
| 330 | result="offset" | |
| 331 | dy="3" | |
| 332 | dx="3" /> | |
| 333 | <feComposite | |
| 334 | id="feComposite2864" | |
| 335 | result="composite2" | |
| 336 | operator="over" | |
| 337 | in2="offset" | |
| 338 | in="SourceGraphic" /> | |
| 339 | </filter> | |
| 340 | <filter | |
| 341 | id="filter2878" | |
| 342 | inkscape:label="Drop Shadow" | |
| 343 | style="color-interpolation-filters:sRGB;"> | |
| 344 | <feFlood | |
| 345 | id="feFlood2868" | |
| 346 | result="flood" | |
| 347 | flood-color="rgb(0,0,0)" | |
| 348 | flood-opacity="0.498039" /> | |
| 349 | <feComposite | |
| 350 | id="feComposite2870" | |
| 351 | result="composite1" | |
| 352 | operator="in" | |
| 353 | in2="SourceGraphic" | |
| 354 | in="flood" /> | |
| 355 | <feGaussianBlur | |
| 356 | id="feGaussianBlur2872" | |
| 357 | result="blur" | |
| 358 | stdDeviation="2" | |
| 359 | in="composite1" /> | |
| 360 | <feOffset | |
| 361 | id="feOffset2874" | |
| 362 | result="offset" | |
| 363 | dy="3" | |
| 364 | dx="3" /> | |
| 365 | <feComposite | |
| 366 | id="feComposite2876" | |
| 367 | result="composite2" | |
| 368 | operator="over" | |
| 369 | in2="offset" | |
| 370 | in="SourceGraphic" /> | |
| 371 | </filter> | |
| 372 | <filter | |
| 373 | id="filter2890" | |
| 374 | inkscape:label="Drop Shadow" | |
| 375 | style="color-interpolation-filters:sRGB;"> | |
| 376 | <feFlood | |
| 377 | id="feFlood2880" | |
| 378 | result="flood" | |
| 379 | flood-color="rgb(0,0,0)" | |
| 380 | flood-opacity="0.498039" /> | |
| 381 | <feComposite | |
| 382 | id="feComposite2882" | |
| 383 | result="composite1" | |
| 384 | operator="in" | |
| 385 | in2="SourceGraphic" | |
| 386 | in="flood" /> | |
| 387 | <feGaussianBlur | |
| 388 | id="feGaussianBlur2884" | |
| 389 | result="blur" | |
| 390 | stdDeviation="2" | |
| 391 | in="composite1" /> | |
| 392 | <feOffset | |
| 393 | id="feOffset2886" | |
| 394 | result="offset" | |
| 395 | dy="3" | |
| 396 | dx="3" /> | |
| 397 | <feComposite | |
| 398 | id="feComposite2888" | |
| 399 | result="composite2" | |
| 400 | operator="over" | |
| 401 | in2="offset" | |
| 402 | in="SourceGraphic" /> | |
| 403 | </filter> | |
| 404 | <filter | |
| 405 | id="filter2902" | |
| 406 | inkscape:label="Drop Shadow" | |
| 407 | style="color-interpolation-filters:sRGB;"> | |
| 408 | <feFlood | |
| 409 | id="feFlood2892" | |
| 410 | result="flood" | |
| 411 | flood-color="rgb(0,0,0)" | |
| 412 | flood-opacity="0.498039" /> | |
| 413 | <feComposite | |
| 414 | id="feComposite2894" | |
| 415 | result="composite1" | |
| 416 | operator="in" | |
| 417 | in2="SourceGraphic" | |
| 418 | in="flood" /> | |
| 419 | <feGaussianBlur | |
| 420 | id="feGaussianBlur2896" | |
| 421 | result="blur" | |
| 422 | stdDeviation="2" | |
| 423 | in="composite1" /> | |
| 424 | <feOffset | |
| 425 | id="feOffset2898" | |
| 426 | result="offset" | |
| 427 | dy="3" | |
| 428 | dx="3" /> | |
| 429 | <feComposite | |
| 430 | id="feComposite2900" | |
| 431 | result="composite2" | |
| 432 | operator="over" | |
| 433 | in2="offset" | |
| 434 | in="SourceGraphic" /> | |
| 435 | </filter> | |
| 436 | <filter | |
| 437 | id="filter2914" | |
| 438 | inkscape:label="Drop Shadow" | |
| 439 | style="color-interpolation-filters:sRGB;"> | |
| 440 | <feFlood | |
| 441 | id="feFlood2904" | |
| 442 | result="flood" | |
| 443 | flood-color="rgb(0,0,0)" | |
| 444 | flood-opacity="0.498039" /> | |
| 445 | <feComposite | |
| 446 | id="feComposite2906" | |
| 447 | result="composite1" | |
| 448 | operator="in" | |
| 449 | in2="SourceGraphic" | |
| 450 | in="flood" /> | |
| 451 | <feGaussianBlur | |
| 452 | id="feGaussianBlur2908" | |
| 453 | result="blur" | |
| 454 | stdDeviation="2" | |
| 455 | in="composite1" /> | |
| 456 | <feOffset | |
| 457 | id="feOffset2910" | |
| 458 | result="offset" | |
| 459 | dy="3" | |
| 460 | dx="3" /> | |
| 461 | <feComposite | |
| 462 | id="feComposite2912" | |
| 463 | result="composite2" | |
| 464 | operator="over" | |
| 465 | in2="offset" | |
| 466 | in="SourceGraphic" /> | |
| 467 | </filter> | |
| 468 | <filter | |
| 469 | id="filter2926" | |
| 470 | inkscape:label="Drop Shadow" | |
| 471 | style="color-interpolation-filters:sRGB;"> | |
| 472 | <feFlood | |
| 473 | id="feFlood2916" | |
| 474 | result="flood" | |
| 475 | flood-color="rgb(0,0,0)" | |
| 476 | flood-opacity="0.498039" /> | |
| 477 | <feComposite | |
| 478 | id="feComposite2918" | |
| 479 | result="composite1" | |
| 480 | operator="in" | |
| 481 | in2="SourceGraphic" | |
| 482 | in="flood" /> | |
| 483 | <feGaussianBlur | |
| 484 | id="feGaussianBlur2920" | |
| 485 | result="blur" | |
| 486 | stdDeviation="2" | |
| 487 | in="composite1" /> | |
| 488 | <feOffset | |
| 489 | id="feOffset2922" | |
| 490 | result="offset" | |
| 491 | dy="3" | |
| 492 | dx="3" /> | |
| 493 | <feComposite | |
| 494 | id="feComposite2924" | |
| 495 | result="composite2" | |
| 496 | operator="over" | |
| 497 | in2="offset" | |
| 498 | in="SourceGraphic" /> | |
| 499 | </filter> | |
| 500 | <filter | |
| 501 | id="filter2938" | |
| 502 | inkscape:label="Drop Shadow" | |
| 503 | style="color-interpolation-filters:sRGB;"> | |
| 504 | <feFlood | |
| 505 | id="feFlood2928" | |
| 506 | result="flood" | |
| 507 | flood-color="rgb(0,0,0)" | |
| 508 | flood-opacity="0.498039" /> | |
| 509 | <feComposite | |
| 510 | id="feComposite2930" | |
| 511 | result="composite1" | |
| 512 | operator="in" | |
| 513 | in2="SourceGraphic" | |
| 514 | in="flood" /> | |
| 515 | <feGaussianBlur | |
| 516 | id="feGaussianBlur2932" | |
| 517 | result="blur" | |
| 518 | stdDeviation="2" | |
| 519 | in="composite1" /> | |
| 520 | <feOffset | |
| 521 | id="feOffset2934" | |
| 522 | result="offset" | |
| 523 | dy="3" | |
| 524 | dx="3" /> | |
| 525 | <feComposite | |
| 526 | id="feComposite2936" | |
| 527 | result="composite2" | |
| 528 | operator="over" | |
| 529 | in2="offset" | |
| 530 | in="SourceGraphic" /> | |
| 531 | </filter> | |
| 532 | <filter | |
| 533 | id="filter2950" | |
| 534 | inkscape:label="Drop Shadow" | |
| 535 | style="color-interpolation-filters:sRGB;"> | |
| 536 | <feFlood | |
| 537 | id="feFlood2940" | |
| 538 | result="flood" | |
| 539 | flood-color="rgb(0,0,0)" | |
| 540 | flood-opacity="0.498039" /> | |
| 541 | <feComposite | |
| 542 | id="feComposite2942" | |
| 543 | result="composite1" | |
| 544 | operator="in" | |
| 545 | in2="SourceGraphic" | |
| 546 | in="flood" /> | |
| 547 | <feGaussianBlur | |
| 548 | id="feGaussianBlur2944" | |
| 549 | result="blur" | |
| 550 | stdDeviation="2" | |
| 551 | in="composite1" /> | |
| 552 | <feOffset | |
| 553 | id="feOffset2946" | |
| 554 | result="offset" | |
| 555 | dy="3" | |
| 556 | dx="3" /> | |
| 557 | <feComposite | |
| 558 | id="feComposite2948" | |
| 559 | result="composite2" | |
| 560 | operator="over" | |
| 561 | in2="offset" | |
| 562 | in="SourceGraphic" /> | |
| 563 | </filter> | |
| 564 | <filter | |
| 565 | id="filter2962" | |
| 566 | inkscape:label="Drop Shadow" | |
| 567 | style="color-interpolation-filters:sRGB;"> | |
| 568 | <feFlood | |
| 569 | id="feFlood2952" | |
| 570 | result="flood" | |
| 571 | flood-color="rgb(0,0,0)" | |
| 572 | flood-opacity="0.498039" /> | |
| 573 | <feComposite | |
| 574 | id="feComposite2954" | |
| 575 | result="composite1" | |
| 576 | operator="in" | |
| 577 | in2="SourceGraphic" | |
| 578 | in="flood" /> | |
| 579 | <feGaussianBlur | |
| 580 | id="feGaussianBlur2956" | |
| 581 | result="blur" | |
| 582 | stdDeviation="2" | |
| 583 | in="composite1" /> | |
| 584 | <feOffset | |
| 585 | id="feOffset2958" | |
| 586 | result="offset" | |
| 587 | dy="3" | |
| 588 | dx="3" /> | |
| 589 | <feComposite | |
| 590 | id="feComposite2960" | |
| 591 | result="composite2" | |
| 592 | operator="over" | |
| 593 | in2="offset" | |
| 594 | in="SourceGraphic" /> | |
| 595 | </filter> | |
| 596 | <filter | |
| 597 | id="filter2974" | |
| 598 | inkscape:label="Drop Shadow" | |
| 599 | style="color-interpolation-filters:sRGB;"> | |
| 600 | <feFlood | |
| 601 | id="feFlood2964" | |
| 602 | result="flood" | |
| 603 | flood-color="rgb(0,0,0)" | |
| 604 | flood-opacity="0.498039" /> | |
| 605 | <feComposite | |
| 606 | id="feComposite2966" | |
| 607 | result="composite1" | |
| 608 | operator="in" | |
| 609 | in2="SourceGraphic" | |
| 610 | in="flood" /> | |
| 611 | <feGaussianBlur | |
| 612 | id="feGaussianBlur2968" | |
| 613 | result="blur" | |
| 614 | stdDeviation="2" | |
| 615 | in="composite1" /> | |
| 616 | <feOffset | |
| 617 | id="feOffset2970" | |
| 618 | result="offset" | |
| 619 | dy="3" | |
| 620 | dx="3" /> | |
| 621 | <feComposite | |
| 622 | id="feComposite2972" | |
| 623 | result="composite2" | |
| 624 | operator="over" | |
| 625 | in2="offset" | |
| 626 | in="SourceGraphic" /> | |
| 627 | </filter> | |
| 628 | <filter | |
| 629 | id="filter2986" | |
| 630 | inkscape:label="Drop Shadow" | |
| 631 | style="color-interpolation-filters:sRGB;"> | |
| 632 | <feFlood | |
| 633 | id="feFlood2976" | |
| 634 | result="flood" | |
| 635 | flood-color="rgb(0,0,0)" | |
| 636 | flood-opacity="0.498039" /> | |
| 637 | <feComposite | |
| 638 | id="feComposite2978" | |
| 639 | result="composite1" | |
| 640 | operator="in" | |
| 641 | in2="SourceGraphic" | |
| 642 | in="flood" /> | |
| 643 | <feGaussianBlur | |
| 644 | id="feGaussianBlur2980" | |
| 645 | result="blur" | |
| 646 | stdDeviation="2" | |
| 647 | in="composite1" /> | |
| 648 | <feOffset | |
| 649 | id="feOffset2982" | |
| 650 | result="offset" | |
| 651 | dy="3" | |
| 652 | dx="3" /> | |
| 653 | <feComposite | |
| 654 | id="feComposite2984" | |
| 655 | result="composite2" | |
| 656 | operator="over" | |
| 657 | in2="offset" | |
| 658 | in="SourceGraphic" /> | |
| 659 | </filter> | |
| 660 | </defs> | |
| 661 | <sodipodi:namedview | |
| 662 | inkscape:snap-text-baseline="false" | |
| 663 | inkscape:document-rotation="0" | |
| 664 | fit-margin-bottom="20" | |
| 665 | fit-margin-right="20" | |
| 666 | fit-margin-left="20" | |
| 667 | fit-margin-top="20" | |
| 668 | inkscape:current-layer="svg4610" | |
| 669 | inkscape:cy="370.55742" | |
| 670 | inkscape:cx="398.61418" | |
| 671 | inkscape:zoom="1.3753763" | |
| 672 | showgrid="false" | |
| 673 | id="namedview4612" | |
| 674 | inkscape:window-height="1280" | |
| 675 | inkscape:window-width="2055" | |
| 676 | inkscape:pageshadow="2" | |
| 677 | inkscape:pageopacity="1" | |
| 678 | guidetolerance="10" | |
| 679 | gridtolerance="10" | |
| 680 | objecttolerance="10" | |
| 681 | borderopacity="1" | |
| 682 | bordercolor="#666666" | |
| 683 | pagecolor="#ffffff" | |
| 684 | inkscape:window-x="215" | |
| 685 | inkscape:window-y="26" | |
| 686 | inkscape:window-maximized="0" /> | |
| 687 | <path | |
| 688 | sodipodi:nodetypes="ccssssc" | |
| 689 | inkscape:connector-curvature="0" | |
| 690 | style="fill:#333333;fill-opacity:0.0666667;fill-rule:nonzero;stroke:#df4d65;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" | |
| 691 | d="M 53.35547,445.11522 V 790.96744 H 741.0332 c 1.6112,0 2.90821,-1.29701 2.90821,-2.9082 V 448.02342 c 0,-1.6112 -1.297,-2.9082 -2.90821,-2.9082 z" | |
| 692 | id="path9961" /> | |
| 693 | <path | |
| 694 | sodipodi:nodetypes="sssccssss" | |
| 695 | id="path9940" | |
| 696 | d="m 20.5,787.82486 c 0,0.87013 0.35019,1.65683 0.91797,2.22461 0.56778,0.56778 1.35253,0.91797 2.22265,0.91797 H 53.35547 V 445.11522 H 23.64062 c -0.87012,0 -1.65487,0.35019 -2.22265,0.91797 -0.56778,0.56778 -0.91797,1.35254 -0.91797,2.22266 z" | |
| 697 | style="fill:#df4d65;fill-opacity:1;fill-rule:nonzero;stroke:#df4d65;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" | |
| 698 | inkscape:connector-curvature="0" /> | |
| 699 | <path | |
| 700 | sodipodi:nodetypes="sssccssss" | |
| 701 | id="path11125" | |
| 702 | d="m 20.5,423.31014 c 0,0.87013 0.35019,1.65683 0.91797,2.22461 0.56778,0.56778 1.354494,0.9764 2.22265,0.91797 H 53.35547 V 210.6005 H 23.64062 c -0.87012,0 -1.65487,0.3502 -2.22265,0.918 C 20.85019,212.08629 20.5,212.871 20.5,213.74109 Z" | |
| 703 | style="fill:#3e3e3e;fill-opacity:1;fill-rule:nonzero;stroke:#3e3e3e;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" | |
| 704 | inkscape:connector-curvature="0" /> | |
| 705 | <path | |
| 706 | sodipodi:nodetypes="ccssssc" | |
| 707 | inkscape:connector-curvature="0" | |
| 708 | style="fill:#333333;fill-opacity:0.0666667;fill-rule:nonzero;stroke:#3e3e3e;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" | |
| 709 | d="m 53.35547,210.6005 v 215.85222 h 687.67774 c 1.6112,0 2.9082,-1.29701 2.9082,-2.9082 V 213.5087 c 0,-1.6112 -1.29701,-2.90352 -2.9082,-2.9082 z" | |
| 710 | id="path11123" /> | |
| 711 | <path | |
| 712 | id="path6150" | |
| 713 | d="m 557.756,222.53493 c -0.87012,0 -1.65683,0.35019 -2.22461,0.91797 -0.56778,0.56778 -0.91797,1.35253 -0.91797,2.22265 v 29.71485 h 165.6211 v -29.71485 c 0,-0.87012 -0.35019,-1.65487 -0.91797,-2.22265 -0.56778,-0.56778 -1.35254,-0.91797 -2.22266,-0.91797 z" | |
| 714 | style="fill:#c53bd7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.218418;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter2926)" | |
| 715 | inkscape:connector-curvature="0" | |
| 716 | sodipodi:nodetypes="sssccssss" /> | |
| 717 | <path | |
| 718 | sodipodi:nodetypes="ccssssc" | |
| 719 | id="path6134" | |
| 720 | d="m 720.75716,255.39041 h -165.6211 v 152.63392 c 0,1.6112 1.29701,2.90821 2.90821,2.90821 h 159.80469 c 1.6112,0 2.9082,-1.29701 2.9082,-2.90821 z" | |
| 721 | style="fill:#e6e7e7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.218418;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter2926)" | |
| 722 | inkscape:connector-curvature="0" /> | |
| 723 | <path | |
| 724 | id="path6082" | |
| 725 | d="m 317.13559,222.53494 c -0.87011,0 -1.65683,0.35019 -2.2246,0.91797 -0.56779,0.56778 -0.91798,1.35253 -0.91798,2.22265 v 29.71485 h 165.62111 v -29.71485 c 0,-0.87012 -0.35019,-1.65487 -0.91798,-2.22265 -0.56778,-0.56778 -1.35254,-0.91797 -2.22266,-0.91797 z" | |
| 726 | style="fill:#3dd092;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.218418;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter2938)" | |
| 727 | inkscape:connector-curvature="0" | |
| 728 | sodipodi:nodetypes="sssccssss" /> | |
| 729 | <path | |
| 730 | sodipodi:nodetypes="ccssssc" | |
| 731 | id="path6080" | |
| 732 | d="M 479.61412,255.39041 H 313.99301 v 152.63392 c 0,1.6112 1.29701,2.90821 2.90821,2.90821 h 159.80469 c 1.6112,0 2.90821,-1.29701 2.90821,-2.90821 z" | |
| 733 | style="fill:#e6e7e7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.218418;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter2938)" | |
| 734 | inkscape:connector-curvature="0" /> | |
| 735 | <path | |
| 736 | id="path10980" | |
| 737 | d="M 53.35547,20.500012 V 188.35224 h 687.67774 c 1.6112,0 2.9082,-1.29701 2.9082,-2.9082 V 23.408212 c 0,-1.6112 -1.29701,-2.912886 -2.9082,-2.9082 z" | |
| 738 | style="fill:#333333;fill-opacity:0.0666667;fill-rule:nonzero;stroke:#3e3e3e;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" | |
| 739 | inkscape:connector-curvature="0" | |
| 740 | sodipodi:nodetypes="ccssssc" /> | |
| 741 | <path | |
| 742 | inkscape:connector-curvature="0" | |
| 743 | style="fill:#3e3e3e;fill-opacity:1;fill-rule:nonzero;stroke:#3e3e3e;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" | |
| 744 | d="m 20.5,185.20966 c 0,0.87013 0.35019,1.65683 0.91797,2.22461 0.56778,0.56778 1.35253,0.91797 2.22265,0.91797 H 53.35547 V 20.500012 H 23.64062 c -0.87012,0 -1.65487,0.350201 -2.22265,0.918 -0.56778,0.5678 -0.91797,1.3525 -0.91797,2.2226 z" | |
| 745 | id="path10982" | |
| 746 | sodipodi:nodetypes="sssccssss" /> | |
| 747 | <path | |
| 748 | sodipodi:nodetypes="sssccssss" | |
| 749 | inkscape:connector-curvature="0" | |
| 750 | style="fill:#c53bd7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.218418;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter2962)" | |
| 751 | d="m 557.75599,36.704447 c -0.87012,0 -1.65683,0.35019 -2.22461,0.91797 -0.56778,0.56778 -0.91797,1.35253 -0.91797,2.22265 v 29.71485 h 165.6211 v -29.71485 c 0,-0.87012 -0.35019,-1.65487 -0.91797,-2.22265 -0.56778,-0.56778 -1.35254,-0.91797 -2.22266,-0.91797 z" | |
| 752 | id="path4857" /> | |
| 753 | <path | |
| 754 | inkscape:connector-curvature="0" | |
| 755 | style="fill:#e6e7e7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.218418;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter2962)" | |
| 756 | d="M 720.23451,69.559917 H 554.61341 V 169.2396 c 0,1.6112 1.29701,2.90821 2.90821,2.90821 h 159.80469 c 1.6112,0 2.9082,-1.29701 2.9082,-2.90821 z" | |
| 757 | id="path4853" /> | |
| 758 | <path | |
| 759 | sodipodi:nodetypes="sssccssss" | |
| 760 | inkscape:connector-curvature="0" | |
| 761 | style="fill:#3dd092;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.218418;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter2974)" | |
| 762 | d="m 317.13558,36.704447 c -0.87011,0 -1.65683,0.35019 -2.2246,0.91797 -0.56779,0.56778 -0.91798,1.35253 -0.91798,2.22265 v 29.71485 h 165.62111 v -29.71485 c 0,-0.87012 -0.35019,-1.65487 -0.91798,-2.22265 -0.56778,-0.56778 -1.35254,-0.91797 -2.22266,-0.91797 z" | |
| 763 | id="path5726" /> | |
| 764 | <path | |
| 765 | inkscape:connector-curvature="0" | |
| 766 | style="fill:#e6e7e7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.218418;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter2974)" | |
| 767 | d="M 479.61411,69.559917 H 313.993 V 169.2396 c 0,1.6112 1.29701,2.90821 2.90821,2.90821 H 476.7059 c 1.6112,0 2.90821,-1.29701 2.90821,-2.90821 z" | |
| 768 | id="path5724" /> | |
| 769 | <path | |
| 770 | id="path4721" | |
| 771 | d="m 235.85308,44.704447 c 0.87012,0 1.65488,0.35019 2.22266,0.91797 0.56778,0.56778 0.91797,1.35253 0.91797,2.22265 v -0.23242 c 0,-1.6112 -1.297,-2.9082 -2.9082,-2.9082 z" | |
| 772 | style="opacity:1;fill:#e6e7e7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.21841836;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" | |
| 773 | inkscape:connector-curvature="0" /> | |
| 774 | <path | |
| 775 | sodipodi:nodetypes="sssccssss" | |
| 776 | id="path4719" | |
| 777 | d="m 76.515197,36.704447 c -0.870125,0 -1.656831,0.35019 -2.22461,0.91797 -0.567778,0.56778 -0.917968,1.35253 -0.917968,2.22265 v 29.71485 H 238.99371 v -29.71485 c 0,-0.87012 -0.35019,-1.65487 -0.91797,-2.22265 -0.56778,-0.56778 -1.35254,-0.91797 -2.22266,-0.91797 z" | |
| 778 | style="fill:#46c7f0;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.218418;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter2986)" | |
| 779 | inkscape:connector-curvature="0" /> | |
| 780 | <path | |
| 781 | id="path4723" | |
| 782 | d="M 238.99372,69.559917 H 73.372613 V 169.2396 c 0,1.6112 1.29701,2.90821 2.90821,2.90821 H 236.08552 c 1.6112,0 2.9082,-1.29701 2.9082,-2.90821 z" | |
| 783 | style="fill:#e6e7e7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.218418;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter2986)" | |
| 784 | inkscape:connector-curvature="0" /> | |
| 785 | <path | |
| 786 | id="rect4622" | |
| 787 | d="m 76.280822,44.704447 c -1.611195,0 -2.908203,1.297 -2.908203,2.9082 v 0.23242 c 0,-0.87012 0.35019,-1.65487 0.917968,-2.22265 0.567779,-0.56778 1.354485,-0.91797 2.22461,-0.91797 z" | |
| 788 | style="opacity:1;fill:#e6e7e7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.21841836;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" | |
| 789 | inkscape:connector-curvature="0" /> | |
| 790 | <path | |
| 791 | sodipodi:nodetypes="cc" | |
| 792 | inkscape:connector-curvature="0" | |
| 793 | id="path9889" | |
| 794 | d="m 397.61301,500.62068 -0.50618,32.59418" | |
| 795 | style="opacity:1;vector-effect:none;fill:#05556e;fill-opacity:1;stroke:#05556e;stroke-width:1.9694221;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker9893)" /> | |
| 796 | <path | |
| 797 | style="opacity:1;vector-effect:none;fill:#05556e;fill-opacity:1;stroke:#05556e;stroke-width:3.94158769;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker9715)" | |
| 798 | d="m 554.61351,648.83688 -69.6817,47.69253" | |
| 799 | id="path9711" | |
| 800 | inkscape:connector-curvature="0" | |
| 801 | sodipodi:nodetypes="cc" /> | |
| 802 | <path | |
| 803 | sodipodi:nodetypes="cc" | |
| 804 | inkscape:connector-curvature="0" | |
| 805 | id="path9675" | |
| 806 | d="M 554.61351,567.95047 484.93181,615.643" | |
| 807 | style="opacity:1;vector-effect:none;fill:#05556e;fill-opacity:1;stroke:#05556e;stroke-width:3.94158769;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker9679)" /> | |
| 808 | <rect | |
| 809 | ry="3.9839513" | |
| 810 | rx="3.9205718" | |
| 811 | y="537.09552" | |
| 812 | x="554.61353" | |
| 813 | height="32.855" | |
| 814 | width="165.621" | |
| 815 | id="rect9618" | |
| 816 | style="opacity:1;fill:#c53bd7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.02355671;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter2842)" /> | |
| 817 | <rect | |
| 818 | ry="3.9839513" | |
| 819 | rx="3.9205718" | |
| 820 | y="537.09552" | |
| 821 | x="73.372665" | |
| 822 | height="32.855" | |
| 823 | width="165.621" | |
| 824 | id="rect9614" | |
| 825 | style="opacity:1;fill:#46c7f0;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.02355671;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter2914)" /> | |
| 826 | <path | |
| 827 | inkscape:connector-curvature="0" | |
| 828 | style="opacity:1;fill:#e6e7e7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.21841836;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" | |
| 829 | d="m 235.85308,545.09525 c 0.87012,0 1.65488,0.35019 2.22266,0.91797 0.56778,0.56778 0.91797,1.35253 0.91797,2.22265 v -0.23242 c 0,-1.6112 -1.297,-2.9082 -2.9082,-2.9082 z" | |
| 830 | id="path9323" /> | |
| 831 | <path | |
| 832 | inkscape:connector-curvature="0" | |
| 833 | style="opacity:1;fill:#e6e7e7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.21841836;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" | |
| 834 | d="m 76.280823,545.09525 c -1.611195,0 -2.908203,1.297 -2.908203,2.9082 v 0.23242 c 0,-0.87012 0.35019,-1.65487 0.917968,-2.22265 0.567779,-0.56778 1.354485,-0.91797 2.22461,-0.91797 z" | |
| 835 | id="path9327" /> | |
| 836 | <rect | |
| 837 | style="opacity:1;fill:#3dd092;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.02355671;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter2902)" | |
| 838 | id="rect9616" | |
| 839 | width="165.621" | |
| 840 | height="32.855" | |
| 841 | x="313.99307" | |
| 842 | y="537.09552" | |
| 843 | rx="3.9205718" | |
| 844 | ry="3.9839513" /> | |
| 845 | <path | |
| 846 | sodipodi:nodetypes="cc" | |
| 847 | inkscape:connector-curvature="0" | |
| 848 | id="path9491" | |
| 849 | d="m 240.99257,554.11276 65.23376,-1.01307" | |
| 850 | style="opacity:1;vector-effect:none;fill:#05556e;fill-opacity:1;stroke:#05556e;stroke-width:3.94158769;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker9513)" /> | |
| 851 | <path | |
| 852 | style="opacity:1;vector-effect:none;fill:#05556e;fill-opacity:1;stroke:#05556e;stroke-width:3.94158769;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker9640)" | |
| 853 | d="m 481.61298,554.11276 65.23376,-1.01307" | |
| 854 | id="path9501" | |
| 855 | inkscape:connector-curvature="0" | |
| 856 | sodipodi:nodetypes="cc" /> | |
| 857 | <rect | |
| 858 | ry="3.9839513" | |
| 859 | rx="3.9205718" | |
| 860 | y="617.79578" | |
| 861 | x="313.99307" | |
| 862 | height="32.855" | |
| 863 | width="165.621" | |
| 864 | id="rect9620" | |
| 865 | style="opacity:1;fill:#3dd092;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.02355671;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter2890)" /> | |
| 866 | <path | |
| 867 | sodipodi:nodetypes="cc" | |
| 868 | inkscape:connector-curvature="0" | |
| 869 | id="path9681" | |
| 870 | d="m 481.61298,634.81299 65.23376,-1.01307" | |
| 871 | style="opacity:1;vector-effect:none;fill:#05556e;fill-opacity:1;stroke:#05556e;stroke-width:3.94158769;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker9685)" /> | |
| 872 | <rect | |
| 873 | style="opacity:1;fill:#c53bd7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.02355671;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter2854)" | |
| 874 | id="rect9687" | |
| 875 | width="165.621" | |
| 876 | height="32.855" | |
| 877 | x="554.61353" | |
| 878 | y="617.79578" | |
| 879 | rx="3.9205718" | |
| 880 | ry="3.9839513" /> | |
| 881 | <path | |
| 882 | style="opacity:1;vector-effect:none;fill:#05556e;fill-opacity:1;stroke:#05556e;stroke-width:3.94158769;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker9750)" | |
| 883 | d="m 481.61298,715.51321 65.23376,-1.01307" | |
| 884 | id="path9734" | |
| 885 | inkscape:connector-curvature="0" | |
| 886 | sodipodi:nodetypes="cc" /> | |
| 887 | <rect | |
| 888 | ry="3.9839513" | |
| 889 | rx="3.9205718" | |
| 890 | y="698.49591" | |
| 891 | x="554.61353" | |
| 892 | height="32.855" | |
| 893 | width="165.621" | |
| 894 | id="rect9736" | |
| 895 | style="opacity:1;fill:#c53bd7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.02355671;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter2866)" /> | |
| 896 | <path | |
| 897 | id="path9830" | |
| 898 | d="m 356.40451,489.45323 c -0.80426,0 -1.45167,0.64741 -1.45167,1.45166 v 0.11602 c 0,-0.43433 0.1748,-0.82605 0.45822,-1.10946 0.28341,-0.28342 0.6761,-0.45822 1.11043,-0.45822 z" | |
| 899 | style="opacity:1;fill:#e6e7e7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.10902636;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" | |
| 900 | inkscape:connector-curvature="0" /> | |
| 901 | <rect | |
| 902 | style="opacity:1;fill:#ffb73a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.9391377;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" | |
| 903 | id="rect9826" | |
| 904 | width="120.98324" | |
| 905 | height="24" | |
| 906 | x="336.82672" | |
| 907 | y="477.86002" | |
| 908 | rx="2.8639088" | |
| 909 | ry="2.9102066" /> | |
| 910 | <path | |
| 911 | id="path10514" | |
| 912 | d="m 235.85301,637.23875 c 0.87012,0 1.65488,0.35019 2.22266,0.91797 0.56778,0.56778 0.91797,1.35253 0.91797,2.22265 v -0.23242 c 0,-1.6112 -1.297,-2.9082 -2.9082,-2.9082 z" | |
| 913 | style="opacity:1;fill:#e6e7e7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.21841836;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" | |
| 914 | inkscape:connector-curvature="0" /> | |
| 915 | <rect | |
| 916 | style="opacity:1;fill:#3dd092;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.02355671;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter2878)" | |
| 917 | id="rect9717" | |
| 918 | width="165.621" | |
| 919 | height="32.855" | |
| 920 | x="313.99307" | |
| 921 | y="698.49591" | |
| 922 | rx="3.9205718" | |
| 923 | ry="3.9839513" /> | |
| 924 | <path | |
| 925 | id="path10537" | |
| 926 | d="M 238.99366,636.97465 H 73.372671 V 729.175 c 0,1.2055 0.970418,2.17592 2.175911,2.17592 H 236.81776 c 1.20549,0 2.1759,-0.97042 2.1759,-2.17592 z" | |
| 927 | style="opacity:1;fill:#333333;fill-opacity:0.93333333;fill-rule:nonzero;stroke:none;stroke-width:0.16342013;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" | |
| 928 | inkscape:connector-curvature="0" | |
| 929 | sodipodi:nodetypes="ccssssc" /> | |
| 930 | <path | |
| 931 | sodipodi:nodetypes="sssccssss" | |
| 932 | id="path10516" | |
| 933 | d="m 75.723937,612.39226 c -0.651025,0 -1.239637,0.26201 -1.664447,0.68682 -0.424811,0.42482 -0.686822,1.01196 -0.686822,1.66299 v 22.23258 H 238.99366 v -22.23258 c 0,-0.65103 -0.26201,-1.23817 -0.68682,-1.66299 -0.42481,-0.42481 -1.01197,-0.68682 -1.66299,-0.68682 z" | |
| 934 | style="opacity:1;fill:#ffb73a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.16342013;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" | |
| 935 | inkscape:connector-curvature="0" /> | |
| 936 | <path | |
| 937 | style="opacity:1;vector-effect:none;fill:#05556e;fill-opacity:1;stroke:#05556e;stroke-width:3.94158769;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker10933)" | |
| 938 | d="m 240.99257,715.51318 65.23376,-1.01307" | |
| 939 | id="path10929" | |
| 940 | inkscape:connector-curvature="0" | |
| 941 | sodipodi:nodetypes="cc" /> | |
| 942 | <path | |
| 943 | style="fill:#df4d65;fill-opacity:1;fill-rule:evenodd;stroke-width:0.05250736" | |
| 944 | d="m 399.47357,99.155037 -0.12716,0.0127 -0.12716,0.0141 -0.12574,0.0141 -0.12716,0.0155 -0.61883,0.967813 -0.29106,0.9325 -0.17943,0.91977 -0.1215,1.09073 -0.30943,0.0636 -0.308,0.0678 -0.308,0.0735 -0.30801,0.0763 -0.58069,-0.93108 -0.5609,-0.75023 -0.66687,-0.71349 -0.97912,-0.6033 -0.12009,0.0409 -0.1201,0.0424 -0.12009,0.0424 -0.12009,0.0424 -0.38854,1.08085 -0.0763,0.97487 0.0297,0.93673 0.12575,1.08932 -0.28823,0.1314 -0.28681,0.13563 -0.28398,0.13987 -0.28117,0.14271 -0.77425,-0.77849 -0.7149,-0.60612 -0.80816,-0.54819 -1.0879,-0.37017 -0.10879,0.0678 -0.10738,0.0679 -0.10738,0.0678 -0.10738,0.0678 -0.13846,1.14018 0.14129,0.9664 0.23735,0.90706 0.36594,1.03563 -0.25149,0.19215 -0.24865,0.19497 -0.24585,0.19922 -0.24442,0.20204 -0.92825,-0.58634 -0.83077,-0.43234 -0.90988,-0.35463 -1.14301,-0.11868 -0.0904,0.0904 -0.0904,0.089 -0.089,0.0904 -0.0904,0.0904 0.11868,1.14301 0.35462,0.90988 0.43234,0.83218 0.58634,0.92684 -0.20204,0.24442 -0.19921,0.24584 -0.19498,0.24867 -0.19215,0.25148 -1.03563,-0.36593 -0.90705,-0.23736 -0.96641,-0.14128 -1.14018,0.13845 -0.0678,0.10738 -0.0678,0.10738 -0.0678,0.10738 -0.0678,0.10879 0.37016,1.0879 0.5482,0.80816 0.60612,0.71491 0.77848,0.77425 -0.1427,0.28117 -0.13987,0.28398 -0.13564,0.28681 -0.13139,0.28823 -1.09073,-0.12575 -0.93532,-0.0297 -0.97487,0.0763 -1.08084,0.38854 -0.0424,0.12009 -0.0424,0.12009 -0.0424,0.1201 -0.0409,0.12009 0.6033,0.97912 0.7135,0.66686 0.75023,0.56091 0.93107,0.58069 -0.0763,0.30801 -0.0735,0.308 -0.0678,0.308 -0.0636,0.30942 -1.09073,0.1215 -0.91977,0.17944 -0.9325,0.29105 -0.96781,0.61883 -0.0156,0.12717 -0.0141,0.12574 -0.0141,0.12716 -0.0127,0.12716 0.80533,0.81804 0.84348,0.49168 0.85619,0.38006 1.03704,0.36028 -0.006,0.31648 -0.003,0.31648 0.003,0.31648 0.006,0.31648 -1.03704,0.35887 -0.85619,0.38006 -0.84348,0.49168 -0.80533,0.81946 0.0127,0.12716 0.0141,0.12574 0.0141,0.12716 0.0156,0.12574 0.96781,0.62026 0.9325,0.29104 0.91977,0.17944 1.09073,0.12009 0.0636,0.30942 0.0678,0.30941 0.0735,0.30801 0.0763,0.30659 -0.93107,0.5821 -0.75023,0.56091 -0.7135,0.66687 -0.6033,0.97771 0.0409,0.12008 0.0424,0.12151 0.0424,0.1201 0.0424,0.11868 1.08084,0.38995 0.97487,0.0763 0.93532,-0.0297 1.09073,-0.12574 0.13139,0.28822 0.13564,0.2854 0.13987,0.28399 0.1427,0.28257 -0.77848,0.77425 -0.60612,0.7135 -0.5482,0.80957 -0.37016,1.08791 0.0678,0.10737 0.0678,0.10879 0.0678,0.10738 0.0678,0.10738 1.14018,0.13846 0.96641,-0.1427 0.90705,-0.23736 1.03563,-0.36452 0.19215,0.25149 0.19498,0.24866 0.19921,0.24584 0.20204,0.24302 -0.58634,0.92825 -0.43234,0.83076 -0.35462,0.9113 -0.11868,1.14159 0.0904,0.0918 0.089,0.089 0.0904,0.0904 0.0904,0.089 1.14301,-0.11868 0.90988,-0.35321 0.83077,-0.43375 0.92825,-0.58493 0.24442,0.20204 0.24585,0.19921 0.24865,0.19497 0.25149,0.19216 -0.36594,1.03563 -0.23735,0.90564 -0.14129,0.9664 0.13846,1.14018 0.10738,0.0692 0.10738,0.0678 0.10738,0.0678 0.10879,0.0664 1.0879,-0.37017 0.80816,-0.54677 0.7149,-0.60754 0.77425,-0.77708 0.28117,0.14271 0.28398,0.13987 0.28681,0.13422 0.28823,0.13139 -0.12575,1.09074 -0.0297,0.93673 0.0763,0.97346 0.38854,1.08084 0.12009,0.0438 0.12009,0.0424 0.1201,0.041 0.12009,0.0409 0.97912,-0.60188 0.66687,-0.71349 0.5609,-0.75165 0.58069,-0.93108 0.30801,0.0777 0.308,0.072 0.308,0.0692 0.30943,0.0636 0.1215,1.09073 0.17943,0.91978 0.29106,0.93249 0.61883,0.9664 0.12716,0.0156 0.12574,0.0141 0.12716,0.0141 0.12716,0.0141 0.81806,-0.80533 0.49167,-0.8449 0.38006,-0.85619 0.36028,-1.03704 0.31648,0.007 0.31648,0.003 0.31649,-0.003 0.31648,-0.007 0.36028,1.03704 0.37865,0.85619 0.49167,0.8449 0.81947,0.80533 0.12715,-0.0141 0.12574,-0.0141 0.12717,-0.0141 0.12574,-0.0156 0.62025,-0.9664 0.29104,-0.93249 0.17944,-0.91978 0.12009,-1.09073 0.30942,-0.0636 0.30942,-0.0692 0.30799,-0.072 0.3066,-0.0777 0.58211,0.93108 0.5609,0.75165 0.66687,0.71349 0.97771,0.60188 0.12009,-0.0409 0.1215,-0.041 0.1201,-0.0424 0.11868,-0.0438 0.38995,-1.08084 0.0763,-0.97346 -0.0297,-0.93673 -0.12574,-1.09074 0.28822,-0.13139 0.2854,-0.13422 0.28398,-0.13987 0.28258,-0.14271 0.77424,0.77708 0.7135,0.60754 0.80957,0.54677 1.08791,0.37017 0.10737,-0.0664 0.10879,-0.0678 0.10738,-0.0678 0.10738,-0.0692 0.13847,-1.14018 -0.14271,-0.9664 -0.23737,-0.90564 -0.36452,-1.03563 0.25149,-0.19216 0.24866,-0.19497 0.24585,-0.19921 0.24301,-0.20204 0.92825,0.58493 0.83077,0.43375 0.91129,0.35321 1.1416,0.11868 0.0904,-0.089 0.0904,-0.0904 0.0904,-0.089 0.089,-0.0918 -0.11868,-1.14159 -0.35321,-0.9113 -0.43375,-0.83076 -0.58492,-0.92825 0.20203,-0.24302 0.19921,-0.24584 0.19498,-0.24866 0.19215,-0.25149 1.03563,0.36452 0.90564,0.23736 0.9664,0.1427 1.14018,-0.13846 0.0692,-0.10738 0.0678,-0.10738 0.0678,-0.10879 0.0664,-0.10737 -0.37017,-1.08791 -0.54677,-0.80957 -0.60754,-0.7135 -0.77706,-0.77425 0.1427,-0.28257 0.13986,-0.28399 0.13423,-0.2854 0.13139,-0.28822 1.09073,0.12574 0.93674,0.0297 0.97345,-0.0763 1.08085,-0.38995 0.0438,-0.11868 0.0424,-0.1201 0.0409,-0.12151 0.041,-0.12008 -0.6019,-0.97771 -0.71349,-0.66687 -0.75164,-0.56091 -0.93108,-0.5821 0.0777,-0.30659 0.072,-0.30801 0.0692,-0.30941 0.0636,-0.30942 1.09073,-0.12009 0.91978,-0.17944 0.93249,-0.29104 0.9664,-0.62026 0.0155,-0.12574 0.0141,-0.12716 0.0141,-0.12574 0.0141,-0.12716 -0.80533,-0.81946 -0.8449,-0.49168 -0.85619,-0.38006 -1.03704,-0.35887 0.007,-0.31648 0.003,-0.31648 -0.003,-0.31648 -0.007,-0.31648 1.03704,-0.36028 0.85619,-0.38006 0.8449,-0.49168 0.80533,-0.81804 -0.0141,-0.12716 -0.0141,-0.12716 -0.0141,-0.12574 -0.0155,-0.12717 -0.9664,-0.61883 -0.93249,-0.29105 -0.91978,-0.17944 -1.09073,-0.1215 -0.0636,-0.30942 -0.0692,-0.308 -0.072,-0.308 -0.0777,-0.30801 0.93108,-0.58069 0.75164,-0.56091 0.71349,-0.66686 0.6019,-0.97912 -0.041,-0.12009 -0.0409,-0.1201 -0.0424,-0.12009 -0.0438,-0.12009 -1.08085,-0.38854 -0.97345,-0.0763 -0.93674,0.0297 -1.09073,0.12575 -0.13139,-0.28823 -0.13423,-0.28681 -0.13986,-0.28398 -0.1427,-0.28117 0.77706,-0.77425 0.60754,-0.71491 0.54677,-0.80816 0.37017,-1.0879 -0.0664,-0.10879 -0.0678,-0.10738 -0.0678,-0.10738 -0.0692,-0.10738 -1.14018,-0.13845 -0.9664,0.14128 -0.90564,0.23736 -1.03563,0.36593 -0.19215,-0.25148 -0.19498,-0.24867 -0.19921,-0.24584 -0.20203,-0.24442 0.58492,-0.92684 0.43375,-0.83218 0.35321,-0.90988 0.11868,-1.14301 -0.089,-0.0904 -0.0904,-0.0904 -0.0904,-0.089 -0.0904,-0.0904 -1.1416,0.11868 -0.91129,0.35463 -0.83077,0.43234 -0.92825,0.58634 -0.24301,-0.20204 -0.24585,-0.19922 -0.24866,-0.19497 -0.25149,-0.19215 0.36452,-1.03563 0.23737,-0.90706 0.14271,-0.9664 -0.13847,-1.14018 -0.10738,-0.0678 -0.10738,-0.0678 -0.10879,-0.0679 -0.10737,-0.0678 -1.08791,0.37017 -0.80957,0.54819 -0.7135,0.60612 -0.77424,0.77849 -0.28258,-0.14271 -0.28398,-0.13987 -0.2854,-0.13563 -0.28822,-0.1314 0.12574,-1.08932 0.0297,-0.93673 -0.0763,-0.97487 -0.38995,-1.08085 -0.11868,-0.0424 -0.1201,-0.0424 -0.1215,-0.0424 -0.12009,-0.0409 -0.97771,0.6033 -0.66687,0.71349 -0.5609,0.75023 -0.58211,0.93108 -0.3066,-0.0763 -0.30799,-0.0735 -0.30942,-0.0678 -0.30942,-0.0636 -0.12009,-1.09073 -0.17944,-0.91977 -0.29104,-0.9325 -0.62025,-0.967813 -0.12574,-0.0155 -0.12717,-0.0141 -0.12574,-0.0141 -0.12715,-0.0127 -0.81947,0.80533 -0.49167,0.843483 -0.37865,0.8562 -0.36028,1.03704 -0.31648,-0.006 -0.31649,-0.003 -0.31648,0.003 -0.31648,0.006 -0.36028,-1.03704 -0.38006,-0.8562 -0.49167,-0.843483 z m 2.68302,20.688573 a 5.3990039,5.3990039 0 0 1 5.39856,5.39997 5.3990039,5.3990039 0 0 1 -5.39856,5.39855 5.3990039,5.3990039 0 0 1 -5.39996,-5.39855 5.3990039,5.3990039 0 0 1 5.39996,-5.39997 z" | |
| 945 | id="path5693" | |
| 946 | inkscape:connector-curvature="0" /> | |
| 947 | <path | |
| 948 | inkscape:connector-curvature="0" | |
| 949 | d="m 380.9529,101.31918 a 4.37599,4.37599 0 0 1 -4.37599,4.37599 4.37599,4.37599 0 0 1 -4.37599,-4.37599 4.37599,4.37599 0 0 1 4.37599,-4.375983 4.37599,4.37599 0 0 1 4.37599,4.375983 z m 4.63493,-1.27213 c -0.32212,-0.118873 -0.95326,0.0926 -0.92258,-0.401293 -0.13877,-0.39635 -0.21401,-0.74537 0.27363,-0.88946 0.78055,-0.47633 1.45123,-1.16128 1.74461,-2.04171 0.15411,-0.39145 -0.3432,-0.48754 -0.63657,-0.53536 -0.91614,-0.25589 -1.86519,0.0578 -2.73328,0.35995 -0.11023,-0.31345 -0.69059,-0.56868 -0.47901,-0.88657 0.56405,-0.84324 0.99162,-1.8335 0.85012,-2.86709 -0.031,-0.41955 -0.52073,-0.29038 -0.8058,-0.20618 -0.93646,0.16692 -1.65537,0.86143 -2.30642,1.51029 -0.23528,-0.23464 -0.86896,-0.21274 -0.81624,-0.59097 0.14241,-1.00446 0.0978,-2.08217 -0.47806,-2.95201 -0.20995,-0.36459 -0.59514,-0.0357 -0.81544,0.16385 -0.7713,0.55671 -1.11768,1.49434 -1.42274,2.36143 -0.3138,-0.10927 -0.87519,0.18536 -0.99181,-0.17826 -0.30757,-0.96675 -0.81528,-1.91841 -1.71153,-2.45229 -0.34734,-0.23737 -0.55176,0.22606 -0.66364,0.50149 -0.45331,0.83622 -0.35865,1.83127 -0.25723,2.74482 -0.33012,0.0378 -0.70817,0.54672 -0.97098,0.26977 -0.69651,-0.73763 -1.56687,-1.37476 -2.60601,-1.46682 -0.41593,-0.0631 -0.39904,0.443 -0.38034,0.73971 -0.0456,0.95009 0.47143,1.80554 0.95918,2.58463 -0.28104,0.17725 -0.40076,0.79984 -0.75777,0.6643 -0.94759,-0.36236 -2.00818,-0.55864 -2.98437,-0.1908 -0.40215,0.12357 -0.16723,0.57227 -0.0217,0.83147 0.37114,0.8758 1.2081,1.42221 1.98561,1.91248 -0.17632,0.28163 -0.0141,0.89453 -0.39449,0.92732 -1.01097,0.0847 -2.05173,0.367983 -2.77166,1.122963 -0.3087,0.2858 0.0976,0.58816 0.34122,0.75853 0.71439,0.62804 1.70558,0.75716 2.6188,0.8616 -0.0367,0.33025 0.37548,0.81204 0.0469,1.00665 -0.87415,0.51488 -1.68886,1.22174 -2.00994,2.2143 -0.15411,0.39144 0.3432,0.48753 0.63657,0.53535 0.91612,0.25589 1.86516,-0.0578 2.73323,-0.35995 0.11029,0.31341 0.69063,0.56869 0.47905,0.88657 -0.56412,0.8432 -0.99155,1.83352 -0.85015,2.86709 0.031,0.41952 0.52075,0.2904 0.80584,0.20618 0.93644,-0.16692 1.65537,-0.86139 2.30637,-1.51029 0.2353,0.23464 0.86901,0.21272 0.81629,0.59098 -0.14241,1.00446 -0.0978,2.08215 0.47802,2.95202 0.20997,0.36455 0.59517,0.0357 0.81548,-0.16387 0.77125,-0.55674 1.11768,-1.49435 1.42274,-2.36142 0.31379,0.10926 0.8752,-0.18537 0.99181,0.17824 0.30754,0.96678 0.81527,1.91842 1.71153,2.45229 0.34733,0.23738 0.55172,-0.22608 0.66362,-0.50146 0.45335,-0.83621 0.35866,-1.83128 0.25725,-2.74484 0.33011,-0.0378 0.70812,-0.54672 0.97093,-0.26977 0.69656,0.7376 1.5669,1.37477 2.60606,1.46683 0.41593,0.0632 0.39897,-0.44304 0.38032,-0.73972 0.0457,-0.95011 -0.4715,-1.8055 -0.95916,-2.58463 0.28105,-0.17722 0.40074,-0.79983 0.75772,-0.6643 0.94761,0.36234 2.00821,0.55865 2.98442,0.1908 0.40215,-0.12357 0.16723,-0.57228 0.0217,-0.83146 -0.37116,-0.87579 -1.20814,-1.42218 -1.98561,-1.91249 0.17632,-0.28163 0.0141,-0.89453 0.39449,-0.92732 1.01097,-0.0847 2.05173,-0.36799 2.77166,-1.12295 0.3087,-0.28581 -0.0976,-0.58817 -0.34122,-0.75854 -0.47483,-0.43652 -1.13407,-0.61787 -1.75144,-0.75008 z" | |
| 950 | style="fill:#05556e;fill-opacity:1;fill-rule:evenodd;stroke-width:0.04014921" | |
| 951 | id="path5687" /> | |
| 952 | <path | |
| 953 | style="fill:#05556e;fill-opacity:1;stroke-width:0.11881336" | |
| 954 | id="path4816" | |
| 955 | d="m 619.92265,90.37586 h 2.72717 v 2.71445 h 2.51374 v -2.71445 h 2.72716 v 8.21477 h -2.72716 v -2.73825 h -2.49003 v 2.73825 h -2.75088 m 11.57268,-5.47651 h -2.40702 v -2.73826 h 7.55307 v 2.73826 h -2.41888 v 5.47651 h -2.72717 m 6.34363,-8.21477 h 2.8576 l 1.75487,2.89303 1.75487,-2.89303 h 2.8576 v 8.21477 h -2.72717 v -4.07167 l -1.90901,2.95256 -1.90902,-2.95256 v 4.07167 h -2.67974 m 10.57667,-8.21477 h 2.72717 v 5.50033 h 3.86546 v 2.71444 h -6.59263" | |
| 956 | inkscape:connector-curvature="0" /> | |
| 957 | <path | |
| 958 | id="path4818" | |
| 959 | d="m 619.82779,146.45062 -3.91289,-44.09786 h 43.01811 l -3.91289,44.07405 -17.63174,4.90505" | |
| 960 | inkscape:connector-curvature="0" | |
| 961 | style="fill:#e44d26;stroke-width:0.11881336" /> | |
| 962 | <path | |
| 963 | id="path4820" | |
| 964 | d="m 637.42396,147.58164 v -41.60962 h 17.5843 l -3.3556,37.62129" | |
| 965 | inkscape:connector-curvature="0" | |
| 966 | style="fill:#f16529;stroke-width:0.11881336" /> | |
| 967 | <path | |
| 968 | id="path4822" | |
| 969 | d="m 623.90669,111.3652 h 13.51727 v 5.40508 h -7.61236 l 0.498,5.53605 h 7.11436 v 5.39318 h -12.04697 m 0.23714,2.71444 h 5.40691 l 0.37943,4.32169 6.02349,1.61914 v 5.64319 L 626.373,138.90255" | |
| 970 | inkscape:connector-curvature="0" | |
| 971 | style="fill:#ebebeb;stroke-width:0.11881336" /> | |
| 972 | <path | |
| 973 | id="path4824" | |
| 974 | d="m 650.89379,111.3652 h -13.49355 v 5.40508 h 12.99555 m -0.48615,5.53605 h -12.5094 v 5.40508 h 6.64006 l -0.62843,7.02423 -6.01163,1.61914 v 5.61938 l 11.02724,-3.07161" | |
| 975 | inkscape:connector-curvature="0" | |
| 976 | style="fill:#ffffff;stroke-width:0.11881336" /> | |
| 977 | <path | |
| 978 | sodipodi:nodetypes="cc" | |
| 979 | inkscape:connector-curvature="0" | |
| 980 | id="path5804" | |
| 981 | d="m 240.99252,105.07517 65.2338,-1.01308" | |
| 982 | style="opacity:1;vector-effect:none;fill:#05556e;fill-opacity:1;stroke:#05556e;stroke-width:3.94158769;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker9479)" /> | |
| 983 | <path | |
| 984 | style="opacity:1;vector-effect:none;fill:#05556e;fill-opacity:1;stroke:#05556e;stroke-width:3.94158769;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker9505)" | |
| 985 | d="m 481.61302,105.07517 65.2337,-1.01308" | |
| 986 | id="path9497" | |
| 987 | inkscape:connector-curvature="0" | |
| 988 | sodipodi:nodetypes="cc" /> | |
| 989 | <path | |
| 990 | inkscape:connector-curvature="0" | |
| 991 | style="opacity:1;fill:#e6e7e7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.21841836;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" | |
| 992 | d="m 235.85308,230.53494 c 0.87012,0 1.65488,0.35019 2.22266,0.91797 0.56778,0.56778 0.91797,1.35253 0.91797,2.22265 v -0.23242 c 0,-1.6112 -1.297,-2.9082 -2.9082,-2.9082 z" | |
| 993 | id="path6102" /> | |
| 994 | <path | |
| 995 | inkscape:connector-curvature="0" | |
| 996 | style="opacity:1;fill:#e6e7e7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.21841836;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" | |
| 997 | d="m 76.280823,230.53494 c -1.611195,0 -2.908203,1.297 -2.908203,2.9082 v 0.23242 c 0,-0.87012 0.35019,-1.65487 0.917968,-2.22265 0.567779,-0.56778 1.354485,-0.91797 2.22461,-0.91797 z" | |
| 998 | id="path6106" /> | |
| 999 | <path | |
| 1000 | inkscape:connector-curvature="0" | |
| 1001 | style="fill:#46c7f0;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.218418;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter2950)" | |
| 1002 | d="m 76.515198,222.53494 c -0.870125,0 -1.656831,0.35019 -2.22461,0.91797 -0.567778,0.56778 -0.917968,1.35253 -0.917968,2.22265 v 29.71485 h 165.62109 v -29.71485 c 0,-0.87012 -0.35019,-1.65487 -0.91797,-2.22265 -0.56778,-0.56778 -1.35254,-0.91797 -2.22266,-0.91797 z" | |
| 1003 | id="path6104" | |
| 1004 | sodipodi:nodetypes="sssccssss" /> | |
| 1005 | <path | |
| 1006 | sodipodi:nodetypes="ccssssc" | |
| 1007 | inkscape:connector-curvature="0" | |
| 1008 | style="fill:#e6e7e7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.218418;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter2950)" | |
| 1009 | d="M 238.99371,255.39041 H 73.37262 v 152.63392 c 0,1.6112 1.297008,2.90821 2.908203,2.90821 H 236.08551 c 1.6112,0 2.9082,-1.29701 2.9082,-2.90821 z" | |
| 1010 | id="path6100" /> | |
| 1011 | <path | |
| 1012 | style="opacity:1;vector-effect:none;fill:#05556e;fill-opacity:1;stroke:#05556e;stroke-width:3.94158769;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker9509)" | |
| 1013 | d="m 240.99257,328.95043 65.23376,-1.01307" | |
| 1014 | id="path9485" | |
| 1015 | inkscape:connector-curvature="0" | |
| 1016 | sodipodi:nodetypes="cc" /> | |
| 1017 | <path | |
| 1018 | sodipodi:nodetypes="cc" | |
| 1019 | inkscape:connector-curvature="0" | |
| 1020 | id="path9757" | |
| 1021 | d="m 481.61298,300.08996 65.23376,-1.01307" | |
| 1022 | style="opacity:1;vector-effect:none;fill:#05556e;fill-opacity:1;stroke:#05556e;stroke-width:3.94158769;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker9761)" /> | |
| 1023 | <path | |
| 1024 | style="opacity:1;vector-effect:none;fill:#05556e;fill-opacity:1;stroke:#05556e;stroke-width:3.94158769;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker9767)" | |
| 1025 | d="M 552.61456,372.04139 487.3808,371.02832" | |
| 1026 | id="path9763" | |
| 1027 | inkscape:connector-curvature="0" | |
| 1028 | sodipodi:nodetypes="cc" /> | |
| 1029 | <text | |
| 1030 | id="text2269" | |
| 1031 | y="62.149761" | |
| 1032 | x="115.43707" | |
| 1033 | style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:0.933333;stroke:none" | |
| 1034 | xml:space="preserve"><tspan | |
| 1035 | y="62.149761" | |
| 1036 | x="115.43707" | |
| 1037 | id="tspan2267" | |
| 1038 | sodipodi:role="line">Text Edit</tspan></text> | |
| 1039 | <text | |
| 1040 | transform="rotate(-90)" | |
| 1041 | id="text2273" | |
| 1042 | y="43.507812" | |
| 1043 | x="-132.24059" | |
| 1044 | style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:0.933333;stroke:none" | |
| 1045 | xml:space="preserve"><tspan | |
| 1046 | y="43.507812" | |
| 1047 | x="-132.24059" | |
| 1048 | id="tspan2271" | |
| 1049 | sodipodi:role="line">Today</tspan></text> | |
| 1050 | <text | |
| 1051 | id="text2277" | |
| 1052 | y="61.540386" | |
| 1053 | x="358.88168" | |
| 1054 | style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:0.933333;stroke:none" | |
| 1055 | xml:space="preserve"><tspan | |
| 1056 | y="61.540386" | |
| 1057 | x="358.88168" | |
| 1058 | id="tspan2275" | |
| 1059 | sodipodi:role="line">Process</tspan></text> | |
| 1060 | <text | |
| 1061 | id="text2281" | |
| 1062 | y="59.34898" | |
| 1063 | x="605.30872" | |
| 1064 | style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:0.933333;stroke:none" | |
| 1065 | xml:space="preserve"><tspan | |
| 1066 | y="59.34898" | |
| 1067 | x="605.30872" | |
| 1068 | id="tspan2279" | |
| 1069 | sodipodi:role="line">Output</tspan></text> | |
| 1070 | <text | |
| 1071 | id="text2285" | |
| 1072 | y="245.17946" | |
| 1073 | x="605.30872" | |
| 1074 | style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:0.933333;stroke:none" | |
| 1075 | xml:space="preserve"><tspan | |
| 1076 | y="245.17946" | |
| 1077 | x="605.30872" | |
| 1078 | id="tspan2283" | |
| 1079 | sodipodi:role="line">Output</tspan></text> | |
| 1080 | <text | |
| 1081 | id="text2289" | |
| 1082 | y="247.37088" | |
| 1083 | x="358.88168" | |
| 1084 | style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:0.933333;stroke:none" | |
| 1085 | xml:space="preserve"><tspan | |
| 1086 | y="247.37088" | |
| 1087 | x="358.88168" | |
| 1088 | id="tspan2287" | |
| 1089 | sodipodi:role="line">Process</tspan></text> | |
| 1090 | <text | |
| 1091 | id="text2293" | |
| 1092 | y="247.98026" | |
| 1093 | x="115.43707" | |
| 1094 | style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:0.933333;stroke:none" | |
| 1095 | xml:space="preserve"><tspan | |
| 1096 | y="247.98026" | |
| 1097 | x="115.43707" | |
| 1098 | id="tspan2291" | |
| 1099 | sodipodi:role="line">Text Edit</tspan></text> | |
| 1100 | <text | |
| 1101 | transform="rotate(-90)" | |
| 1102 | id="text2297" | |
| 1103 | y="43.630859" | |
| 1104 | x="-363.15442" | |
| 1105 | style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:0.933333;stroke:none" | |
| 1106 | xml:space="preserve"><tspan | |
| 1107 | y="43.630859" | |
| 1108 | x="-363.15442" | |
| 1109 | id="tspan2295" | |
| 1110 | sodipodi:role="line">Proposed</tspan></text> | |
| 1111 | <text | |
| 1112 | id="text2301" | |
| 1113 | y="314.01108" | |
| 1114 | x="98.034729" | |
| 1115 | style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#05556e;fill-opacity:1;stroke:none" | |
| 1116 | xml:space="preserve"><tspan | |
| 1117 | id="tspan2299" | |
| 1118 | sodipodi:role="line" | |
| 1119 | x="98.034729" | |
| 1120 | y="314.01108">R Markdown</tspan></text> | |
| 1121 | <text | |
| 1122 | id="text2305" | |
| 1123 | y="285.84311" | |
| 1124 | x="107.43903" | |
| 1125 | style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#05556e;fill-opacity:1;stroke:none" | |
| 1126 | xml:space="preserve"><tspan | |
| 1127 | id="tspan2303" | |
| 1128 | sodipodi:role="line" | |
| 1129 | x="107.43903" | |
| 1130 | y="285.84311">Markdown</tspan></text> | |
| 1131 | <text | |
| 1132 | id="text2309" | |
| 1133 | y="342.91147" | |
| 1134 | x="134.3277" | |
| 1135 | style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#05556e;fill-opacity:1;stroke:none" | |
| 1136 | xml:space="preserve"><tspan | |
| 1137 | id="tspan2307" | |
| 1138 | sodipodi:role="line" | |
| 1139 | x="134.3277" | |
| 1140 | y="342.91147">XML</tspan></text> | |
| 1141 | <text | |
| 1142 | id="text2313" | |
| 1143 | y="370.34702" | |
| 1144 | x="113.56207" | |
| 1145 | style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#05556e;fill-opacity:1;stroke:none" | |
| 1146 | xml:space="preserve"><tspan | |
| 1147 | id="tspan2311" | |
| 1148 | sodipodi:role="line" | |
| 1149 | x="113.56207" | |
| 1150 | y="370.34702">DocBook</tspan></text> | |
| 1151 | <text | |
| 1152 | id="text2317" | |
| 1153 | y="398.51498" | |
| 1154 | x="114.3526" | |
| 1155 | style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#05556e;fill-opacity:1;stroke:none" | |
| 1156 | xml:space="preserve"><tspan | |
| 1157 | id="tspan2315" | |
| 1158 | sodipodi:role="line" | |
| 1159 | x="114.3526" | |
| 1160 | y="398.51498">AsciiDoc</tspan></text> | |
| 1161 | <text | |
| 1162 | transform="rotate(-90)" | |
| 1163 | id="text2329" | |
| 1164 | y="43.507812" | |
| 1165 | x="-774.87335" | |
| 1166 | style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:0.933333;stroke:none" | |
| 1167 | xml:space="preserve"><tspan | |
| 1168 | y="43.507812" | |
| 1169 | x="-774.87335" | |
| 1170 | id="tspan2327" | |
| 1171 | sodipodi:role="line">Example Processing Combination</tspan></text> | |
| 1172 | <text | |
| 1173 | id="text2333" | |
| 1174 | y="562.05426" | |
| 1175 | x="135.31207" | |
| 1176 | style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#f3fbfe;fill-opacity:1;stroke:none" | |
| 1177 | xml:space="preserve"><tspan | |
| 1178 | y="562.05426" | |
| 1179 | x="135.31207" | |
| 1180 | id="tspan2331" | |
| 1181 | sodipodi:role="line">XML</tspan></text> | |
| 1182 | <text | |
| 1183 | id="text2337" | |
| 1184 | y="495.6918" | |
| 1185 | x="381.64142" | |
| 1186 | style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:16.4059px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#333333;fill-opacity:0.866667;stroke:none" | |
| 1187 | xml:space="preserve"><tspan | |
| 1188 | y="495.6918" | |
| 1189 | x="381.64142" | |
| 1190 | id="tspan2335" | |
| 1191 | sodipodi:role="line">XSLT</tspan></text> | |
| 1192 | <text | |
| 1193 | id="text2341" | |
| 1194 | y="562.05426" | |
| 1195 | x="323.97742" | |
| 1196 | style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:0.933333;stroke:none" | |
| 1197 | xml:space="preserve"><tspan | |
| 1198 | y="562.05426" | |
| 1199 | x="323.97742" | |
| 1200 | id="tspan2339" | |
| 1201 | sodipodi:role="line">XSLT Processor</tspan></text> | |
| 1202 | <text | |
| 1203 | id="text2345" | |
| 1204 | y="562.54059" | |
| 1205 | x="579.27557" | |
| 1206 | style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:0.933333;stroke:none" | |
| 1207 | xml:space="preserve"><tspan | |
| 1208 | y="562.54059" | |
| 1209 | x="579.27557" | |
| 1210 | id="tspan2343" | |
| 1211 | sodipodi:role="line">R Markdown</tspan></text> | |
| 1212 | <text | |
| 1213 | id="text2349" | |
| 1214 | y="643.24084" | |
| 1215 | x="588.75018" | |
| 1216 | style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:0.933333;stroke:none" | |
| 1217 | xml:space="preserve"><tspan | |
| 1218 | y="643.24084" | |
| 1219 | x="588.75018" | |
| 1220 | id="tspan2347" | |
| 1221 | sodipodi:role="line">Markdown</tspan></text> | |
| 1222 | <text | |
| 1223 | id="text2353" | |
| 1224 | y="642.63147" | |
| 1225 | x="339.61023" | |
| 1226 | style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:0.933333;stroke:none" | |
| 1227 | xml:space="preserve"><tspan | |
| 1228 | y="642.63147" | |
| 1229 | x="339.61023" | |
| 1230 | id="tspan2351" | |
| 1231 | sodipodi:role="line">R Processor</tspan></text> | |
| 1232 | <text | |
| 1233 | id="text2357" | |
| 1234 | y="722.93903" | |
| 1235 | x="318.43912" | |
| 1236 | style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:21.3333px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:0.933333;stroke:none" | |
| 1237 | xml:space="preserve"><tspan | |
| 1238 | y="722.93903" | |
| 1239 | x="318.43912" | |
| 1240 | id="tspan2355" | |
| 1241 | sodipodi:role="line">Variable Processor</tspan></text> | |
| 1242 | <text | |
| 1243 | id="text2361" | |
| 1244 | y="723.3316" | |
| 1245 | x="604.07831" | |
| 1246 | style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:0.933333;stroke:none" | |
| 1247 | xml:space="preserve"><tspan | |
| 1248 | y="723.3316" | |
| 1249 | x="604.07831" | |
| 1250 | id="tspan2359" | |
| 1251 | sodipodi:role="line">HTML5</tspan></text> | |
| 1252 | <text | |
| 1253 | id="text2365" | |
| 1254 | y="630.84766" | |
| 1255 | x="81.211723" | |
| 1256 | style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:16.4059px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#333333;fill-opacity:0.866667;stroke:none" | |
| 1257 | xml:space="preserve"><tspan | |
| 1258 | y="630.84766" | |
| 1259 | x="81.211723" | |
| 1260 | id="tspan2363" | |
| 1261 | sodipodi:role="line">Structured Data Source</tspan></text> | |
| 1262 | <text | |
| 1263 | id="text2369" | |
| 1264 | y="756.39404" | |
| 1265 | x="215.65826" | |
| 1266 | style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:16.4059px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#05556e;fill-opacity:1;stroke:none" | |
| 1267 | xml:space="preserve"><tspan | |
| 1268 | y="756.39404" | |
| 1269 | x="215.65826" | |
| 1270 | id="tspan2367" | |
| 1271 | sodipodi:role="line">interpolated values</tspan></text> | |
| 1272 | <g | |
| 1273 | transform="translate(-0.25585322,11.831789)" | |
| 1274 | id="g2523"> | |
| 1275 | <text | |
| 1276 | xml:space="preserve" | |
| 1277 | style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:16.4059px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:0.933333;stroke:none" | |
| 1278 | x="156.49219" | |
| 1279 | y="708.2467" | |
| 1280 | id="text2373"><tspan | |
| 1281 | sodipodi:role="line" | |
| 1282 | id="tspan2371" | |
| 1283 | x="156.49219" | |
| 1284 | y="708.2467">CSON</tspan></text> | |
| 1285 | <text | |
| 1286 | xml:space="preserve" | |
| 1287 | style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:16.4059px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:0.933333;stroke:none" | |
| 1288 | x="156.49219" | |
| 1289 | y="688.41504" | |
| 1290 | id="text2377"><tspan | |
| 1291 | sodipodi:role="line" | |
| 1292 | id="tspan2375" | |
| 1293 | x="156.49219" | |
| 1294 | y="688.41504">JSONNET</tspan></text> | |
| 1295 | <text | |
| 1296 | xml:space="preserve" | |
| 1297 | style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:16.4059px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:0.933333;stroke:none" | |
| 1298 | x="156.49219" | |
| 1299 | y="668.24695" | |
| 1300 | id="text2381"><tspan | |
| 1301 | sodipodi:role="line" | |
| 1302 | id="tspan2379" | |
| 1303 | x="156.49219" | |
| 1304 | y="668.24695">JSON5</tspan></text> | |
| 1305 | <text | |
| 1306 | xml:space="preserve" | |
| 1307 | style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:16.4059px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:0.933333;stroke:none" | |
| 1308 | x="156.49219" | |
| 1309 | y="648.07886" | |
| 1310 | id="text2385"><tspan | |
| 1311 | sodipodi:role="line" | |
| 1312 | id="tspan2383" | |
| 1313 | x="156.49219" | |
| 1314 | y="648.07886">JSON</tspan></text> | |
| 1315 | <text | |
| 1316 | xml:space="preserve" | |
| 1317 | style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:16.4059px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:0.933333;stroke:none" | |
| 1318 | x="94.110725" | |
| 1319 | y="648.41534" | |
| 1320 | id="text2389"><tspan | |
| 1321 | sodipodi:role="line" | |
| 1322 | id="tspan2387" | |
| 1323 | x="94.110725" | |
| 1324 | y="648.41534">YAML</tspan></text> | |
| 1325 | <text | |
| 1326 | xml:space="preserve" | |
| 1327 | style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:16.4059px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:0.933333;stroke:none" | |
| 1328 | x="94.110725" | |
| 1329 | y="668.24695" | |
| 1330 | id="text2393"><tspan | |
| 1331 | sodipodi:role="line" | |
| 1332 | id="tspan2391" | |
| 1333 | x="94.110725" | |
| 1334 | y="668.24695">TOML</tspan></text> | |
| 1335 | <text | |
| 1336 | xml:space="preserve" | |
| 1337 | style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:16.4059px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:0.933333;stroke:none" | |
| 1338 | x="94.110725" | |
| 1339 | y="688.41504" | |
| 1340 | id="text2397"><tspan | |
| 1341 | sodipodi:role="line" | |
| 1342 | id="tspan2395" | |
| 1343 | x="94.110725" | |
| 1344 | y="688.41504">XML</tspan></text> | |
| 1345 | </g> | |
| 1346 | <g | |
| 1347 | transform="translate(-1.2304677,-0.85937628)" | |
| 1348 | id="g2593"> | |
| 1349 | <g | |
| 1350 | id="g2532"> | |
| 1351 | <rect | |
| 1352 | id="rect4698" | |
| 1353 | ry="2.7292624" | |
| 1354 | y="91.740654" | |
| 1355 | x="129.16347" | |
| 1356 | height="32.205296" | |
| 1357 | width="54.039394" | |
| 1358 | style="fill:none;stroke:#05556e;stroke-width:2.72926;stroke-opacity:1" /> | |
| 1359 | <path | |
| 1360 | style="fill:#05556e;fill-opacity:1;stroke-width:0.272926" | |
| 1361 | id="path4700" | |
| 1362 | d="M 135.98663,117.12279 V 98.56381 h 5.45852 l 5.45853,6.82315 5.45852,-6.82315 h 5.45853 v 18.55898 h -5.45853 v -10.64412 l -5.45852,6.82315 -5.45853,-6.82315 v 10.64412 z m 34.11578,0 -8.18779,-9.00657 h 5.45852 v -9.55241 h 5.45853 v 9.55241 h 5.45852 z" | |
| 1363 | inkscape:connector-curvature="0" /> | |
| 1364 | </g> | |
| 1365 | <text | |
| 1366 | xml:space="preserve" | |
| 1367 | style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#05556e;fill-opacity:1;stroke:none" | |
| 1368 | x="108.73981" | |
| 1369 | y="152.80437" | |
| 1370 | id="text2407"><tspan | |
| 1371 | sodipodi:role="line" | |
| 1372 | id="tspan2405" | |
| 1373 | x="108.73981" | |
| 1374 | y="152.80437">Markdown</tspan></text> | |
| 1375 | </g> | |
| 1376 | <path | |
| 1377 | inkscape:connector-curvature="0" | |
| 1378 | d="m 417.86562,272.90923 c -2.81873,0.35302 -5.58858,1.78683 -7.90222,4.10047 -1.79226,1.78682 -3.43787,4.20365 -5.01832,7.35911 -1.28173,2.56347 -2.29191,5.21927 -2.90019,7.59265 l -0.1738,0.68975 -0.68975,0.35302 c -0.96673,0.49423 -1.81398,1.01561 -2.77528,1.69993 -3.29666,2.35709 -6.15341,5.19211 -8.53222,8.46705 -0.23354,0.32586 -0.45621,0.58656 -0.49966,0.58656 -0.038,0 -0.33673,-0.0435 -0.65716,-0.0923 -0.73863,-0.11949 -3.19891,-0.13578 -4.11676,-0.0272 -3.79633,0.46164 -7.25593,1.57502 -11.41613,3.68228 -3.00339,1.5207 -4.93685,2.87304 -6.8323,4.77391 -2.37881,2.37882 -3.80176,5.01832 -4.21452,7.82076 -0.0978,0.62457 -0.0978,2.39511 0,3.0414 0.51052,3.55193 2.55804,6.94636 5.27358,8.74404 3.15003,2.08554 7.40256,2.6558 12.27424,1.65105 3.62253,-0.75492 7.20161,-2.14527 10.77526,-4.19822 3.47046,-1.99321 5.87643,-4.18193 7.57093,-6.87575 0.27155,-0.43449 0.35845,-0.52682 0.53224,-0.59199 2.79701,-1.01018 4.74677,-2.05295 6.96265,-3.72572 2.02036,-1.5207 3.43244,-2.85675 6.0991,-5.77324 0.68432,-0.74949 0.8038,-0.91785 0.84182,-1.16225 0.0326,-0.17379 0.0543,-0.20095 0.15207,-0.17922 0.51595,0.10319 2.20502,0.11948 2.94908,0.0272 2.08553,-0.25526 4.05701,-1.10251 6.01763,-2.57976 2.61778,-1.97691 5.06177,-5.27901 6.78885,-9.17853 2.59606,-5.86556 3.57908,-10.80785 3.01425,-15.19073 -0.14121,-1.12423 -0.28241,-1.74881 -0.59742,-2.71554 -0.42905,-1.29803 -1.08621,-2.55804 -1.89001,-3.62796 -0.43449,-0.57026 -1.57502,-1.70536 -2.14528,-2.12898 -1.59131,-1.17855 -3.93753,-2.13442 -6.03936,-2.46028 -0.66259,-0.10319 -2.29735,-0.14664 -2.85132,-0.0815 z m 2.44399,7.82076 c 1.94433,0.46707 3.2152,2.04751 3.5302,4.39917 0.0815,0.58656 0.0815,2.10183 0,2.7427 -0.32043,2.62864 -1.26544,5.70263 -2.61235,8.48878 -1.01561,2.10725 -1.79226,3.34011 -2.88933,4.58383 -0.32587,0.36931 -1.38493,1.31975 -1.42838,1.2763 -0.005,-0.005 0.0706,-0.34216 0.1738,-0.74406 0.24983,-0.97759 0.34215,-1.56958 0.3856,-2.41683 0.0706,-1.58044 -0.27155,-3.09571 -0.98302,-4.30684 -1.20027,-2.05295 -3.17175,-3.41072 -5.47453,-3.78547 -0.11405,-0.0163 -0.20638,-0.0489 -0.20638,-0.076 0,-0.0217 0.19552,-0.53768 0.42905,-1.15139 1.41752,-3.67684 2.66666,-5.83298 4.30142,-7.40799 1.0482,-1.01562 1.70536,-1.40665 2.73726,-1.62933 0.51596,-0.11405 1.49355,-0.0978 2.03666,0.0272 z m -10.34078,17.93885 c 0.52139,0.54311 0.56483,0.76579 0.46164,2.25933 l -0.0326,0.51596 -0.14121,-0.21725 c -0.22811,-0.34215 -0.40733,-0.72233 -0.52682,-1.1188 -0.0652,-0.20095 -0.15207,-0.43992 -0.20095,-0.53224 -0.0706,-0.13035 -0.17922,-0.91243 -0.19008,-1.34691 0,-0.11949 0.29871,0.0923 0.63,0.43991 z m -7.36997,3.01425 c 0.3856,2.28649 1.18397,4.05159 2.44941,5.40393 l 0.45078,0.47793 -0.13577,0.14664 c -0.0706,0.0815 -0.46165,0.51052 -0.86355,0.9613 -1.55328,1.73795 -2.81873,2.98167 -4.05158,3.97012 -0.41819,0.34216 -0.78208,0.61915 -0.79837,0.61915 -0.0163,0 -0.0435,-0.0923 -0.0652,-0.20638 -0.076,-0.4019 -0.46708,-1.4664 -0.8038,-2.15614 -0.54311,-1.12424 -1.14596,-2.0095 -2.08554,-3.0577 l -0.45621,-0.50509 0.41276,-0.50509 c 1.19484,-1.47182 2.92192,-3.26951 4.43177,-4.62728 0.85811,-0.76578 1.37949,-1.21656 1.39578,-1.20027 0.005,0.005 0.0597,0.315 0.11949,0.67888 z m -16.52135,9.77052 c -0.0163,0.11405 -0.0815,0.54311 -0.14664,0.9613 -0.22267,1.47182 -0.23353,3.57365 -0.0272,4.78478 0.19008,1.10251 0.57569,2.11812 1.08078,2.81873 0.27699,0.38018 0.87441,0.97759 1.22199,1.20027 l 0.23354,0.1575 -0.15207,0.12492 c -0.60285,0.48879 -2.54174,1.58044 -4.18193,2.34622 -2.4114,1.12967 -4.36659,1.7651 -6.62049,2.16157 -0.77664,0.13578 -0.99932,0.15207 -2.09096,0.15207 -0.98846,0 -1.30889,-0.0217 -1.67278,-0.0978 -1.5207,-0.33672 -2.53088,-0.97216 -3.1989,-2.0095 -0.53225,-0.82552 -0.72234,-1.48268 -0.72777,-2.43855 0,-1.56415 0.57027,-2.68296 2.17244,-4.27969 1.78682,-1.77597 3.93753,-3.05227 7.72299,-4.5784 2.01493,-0.81467 4.20366,-1.37407 5.75151,-1.4664 0.74406,-0.0434 0.66803,-0.0652 0.63544,0.16294 z m 6.13712,3.5302 c -0.0163,0.0543 -0.0272,0.0109 -0.0272,-0.0923 0,-0.10319 0.0109,-0.14664 0.0272,-0.0978 0.0109,0.0543 0.0109,0.14121 0,0.19009 z" | |
| 1379 | id="path8164" | |
| 1380 | style="fill:#df4d65;fill-opacity:1;stroke:none;stroke-width:0.00543108" /> | |
| 1381 | <g | |
| 1382 | transform="translate(1.378418e-5,1.0193503)" | |
| 1383 | id="g1168"> | |
| 1384 | <text | |
| 1385 | id="text1158" | |
| 1386 | y="364.17905" | |
| 1387 | x="349.05551" | |
| 1388 | style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#05556e;fill-opacity:1;stroke:none" | |
| 1389 | xml:space="preserve"><tspan | |
| 1390 | id="tspan1156" | |
| 1391 | sodipodi:role="line" | |
| 1392 | x="349.05551" | |
| 1393 | y="364.17905">Processor</tspan></text> | |
| 1394 | <text | |
| 1395 | xml:space="preserve" | |
| 1396 | style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#05556e;fill-opacity:1;stroke:none" | |
| 1397 | x="370.40707" | |
| 1398 | y="392.17905" | |
| 1399 | id="text1162"><tspan | |
| 1400 | y="392.17905" | |
| 1401 | x="370.40707" | |
| 1402 | sodipodi:role="line" | |
| 1403 | id="tspan1160">Chain</tspan></text> | |
| 1404 | </g> | |
| 1405 | <g | |
| 1406 | transform="translate(0,-2.3144459)" | |
| 1407 | id="g1206"> | |
| 1408 | <text | |
| 1409 | xml:space="preserve" | |
| 1410 | style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#05556e;fill-opacity:1;stroke:none" | |
| 1411 | x="586.44855" | |
| 1412 | y="327.56967" | |
| 1413 | id="text1190"><tspan | |
| 1414 | y="327.56967" | |
| 1415 | x="586.44855" | |
| 1416 | sodipodi:role="line" | |
| 1417 | id="tspan1188">Processor-</tspan></text> | |
| 1418 | <text | |
| 1419 | id="text1194" | |
| 1420 | y="355.56967" | |
| 1421 | x="588.43488" | |
| 1422 | style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#05556e;fill-opacity:1;stroke:none" | |
| 1423 | xml:space="preserve"><tspan | |
| 1424 | id="tspan1192" | |
| 1425 | sodipodi:role="line" | |
| 1426 | x="588.43488" | |
| 1427 | y="355.56967">dependent</tspan></text> | |
| 1428 | </g> | |
| 1429 | </svg> | |
| 1 | 1430 |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"> | |
| 2 | <title>HTML5 Logo</title> | |
| 3 | <path d="M108.4 0h23v22.8h21.2V0h23v69h-23V46h-21v23h-23.2M206 23h-20.3V0h63.7v23H229v46h-23M259.5 0h24.1l14.8 24.3L313.2 0h24.1v69h-23V34.8l-16.1 24.8l-16.1-24.8v34.2h-22.6M348.7 0h23v46.2h32.6V69h-55.6"/> | |
| 4 | <path fill="#e44d26" d="M107.6 471l-33-370.4h362.8l-33 370.2L255.7 512"/> | |
| 5 | <path fill="#f16529" d="M256 480.5V131H404.3L376 447"/> | |
| 6 | <path fill="#ebebeb" d="M142 176.3h114v45.4h-64.2l4.2 46.5h60v45.3H154.4M156.4 336.3H202l3.2 36.3 50.8 13.6v47.4l-93.2-26"/> | |
| 7 | <path fill="#fff" d="M369.6 176.3H255.8v45.4h109.6M361.3 268.2H255.8v45.4h56l-5.3 59-50.7 13.6v47.2l93-25.8"/> | |
| 8 | </svg> |
| 1 | <?xml version="1.0" standalone="no"?> | |
| 2 | <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" | |
| 3 | "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"> | |
| 4 | <svg version="1.0" xmlns="http://www.w3.org/2000/svg" | |
| 5 | width="1280.000000pt" height="1123.000000pt" viewBox="0 0 1280.000000 1123.000000" | |
| 6 | preserveAspectRatio="xMidYMid meet"> | |
| 7 | <metadata> | |
| 8 | Created by potrace 1.15, written by Peter Selinger 2001-2017 | |
| 9 | </metadata> | |
| 10 | <g transform="translate(0.000000,1123.000000) scale(0.100000,-0.100000)" | |
| 11 | fill="#000000" stroke="none"> | |
| 12 | <path d="M10280 11220 c-519 -65 -1029 -329 -1455 -755 -330 -329 -633 -774 | |
| 13 | -924 -1355 -236 -472 -422 -961 -534 -1398 l-32 -127 -127 -65 c-178 -91 -334 | |
| 14 | -187 -511 -313 -607 -434 -1133 -956 -1571 -1559 -43 -60 -84 -108 -92 -108 | |
| 15 | -7 0 -62 8 -121 17 -136 22 -589 25 -758 5 -699 -85 -1336 -290 -2102 -678 | |
| 16 | -553 -280 -909 -529 -1258 -879 -438 -438 -700 -924 -776 -1440 -18 -115 -18 | |
| 17 | -441 0 -560 94 -654 471 -1279 971 -1610 580 -384 1363 -489 2260 -304 667 | |
| 18 | 139 1326 395 1984 773 639 367 1082 770 1394 1266 50 80 66 97 98 109 515 186 | |
| 19 | 874 378 1282 686 372 280 632 526 1123 1063 126 138 148 169 155 214 6 32 10 | |
| 20 | 37 28 33 95 -19 406 -22 543 -5 384 47 747 203 1108 475 482 364 932 972 1250 | |
| 21 | 1690 478 1080 659 1990 555 2797 -26 207 -52 322 -110 500 -79 239 -200 471 | |
| 22 | -348 668 -80 105 -290 314 -395 392 -293 217 -725 393 -1112 453 -122 19 -423 | |
| 23 | 27 -525 15z m450 -1440 c358 -86 592 -377 650 -810 15 -108 15 -387 0 -505 | |
| 24 | -59 -484 -233 -1050 -481 -1563 -187 -388 -330 -615 -532 -844 -60 -68 -255 | |
| 25 | -243 -263 -235 -1 1 13 63 32 137 46 180 63 289 71 445 13 291 -50 570 -181 | |
| 26 | 793 -221 378 -584 628 -1008 697 -21 3 -38 9 -38 14 0 4 36 99 79 212 261 677 | |
| 27 | 491 1074 792 1364 193 187 314 259 504 300 95 21 275 18 375 -5z m-1904 -3303 | |
| 28 | c96 -100 104 -141 85 -416 l-6 -95 -26 40 c-42 63 -75 133 -97 206 -12 37 -28 | |
| 29 | 81 -37 98 -13 24 -33 168 -35 248 0 22 55 -17 116 -81z m-1357 -555 c71 -421 | |
| 30 | 218 -746 451 -995 l83 -88 -25 -27 c-13 -15 -85 -94 -159 -177 -286 -320 -519 | |
| 31 | -549 -746 -731 -77 -63 -144 -114 -147 -114 -3 0 -8 17 -12 38 -14 74 -86 270 | |
| 32 | -148 397 -100 207 -211 370 -384 563 l-84 93 76 93 c220 271 538 602 816 852 | |
| 33 | 158 141 254 224 257 221 1 -1 11 -58 22 -125z m-3042 -1799 c-3 -21 -15 -100 | |
| 34 | -27 -177 -41 -271 -43 -658 -5 -881 35 -203 106 -390 199 -519 51 -70 161 | |
| 35 | -180 225 -221 l43 -29 -28 -23 c-111 -90 -468 -291 -770 -432 -444 -208 -804 | |
| 36 | -325 -1219 -398 -143 -25 -184 -28 -385 -28 -182 0 -241 4 -308 18 -280 62 | |
| 37 | -466 179 -589 370 -98 152 -133 273 -134 449 0 288 105 494 400 788 329 327 | |
| 38 | 725 562 1422 843 371 150 774 253 1059 270 137 8 123 12 117 -30z m1130 -650 | |
| 39 | c-3 -10 -5 -2 -5 17 0 19 2 27 5 18 2 -10 2 -26 0 -35z"/> | |
| 40 | </g> | |
| 41 | </svg> | |
| 1 | 42 |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="208" height="128" viewBox="0 0 208 128"><rect width="198" height="118" x="5" y="5" ry="10" stroke="#000" stroke-width="10" fill="none"/><path d="M30 98V30h20l20 25 20-25h20v68H90V59L70 84 50 59v39zm125 0l-30-33h20V30h20v35h20z"/></svg> |
| 1 | 1 | |
| 2 | Apache License | |
| 3 | Version 2.0, January 2004 | |
| 4 | http://www.apache.org/licenses/ | |
| 5 | ||
| 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | |
| 7 | ||
| 8 | 1. Definitions. | |
| 9 | ||
| 10 | "Licen[][yyyy] [name of copyright owner] |
| 1 | The MIT License (MIT) | |
| 2 | ||
| 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: | |
| 4 | ||
| 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. | |
| 6 | ||
| 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
| 8 | ||
| 1 | 9 |
| 1 | Released into the Public Domain by David Croft. | |
| 2 | ||
| 3 | http://www.davidc.net/programming/java/java-preferences-using-file-backing-store | |
| 4 | http://creativecommons.org/publicdomain/zero/1.0/ | |
| 5 | ||
| 6 | CC0 1.0 Universal (CC0 1.0) | |
| 7 | ||
| 8 | Public Domain Dedication | |
| 9 | ||
| 10 | This is a human-readable summary of the Legal Code (read the full text). | |
| 11 | ||
| 12 | Disclaimer | |
| 13 | ||
| 14 | No Copyright | |
| 15 | ||
| 16 | * The person who associated a work with this deed has dedicated the work to the public domain by waiving all of his or her rights to the work worldwide under copyright law, including all related and neighboring rights, to the extent allowed by law. | |
| 17 | ||
| 18 | * You can copy, modify, distribute and perform the work, even for commercial purposes, all without asking permission. See Other Information below. | |
| 19 | ||
| 20 | This license is acceptable for Free Cultural Works. | |
| 21 | ||
| 22 | Other Information | |
| 23 | ||
| 24 | * In no way are the patent or trademark rights of any person affected by CC0, nor are the rights that other persons may have in the work or in how the work is used, such as publicity or privacy rights. | |
| 25 | * Unless expressly stated otherwise, the person who associated a work with this deed makes no warranties about the work, and disclaims liability for all uses of the work, to the fullest extent permitted by applicable law. | |
| 26 | * When using or citing the work, you should not imply endorsement by the author or the affirmer. | |
| 27 | ||
| 1 | 28 |
| 1 | Copyright (c) 2015-2016, Atlassian Pty Ltd | |
| 2 | All rights reserved. | |
| 3 | ||
| 4 | Copyright (c) 2016-2018, Vladimir Schneider, | |
| 5 | All rights reserved. | |
| 6 | ||
| 7 | Redistribution and use in source and binary forms, with or without | |
| 8 | modification, are permitted provided that the following conditions are met: | |
| 1 | 9 | |
| 10 | * Redistributions of source code |
| 1 | Copyright (c) 2014, TomasMikula | |
| 2 | All rights reserved. | |
| 3 | ||
| 4 | Redistribution and use in source and binary forms, with or without | |
| 5 | modification, are permitted provided that the following conditions are met: | |
| 1 | 6 | |
| 7 | * Redistributions of source code |
| 1 | 1 | |
| 2 | Apache License | |
| 3 | Version 2.0, January 2004 | |
| 4 | http://www.apache.org/licenses/ | |
| 5 | ||
| 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | |
| 7 | ||
| 8 | 1. Definitions. | |
| 9 | ||
| 10 | "Licen[][yyyy] [name of copyright owner] |
| 1 | Java Image Scaling | |
| 2 | ||
| 3 | Copyright (c) 2013, Morten Nobel-Joergensen | |
| 4 | All rights reserved. | |
| 5 | ||
| 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the | |
| 7 | following conditions are met: | |
| 8 | ||
| 9 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following | |
| 10 | disclaimer. | |
| 11 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following | |
| 12 | disclaimer in the documentation and/or other materials provided with the distribution. | |
| 13 | Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products | |
| 14 | derived from this software without specific prior written permission. | |
| 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, | |
| 16 | INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
| 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| 18 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
| 19 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |
| 20 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| 21 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 1 | 22 |
| 1 | MIT License | |
| 2 | ||
| 3 | Copyright (c) 2019 Raul Garcia | |
| 4 | ||
| 5 | Permission is hereby granted, free of charge, to any person obtaining a copy | |
| 6 | of this software and associated documentation files (the "Software"), to deal | |
| 7 | in the Software without restriction, including without limitation the rights | |
| 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| 9 | copies of the Software, and to permit persons to whom the Software is | |
| 10 | furnished to do so, subject to the following conditions: | |
| 11 | ||
| 12 | The above copyright notice and this permission notice shall be included in all | |
| 13 | copies or substantial portions of the Software. | |
| 14 | ||
| 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
| 21 | SOFTWARE. | |
| 1 | 22 |
| 1 | Version: MPL 1.1/GPL 2.0/LGPL 2.1 | |
| 2 | ||
| 3 | The contents of this file are subject to the Mozilla Public License Version | |
| 4 | 1.1 (the "License"); you may not use this file except in compliance with | |
| 5 | the License. You may obtain a copy of the License at | |
| 6 | http://www.mozilla.org/MPL/ | |
| 7 | ||
| 8 | Software distributed under the License is distributed on an "AS IS" basis, | |
| 9 | WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | |
| 10 | for the specific language governing rights and limitations under the | |
| 11 | License. | |
| 12 | ||
| 13 | The Original Code is Mozilla Universal charset detector code. | |
| 14 | ||
| 15 | The Initial Developer of the Original Code is | |
| 16 | Netscape Communications Corporation. | |
| 17 | Portions created by the Initial Developer are Copyright (C) 2001 | |
| 18 | the Initial Developer. All Rights Reserved. | |
| 19 | ||
| 20 | Contributor(s): | |
| 21 | Alberto Fernández <infjaf@gmail.com> | |
| 22 | Shy Shalom <shooshX@gmail.com> | |
| 23 | Kohei TAKETA <k-tak@void.in> (Java port) | |
| 24 | ||
| 25 | Alternatively, the contents of this file may be used under the terms of | |
| 26 | either the GNU General Public License Version 2 or later (the "GPL"), or | |
| 27 | the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), | |
| 28 | in which case the provisions of the GPL or the LGPL are applicable instead | |
| 29 | of those above. If you wish to allow use of your version of this file only | |
| 30 | under the terms of either the GPL or the LGPL, and not to allow others to | |
| 31 | use your version of this file under the terms of the MPL, indicate your | |
| 32 | decision by deleting the provisions above and replace them with the notice | |
| 33 | and other provisions required by the GPL or the LGPL. If you do not delete | |
| 34 | the provisions above, a recipient may use your version of this file under | |
| 35 | the terms of any one of the MPL, the GPL or the LGPL. | |
| 1 | 36 |
| 1 | Apache License | |
| 2 | Version 2.0, January 2004 | |
| 3 | http://www.apache.org/licenses/ | |
| 4 | ||
| 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | |
| 6 | ||
| 7 | 1. Definitions. | |
| 8 | ||
| 9 | "License" shall mean the terms and conditions for use, reproduction, | |
| 10 | and distribution as defined by Sections 1 through 9 of this document. | |
| 11 | ||
| 12 | "Licensor" shall mean the copyright owner or entity authorized by | |
| 13 | the copyright owner that is granting the License. | |
| 14 | ||
| 15 | "Legal Entity" shall mean the union of the acting entity and all | |
| 16 | other entities that control, are controlled by, or are under common | |
| 17 | control with that entity. For the purposes of this definition, | |
| 18 | "control" means (i) the power, direct or indirect, to cause the | |
| 19 | direction or management of such entity, whether by contract or | |
| 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the | |
| 21 | outstanding shares, or (iii) beneficial ownership of such entity. | |
| 22 | ||
| 23 | "You" (or "Your") shall mean an individual or Legal Entity | |
| 24 | exercising permissions granted by this License. | |
| 25 | ||
| 26 | "Source" form shall mean the preferred form for making modifications, | |
| 27 | including but not limited to software source code, documentation | |
| 28 | source, and configuration files. | |
| 29 | ||
| 30 | "Object" form shall mean any form resulting from mechanical | |
| 31 | transformation or translation of a Source form, including but | |
| 32 | not limited to compiled object code, generated documentation, | |
| 33 | and conversions to other media types. | |
| 34 | ||
| 35 | "Work" shall mean the work of authorship, whether in Source or | |
| 36 | Object form, made available under the License, as indicated by a | |
| 37 | copyright notice that is included in or attached to the work | |
| 38 | (an example is provided in the Appendix below). | |
| 39 | ||
| 40 | "Derivative Works" shall mean any work, whether in Source or Object | |
| 41 | form, that is based on (or derived from) the Work and for which the | |
| 42 | editorial revisions, annotations, elaborations, or other modifications | |
| 43 | represent, as a whole, an original work of authorship. For the purposes | |
| 44 | of this License, Derivative Works shall not include works that remain | |
| 45 | separable from, or merely link (or bind by name) to the interfaces of, | |
| 46 | the Work and Derivative Works thereof. | |
| 47 | ||
| 48 | "Contribution" shall mean any work of authorship, including | |
| 49 | the original version of the Work and any modifications or additions | |
| 50 | to that Work or Derivative Works thereof, that is intentionally | |
| 51 | submitted to Licensor for inclusion in the Work by the copyright owner | |
| 52 | or by an individual or Legal Entity authorized to submit on behalf of | |
| 53 | the copyright owner. For the purposes of this definition, "submitted" | |
| 54 | means any form of electronic, verbal, or written communication sent | |
| 55 | to the Licensor or its representatives, including but not limited to | |
| 56 | communication on electronic mailing lists, source code control systems, | |
| 57 | and issue tracking systems that are managed by, or on behalf of, the | |
| 58 | Licensor for the purpose of discussing and improving the Work, but | |
| 59 | excluding communication that is conspicuously marked or otherwise | |
| 60 | designated in writing by the copyright owner as "Not a Contribution." | |
| 61 | ||
| 62 | "Contributor" shall mean Licensor and any individual or Legal Entity | |
| 63 | on behalf of whom a Contribution has been received by Licensor and | |
| 64 | subsequently incorporated within the Work. | |
| 65 | ||
| 66 | 2. Grant of Copyright License. Subject to the terms and conditions of | |
| 67 | this License, each Contributor hereby grants to You a perpetual, | |
| 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable | |
| 69 | copyright license to reproduce, prepare Derivative Works of, | |
| 70 | publicly display, publicly perform, sublicense, and distribute the | |
| 71 | Work and such Derivative Works in Source or Object form. | |
| 72 | ||
| 73 | 3. Grant of Patent License. Subject to the terms and conditions of | |
| 74 | this License, each Contributor hereby grants to You a perpetual, | |
| 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable | |
| 76 | (except as stated in this section) patent license to make, have made, | |
| 77 | use, offer to sell, sell, import, and otherwise transfer the Work, | |
| 78 | where such license applies only to those patent claims licensable | |
| 79 | by such Contributor that are necessarily infringed by their | |
| 80 | Contribution(s) alone or by combination of their Contribution(s) | |
| 81 | with the Work to which such Contribution(s) was submitted. If You | |
| 82 | institute patent litigation against any entity (including a | |
| 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work | |
| 84 | or a Contribution incorporated within the Work constitutes direct | |
| 85 | or contributory patent infringement, then any patent licenses | |
| 86 | granted to You under this License for that Work shall terminate | |
| 87 | as of the date such litigation is filed. | |
| 88 | ||
| 89 | 4. Redistribution. You may reproduce and distribute copies of the | |
| 90 | Work or Derivative Works thereof in any medium, with or without | |
| 91 | modifications, and in Source or Object form, provided that You | |
| 92 | meet the following conditions: | |
| 93 | ||
| 94 | (a) You must give any other recipients of the Work or | |
| 95 | Derivative Works a copy of this License; and | |
| 96 | ||
| 97 | (b) You must cause any modified files to carry prominent notices | |
| 98 | stating that You changed the files; and | |
| 99 | ||
| 100 | (c) You must retain, in the Source form of any Derivative Works | |
| 101 | that You distribute, all copyright, patent, trademark, and | |
| 102 | attribution notices from the Source form of the Work, | |
| 103 | excluding those notices that do not pertain to any part of | |
| 104 | the Derivative Works; and | |
| 105 | ||
| 106 | (d) If the Work includes a "NOTICE" text file as part of its | |
| 107 | distribution, then any Derivative Works that You distribute must | |
| 108 | include a readable copy of the attribution notices contained | |
| 109 | within such NOTICE file, excluding those notices that do not | |
| 110 | pertain to any part of the Derivative Works, in at least one | |
| 111 | of the following places: within a NOTICE text file distributed | |
| 112 | as part of the Derivative Works; within the Source form or | |
| 113 | documentation, if provided along with the Derivative Works; or, | |
| 114 | within a display generated by the Derivative Works, if and | |
| 115 | wherever such third-party notices normally appear. The contents | |
| 116 | of the NOTICE file are for informational purposes only and | |
| 117 | do not modify the License. You may add Your own attribution | |
| 118 | notices within Derivative Works that You distribute, alongside | |
| 119 | or as an addendum to the NOTICE text from the Work, provided | |
| 120 | that such additional attribution notices cannot be construed | |
| 121 | as modifying the License. | |
| 122 | ||
| 123 | You may add Your own copyright statement to Your modifications and | |
| 124 | may provide additional or different license terms and conditions | |
| 125 | for use, reproduction, or distribution of Your modifications, or | |
| 126 | for any such Derivative Works as a whole, provided Your use, | |
| 127 | reproduction, and distribution of the Work otherwise complies with | |
| 128 | the conditions stated in this License. | |
| 129 | ||
| 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, | |
| 131 | any Contribution intentionally submitted for inclusion in the Work | |
| 132 | by You to the Licensor shall be under the terms and conditions of | |
| 133 | this License, without any additional terms or conditions. | |
| 134 | Notwithstanding the above, nothing herein shall supersede or modify | |
| 135 | the terms of any separate license agreement you may have executed | |
| 136 | with Licensor regarding such Contributions. | |
| 137 | ||
| 138 | 6. Trademarks. This License does not grant permission to use the trade | |
| 139 | names, trademarks, service marks, or product names of the Licensor, | |
| 140 | except as required for reasonable and customary use in describing the | |
| 141 | origin of the Work and reproducing the content of the NOTICE file. | |
| 142 | ||
| 143 | 7. Disclaimer of Warranty. Unless required by applicable law or | |
| 144 | agreed to in writing, Licensor provides the Work (and each | |
| 145 | Contributor provides its Contributions) on an "AS IS" BASIS, | |
| 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | |
| 147 | implied, including, without limitation, any warranties or conditions | |
| 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A | |
| 149 | PARTICULAR PURPOSE. You are solely responsible for determining the | |
| 150 | appropriateness of using or redistributing the Work and assume any | |
| 151 | risks associated with Your exercise of permissions under this License. | |
| 152 | ||
| 153 | 8. Limitation of Liability. In no event and under no legal theory, | |
| 154 | whether in tort (including negligence), contract, or otherwise, | |
| 155 | unless required by applicable law (such as deliberate and grossly | |
| 156 | negligent acts) or agreed to in writing, shall any Contributor be | |
| 157 | liable to You for damages, including any direct, indirect, special, | |
| 158 | incidental, or consequential damages of any character arising as a | |
| 159 | result of this License or out of the use or inability to use the | |
| 160 | Work (including but not limited to damages for loss of goodwill, | |
| 161 | work stoppage, computer failure or malfunction, or any and all | |
| 162 | other commercial damages or losses), even if such Contributor | |
| 163 | has been advised of the possibility of such damages. | |
| 164 | ||
| 165 | 9. Accepting Warranty or Additional Liability. While redistributing | |
| 166 | the Work or Derivative Works thereof, You may choose to offer, | |
| 167 | and charge a fee for, acceptance of support, warranty, indemnity, | |
| 168 | or other liability obligations and/or rights consistent with this | |
| 169 | License. However, in accepting such obligations, You may act only | |
| 170 | on Your own behalf and on Your sole responsibility, not on behalf | |
| 171 | of any other Contributor, and only if You agree to indemnify, | |
| 172 | defend, and hold each Contributor harmless for any liability | |
| 173 | incurred by, or claims asserted against, such Contributor by reason | |
| 174 | of your accepting any such warranty or additional liability. | |
| 175 | ||
| 176 | END OF TERMS AND CONDITIONS | |
| 177 | ||
| 178 | APPENDIX: How to apply the Apache License to your work. | |
| 179 | ||
| 180 | To apply the Apache License to your work, attach the following | |
| 181 | boilerplate notice, with the fields enclosed by brackets "{}" | |
| 182 | replaced with your own identifying information. (Don't include | |
| 183 | the brackets!) The text should be enclosed in the appropriate | |
| 184 | comment syntax for the file format. We also recommend that a | |
| 185 | file or class name and description of purpose be included on the | |
| 186 | same "printed page" as the copyright notice for easier | |
| 187 | identification within third-party archives. | |
| 188 | ||
| 189 | Copyright {yyyy} {name of copyright owner} | |
| 190 | ||
| 191 | Licensed under the Apache License, Version 2.0 (the "License"); | |
| 192 | you may not use this file except in compliance with the License. | |
| 193 | You may obtain a copy of the License at | |
| 194 | ||
| 195 | http://www.apache.org/licenses/LICENSE-2.0 | |
| 196 | ||
| 197 | Unless required by applicable law or agreed to in writing, software | |
| 198 | distributed under the License is distributed on an "AS IS" BASIS, | |
| 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 200 | See the License for the specific language governing permissions and | |
| 201 | limitations under the License. | |
| 1 | 202 |
| 1 | GNU GENERAL PUBLIC LICENSE | |
| 2 | Version 2, June 1991 | |
| 3 | ||
| 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. | |
| 5 | 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
| 6 | Everyone is permitted to copy and distribute verbatim copies | |
| 7 | of this license document, but changing it is not allowed. | |
| 8 | ||
| 9 | Preamble | |
| 10 | ||
| 11 | The licenses for most software are designed to take away your | |
| 12 | freedom to share and change it. By contrast, the GNU General Public | |
| 13 | License is intended to guarantee your freedom to share and change free | |
| 14 | software--to make sure the software is free for all its users. This | |
| 15 | General Public License applies to most of the Free Software | |
| 16 | Foundation's software and to any other program whose authors commit to | |
| 17 | using it. (Some other Free Software Foundation software is covered by | |
| 18 | the GNU Library General Public License instead.) You can apply it to | |
| 19 | your programs, too. | |
| 20 | ||
| 21 | When we speak of free software, we are referring to freedom, not | |
| 22 | price. Our General Public Licenses are designed to make sure that you | |
| 23 | have the freedom to distribute copies of free software (and charge for | |
| 24 | this service if you wish), that you receive source code or can get it | |
| 25 | if you want it, that you can change the software or use pieces of it | |
| 26 | in new free programs; and that you know you can do these things. | |
| 27 | ||
| 28 | To protect your rights, we need to make restrictions that forbid | |
| 29 | anyone to deny you these rights or to ask you to surrender the rights. | |
| 30 | These restrictions translate to certain responsibilities for you if you | |
| 31 | distribute copies of the software, or if you modify it. | |
| 32 | ||
| 33 | For example, if you distribute copies of such a program, whether | |
| 34 | gratis or for a fee, you must give the recipients all the rights that | |
| 35 | you have. You must make sure that they, too, receive or can get the | |
| 36 | source code. And you must show them these terms so they know their | |
| 37 | rights. | |
| 38 | ||
| 39 | We protect your rights with two steps: (1) copyright the software, and | |
| 40 | (2) offer you this license which gives you legal permission to copy, | |
| 41 | distribute and/or modify the software. | |
| 42 | ||
| 43 | Also, for each author's protection and ours, we want to make certain | |
| 44 | that everyone understands that there is no warranty for this free | |
| 45 | software. If the software is modified by someone else and passed on, we | |
| 46 | want its recipients to know that what they have is not the original, so | |
| 47 | that any problems introduced by others will not reflect on the original | |
| 48 | authors' reputations. | |
| 49 | ||
| 50 | Finally, any free program is threatened constantly by software | |
| 51 | patents. We wish to avoid the danger that redistributors of a free | |
| 52 | program will individually obtain patent licenses, in effect making the | |
| 53 | program proprietary. To prevent this, we have made it clear that any | |
| 54 | patent must be licensed for everyone's free use or not licensed at all. | |
| 55 | ||
| 56 | The precise terms and conditions for copying, distribution and | |
| 57 | modification follow. | |
| 58 | ||
| 59 | GNU GENERAL PUBLIC LICENSE | |
| 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION | |
| 61 | ||
| 62 | 0. This License applies to any program or other work which contains | |
| 63 | a notice placed by the copyright holder saying it may be distributed | |
| 64 | under the terms of this General Public License. The "Program", below, | |
| 65 | refers to any such program or work, and a "work based on the Program" | |
| 66 | means either the Program or any derivative work under copyright law: | |
| 67 | that is to say, a work containing the Program or a portion of it, | |
| 68 | either verbatim or with modifications and/or translated into another | |
| 69 | language. (Hereinafter, translation is included without limitation in | |
| 70 | the term "modification".) Each licensee is addressed as "you". | |
| 71 | ||
| 72 | Activities other than copying, distribution and modification are not | |
| 73 | covered by this License; they are outside its scope. The act of | |
| 74 | running the Program is not restricted, and the output from the Program | |
| 75 | is covered only if its contents constitute a work based on the | |
| 76 | Program (independent of having been made by running the Program). | |
| 77 | Whether that is true depends on what the Program does. | |
| 78 | ||
| 79 | 1. You may copy and distribute verbatim copies of the Program's | |
| 80 | source code as you receive it, in any medium, provided that you | |
| 81 | conspicuously and appropriately publish on each copy an appropriate | |
| 82 | copyright notice and disclaimer of warranty; keep intact all the | |
| 83 | notices that refer to this License and to the absence of any warranty; | |
| 84 | and give any other recipients of the Program a copy of this License | |
| 85 | along with the Program. | |
| 86 | ||
| 87 | You may charge a fee for the physical act of transferring a copy, and | |
| 88 | you may at your option offer warranty protection in exchange for a fee. | |
| 89 | ||
| 90 | 2. You may modify your copy or copies of the Program or any portion | |
| 91 | of it, thus forming a work based on the Program, and copy and | |
| 92 | distribute such modifications or work under the terms of Section 1 | |
| 93 | above, provided that you also meet all of these conditions: | |
| 94 | ||
| 95 | a) You must cause the modified files to carry prominent notices | |
| 96 | stating that you changed the files and the date of any change. | |
| 97 | ||
| 98 | b) You must cause any work that you distribute or publish, that in | |
| 99 | whole or in part contains or is derived from the Program or any | |
| 100 | part thereof, to be licensed as a whole at no charge to all third | |
| 101 | parties under the terms of this License. | |
| 102 | ||
| 103 | c) If the modified program normally reads commands interactively | |
| 104 | when run, you must cause it, when started running for such | |
| 105 | interactive use in the most ordinary way, to print or display an | |
| 106 | announcement including an appropriate copyright notice and a | |
| 107 | notice that there is no warranty (or else, saying that you provide | |
| 108 | a warranty) and that users may redistribute the program under | |
| 109 | these conditions, and telling the user how to view a copy of this | |
| 110 | License. (Exception: if the Program itself is interactive but | |
| 111 | does not normally print such an announcement, your work based on | |
| 112 | the Program is not required to print an announcement.) | |
| 113 | ||
| 114 | These requirements apply to the modified work as a whole. If | |
| 115 | identifiable sections of that work are not derived from the Program, | |
| 116 | and can be reasonably considered independent and separate works in | |
| 117 | themselves, then this License, and its terms, do not apply to those | |
| 118 | sections when you distribute them as separate works. But when you | |
| 119 | distribute the same sections as part of a whole which is a work based | |
| 120 | on the Program, the distribution of the whole must be on the terms of | |
| 121 | this License, whose permissions for other licensees extend to the | |
| 122 | entire whole, and thus to each and every part regardless of who wrote it. | |
| 123 | ||
| 124 | Thus, it is not the intent of this section to claim rights or contest | |
| 125 | your rights to work written entirely by you; rather, the intent is to | |
| 126 | exercise the right to control the distribution of derivative or | |
| 127 | collective works based on the Program. | |
| 128 | ||
| 129 | In addition, mere aggregation of another work not based on the Program | |
| 130 | with the Program (or with a work based on the Program) on a volume of | |
| 131 | a storage or distribution medium does not bring the other work under | |
| 132 | the scope of this License. | |
| 133 | ||
| 134 | 3. You may copy and distribute the Program (or a work based on it, | |
| 135 | under Section 2) in object code or executable form under the terms of | |
| 136 | Sections 1 and 2 above provided that you also do one of the following: | |
| 137 | ||
| 138 | a) Accompany it with the complete corresponding machine-readable | |
| 139 | source code, which must be distributed under the terms of Sections | |
| 140 | 1 and 2 above on a medium customarily used for software interchange; or, | |
| 141 | ||
| 142 | b) Accompany it with a written offer, valid for at least three | |
| 143 | years, to give any third party, for a charge no more than your | |
| 144 | cost of physically performing source distribution, a complete | |
| 145 | machine-readable copy of the corresponding source code, to be | |
| 146 | distributed under the terms of Sections 1 and 2 above on a medium | |
| 147 | customarily used for software interchange; or, | |
| 148 | ||
| 149 | c) Accompany it with the information you received as to the offer | |
| 150 | to distribute corresponding source code. (This alternative is | |
| 151 | allowed only for noncommercial distribution and only if you | |
| 152 | received the program in object code or executable form with such | |
| 153 | an offer, in accord with Subsection b above.) | |
| 154 | ||
| 155 | The source code for a work means the preferred form of the work for | |
| 156 | making modifications to it. For an executable work, complete source | |
| 157 | code means all the source code for all modules it contains, plus any | |
| 158 | associated interface definition files, plus the scripts used to | |
| 159 | control compilation and installation of the executable. However, as a | |
| 160 | special exception, the source code distributed need not include | |
| 161 | anything that is normally distributed (in either source or binary | |
| 162 | form) with the major components (compiler, kernel, and so on) of the | |
| 163 | operating system on which the executable runs, unless that component | |
| 164 | itself accompanies the executable. | |
| 165 | ||
| 166 | If distribution of executable or object code is made by offering | |
| 167 | access to copy from a designated place, then offering equivalent | |
| 168 | access to copy the source code from the same place counts as | |
| 169 | distribution of the source code, even though third parties are not | |
| 170 | compelled to copy the source along with the object code. | |
| 171 | ||
| 172 | 4. You may not copy, modify, sublicense, or distribute the Program | |
| 173 | except as expressly provided under this License. Any attempt | |
| 174 | otherwise to copy, modify, sublicense or distribute the Program is | |
| 175 | void, and will automatically terminate your rights under this License. | |
| 176 | However, parties who have received copies, or rights, from you under | |
| 177 | this License will not have their licenses terminated so long as such | |
| 178 | parties remain in full compliance. | |
| 179 | ||
| 180 | 5. You are not required to accept this License, since you have not | |
| 181 | signed it. However, nothing else grants you permission to modify or | |
| 182 | distribute the Program or its derivative works. These actions are | |
| 183 | prohibited by law if you do not accept this License. Therefore, by | |
| 184 | modifying or distributing the Program (or any work based on the | |
| 185 | Program), you indicate your acceptance of this License to do so, and | |
| 186 | all its terms and conditions for copying, distributing or modifying | |
| 187 | the Program or works based on it. | |
| 188 | ||
| 189 | 6. Each time you redistribute the Program (or any work based on the | |
| 190 | Program), the recipient automatically receives a license from the | |
| 191 | original licensor to copy, distribute or modify the Program subject to | |
| 192 | these terms and conditions. You may not impose any further | |
| 193 | restrictions on the recipients' exercise of the rights granted herein. | |
| 194 | You are not responsible for enforcing compliance by third parties to | |
| 195 | this License. | |
| 196 | ||
| 197 | 7. If, as a consequence of a court judgment or allegation of patent | |
| 198 | infringement or for any other reason (not limited to patent issues), | |
| 199 | conditions are imposed on you (whether by court order, agreement or | |
| 200 | otherwise) that contradict the conditions of this License, they do not | |
| 201 | excuse you from the conditions of this License. If you cannot | |
| 202 | distribute so as to satisfy simultaneously your obligations under this | |
| 203 | License and any other pertinent obligations, then as a consequence you | |
| 204 | may not distribute the Program at all. For example, if a patent | |
| 205 | license would not permit royalty-free redistribution of the Program by | |
| 206 | all those who receive copies directly or indirectly through you, then | |
| 207 | the only way you could satisfy both it and this License would be to | |
| 208 | refrain entirely from distribution of the Program. | |
| 209 | ||
| 210 | If any portion of this section is held invalid or unenforceable under | |
| 211 | any particular circumstance, the balance of the section is intended to | |
| 212 | apply and the section as a whole is intended to apply in other | |
| 213 | circumstances. | |
| 214 | ||
| 215 | It is not the purpose of this section to induce you to infringe any | |
| 216 | patents or other property right claims or to contest validity of any | |
| 217 | such claims; this section has the sole purpose of protecting the | |
| 218 | integrity of the free software distribution system, which is | |
| 219 | implemented by public license practices. Many people have made | |
| 220 | generous contributions to the wide range of software distributed | |
| 221 | through that system in reliance on consistent application of that | |
| 222 | system; it is up to the author/donor to decide if he or she is willing | |
| 223 | to distribute software through any other system and a licensee cannot | |
| 224 | impose that choice. | |
| 225 | ||
| 226 | This section is intended to make thoroughly clear what is believed to | |
| 227 | be a consequence of the rest of this License. | |
| 228 | ||
| 229 | 8. If the distribution and/or use of the Program is restricted in | |
| 230 | certain countries either by patents or by copyrighted interfaces, the | |
| 231 | original copyright holder who places the Program under this License | |
| 232 | may add an explicit geographical distribution limitation excluding | |
| 233 | those countries, so that distribution is permitted only in or among | |
| 234 | countries not thus excluded. In such case, this License incorporates | |
| 235 | the limitation as if written in the body of this License. | |
| 236 | ||
| 237 | 9. The Free Software Foundation may publish revised and/or new versions | |
| 238 | of the General Public License from time to time. Such new versions will | |
| 239 | be similar in spirit to the present version, but may differ in detail to | |
| 240 | address new problems or concerns. | |
| 241 | ||
| 242 | Each version is given a distinguishing version number. If the Program | |
| 243 | specifies a version number of this License which applies to it and "any | |
| 244 | later version", you have the option of following the terms and conditions | |
| 245 | either of that version or of any later version published by the Free | |
| 246 | Software Foundation. If the Program does not specify a version number of | |
| 247 | this License, you may choose any version ever published by the Free Software | |
| 248 | Foundation. | |
| 249 | ||
| 250 | 10. If you wish to incorporate parts of the Program into other free | |
| 251 | programs whose distribution conditions are different, write to the author | |
| 252 | to ask for permission. For software which is copyrighted by the Free | |
| 253 | Software Foundation, write to the Free Software Foundation; we sometimes | |
| 254 | make exceptions for this. Our decision will be guided by the two goals | |
| 255 | of preserving the free status of all derivatives of our free software and | |
| 256 | of promoting the sharing and reuse of software generally. | |
| 257 | ||
| 258 | NO WARRANTY | |
| 259 | ||
| 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY | |
| 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN | |
| 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES | |
| 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED | |
| 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
| 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS | |
| 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE | |
| 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, | |
| 268 | REPAIR OR CORRECTION. | |
| 269 | ||
| 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING | |
| 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR | |
| 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, | |
| 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING | |
| 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED | |
| 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY | |
| 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER | |
| 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE | |
| 278 | POSSIBILITY OF SUCH DAMAGES. | |
| 279 | ||
| 280 | END OF TERMS AND CONDITIONS | |
| 281 | ||
| 282 | How to Apply These Terms to Your New Programs | |
| 283 | ||
| 284 | If you develop a new program, and you want it to be of the greatest | |
| 285 | possible use to the public, the best way to achieve this is to make it | |
| 286 | free software which everyone can redistribute and change under these terms. | |
| 287 | ||
| 288 | To do so, attach the following notices to the program. It is safest | |
| 289 | to attach them to the start of each source file to most effectively | |
| 290 | convey the exclusion of warranty; and each file should have at least | |
| 291 | the "copyright" line and a pointer to where the full notice is found. | |
| 292 | ||
| 293 | <one line to give the program's name and a brief idea of what it does.> | |
| 294 | Copyright (C) <year> <name of author> | |
| 295 | ||
| 296 | This program is free software; you can redistribute it and/or modify | |
| 297 | it under the terms of the GNU General Public License as published by | |
| 298 | the Free Software Foundation; either version 2 of the License, or | |
| 299 | (at your option) any later version. | |
| 300 | ||
| 301 | This program is distributed in the hope that it will be useful, | |
| 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 304 | GNU General Public License for more details. | |
| 305 | ||
| 306 | You should have received a copy of the GNU General Public License | |
| 307 | along with this program; if not, write to the Free Software | |
| 308 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
| 309 | ||
| 310 | ||
| 311 | Also add information on how to contact you by electronic and paper mail. | |
| 312 | ||
| 313 | If the program is interactive, make it output a short notice like this | |
| 314 | when it starts in an interactive mode: | |
| 315 | ||
| 316 | Gnomovision version 69, Copyright (C) year name of author | |
| 317 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. | |
| 318 | This is free software, and you are welcome to redistribute it | |
| 319 | under certain conditions; type `show c' for details. | |
| 320 | ||
| 321 | The hypothetical commands `show w' and `show c' should show the appropriate | |
| 322 | parts of the General Public License. Of course, the commands you use may | |
| 323 | be called something other than `show w' and `show c'; they could even be | |
| 324 | mouse-clicks or menu items--whatever suits your program. | |
| 325 | ||
| 326 | You should also get your employer (if you work as a programmer) or your | |
| 327 | school, if any, to sign a "copyright disclaimer" for the program, if | |
| 328 | necessary. Here is a sample; alter the names: | |
| 329 | ||
| 330 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program | |
| 331 | `Gnomovision' (which makes passes at compilers) written by James Hacker. | |
| 332 | ||
| 333 | <signature of Ty Coon>, 1 April 1989 | |
| 334 | Ty Coon, President of Vice | |
| 335 | ||
| 336 | This General Public License does not permit incorporating your program into | |
| 337 | proprietary programs. If your program is a subroutine library, you may | |
| 338 | consider it more useful to permit linking proprietary applications with the | |
| 339 | library. If this is what you want to do, use the GNU Library General | |
| 340 | Public License instead of this License. | |
| 1 | 341 |
| 1 | Copyright (c) 2013-2017, Tomas Mikula and contributors | |
| 2 | All rights reserved. | |
| 3 | ||
| 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: | |
| 1 | 5 | |
| 6 | 1. Redistributions of source code. | |
| 7 | COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS |
| 1 | Copyright (c) 2014, TomasMikula | |
| 2 | All rights reserved. | |
| 3 | ||
| 4 | Redistribution and use in source and binary forms, with or without modification, | |
| 5 | are permitted provided that the following conditions are met: | |
| 6 | ||
| 7 | * Redistributions of source code | |
| 8 | . | |
| 9 | ||
| 10 | * | |
| 11 | ||
| 12 | ||
| 13 | ||
| 14 | ||
| 15 | ||
| 16 | ||
| 17 | ( | |
| 18 | ||
| 19 | ||
| 20 | ||
| 1 | 21 |
| 1 | Copyright (c) 2014, TomasMikula | |
| 2 | All rights reserved. | |
| 3 | ||
| 4 | Redistribution and use in source and binary forms, with or without | |
| 5 | modification, are permitted provided that the following conditions are met: | |
| 6 | ||
| 7 | * Redistributions of source code | |
| 8 | . | |
| 9 | ||
| 10 | * | |
| 11 | ||
| 12 | ||
| 13 | ||
| 14 | ||
| 15 | ||
| 16 | ||
| 17 | ||
| 18 | ||
| 19 | ||
| 20 | ||
| 21 | ||
| 1 | 22 |
| 1 | URL: https://github.com/googlefonts/noto-cjk | |
| 2 | ||
| 3 | Version: 1.002 or later | |
| 4 | ||
| 5 | License: SIL Open Font License v1.1 | |
| 6 | ||
| 7 | License File: LICENSE | |
| 8 | ||
| 9 | Note: prior releases of the CJK fonts were issued under the Apache 2 | |
| 10 | license. This was changed to the SIL OFL v1.1 starting with Version 1.002. | |
| 11 | ||
| 12 | Description: | |
| 13 | Noto CJK fonts, supporting Simplified Chinese, Traditional Chinese, | |
| 14 | Japanese, and Korean. The supported scripts are Han, Hiragana, Katakana, | |
| 15 | Hangul, and Bopomofo. Latin, Greek, Cyrillic, and various symbols are also | |
| 16 | supported for compatibility with CJK standards. | |
| 17 | ||
| 18 | The fonts in this directory are developed by Google and Adobe and are | |
| 19 | released as open source under the Apache license version 2.0. The copyright | |
| 20 | is held by Adobe, while the trademarks on the names are held by Google. | |
| 21 | ||
| 22 | A README-formats file has been added explaining the different formats | |
| 23 | provided and their features and limitations. | |
| 1 | 24 |
| 1 | 1 | |
| 2 | Apache License | |
| 3 | Version 2.0, January 2004 | |
| 4 | http://www.apache.org/licenses/ | |
| 5 | ||
| 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | |
| 7 | ||
| 8 | 1. Definitions. | |
| 9 | ||
| 10 | "Licen[][yyyy] [name of copyright owner] |
| 1 | Copyright 2018 The Noto Project Authors (https://github.com/googlei18n/noto-fonts) | |
| 2 | ||
| 3 | This Font Software is licensed under the SIL Open Font License, | |
| 4 | Version 1.1. | |
| 1 | 5 | |
| 6 | This license is cop |
| 1 | Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. | |
| 1 | 2 | |
| 3 | This Font Software is licensed under the SIL Open Font License, Version | |
| 4 |
| 1 | Copyright 2014-2019 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe in the United States and/or other countries. | |
| 2 | ||
| 3 | This Font Software is licensed under the SIL Open Font License, Version 1.1. | |
| 4 | ||
| 5 | This license is cop | |
| 6 | creation | |
| 7 | provide a free and | |
| 8 | improved in partnership | |
| 9 | ||
| 10 | to components as | |
| 11 | deleting, | |
| 12 | components of the | |
| 13 | the Font Software to a | |
| 14 | modify, | |
| 15 | ||
| 16 | in corresponding | |
| 17 | primary font name as | |
| 1 | 18 | |
| 19 | using |
| 1 | Merriweather Sans ExtraBold Italic | |
| 2 | ||
| 3 | https://github.com/SorkinType/Merriweather-Sans/blob/master/fonts/otf/MerriweatherSans-ExtraBoldItalic.otf | |
| 4 | ||
| 5 | Weight 800 | |
| 6 | ||
| 7 | https://fonts.google.com/specimen/Merriweather+Sans | |
| 8 | ||
| 1 | 9 |
| 1 | ||
| 1 | <?xml version="1.0" encoding="UTF-8" standalone="no" ?> | |
| 2 | <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> | |
| 3 | <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="1280" height="1024" viewBox="0 0 1280 1024" xml:space="preserve"> | |
| 4 | <desc>Created with Fabric.js 3.6.3</desc> | |
| 5 | <defs> | |
| 6 | </defs> | |
| 7 | <g transform="matrix(1.9692780337941629 0 0 1.9692780337941629 640.0153846153846 512.012312418764)" id="background-logo" > | |
| 8 | <rect style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(255,255,255); fill-rule: nonzero; opacity: 1;" paint-order="stroke" x="-325" y="-260" rx="0" ry="0" width="650" height="520" /> | |
| 9 | </g> | |
| 10 | <g transform="matrix(1.9692780337941629 0 0 1.9692780337941629 640.0170725174504 420.4016715831266)" id="logo-logo" > | |
| 11 | <g style="" paint-order="stroke" > | |
| 12 | <g transform="matrix(2.537 0 0 -2.537 -86.35385711719567 85.244912)" > | |
| 13 | <linearGradient id="SVGID_1_302284" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-24.348526 -27.478867 -27.478867 24.348526 138.479 129.67187)" x1="0" y1="0" x2="1" y2="0"> | |
| 14 | <stop offset="0%" style="stop-color:rgb(245,132,41);stop-opacity: 1"/> | |
| 15 | <stop offset="100%" style="stop-color:rgb(251,173,23);stop-opacity: 1"/> | |
| 16 | </linearGradient> | |
| 17 | <path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: url(#SVGID_1_302284); fill-rule: nonzero; opacity: 1;" paint-order="stroke" transform=" translate(-127.92674550729492, -117.16399999999999)" d="m 118.951 124.648 c -9.395 -14.441 -5.243 -20.693 -5.243 -20.693 v 0 c 0 0 6.219 9.126 9.771 5.599 v 0 c 3.051 -3.023 -2.415 -8.668 -2.415 -8.668 v 0 c 0 0 33.24 13.698 17.995 28.872 v 0 c 0 0 -3.203 3.683 -7.932 3.684 v 0 c -3.46 0 -7.736 -1.97 -12.176 -8.794" stroke-linecap="round" /> | |
| 18 | </g> | |
| 19 | <g transform="matrix(2.537 0 0 -2.537 -84.52085711719567 70.2729119999999)" > | |
| 20 | <path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(250,220,153); fill-rule: nonzero; opacity: 1;" paint-order="stroke" transform=" translate(11.9895, -1.2609990716440347)" d="m 0 0 c 0 0 -6.501 6.719 -11.093 5.443 c -5.584 -1.545 -12.886 -12.078 -12.886 -12.078 c 0 0 5.98 16.932 15.29 15.731 C -1.19 8.127 0 0 0 0" stroke-linecap="round" /> | |
| 21 | </g> | |
| 22 | <g transform="matrix(2.537 0 0 -2.537 -22.327857117195663 48.729911999999956)" > | |
| 23 | <path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(201,158,82); fill-rule: nonzero; opacity: 1;" paint-order="stroke" transform=" translate(-4.189, -10.432)" d="m 0 0 l -0.87 16.89 l 3.995 3.974 l 6.123 -6.156 z" stroke-linecap="round" /> | |
| 24 | </g> | |
| 25 | <g transform="matrix(2.537 0 0 -2.537 -11.3118571171957 24.124911999999966)" > | |
| 26 | <path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(201,158,82); fill-rule: nonzero; opacity: 1;" paint-order="stroke" transform=" translate(4.0955, -2.037)" d="m 0 0 l -2.081 -2.069 l -6.11 6.143 l 2.081 2.069 z" stroke-linecap="round" /> | |
| 27 | </g> | |
| 28 | <g transform="matrix(2.537 0 0 -2.537 46.27614288280432 -57.96708800000005)" > | |
| 29 | <path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(217,170,93); fill-rule: nonzero; opacity: 1;" paint-order="stroke" transform=" translate(12.070999999999998, 9.599000000000004)" d="m 0 0 c -1.226 0.69 -2.81 0.523 -3.862 -0.524 c -1.275 -1.268 -1.28 -3.33 -0.013 -4.604 l -31.681 -31.501 l -6.11 6.143 c 19.224 19.305 25.369 35.582 25.369 35.582 c 15.857 2.364 27.851 8.624 33.821 12.335 z" stroke-linecap="round" /> | |
| 30 | </g> | |
| 31 | <g transform="matrix(2.537 0 0 -2.537 -26.842857117195706 8.501911999999976)" > | |
| 32 | <path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(217,170,93); fill-rule: nonzero; opacity: 1;" paint-order="stroke" transform=" translate(4.1075, -2.0525)" d="M 0 0 L -2.081 -2.069 L -8.215 4.11 L -6.141 6.174 Z" stroke-linecap="round" /> | |
| 33 | </g> | |
| 34 | <g transform="matrix(2.537 0 0 -2.537 -51.495857117195726 19.491911999999985)" > | |
| 35 | <path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(217,170,93); fill-rule: nonzero; opacity: 1;" paint-order="stroke" transform=" translate(10.434000000000001, -1.0939999999999994)" d="m 0 0 l -3.995 -3.974 l -16.873 0.96 l 14.752 9.176 z" stroke-linecap="round" /> | |
| 36 | </g> | |
| 37 | <g transform="matrix(2.537 0 0 -2.537 55.72014288280434 -48.441088000000036)" > | |
| 38 | <path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(201,158,82); fill-rule: nonzero; opacity: 1;" paint-order="stroke" transform=" translate(9.671499999999998, 11.999499999999998)" d="M 0 0 L 17.536 17.443 C 13.788 11.486 7.47 -0.468 5.021 -16.312 c 0 0 -15.526 -6.982 -35.765 -25.13 l -6.135 6.168 l 31.681 31.5 c 1.273 -1.28 3.33 -1.279 4.604 -0.012 C 0.435 -2.764 0.629 -1.223 0 0" stroke-linecap="round" /> | |
| 39 | </g> | |
| 40 | </g> | |
| 41 | </g> | |
| 42 | <g transform="matrix(1.9692780337941629 0 0 1.9692780337941629 643.7363123827618 766.1975713477327)" id="text-logo-path" > | |
| 43 | <path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(247,149,33); fill-rule: nonzero; opacity: 1;" paint-order="stroke" transform=" translate(-186.83999999999997, 27.08)" d="M 4.47 -6.1 L 4.47 -6.1 L 4.47 -47.5 Q 4.47 -50.27 6.43 -52.23 Q 8.39 -54.19 11.16 -54.19 L 11.16 -54.19 Q 14.01 -54.19 15.95 -52.23 Q 17.89 -50.27 17.89 -47.5 L 17.89 -47.5 L 17.89 -30.09 L 34.95 -51.97 Q 35.74 -52.97 36.94 -53.58 Q 38.13 -54.19 39.42 -54.19 L 39.42 -54.19 Q 41.77 -54.19 43.42 -52.5 Q 45.07 -50.82 45.07 -48.5 L 45.07 -48.5 Q 45.07 -46.46 43.82 -44.93 L 43.82 -44.93 L 32.93 -31.44 L 46.8 -9.81 Q 47.84 -8.11 47.84 -6.27 L 47.84 -6.27 Q 47.84 -3.33 45.9 -1.39 Q 43.96 0.55 41.19 0.55 L 41.19 0.55 Q 39.42 0.55 37.89 -0.29 Q 36.37 -1.14 35.43 -2.57 L 35.43 -2.57 L 23.78 -21.15 L 17.89 -13.9 L 17.89 -6.1 Q 17.89 -3.33 15.93 -1.39 Q 13.97 0.55 11.16 0.55 L 11.16 0.55 Q 8.39 0.55 6.43 -1.39 Q 4.47 -3.33 4.47 -6.1 Z M 50.27 -19.24 L 50.27 -19.24 Q 50.27 -25.13 52.71 -29.78 Q 55.16 -34.43 59.7 -37.06 Q 64.24 -39.69 70.27 -39.69 L 70.27 -39.69 Q 76.37 -39.69 80.78 -37.09 Q 85.18 -34.49 87.43 -30.32 Q 89.69 -26.14 89.69 -21.6 L 89.69 -21.6 Q 89.69 -18.69 88.33 -17.26 Q 86.98 -15.84 83.86 -15.84 L 83.86 -15.84 L 62.89 -15.84 Q 63.23 -12.38 65.38 -10.31 Q 67.53 -8.25 70.86 -8.25 L 70.86 -8.25 Q 72.84 -8.25 74.19 -8.91 Q 75.54 -9.57 76.62 -10.64 L 76.62 -10.64 Q 77.62 -11.58 78.42 -12.03 Q 79.22 -12.48 80.43 -12.48 L 80.43 -12.48 Q 82.61 -12.48 84.19 -10.89 Q 85.77 -9.29 85.77 -7.04 L 85.77 -7.04 Q 85.77 -4.54 83.62 -2.77 L 83.62 -2.77 Q 81.71 -1.14 78.16 -0.03 Q 74.61 1.07 70.58 1.07 L 70.58 1.07 Q 64.76 1.07 60.13 -1.42 Q 55.5 -3.92 52.89 -8.53 Q 50.27 -13.14 50.27 -19.24 Z M 62.96 -23.57 L 62.96 -23.57 L 76.96 -23.57 Q 76.82 -26.97 74.93 -28.97 Q 73.05 -30.96 70.06 -30.96 L 70.06 -30.96 Q 67.08 -30.96 65.21 -28.97 Q 63.34 -26.97 62.96 -23.57 Z M 91.63 -19.24 L 91.63 -19.24 Q 91.63 -25.13 94.07 -29.78 Q 96.52 -34.43 101.06 -37.06 Q 105.6 -39.69 111.63 -39.69 L 111.63 -39.69 Q 117.73 -39.69 122.14 -37.09 Q 126.54 -34.49 128.79 -30.32 Q 131.04 -26.14 131.04 -21.6 L 131.04 -21.6 Q 131.04 -18.69 129.69 -17.26 Q 128.34 -15.84 125.22 -15.84 L 125.22 -15.84 L 104.25 -15.84 Q 104.59 -12.38 106.74 -10.31 Q 108.89 -8.25 112.22 -8.25 L 112.22 -8.25 Q 114.2 -8.25 115.55 -8.91 Q 116.9 -9.57 117.98 -10.64 L 117.98 -10.64 Q 118.98 -11.58 119.78 -12.03 Q 120.58 -12.48 121.79 -12.48 L 121.79 -12.48 Q 123.97 -12.48 125.55 -10.89 Q 127.13 -9.29 127.13 -7.04 L 127.13 -7.04 Q 127.13 -4.54 124.98 -2.77 L 124.98 -2.77 Q 123.07 -1.14 119.52 -0.03 Q 115.96 1.07 111.94 1.07 L 111.94 1.07 Q 106.12 1.07 101.49 -1.42 Q 96.86 -3.92 94.24 -8.53 Q 91.63 -13.14 91.63 -19.24 Z M 104.32 -23.57 L 104.32 -23.57 L 118.32 -23.57 Q 118.18 -26.97 116.29 -28.97 Q 114.4 -30.96 111.42 -30.96 L 111.42 -30.96 Q 108.44 -30.96 106.57 -28.97 Q 104.7 -26.97 104.32 -23.57 Z M 135.03 -6.03 L 135.03 -6.03 L 135.03 -33.14 Q 135.03 -35.64 136.85 -37.46 Q 138.67 -39.28 141.13 -39.28 L 141.13 -39.28 Q 143.7 -39.28 145.52 -37.46 Q 147.34 -35.64 147.34 -33.14 L 147.34 -33.14 L 147.34 -32.17 Q 148.97 -35.36 152.09 -37.42 Q 155.21 -39.49 159.82 -39.49 L 159.82 -39.49 Q 166.93 -39.49 170.19 -35.47 Q 173.44 -31.44 173.44 -24.44 L 173.44 -24.44 L 173.44 -6.03 Q 173.44 -3.33 171.5 -1.39 Q 169.56 0.55 166.86 0.55 L 166.86 0.55 Q 164.15 0.55 162.19 -1.39 Q 160.24 -3.33 160.24 -6.03 L 160.24 -6.03 L 160.24 -22.36 Q 160.24 -26.35 158.54 -27.91 Q 156.84 -29.47 154.65 -29.47 L 154.65 -29.47 Q 152.02 -29.47 150.13 -27.58 Q 148.24 -25.69 148.24 -20.73 L 148.24 -20.73 L 148.24 -6.03 Q 148.24 -3.33 146.3 -1.39 Q 144.36 0.55 141.65 0.55 L 141.65 0.55 Q 138.95 0.55 136.99 -1.39 Q 135.03 -3.33 135.03 -6.03 Z M 177.71 -47.56 L 177.71 -47.56 Q 177.71 -50.34 179.63 -52.26 Q 181.56 -54.19 184.23 -54.19 L 184.23 -54.19 Q 186.58 -54.19 188.39 -52.73 Q 190.19 -51.27 190.71 -48.99 L 190.71 -48.99 L 197.88 -15.12 L 206.52 -48.64 Q 207.07 -51.07 209.12 -52.63 Q 211.16 -54.19 213.69 -54.19 L 213.69 -54.19 Q 216.26 -54.19 218.25 -52.57 Q 220.25 -50.96 220.8 -48.64 L 220.8 -48.64 L 229.4 -15.39 L 236.64 -49.33 Q 237.06 -51.38 238.76 -52.78 Q 240.46 -54.19 242.61 -54.19 L 242.61 -54.19 Q 245.17 -54.19 246.94 -52.4 Q 248.71 -50.62 248.71 -48.05 L 248.71 -48.05 Q 248.71 -47.56 248.57 -46.73 L 248.57 -46.73 L 239.69 -7.38 Q 238.9 -3.99 236.11 -1.72 Q 233.32 0.55 229.68 0.55 L 229.68 0.55 Q 226.14 0.55 223.37 -1.61 Q 220.59 -3.78 219.73 -7.11 L 219.73 -7.11 L 213.07 -33.45 L 206.38 -7.11 Q 205.51 -3.71 202.79 -1.58 Q 200.07 0.55 196.53 0.55 L 196.53 0.55 Q 192.89 0.55 190.17 -1.72 Q 187.45 -3.99 186.65 -7.38 L 186.65 -7.38 L 177.85 -46.14 Q 177.71 -47.15 177.71 -47.56 Z M 253.35 -6.03 L 253.35 -6.03 L 253.35 -33.14 Q 253.35 -35.64 255.17 -37.46 Q 256.99 -39.28 259.46 -39.28 L 259.46 -39.28 Q 262.02 -39.28 263.84 -37.46 Q 265.66 -35.64 265.66 -33.14 L 265.66 -33.14 L 265.66 -31.44 L 265.94 -31.44 Q 266.8 -33.56 268.1 -35.24 Q 269.4 -36.92 270.69 -37.61 L 270.69 -37.61 Q 271.9 -38.24 273.46 -38.27 L 273.46 -38.27 Q 276.65 -38.27 278.14 -36.45 Q 279.63 -34.63 279.63 -32.52 L 279.63 -32.52 Q 279.63 -30.33 278.11 -28.62 Q 276.58 -26.9 274.08 -26.9 L 274.08 -26.9 Q 272.59 -26.9 271.07 -26.26 Q 269.54 -25.62 268.47 -24.34 L 268.47 -24.34 Q 266.56 -21.98 266.56 -17.68 L 266.56 -17.68 L 266.56 -6.03 Q 266.56 -3.33 264.62 -1.39 Q 262.68 0.55 259.98 0.55 L 259.98 0.55 Q 257.27 0.55 255.31 -1.39 Q 253.35 -3.33 253.35 -6.03 Z M 282.41 -49.71 L 282.41 -49.71 Q 282.41 -52 284.03 -53.61 Q 285.66 -55.23 287.95 -55.23 L 287.95 -55.23 L 291.21 -55.23 Q 293.5 -55.23 295.13 -53.6 Q 296.76 -51.97 296.76 -49.71 L 296.76 -49.71 Q 296.76 -47.43 295.11 -45.8 Q 293.46 -44.17 291.21 -44.17 L 291.21 -44.17 L 287.95 -44.17 Q 285.66 -44.17 284.03 -45.8 Q 282.41 -47.43 282.41 -49.71 Z M 282.96 -6.03 L 282.96 -6.03 L 282.96 -32.66 Q 282.96 -35.36 284.92 -37.32 Q 286.88 -39.28 289.58 -39.28 L 289.58 -39.28 Q 292.29 -39.28 294.23 -37.32 Q 296.17 -35.36 296.17 -32.66 L 296.17 -32.66 L 296.17 -6.03 Q 296.17 -3.33 294.21 -1.39 Q 292.25 0.55 289.58 0.55 L 289.58 0.55 Q 286.88 0.55 284.92 -1.39 Q 282.96 -3.33 282.96 -6.03 Z M 299.43 -34.29 L 299.43 -34.29 Q 299.43 -36.12 300.71 -37.41 Q 301.99 -38.69 303.76 -38.69 L 303.76 -38.69 L 306.19 -38.69 L 306.46 -43.96 Q 306.6 -46.32 308.34 -47.98 Q 310.07 -49.64 312.5 -49.64 L 312.5 -49.64 Q 314.99 -49.64 316.76 -47.86 Q 318.53 -46.07 318.53 -43.58 L 318.53 -43.58 L 318.53 -38.69 L 322.72 -38.69 Q 324.49 -38.69 325.77 -37.41 Q 327.06 -36.12 327.06 -34.36 L 327.06 -34.36 Q 327.06 -32.52 325.77 -31.24 Q 324.49 -29.95 322.72 -29.95 L 322.72 -29.95 L 318.81 -29.95 L 318.81 -14.14 Q 318.81 -11.23 320.05 -10.02 Q 321.3 -8.81 323.83 -8.81 L 323.83 -8.81 Q 325.46 -8.46 326.61 -7.14 Q 327.75 -5.82 327.75 -4.06 L 327.75 -4.06 Q 327.75 -2.57 326.94 -1.39 Q 326.12 -0.21 324.84 0.35 L 324.84 0.35 Q 322 0.83 318.11 0.87 L 318.11 0.87 Q 311.28 0.9 308.44 -2.5 L 308.44 -2.5 Q 305.67 -5.79 305.67 -12.65 L 305.67 -12.65 Q 305.67 -12.83 305.67 -13 L 305.67 -13 L 305.74 -29.95 L 303.76 -29.95 Q 301.99 -29.95 300.71 -31.24 Q 299.43 -32.52 299.43 -34.29 Z M 329.8 -19.24 L 329.8 -19.24 Q 329.8 -25.13 332.24 -29.78 Q 334.68 -34.43 339.23 -37.06 Q 343.77 -39.69 349.8 -39.69 L 349.8 -39.69 Q 355.9 -39.69 360.3 -37.09 Q 364.71 -34.49 366.96 -30.32 Q 369.21 -26.14 369.21 -21.6 L 369.21 -21.6 Q 369.21 -18.69 367.86 -17.26 Q 366.51 -15.84 363.39 -15.84 L 363.39 -15.84 L 342.42 -15.84 Q 342.76 -12.38 344.91 -10.31 Q 347.06 -8.25 350.39 -8.25 L 350.39 -8.25 Q 352.37 -8.25 353.72 -8.91 Q 355.07 -9.57 356.14 -10.64 L 356.14 -10.64 Q 357.15 -11.58 357.95 -12.03 Q 358.74 -12.48 359.96 -12.48 L 359.96 -12.48 Q 362.14 -12.48 363.72 -10.89 Q 365.3 -9.29 365.3 -7.04 L 365.3 -7.04 Q 365.3 -4.54 363.15 -2.77 L 363.15 -2.77 Q 361.24 -1.14 357.69 -0.03 Q 354.13 1.07 350.11 1.07 L 350.11 1.07 Q 344.29 1.07 339.66 -1.42 Q 335.03 -3.92 332.41 -8.53 Q 329.8 -13.14 329.8 -19.24 Z M 342.48 -23.57 L 342.48 -23.57 L 356.49 -23.57 Q 356.35 -26.97 354.46 -28.97 Q 352.57 -30.96 349.59 -30.96 L 349.59 -30.96 Q 346.61 -30.96 344.74 -28.97 Q 342.87 -26.97 342.48 -23.57 Z" stroke-linecap="round" /> | |
| 44 | </g> | |
| 45 | </svg> |
| 1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> | |
| 2 | <svg | |
| 3 | xmlns:dc="http://purl.org/dc/elements/1.1/" | |
| 4 | xmlns:cc="http://creativecommons.org/ns#" | |
| 5 | xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | |
| 6 | xmlns:svg="http://www.w3.org/2000/svg" | |
| 7 | xmlns="http://www.w3.org/2000/svg" | |
| 8 | xmlns:xlink="http://www.w3.org/1999/xlink" | |
| 9 | xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | |
| 10 | xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | |
| 11 | height="197.4767" | |
| 12 | viewBox="0 0 695.99768 197.4767" | |
| 13 | width="695.99768" | |
| 14 | version="1.1" | |
| 15 | id="svg37" | |
| 16 | sodipodi:docname="new-logo-text.svg" | |
| 17 | inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)"> | |
| 18 | <metadata | |
| 19 | id="metadata43"> | |
| 20 | <rdf:RDF> | |
| 21 | <cc:Work | |
| 22 | rdf:about=""> | |
| 23 | <dc:format>image/svg+xml</dc:format> | |
| 24 | <dc:type | |
| 25 | rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | |
| 26 | <dc:title></dc:title> | |
| 27 | </cc:Work> | |
| 28 | </rdf:RDF> | |
| 29 | </metadata> | |
| 30 | <defs | |
| 31 | id="defs41"> | |
| 32 | <linearGradient | |
| 33 | id="a" | |
| 34 | gradientTransform="matrix(-8.7796153,42.985832,-42.985832,-8.7796153,514.83476,136.06192)" | |
| 35 | gradientUnits="userSpaceOnUse" | |
| 36 | x1=".152358" | |
| 37 | x2=".968809" | |
| 38 | y1="-.044912" | |
| 39 | y2="-.049471"> | |
| 40 | <stop | |
| 41 | offset="0" | |
| 42 | stop-color="#ec706a" | |
| 43 | id="stop2" /> | |
| 44 | <stop | |
| 45 | offset="1" | |
| 46 | stop-color="#ecd980" | |
| 47 | id="stop4" /> | |
| 48 | </linearGradient> | |
| 49 | </defs> | |
| 50 | <path | |
| 51 | style="fill:url(#a);fill-opacity:1.0;fill-rule:nonzero;stroke:none;stroke-width:1.226;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0" | |
| 52 | paint-order="stroke" | |
| 53 | d="m 496.76229,150.80474 c -4.25368,20.68081 3.28191,25.95476 3.28191,25.95476 v 0 c 0,0 3.00963,-13.19543 8.64082,-10.76172 v 0 c 4.83401,2.08299 1.12516,10.97002 1.12516,10.97002 v 0 c 0,0 31.78993,-30.5076 7.60484,-40.99434 v 0 c 0,0 -5.30287,-2.76791 -10.69842,-0.65209 v 0 c -3.94735,1.54891 -7.94375,5.71058 -9.95431,15.48337" | |
| 54 | stroke-linecap="round" | |
| 55 | id="path14" /> | |
| 56 | <path | |
| 57 | d="m 530.80335,138.63592 -10.99206,-16.95952 1.75995,-6.49966 10.01483,2.71233 z" | |
| 58 | fill="#126d95" | |
| 59 | id="path9" /> | |
| 60 | <path | |
| 61 | d="m 533.0598,112.36676 -0.91739,3.38458 -9.99361,-2.70665 0.91739,-3.38458 z" | |
| 62 | fill="#126d95" | |
| 63 | id="path11" /> | |
| 64 | <g | |
| 65 | fill="#51a9cf" | |
| 66 | id="g19" | |
| 67 | transform="translate(-295.50101,-692.52836)"> | |
| 68 | <path | |
| 69 | d="m 834.01973,741.0381 c -1.68105,0.0185 -3.22054,1.13771 -3.68367,2.84981 -0.56186,2.07405 0.665,4.21099 2.73743,4.77241 l -13.96475,51.52944 -9.99361,-2.70665 c 8.36013,-31.46487 4.99411,-51.98144 4.99411,-51.98144 14.99782,-11.92097 23.67,-25.56577 27.63101,-32.97331 z" | |
| 70 | id="path13" /> | |
| 71 | <path | |
| 72 | d="m 818.56767,802.18881 -0.9174,3.38458 -10.03996,-2.72957 0.91314,-3.37522 z" | |
| 73 | id="path15" /> | |
| 74 | <path | |
| 75 | d="m 817.07405,807.70594 -1.75995,6.49966 -18.03534,9.08805 9.78412,-18.31044 z" | |
| 76 | id="path17" /> | |
| 77 | </g> | |
| 78 | <path | |
| 79 | d="m 540.69709,49.12083 7.72577,-28.52932 c -0.3195,8.40427 0.28451,24.55036 7.21678,42.41047 0,0 -11.89603,16.50235 -21.99788,47.3763 l -10.03442,-2.71758 13.96533,-51.5284 c 2.08221,0.56405 4.21039,-0.66603 4.77182,-2.73844 0.45427,-1.67248 -0.26571,-3.38317 -1.64739,-4.27302" | |
| 80 | fill="#126d95" | |
| 81 | id="path21" /> | |
| 82 | <text | |
| 83 | transform="translate(-295.73751 -689.6407)" | |
| 84 | id="text25" /> | |
| 85 | <g | |
| 86 | style="font-style:italic;font-weight:800;font-size:133.333;font-family:Merriweather Sans;letter-spacing:0;word-spacing:0;fill:#51a9cf" | |
| 87 | id="g35"> | |
| 88 | <text | |
| 89 | x="16.133343" | |
| 90 | y="130.6234" | |
| 91 | id="text29"><tspan | |
| 92 | x="16.133343" | |
| 93 | y="130.6234" | |
| 94 | id="tspan27">KeenWr</tspan></text> | |
| 95 | <text | |
| 96 | x="552.53137" | |
| 97 | y="130.6234" | |
| 98 | id="text33"><tspan | |
| 99 | x="552.53137" | |
| 100 | y="130.6234" | |
| 101 | id="tspan31">te</tspan></text> | |
| 102 | </g> | |
| 103 | </svg> | |
| 1 | 104 |
| 1 | ||
| 1 | <svg height="197.4767" viewBox="0 0 493.25561 197.4767" width="493.25562" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientTransform="matrix(-8.7796153 42.985832 -42.985832 -8.7796153 810.33577 8312.52749 -472.07353)"/><text fill="#51a9cf" font-family="'Noto Serif CJK SC'" font-size="35.1025" letter-spacing="0" transform="matrix(3.7983969 0 0 3.7983969 -330.7653 961.00598)" word-spacing="0"><tspan x="91.011719" y="-209.05206"><tspan x="91.011719" y="-209.05206">智能写<tspan fill="#51a9cf"/></tspan></tspan><tspan x="91.011719" y="-165.17393"/></text><g transform="tran377.88503/svg> |
| 1 | 1 | |
| 2 | Blues | |
| 3 | Light - 51a9cf | |
| 4 | Dark - 126d95 | |
| 5 | ||
| 6 | Red & Yellow | |
| 7 | Light yellow - ecd980 | |
| 8 | Light red - ec706a | |
| 9 | Dark red - 7e252f | |
| 10 | ||
| 11 | Greens | |
| 12 | Light - 76A786 | |
| 13 | Dark - 385742 | |
| 14 | ||
| 15 | Grayscale | |
| 16 | Light - bac2c5 | |
| 17 | Dark - 394343 | |
| 18 | ||
| 19 |
| 1 | # Document metadata | |
| 2 | ||
| 3 | Document metadata is information about a document. Metadata often includes | |
| 4 | a title, author name, copyright date, and keywords. | |
| 5 | ||
| 6 | # Custom metadata | |
| 7 | ||
| 8 | The following screenshot shows example metadata preferences: | |
| 9 | ||
| 10 |  | |
| 11 | ||
| 12 | The **Key** column lists metadata names and the **Value** column lists | |
| 13 | the metadata content for each corresponding **Key**. The content may | |
| 14 | include references to variable definitions. When the document is typeset, | |
| 15 | the values for the variables will be substituted upon export. | |
| 16 | ||
| 17 | When the document is exported as XHTML, the header will include the | |
| 18 | keys and values conforming to the XHTML specification. For example: | |
| 19 | ||
| 20 | ``` html | |
| 21 | <head> | |
| 22 | <title>Document Title</title> | |
| 23 | <meta content="science, nature" name="keywords"/> | |
| 24 | <meta content="Penn Surnom" name="author"/> | |
| 25 | <meta content="4311" name="count"/> | |
| 26 | </head> | |
| 27 | ``` | |
| 28 | ||
| 29 | # Special metadata | |
| 30 | ||
| 31 | When exporting the document, note the following special metadata: | |
| 32 | ||
| 33 | * **author** -- Included as PDF metadata | |
| 34 | * **byline** -- Replaces author in PDF metadata (e.g., for pen names) | |
| 35 | * **count** -- Total word count in document, automatically included | |
| 36 | * **keywords** -- Included as PDF metadata | |
| 37 | * **title** -- Included as a `<title>` tag, rather than a `<meta>` tag | |
| 38 | ||
| 1 | 39 |
| 1 | # R Functions | |
| 2 | ||
| 3 | Import the files in this directory into the application, which include: | |
| 4 | ||
| 5 | * bootstrap.R | |
| 6 | * pluralize.R | |
| 7 | * possessive.R | |
| 8 | * conversion.R | |
| 9 | * csv.R | |
| 10 | ||
| 11 | # bootstrap.R | |
| 12 | ||
| 13 | Copy the contents of `bootstrap.R` into the R script preferences, shown in the | |
| 14 | following figure, then restart the application: | |
| 15 | ||
| 16 | #  | |
| 17 | ||
| 18 | Setting the **Working Directory** allows the startup script to load files | |
| 19 | using a relative to said directory. | |
| 20 | ||
| 21 | # pluralize.R | |
| 22 | ||
| 23 | This file defines a function that implements most of Damian Conway's [An Algorithmic Approach to English Pluralization](http://blob.perl.org/tpc/1998/User_Applications/Algorithmic%20Approach%20Plurals/Algorithmic_Plurals.html). | |
| 24 | ||
| 25 | ## Usage | |
| 26 | ||
| 27 | Example usages of the pluralize function include: | |
| 28 | ||
| 29 | `r#pluralize( "mouse" )` - mice | |
| 30 | `r#pluralize( "buzz" )` - buzzes | |
| 31 | `r#pluralize( "bus" )` - buses | |
| 32 | ||
| 33 | # possessive.R | |
| 34 | ||
| 35 | This file defines a function that applies possessives to English words. | |
| 36 | ||
| 37 | ## Usage | |
| 38 | ||
| 39 | Example usages of the possessive function include: | |
| 40 | ||
| 41 | `r#pos( "Ross" )` - Ross' | |
| 42 | `r#pos( "Ruby" )` - Ruby's | |
| 43 | `r#pos( "Lois" )` - Lois' | |
| 44 | `r#pos( "my" )` - mine | |
| 45 | `r#pos( "Your" )` - Yours | |
| 46 | ||
| 1 | 47 |
| 1 | # R Scripts | |
| 1 | 2 | |
| 3 | These scripts illustrate how R can perform calculations using variables, to help automate repetitive tasks. Authors are free to write their own scripts date: | |
| 4 | calculate a total for all numeric columnsx =math$x )`; | |
| 5 | y =; | |
| 6 | z = |
| 1 | # Introduction | |
| 2 | ||
| 3 | This document describes how to use the [R](https://www.r-project.org/) | |
| 4 | programming language from within the application. The application uses an | |
| 5 | interpreter known as [Renjin](https://www.renjin.org/) to integrate with R. | |
| 6 | ||
| 7 | # Hello world | |
| 1 | 8 | |
| 9 | Cov$application$r$working$directory ); | |
| 10 | source( "library.R"v$application$r$working$directory |
| 1 | # Captions and cross-references | |
| 2 | ||
| 3 | Users may define captions and cross-references to tables, figures, | |
| 4 | and equations. Unfortunately, at time of writing, the CommonMark | |
| 5 | specification is frozen. This means cross-references must be implemented | |
| 6 | as an extension to the Markdown specification, leaving the door open for | |
| 7 | differing Markdown rendering libraries and applications to diverge with | |
| 8 | respect to syntax. | |
| 9 | ||
| 10 | # Syntax | |
| 11 | ||
| 12 | This section describes how to use captions and cross-references within | |
| 13 | Markdown documents. The CommonMark standard details different ways to | |
| 14 | add captions to tables and figures. While those are supported, a more | |
| 15 | consistent syntax has been implemented. | |
| 16 | ||
| 17 | ## Captions | |
| 18 | ||
| 19 | Tables, figures, and equations are captioned using the same syntax. In | |
| 20 | general, a line that starts with a double colon after a blank line will | |
| 21 | result in a caption added to the item immediately preceding it. The | |
| 22 | remainder of this section provides examples. | |
| 23 | ||
| 24 | ### Images | |
| 25 | ||
| 26 | An image caption: | |
| 27 | ||
| 28 | ``` | |
| 29 |  | |
| 30 | ||
| 31 | :: Figure caption text | |
| 32 | ``` | |
| 33 | ||
| 34 | ### Table | |
| 35 | ||
| 36 | A table caption: | |
| 37 | ||
| 38 | ``` | |
| 39 | | a | b | c | | |
| 40 | |---|---|---| | |
| 41 | | 1 | 2 | 3 | | |
| 42 | | 4 | 5 | 6 | | |
| 43 | | 7 | 8 | 9 | | |
| 44 | ||
| 45 | :: Table caption text | |
| 46 | ``` | |
| 47 | ||
| 48 | ### Equation | |
| 49 | ||
| 50 | An equation caption: | |
| 51 | ||
| 52 | ``` | |
| 53 | $$E = mc^2$$ | |
| 54 | ||
| 55 | :: Equation caption | |
| 56 | ``` | |
| 57 | ||
| 58 | # Cross-references | |
| 59 | ||
| 60 | There are two parts to a cross-reference: the anchor name and its references. | |
| 61 | An anchor name must be uniquely defined. Any number of references may refer | |
| 62 | to an anchor name. Anchor names can be associated with any item in the | |
| 63 | document, and are primarily added to captions. | |
| 64 | ||
| 65 | The general syntax for anchor names and references is: | |
| 66 | ||
| 67 | * `{#type-name:label}` (anchor name) | |
| 68 | * `[@type-name:label]` (reference) | |
| 69 | ||
| 70 | The `type-name` can be any alphanumeric value, starting with a letter or | |
| 71 | ideogram. Type names are user-defined categories for the item type. Labels | |
| 72 | are user-defined identifiers that must be unique per item. | |
| 73 | ||
| 74 | Consider the following example: | |
| 75 | ||
| 76 | ``` | |
| 77 | In [@fig:animal], a cute animal is shown. | |
| 78 | ||
| 79 |  | |
| 80 | ||
| 81 | :: World's cutest animal {#fig:animal} | |
| 82 | ||
| 83 | There is no cuter animal than the one in [@fig:animal]. | |
| 84 | ``` | |
| 85 | ||
| 86 | The anchor name uniquely defines where an item in a document is located. Any | |
| 87 | number of references, anywhere in the document, may reference an anchor name. | |
| 88 | There are few restrictions placed on the possible type names and labels. Here | |
| 89 | are a few more anchor name examples: | |
| 90 | ||
| 91 | ``` | |
| 92 | {#fig:cats} | |
| 93 | {#図版:猫} | |
| 94 | {#eq:mass-energy} | |
| 95 | {#eqn:laplace} | |
| 96 | ``` | |
| 97 | ||
| 98 | ## Type names | |
| 99 | ||
| 100 | To avoid duplicating writing the label each time (e.g., Figure, Table, | |
| 101 | Equation), there are a number of predefined labels associated with | |
| 102 | type names. The following table lists the type names and the label | |
| 103 | generated by the typesetting system: | |
| 104 | ||
| 105 | | Type name | English name | | |
| 106 | |-----------|--------------| | |
| 107 | | algorithm | Algorithm | | |
| 108 | | alg | Algorithm | | |
| 109 | | equation | Equation | | |
| 110 | | eqn | Equation | | |
| 111 | | eq | Equation | | |
| 112 | | figure | Figure | | |
| 113 | | fig | Figure | | |
| 114 | | formula | Formula | | |
| 115 | | listing | Listing | | |
| 116 | | list | Listing | | |
| 117 | | lst | Listing | | |
| 118 | | lyric | Lyrics | | |
| 119 | | music | Score | | |
| 120 | | score | Score | | |
| 121 | | source | Listing | | |
| 122 | | src | Listing | | |
| 123 | | tab | Table | | |
| 124 | | table | Table | | |
| 125 | | tbl | Table | | |
| 126 | ||
| 127 | These values are defined in the theme's `xhtml/xml-references.tex` file. | |
| 1 | 128 |
| 1 | *Song of the Yellow Bird*: | |
| 2 | ||
| 3 | 翩翩黃鳥, | |
| 4 | 雌雄相依。 | |
| 5 | 念我之獨, | |
| 6 | 誰其與歸? | |
| 7 | ||
| 8 | English translation: | |
| 9 | ||
| 10 | Orioles fly smoothly | |
| 11 | Female and male cuddle close together | |
| 12 | Thinking of my loneliness | |
| 13 | Whom shall I go with? | |
| 14 | ||
| 15 | Fonts: | |
| 16 | ||
| 17 | * Regular: 활판 인쇄술 | |
| 18 | * Bold: **활판 인쇄술** | |
| 19 | * Monospace: `활판 인쇄술` | |
| 20 | * Monospace bold: **`활판 인쇄술`** | |
| 21 | * Math: $E=mc^2$ | |
| 22 | ||
| 1 | 23 |
| 1 | --- | |
| 2 | formula: | |
| 3 | sqrt: | |
| 4 | value: "420" | |
| 5 | quadratic: | |
| 6 | a: "25" | |
| 7 | b: "84.906" | |
| 8 | c: "20" | |
| 1 | 9 |
| 1 |  | |
| 2 | ||
| 3 | Given the quadratic formula: | |
| 4 | ||
| 5 | $x = \frac{-b \pm \sqrt{b^2 -4ac}}{2a}$ | |
| 6 | ||
| 7 | Formatted in an R Markdown document as follows: | |
| 8 | ||
| 9 | $x = \frac{-b \pm \sqrt{b^2 -4ac}}{2a}$ | |
| 10 | ||
| 11 | We can substitute the following values: | |
| 12 | ||
| 13 | $a = `r# x(v$formula$quadratic$a)`, b = `r# x(v$formula$quadratic$b)`, c = `r# x(v$formula$quadratic$c)`$ | |
| 14 | ||
| 15 | `r# -x(v$formula$quadratic$b) + sqrt( v$formula$quadratic$b^2 - 4 * v$formula$quadratic$a * v$formula$quadratic$c )` | |
| 16 | ||
| 17 | To arrive at two solutions: | |
| 18 | ||
| 19 | $x = \frac{-b + \sqrt{b^2 -4ac}}{2a} = `r# (-x(v$formula$quadratic$b) + sqrt( x(v$formula$quadratic$b)^2 - 4 * x(v$formula$quadratic$a) * x(v$formula$quadratic$c) )) / (2 * x(v$formula$quadratic$a))`$ | |
| 20 | ||
| 21 | $x = \frac{-b - \sqrt{b^2 -4ac}}{2a} = `r# (-x(v$formula$quadratic$b) - sqrt( x(v$formula$quadratic$b)^2 - 4 * x(v$formula$quadratic$a) * x(v$formula$quadratic$c) )) / (2 * x(v$formula$quadratic$a))`$ | |
| 22 | ||
| 23 | Changing the variable values is reflected in the output immediately. | |
| 1 | 24 |
| 1 | #  | |
| 2 | ||
| 3 | # Real-time equation rendering | |
| 4 | ||
| 5 | Interpolated variables within R calculations, formatted as an equation: | |
| 6 | ||
| 7 | $\sqrt{`r#x( v$formula$sqrt$value)`} = \pm `r# round(sqrt(x( v$formula$sqrt$value )),5)`$ | |
| 8 | ||
| 9 | # Maxwell's equations | |
| 10 | ||
| 11 | $rot \vec{E} = \frac{1}{c} \frac{\partial{\vec{B}}}{\partial t}, div \vec{B} = 0$ | |
| 12 | ||
| 13 | $rot \vec{B} = \frac{1}{c} \frac{\partial{\vec{E}}}{\partial t} + \frac{4\pi}{c} \vec{j}, div \vec{E} = 4 \pi \rho_{\varepsilon}$ | |
| 14 | ||
| 15 | # Time-dependent Schrödinger equation | |
| 16 | ||
| 17 | $- \frac{{\hbar ^2 }}{{2m}}\frac{{\partial ^2 \psi (x,t)}}{{\partial x^2 }} + U(x)\psi (x,t) = i\hbar \frac{{\partial \psi (x,t)}}{{\partial t}}$ | |
| 18 | ||
| 19 | # Discrete-time Fourier transforms | |
| 20 | ||
| 21 | Unit step function: $u(n) \Leftrightarrow \frac{1}{1-e^{-jw}} + \sum_{k=-\infty}^{\infty} \pi \delta (\omega + 2\pi k)$ | |
| 22 | ||
| 23 | Shifted delta: $\delta (n - n_o ) \Leftrightarrow e^{ - j\omega n_o }$ | |
| 24 | ||
| 25 | # Faraday's Law | |
| 26 | ||
| 27 | $\oint_C {E \cdot d\ell = - \frac{d}{{dt}}} \int_S {B_n dA}$ | |
| 28 | ||
| 29 | # Infinite series | |
| 30 | ||
| 31 | $sin(x) = \sum_{n = 1}^{\infty} {\frac{{( { - 1})^{n - 1} x^{2n - 1} }}{{( {2n - 1})!}}}$ | |
| 32 | ||
| 33 | # Magnetic flux | |
| 34 | ||
| 35 | $\phi _m = \int_S {N{{B}} \cdot {{\hat n}}dA = } \int_S {NB_n dA}$ | |
| 36 | ||
| 37 | # Driven oscillation amplitude | |
| 38 | ||
| 39 | $A = \frac{{F_0 }}{{\sqrt {m^2 ( {\omega _0^2 - \omega ^2 } )^2 + b^2 \omega ^2 } }}$ | |
| 40 | ||
| 41 | # Optics | |
| 42 | ||
| 43 | $\phi = \frac{{2\pi }}{\lambda }a sin(\theta)$ | |
| 1 | 44 |
| 1 | # Variables | |
| 2 | ||
| 3 | Diagrams that include variables: | |
| 4 | ||
| 5 |  | |
| 6 | ||
| 7 |  | |
| 8 | ||
| 9 | # PDF themes | |
| 10 | ||
| 11 | In the background of the following screenshot, the editor shows a novel | |
| 12 | being edited: | |
| 13 | ||
| 14 |  | |
| 15 | ||
| 16 | Highlighted items of note: | |
| 17 | ||
| 18 | * PDF icon in the upper-left | |
| 19 | * Novel metadata as integrated variables towards the top-left | |
| 20 | * Theme selection dialog in the upper-middle | |
| 21 | * Three different styles, including: | |
| 22 | * Boschet, based on Baskerville font, nicely styled | |
| 23 | * Handrit, based on Courier font, double-spaced, manuscript format | |
| 24 | * Tarmes, based on Times Roman font, minimal styling | |
| 25 | * Variations in page numbers | |
| 26 | * Manuscript includes word count, automatically | |
| 27 | * Preferences dialog in the middle | |
| 28 | ||
| 29 | # Internationalization | |
| 30 | ||
| 31 | Poem with locale settings: | |
| 32 | ||
| 33 |  | |
| 34 | ||
| 35 | # Equations | |
| 36 | ||
| 37 | TeX equations with detached preview: | |
| 38 | ||
| 39 |  | |
| 40 | ||
| 41 | # Dockable tabs | |
| 42 | ||
| 43 | Document outline opened and docked in bottom-left corner: | |
| 44 | ||
| 45 |  | |
| 46 | ||
| 1 | 47 |
| 1 | # Skins | |
| 2 | ||
| 3 | The application provides bundled skins and the ability to add custom | |
| 4 | skins. This document describes the interplay between bundled skins | |
| 5 | and building your own look and feel. | |
| 6 | ||
| 7 | A skin is a set of styles, similar to cascading style sheet classes, | |
| 8 | that configures the user interface colours, fonts, spacing, highlights, | |
| 9 | drop-shadows, gradients, and more. | |
| 10 | ||
| 11 | For more information on CSS, see the [W3C CSS tutorial](https://www.w3.org/Style/Examples/011/firstcss). | |
| 12 | ||
| 13 | # Order | |
| 14 | ||
| 15 | The order that stylesheets are applied matters so that stylesheets can | |
| 16 | override styles defined previously. The application's user interface | |
| 17 | is made up of the following stylesheets, applied in the order listed: | |
| 18 | ||
| 19 | * **scene.css** --- Defines toolbar styling. | |
| 20 | * **markdown.css** --- Defines text editor styling. | |
| 21 | * **skins/skin_name.css** --- Bundled skin selected in preferences. | |
| 22 | * **custom.css** --- User-defined file set in preferences. | |
| 23 | ||
| 24 | # Customization | |
| 25 | ||
| 26 | Create a custom skin as follows: | |
| 27 | ||
| 28 | 1. Start the application. | |
| 29 | 1. Click **File → New** to create a new file. | |
| 30 | 1. Click **File → Save As** to rename the file. | |
| 31 | 1. Save the file as `custom.css`. | |
| 32 | 1. Change the content to the following: | |
| 33 | ``` css | |
| 34 | .root { | |
| 35 | -fx-base: rgb( 30, 30, 30 ); | |
| 36 | -fx-background: -fx-base; | |
| 37 | } | |
| 38 | ``` | |
| 39 | ||
| 40 | Next, apply the skin as follows: | |
| 41 | ||
| 42 | 1. Click **Edit → Preferences** to open the preferences dialog. | |
| 43 | 1. Click **Skins** to view the available options. | |
| 44 | 1. Click **Browse** to select a custom file. | |
| 45 | 1. Browse to and select `custom.css`, created previously. | |
| 46 | 1. Click **Open**. | |
| 47 | 1. Click **Apply**. | |
| 48 | ||
| 49 | The user interface immediately changes to a dark mode. Continue: | |
| 50 | ||
| 51 | 1. Click **OK** to close the dialog. | |
| 52 | 1. Change the **rgb** numbers in **custom.css** from `30` to `60`. | |
| 53 | 1. Click **File → Save** to save the CSS file. | |
| 54 | ||
| 55 | The user interface immediately changes colour. | |
| 56 | ||
| 57 | # Classes | |
| 58 | ||
| 59 | When creating your own skin, there many classes that can be styled. The | |
| 60 | previous section showed how to set up a rudimentary skin. Instead, start | |
| 61 | with a template that already has a number of classes defined so that you | |
| 62 | can tweak them to your taste. Accomplish this as follows: | |
| 63 | ||
| 64 | 1. Visit the [skin](https://gitlab.com/DaveJarvis/KeenWrite/-/tree/main/src/main/resources/com/keenwrite/skins) repository directory | |
| 65 | 1. Click one of the files (e.g., `haunted_grey.css`). | |
| 66 | 1. Click **Raw**. | |
| 67 | 1. Copy the entire text. | |
| 68 | 1. Return to `custom.css`. | |
| 69 | 1. Delete the contents. | |
| 70 | 1. Paste the copied text. | |
| 71 | 1. Save the file. | |
| 72 | ||
| 73 | To see how the CSS styles are applied to the text editor, open | |
| 74 | [markdown.css](https://gitlab.com/DaveJarvis/KeenWrite/-/blob/main/src/main/resources/com/keenwrite/editor/markdown.css), which is also in the repository. | |
| 75 | ||
| 76 | # Modena | |
| 77 | ||
| 78 | The basic look used by the application is _Modena Light_. Typically we | |
| 79 | only need to override a few classes to completely change the application's | |
| 80 | look and feel. For a full listing of available styles see the OpenJDK's | |
| 81 | [Modena CSS file](https://github.com/openjdk/jfx/blob/master/modules/javafx.controls/src/main/resources/com/sun/javafx/scene/control/skin/modena/modena.css). | |
| 82 | ||
| 83 | # JavaFX CSS | |
| 84 | ||
| 85 | The [Java CSS Reference Guide](https://openjfx.io/javadoc/21/javafx.graphics/javafx/scene/doc-files/cssref.html) is exhaustive. In addition to showing many | |
| 86 | differences between JavaFX CSS and W3C CSS, the guide introduces numerous | |
| 87 | helpful functions for manipulating colours and gradients using existing | |
| 88 | colour definitions. | |
| 89 | ||
| 90 | # RichTextFX | |
| 91 | ||
| 92 | The application uses RichTextFX to render the text editor. Styling various | |
| 93 | text editor classes can require using the prefix `-rtfx` instead of the | |
| 94 | regular JavaFX `-fx`. | |
| 95 | ||
| 96 | # Submit | |
| 97 | ||
| 98 | If you have a look that you'd like to contribute to the project, do pass | |
| 99 | it along. Either open a new issue in the [issue tracker](https://gitlab.com/DaveJarvis/KeenWrite/-/issues) that contains the CSS file or submit a pull request. | |
| 100 | ||
| 1 | 101 |
| 1 | # Introduction | |
| 2 | ||
| 3 | The Scalable Vector Graphics (SVG) drawing software---[Batik](https://xmlgraphics.apache.org/batik/)---that's used by the application may be unable to read certain SVG files produced by [Inkscape](https://inkscape.org/). The result is that embedding the vector graphics files may trigger the following issues: | |
| 4 | ||
| 5 | * Unable to create nested element | |
| 6 | * Black blocks, no text displayed | |
| 7 | * Black text instead of coloured | |
| 8 | ||
| 9 | The remainder of this document explains these problems and how to fix them. | |
| 10 | ||
| 11 | # Nested element | |
| 12 | ||
| 13 | When referencing a vector graphic using Markdown, the status bar may show the following error: | |
| 14 | ||
| 15 | > The current document is unable to create an element of the requested type (namespace: http://www.w3.org/2000/svg, name: flowRoot). | |
| 16 | ||
| 17 | This error is due to a version mismatch of the `flowRoot` element that Inkscape creates. | |
| 18 | ||
| 19 | ## Fix | |
| 20 | ||
| 21 | Resolve the issue by changing the SVG version number as follows: | |
| 22 | ||
| 23 | 1. Edit the vector graphics file using any text editor. | |
| 24 | 1. Find `version="1.1"` and change it to `version="1.2"`. | |
| 25 | 1. Save the file. | |
| 26 | ||
| 27 | The SVG will now appear inside the application; however, the text may appear as black blocks. | |
| 28 | ||
| 29 | # Black blocks | |
| 30 | ||
| 31 | Depending on how text is added to a vector graphic in Inkscape, the text may be inserted within an element called a `flowRoot`. Although Batik recognizes `flowRoot` for SVG version 1.2, it cannot fully interpret the contents. Black blocks are drawn instead of the text, such as those depicted in the following figure: | |
| 32 | ||
| 33 |  | |
| 34 | ||
| 35 | ## Fix | |
| 36 | ||
| 37 | Resolve the issue by "unflowing" all text elements as follows: | |
| 38 | ||
| 39 | 1. Start Inkscape. | |
| 40 | 1. Load the SVG file. | |
| 41 | 1. Select all the text elements. | |
| 42 | 1. Click **Text → Unflow**. | |
| 43 | ||
| 44 | The text may change size and position; recreate the text without dragging using the text tool. After all the text areas have been recreated, continue as follows: | |
| 45 | ||
| 46 | 1. Click **Edit → XML Editor**. | |
| 47 | 1. Expand the **XML Editor** to see more elements. | |
| 48 | 1. Delete all elements named `svg:flowRoot`. | |
| 49 | 1. Save the file. | |
| 50 | ||
| 51 | When the illustration is reloaded, the black blocks will have disappeared, but the text elements ignore any assigned colour. | |
| 52 | ||
| 53 | # Black text | |
| 54 | ||
| 55 | When an SVG `style` attribute contains a reference to `-inkscape-font-specification`, Batik ignores all values that follow said reference. This results in black text, such as: | |
| 56 | ||
| 57 |  | |
| 58 | ||
| 59 | ## Fix | |
| 60 | ||
| 61 | Resolve the issue of colourless text as follows: | |
| 62 | ||
| 63 | 1. Open the SVG file in a plain text editor. | |
| 64 | 1. Remove all references `-inkscape-font-specification:'<FONT>';`, including the trailing (or leading) semicolon. | |
| 65 | 1. Save the file. | |
| 66 | ||
| 67 | When the illustration is reloaded, the colours will have reappeared, such as: | |
| 68 | ||
| 69 |  | |
| 70 | ||
| 1 | 71 |
| 1 | # Overview | |
| 2 | ||
| 3 | Typesetting PDF files entails the following: | |
| 4 | ||
| 5 | * Download and install typesetting software | |
| 6 | * Download a theme pack | |
| 7 | ||
| 8 | These are described in the subsequent sections. Once the requirements have been met, continue reading to learn how to typeset a document. | |
| 9 | ||
| 10 | # Download typesetter | |
| 11 | ||
| 12 | Download the typesetting software as follows: | |
| 13 | ||
| 14 | 1. Start the text editor. | |
| 15 | 1. Click **File → Export As → PDF**. | |
| 16 | * Note the following details (e.g., Windows X86 64-bit): | |
| 17 | * operating system name; | |
| 18 | * instruction set; and | |
| 19 | * architecture. | |
| 20 | 1. Click the [link](https://wiki.contextgarden.net/Installation) in the dialog. | |
| 21 | 1. Download the appropriate archive file. | |
| 22 | ||
| 23 | # Install typesetter | |
| 24 | ||
| 25 | This section describes the installation steps for various platforms. Follow the steps that apply to the computer's operating system: | |
| 26 | ||
| 27 | * [Windows](#windows) (includes Windows 7, Windows 10, and similar) | |
| 28 | * [Unix](#unix) (includes MacOS, FreeBSD, Linux, and similar) | |
| 29 | ||
| 30 | ## Windows | |
| 31 | ||
| 32 | Proceed with a Windows installation of the typesetting software as follows: | |
| 33 | ||
| 34 | 1. Extract the `.zip` file into `C:\Users\%USERNAME%\AppData\Local\context` (the "root" directory) | |
| 35 | 1. Run **install.bat** to download and install the software. | |
| 36 | * If prompted, click **Run anyway** (or click **More info** first). | |
| 37 | 1. Right-click [localpath.bat](https://gitlab.com/DaveJarvis/KeenWrite/-/raw/main/scripts/localpath.bat). | |
| 38 | 1. Select **Save Link As** (or similar). | |
| 39 | 1. Save the file to the typesetting software's "root" directory. | |
| 40 | 1. Rename `localpath.bat.txt` to `localpath.bat`, if necessary. | |
| 41 | 1. Run `localpath.bat` (to set and save the `PATH` environment variable). | |
| 42 | ||
| 43 | Installation is complete. Verify the installation as follows: | |
| 44 | ||
| 45 | 1. Type: `context --version` | |
| 46 | 1. Press `Enter`. | |
| 47 | ||
| 48 | If version information is displayed then the software is installed correctly. | |
| 49 | ||
| 50 | Continue by installing a [theme pack](#theme-pack). | |
| 51 | ||
| 52 | ## Unix | |
| 53 | ||
| 54 | For Linux, MacOS, FreeBSD, and similar operating systems, proceed as follows: | |
| 55 | ||
| 56 | 1. Create `$HOME/.local/bin/context` | |
| 57 | 1. Extract the `.zip` file within `$HOME/.local/bin/context` | |
| 58 | 1. Run `sh install.sh` | |
| 59 | 1. Add `export PATH=$PATH:$HOME/.local/bin/context/tex/texmf-linux-64/bin` to the login script. | |
| 60 | ||
| 61 | Installation is complete. Verify the installation as follows: | |
| 62 | ||
| 63 | 1. Open a new terminal (to export the new PATH setting). | |
| 64 | 1. Type: `context --version` | |
| 65 | 1. Press `Enter`. | |
| 66 | ||
| 67 | If version information is displayed then the software is installed correctly. | |
| 68 | ||
| 69 | Continue by installing a [theme pack](#theme-pack). | |
| 70 | ||
| 71 | # Theme pack | |
| 72 | ||
| 73 | A theme pack is a set of themes that define how documents appear when typeset. Broadly, themes are applied as follows: | |
| 74 | ||
| 75 | * Install a theme pack | |
| 76 | * Configure individual themes | |
| 77 | ||
| 78 | ## Install theme pack | |
| 79 | ||
| 80 | Install and configure the default theme pack as follows: | |
| 81 | ||
| 82 | 1. Download the <a href="https://gitlab.com/DaveJarvis/keenwrite-themes/-/releases/permalink/latest/downloads/theme-pack.zip">theme-pack.zip</a> archive. | |
| 83 | 1. Extract archive into a known location. | |
| 84 | 1. Start the text editor, if not already running. | |
| 85 | 1. Click **Edit → Preferences**. | |
| 86 | 1. Click **Typesetting**. | |
| 87 | 1. Click **Browse** beside **Themes**. | |
| 88 | 1. Navigate to the `themes` directory. | |
| 89 | 1. Click **Open**. | |
| 90 | 1. Click **OK**. | |
| 91 | ||
| 92 | The theme pack is installed. | |
| 93 | ||
| 94 | Each theme has its own requirements, described below. | |
| 95 | ||
| 96 | ## Configure Boschet theme | |
| 97 | ||
| 98 | Download and install the following font families: | |
| 99 | ||
| 100 | * [Libre Baskerville](https://fonts.google.com/specimen/Libre+Baskerville) | |
| 101 | * [Archivo Narrow](https://fonts.google.com/specimen/Archivo+Narrow) | |
| 102 | * [Inconsolata](https://fonts.google.com/specimen/Inconsolata) | |
| 103 | ||
| 104 | The theme is configured. | |
| 105 | ||
| 106 | # Typeset single document | |
| 107 | ||
| 108 | Typeset a document as follows: | |
| 109 | ||
| 110 | 1. Start the text editor, if not already running. | |
| 111 | 1. Click **File → New** (or type `Ctrl+n`). | |
| 112 | 1. Type in some text. | |
| 113 | 1. Click **File → Export As → PDF** (or type `Ctrl+p`). | |
| 114 | 1. Select a theme from the drop-down list. | |
| 115 | 1. Click **OK** (or press `Enter`). | |
| 116 | 1. Set the **File name** to the PDF file name. | |
| 117 | 1. Click **Save**. | |
| 118 | ||
| 119 | The document is typeset; open the PDF file in a PDF reader to view the result. | |
| 120 | ||
| 121 | # Typeset multiple documents | |
| 122 | ||
| 123 | Typeset multiple documents similar to single documents, with one difference: | |
| 124 | ||
| 125 | * Click **File → Export As → Joined PDF** (or type `Ctrl+Shift+p`). | |
| 126 | ||
| 127 | All documents having the same file name extension in the same directory | |
| 128 | (or sub-directories) as the actively edited file are first concatenated then | |
| 129 | typeset into a single PDF document. The order that files are concatenated | |
| 130 | is numeric and alphabetic. | |
| 131 | ||
| 132 | For example, if `1.Rmd` is a sibling of the following files in the same | |
| 133 | directory, then all the files will be included in the PDF, as expected: | |
| 134 | ||
| 135 | chapter_1.Rmd | |
| 136 | chapter_2.Rmd | |
| 137 | chapter_2a.Rmd | |
| 138 | chapter_2b.Rmd | |
| 139 | chapter_3.Rmd | |
| 140 | chapter_10.Rmd | |
| 141 | ||
| 142 | Basically, sorting honours numbers and letters in file names. | |
| 143 | ||
| 144 | # Background | |
| 145 | ||
| 146 | This text editor helps keep content separated from presentation. Plain text documents will remain readable long after proprietary formats have become obsolete. However, we've come to expect much more in what we read than mere text: from hyperlinked tables of contents to indexes, from footers to footnotes, from mathematical expressions to complex graphics, modern documents are nuanced and multifaceted. | |
| 147 | ||
| 148 | ## History | |
| 149 | ||
| 150 | Before computer-based typesetting, much of mathematics was put to page by hand. Professional typesetters, who were often expensive and usually not mathematicians, would inadvertently introduce typographic errors into equations. Phototypesetting technology improved upon hand-typesetting, but well-known computer scientist Donald Knuth---whose third volume of *The Art of Computer Programming* was phototypeset in 1976---expressed dissatisfaction with its typographic quality. He set himself two goals: let anyone create high-quality books without much effort and provide software that typesets consistently on all capable computers. Two years later, he released a typesetting system and a font description language: TeX and METAFONT, respectively. | |
| 151 | ||
| 152 | In short, TeX is software that helps typeset plain text documents. | |
| 153 | ||
| 154 | ## ConTeXt | |
| 155 | ||
| 156 | Programming computers to typeset internationalized text automatically at the level we've become accustomed takes decades of development effort. Many free and open source software solutions can typeset text, including: ConTeXt, LaTeX, Sile, and others. ConTeXt, which builds upon TeX, is ideal for typesetting plain text into beautiful documents because it is developed with a notion of *setups*. These setups can wholly describe how text is to be typeset and---by being external to the text itself---configuring setups provides ample control over the document's final appearance without changing the prose. | |
| 157 | ||
| 158 | # Further reading | |
| 159 | ||
| 160 | Here are a few documents that introduce the typesetting system: | |
| 161 | ||
| 162 | * [What is ConTeXt?](https://www.pragma-ade.com/general/manuals/what-is-context.pdf) | |
| 163 | * [A not so short introduction to ConTeXt](https://github.com/contextgarden/not-so-short-introduction-to-context) | |
| 164 | * [Dealing with XML in ConTeXt MKIV](https://pragma-ade.com/general/manuals/xml-mkiv.pdf) | |
| 165 | * [Typographic Programming](https://www.pragma-ade.com/general/manuals/style.pdf) | |
| 166 | ||
| 167 | The [documentation library](https://wiki.contextgarden.net/Documentation) includes the following gems: | |
| 168 | ||
| 169 | * [ConTeXt Manual](https://www.pragma-ade.nl/general/manuals/ma-cb-en.pdf) | |
| 170 | * [ConTeXt command reference](https://www.pragma-ade.nl/general/qrcs/setup-en.pdf) | |
| 171 | * [METAFUN Manual](https://www.pragma-ade.nl/general/manuals/metafun-p.pdf) | |
| 172 | * [It's in the Details](https://www.pragma-ade.nl/general/manuals/details.pdf) | |
| 173 | * [Fonts out of ConTeXt](https://www.pragma-ade.com/general/manuals/fonts-mkiv.pdf) | |
| 174 | ||
| 175 | Expert-level documentation includes the [LuaTeX Reference Manual](https://www.pragma-ade.nl/general/manuals/luatex.pdf). | |
| 176 | ||
| 1 | 177 |
| 1 | # Typesetting | |
| 2 | ||
| 3 | The application uses the [ConTeXt](https://contextgarden.net) typesetting | |
| 4 | system, the [podman](https://podman.io/) container manager, various | |
| 5 | [themes](https://gitlab.com/DaveJarvis/keenwrite-themes), and numerous | |
| 6 | fonts to produce high-quality PDF files. The container manager significantly | |
| 7 | reduces the number of manual steps in the installation process. | |
| 8 | ||
| 9 | When exporting a document to a PDF file for the first time, a series of | |
| 10 | semi-automated steps guides users through the installation process. These | |
| 11 | steps differ depending on the operating system. | |
| 12 | ||
| 13 | Run the installation wizard as follows: | |
| 14 | ||
| 15 | 1. Start the application. | |
| 16 | 1. Click **File → Export As → PDF**. | |
| 17 | ||
| 18 | Follow the steps in the wizard to install the requisite software and | |
| 19 | typesetting themes. | |
| 20 | ||
| 1 | 21 |
| 1 | # Introduction | |
| 2 | ||
| 3 | This document describes how to use the application. | |
| 4 | ||
| 5 | # Variable definitions | |
| 1 | 6 | |
| 7 | Variable definitions provide a way to insert key names having associated values into a document. The variable names and values are declared inside an external filbookending the key name within{{key}} 1 | |
| 8 | key_2: {{key}}{{novel.author}}Variable Files** to listVariable{{novel.author}}uble brace{{novel.title}}{{novel.title}} |
| 1 | # Fonts | |
| 2 | ||
| 3 | For best results, it is recommended that the Noto Font family is installed | |
| 4 | on the system. The required font families include: | |
| 1 | 5 | |
| 6 | * Sans-serif --- editor pane | |
| 7 | * Serif --- preview pane | |
| 8 | * Serif monospace --- prevnt familie |
| 1 | org.gradle.jvmargs=-Xmx1G | |
| 2 | org.gradle.daemon=true | |
| 3 | org.gradle.parallel=true | |
| 1 | 4 |
| 1 | <svg height='19pt' viewBox='0 0 25 19' width='25pt' xmlns='http://www.w3.org/2000/svg'><g fill='#454545'><path d='m8.042969 11.085938c.332031 1.445312 1.660156 2.503906 3.214843 2.558593zm0 0'/><path d='m6.792969 9.621094-.300781.226562.242187.195313c.015625-.144531.03125-.28125.058594-.421875zm0 0'/><path d='m10.597656.949219-2.511718.207031c-.777344.066406-1.429688.582031-1.636719 1.292969l-.367188 1.253906-3.414062.28125c-1.027344.085937-1.792969.949219-1.699219 1.925781l.976562 10.621094c.089844.976562.996094 1.699219 2.023438 1.613281l11.710938-.972656-3.117188-2.484375c-.246094.0625-.5.109375-.765625.132812-2.566406.210938-4.835937-1.597656-5.0625-4.039062-.023437-.25-.019531-.496094 0-.738281l-.242187-.195313.300781-.226562c.359375-1.929688 2.039062-3.472656 4.191406-3.652344.207031-.015625.414063-.015625.617187-.007812l.933594-.707032zm0 0'/><path d='m10.234375 11.070312 2.964844 2.820313c.144531.015625.285156.027344.433593.027344 1.890626 0 3.429688-1.460938 3.429688-3.257813 0-1.792968-1.539062-3.257812-3.429688-3.257812-1.890624 0-3.429687 1.464844-3.429687 3.257812 0 .140625.011719.277344.03125.410156zm0 0'/><path d='m14.488281.808594 1.117188 4.554687-1.042969.546875c2.25.476563 3.84375 2.472656 3.636719 4.714844-.199219 2.191406-2.050781 3.871094-4.285157 4.039062l2.609376 2.957032 4.4375.371094c1.03125.085937 1.9375-.640626 2.027343-1.617188l.976563-10.617188c.089844-.980468-.667969-1.839843-1.699219-1.925781l-3.414063-.285156-.371093-1.253906c-.207031-.710938-.859375-1.226563-1.636719-1.289063zm0 0'/></g></svg> | |
| 1 | 2 |
| 1 | #!/usr/bin/env bash | |
| 1 | 2 | |
| 3 | # --------------------------------------------------------------------------- | |
| 4 | # This script cross-compiles application launchers for different platforms. | |
| 5 | # | |
| 6 | # The application binaries are self-contained launchers that do not need | |
| 7 | # to enable-preview"21.0.2" | |
| 8 | ARG_JAVA_UPDATE="14" |
| 1 | #!/usr/bin/env bash | |
| 2 | ||
| 3 | SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd) | |
| 4 | ||
| 5 | java \ | |
| 6 | -Dprism.order=sw \ | |
| 7 | =ALL-UNNAMED \ | |
| 8 | =ALL-UNNAMED \ | |
| 9 | \ | |
| 10 | -jar ${SCRIPT_DIR}/keenwrite.jar $@ | |
| 11 | ||
| 1 | 12 |
| 1 | #!/usr/bin/env bash | |
| 2 | ||
| 3 | # --------------------------------------------------------------------------- | |
| 4 | # This script uploads the latest application release for all supported | |
| 5 | # platforms. | |
| 6 | # --------------------------------------------------------------------------- | |
| 7 | ||
| 8 | readonly RELEASE=$(git describe --abbrev=0 --tags) | |
| 9 | readonly APP_NAME=$(cut -d= -f2 ./src/main/resources/bootstrap.properties) | |
| 10 | readonly APP_NAME_LC=${APP_NAME,,} | |
| 11 | readonly PATH_TOKEN="tokens/${APP_NAME_LC}.pat" | |
| 12 | readonly URL=$(cat "tokens/publish.url") | |
| 13 | readonly FILE_VERSION="version.txt" | |
| 14 | ||
| 15 | # --------------------------------------------------------------------------- | |
| 16 | # Adds download URLs to a release. | |
| 17 | # | |
| 18 | # $1 - The system (Linux, WIndows, MacOS, Java) | |
| 19 | # --------------------------------------------------------------------------- | |
| 20 | release() { | |
| 21 | local -r OS="${1}" | |
| 22 | local ARCH=" (64-bit, x86)" | |
| 23 | local FILE_PREFIX="${APP_NAME_LC}" | |
| 24 | local FILE_SUFFIX="bin" | |
| 25 | ||
| 26 | case ${OS} in | |
| 27 | MacOS) | |
| 28 | FILE_SUFFIX="app" | |
| 29 | ;; | |
| 30 | Windows) | |
| 31 | FILE_PREFIX="${APP_NAME}" | |
| 32 | FILE_SUFFIX="exe" | |
| 33 | ;; | |
| 34 | Java) | |
| 35 | ARCH="" | |
| 36 | FILE_SUFFIX="jar" | |
| 37 | ;; | |
| 38 | *) | |
| 39 | # Linux, others | |
| 40 | ;; | |
| 41 | esac | |
| 42 | ||
| 43 | local -r BINARY="${FILE_PREFIX}.${FILE_SUFFIX}" | |
| 44 | ||
| 45 | upload "${BINARY}" | |
| 46 | ||
| 47 | glab release upload ${RELEASE} \ | |
| 48 | --assets-links="[{ | |
| 49 | \"name\":\"${APP_NAME} for ${OS}${ARCH}\", | |
| 50 | \"url\":\"https://${APP_NAME_LC}.com/downloads/${BINARY}\", | |
| 51 | \"link_type\":\"other\" | |
| 52 | }]" | |
| 53 | } | |
| 54 | ||
| 55 | # --------------------------------------------------------------------------- | |
| 56 | # Uploads a file to the remote host. | |
| 57 | # | |
| 58 | # $1 - The relative path to the file to upload. | |
| 59 | # --------------------------------------------------------------------------- | |
| 60 | upload() { | |
| 61 | local -r FILENAME="${1}" | |
| 62 | ||
| 63 | if [ -f "${FILENAME}" ]; then | |
| 64 | scp "${FILENAME}" "${URL}" | |
| 65 | else | |
| 66 | echo "Missing ${FILE_BINARY}, continuing." | |
| 67 | fi | |
| 68 | } | |
| 69 | ||
| 70 | if [ -f "${PATH_TOKEN}" ]; then | |
| 71 | cat "${PATH_TOKEN}" | glab auth login --hostname gitlab.com --stdin | |
| 72 | ||
| 73 | glab release create ${RELEASE} | |
| 74 | ||
| 75 | release "Windows" | |
| 76 | release "MacOS" | |
| 77 | release "Linux" | |
| 78 | release "Java" | |
| 79 | ||
| 80 | echo "${RELEASE}" > "${FILE_VERSION}" | |
| 81 | upload "${FILE_VERSION}" | |
| 82 | mv "${FILE_VERSION}" "www/downloads" | |
| 83 | else | |
| 84 | echo "Create ${PATH_TOKEN} before publishing the release." | |
| 85 | fi | |
| 86 | ||
| 1 | 87 |
| 1 | #!/usr/bin/env bash | |
| 2 | ||
| 3 | # --------------------------------------------------------------------------- | |
| 4 | # This script builds Windows, Linux, and Java archive binaries for a | |
| 5 | # release. | |
| 6 | # --------------------------------------------------------------------------.shzip,http://infozip.sourceforge.netRemove distribution directory" | |
| 7 | rm -rf "${SCRIPT_DIR}/dist" | |
| 8 | ||
| 9 | $log "Remove stale binaries" | |
| 10 | rm -f "${application_title,,}.jar" | |
| 11 | rm -f "${application_title,,}.bin" | |
| 12 | rm -f "${application_title}.exe",,}.jar" .MacOSmacos | |
| 1 | 13 |
| 1 | code-sign-cert.pfx | |
| 1 | 2 |
| 1 | #!/usr/bin/env bash | |
| 2 | ||
| 3 | # ----------------------------------------------------------------------------- | |
| 4 | # Copyright 2020 Dave Jarvis | |
| 5 | # | |
| 6 | # Permission is hereby granted, free of charge, to any person obtaining a | |
| 7 | # copy of this software and associated documentation files (the | |
| 8 | # "Software"), to deal in the Software without restriction, including | |
| 9 | # without limitation the rights to use, copy, modify, merge, publish, | |
| 10 | # distribute, sublicense, and/or sell copies of the Software, and to | |
| 11 | # permit persons to whom the Software is furnished to do so, subject to | |
| 12 | # the following conditions: | |
| 13 | # | |
| 14 | # The above copyright notice and this permission notice shall be included | |
| 15 | # in all copies or substantial portions of the Software. | |
| 16 | # | |
| 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
| 18 | # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
| 19 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
| 20 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | |
| 21 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | |
| 22 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | |
| 23 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
| 24 | # ----------------------------------------------------------------------------- | |
| 25 | ||
| 26 | set -o errexit | |
| 27 | set -o nounset | |
| 28 | ||
| 29 | readonly SCRIPT_SRC="$(dirname "${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}")" | |
| 30 | readonly SCRIPT_DIR="$(cd "${SCRIPT_SRC}" >/dev/null 2>&1 && pwd)" | |
| 31 | readonly SCRIPT_NAME=$(basename "$0") | |
| 32 | ||
| 33 | # ----------------------------------------------------------------------------- | |
| 34 | # The main entry point is responsible for parsing command-line arguments, | |
| 35 | # changing to the appropriate directory, and running all commands requested | |
| 36 | # by the user. | |
| 37 | # | |
| 38 | # $@ - Command-line arguments | |
| 39 | # ----------------------------------------------------------------------------- | |
| 40 | main() { | |
| 41 | arguments "$@" | |
| 42 | ||
| 43 | $usage && terminate 3 | |
| 44 | requirements && terminate 4 | |
| 45 | traps && terminate 5 | |
| 46 | ||
| 47 | directory && terminate 6 | |
| 48 | preprocess && terminate 7 | |
| 49 | execute && terminate 8 | |
| 50 | postprocess && terminate 9 | |
| 51 | ||
| 52 | terminate 0 | |
| 53 | } | |
| 54 | ||
| 55 | # ----------------------------------------------------------------------------- | |
| 56 | # Perform all commands that the script requires. | |
| 57 | # | |
| 58 | # @return 0 - Indicate to terminate the script with non-zero exit level | |
| 59 | # @return 1 - All tasks completed successfully (default) | |
| 60 | # ----------------------------------------------------------------------------- | |
| 61 | execute() { | |
| 62 | return 1 | |
| 63 | } | |
| 64 | ||
| 65 | # ----------------------------------------------------------------------------- | |
| 66 | # Changes to the script's working directory, provided it exists. | |
| 67 | # | |
| 68 | # @return 0 - Change directory failed | |
| 69 | # @return 1 - Change directory succeeded | |
| 70 | # ----------------------------------------------------------------------------- | |
| 71 | directory() { | |
| 72 | $log "Change directory" | |
| 73 | local result=1 | |
| 74 | ||
| 75 | # Track whether change directory failed. | |
| 76 | cd "${SCRIPT_DIR}" > /dev/null 2>&1 || result=0 | |
| 77 | ||
| 78 | return "${result}" | |
| 79 | } | |
| 80 | ||
| 81 | # ----------------------------------------------------------------------------- | |
| 82 | # Perform any initialization required prior to executing tasks. | |
| 83 | # | |
| 84 | # @return 0 - Preprocessing failed | |
| 85 | # @return 1 - Preprocessing succeeded | |
| 86 | # ----------------------------------------------------------------------------- | |
| 87 | preprocess() { | |
| 88 | $log "Preprocess" | |
| 89 | ||
| 90 | return 1 | |
| 91 | } | |
| 92 | ||
| 93 | # ----------------------------------------------------------------------------- | |
| 94 | # Perform any clean up required prior to executing tasks. | |
| 95 | # | |
| 96 | # @return 0 - Postprocessing failed | |
| 97 | # @return 1 - Postprocessing succeeded | |
| 98 | # ----------------------------------------------------------------------------- | |
| 99 | postprocess() { | |
| 100 | $log "Postprocess" | |
| 101 | ||
| 102 | return 1 | |
| 103 | } | |
| 104 | ||
| 105 | # ----------------------------------------------------------------------------- | |
| 106 | # Check that all required commands are available. | |
| 107 | # | |
| 108 | # @return 0 - At least one command is missing | |
| 109 | # @return 1 - All commands are available | |
| 110 | # ----------------------------------------------------------------------------- | |
| 111 | requirements() { | |
| 112 | $log "Verify requirements" | |
| 113 | local -r expected_count=${#DEPENDENCIES[@]} | |
| 114 | local total_count=0 | |
| 115 | ||
| 116 | # Verify that each command exists. | |
| 117 | for dependency in "${DEPENDENCIES[@]}"; do | |
| 118 | # Extract the command name [0] and URL [1]. | |
| 119 | IFS=',' read -ra dependent <<< "${dependency}" | |
| 120 | ||
| 121 | required "${dependent[0]}" "${dependent[1]}" | |
| 122 | total_count=$(( total_count + $? )) | |
| 123 | done | |
| 124 | ||
| 125 | unset IFS | |
| 126 | ||
| 127 | # Total dependencies found must match the expected number. | |
| 128 | # Integer-only division rounds down. | |
| 129 | return $(( total_count / expected_count )) | |
| 130 | } | |
| 131 | ||
| 132 | # ----------------------------------------------------------------------------- | |
| 133 | # Called before terminating the script. | |
| 134 | # ----------------------------------------------------------------------------- | |
| 135 | cleanup() { | |
| 136 | $log "Cleanup" | |
| 137 | } | |
| 138 | ||
| 139 | # ----------------------------------------------------------------------------- | |
| 140 | # Terminates the program immediately. | |
| 141 | # ----------------------------------------------------------------------------- | |
| 142 | trap_control_c() { | |
| 143 | $log "Interrupted" | |
| 144 | cleanup | |
| 145 | error "⯃" | |
| 146 | terminate 1 | |
| 147 | } | |
| 148 | ||
| 149 | # ----------------------------------------------------------------------------- | |
| 150 | # Configure signal traps. | |
| 151 | # | |
| 152 | # @return 1 - Signal traps are set. | |
| 153 | # ----------------------------------------------------------------------------- | |
| 154 | traps() { | |
| 155 | # Suppress echoing ^C if pressed. | |
| 156 | stty -echoctl | |
| 157 | trap trap_control_c INT | |
| 158 | ||
| 159 | return 1 | |
| 160 | } | |
| 161 | ||
| 162 | # ----------------------------------------------------------------------------- | |
| 163 | # Check for a required command. | |
| 164 | # | |
| 165 | # $1 - Command or file to check for existence | |
| 166 | # $2 - Command's website (e.g., download for binaries and source code) | |
| 167 | # | |
| 168 | # @return 0 - Command is missing | |
| 169 | # @return 1 - Command exists | |
| 170 | # ----------------------------------------------------------------------------- | |
| 171 | required() { | |
| 172 | local result=0 | |
| 173 | ||
| 174 | test -f "$1" || \ | |
| 175 | command -v "$1" > /dev/null 2>&1 && result=1 || \ | |
| 176 | warning "Missing: $1 ($2)" | |
| 177 | ||
| 178 | return ${result} | |
| 179 | } | |
| 180 | ||
| 181 | # ----------------------------------------------------------------------------- | |
| 182 | # Show acceptable command-line arguments. | |
| 183 | # | |
| 184 | # @return 0 - Indicate script may not continue | |
| 185 | # ----------------------------------------------------------------------------- | |
| 186 | utile_usage() { | |
| 187 | printf "Usage: %s [OPTIONS...]\n\n" "${SCRIPT_NAME}" >&2 | |
| 188 | ||
| 189 | # Number of spaces to pad after the longest long argument. | |
| 190 | local -r PADDING=2 | |
| 191 | ||
| 192 | # Determine the longest long argument to adjust spacing. | |
| 193 | local -r LEN=$(printf '%s\n' "${ARGUMENTS[@]}" | \ | |
| 194 | awk -F"," '{print length($2)+'${PADDING}'}' | sort -n | tail -1) | |
| 195 | ||
| 196 | local duplicates | |
| 197 | ||
| 198 | for argument in "${ARGUMENTS[@]}"; do | |
| 199 | # Extract the short [0] and long [1] arguments and description [2]. | |
| 200 | arg=("$(echo ${argument} | cut -d ',' -f1)" \ | |
| 201 | "$(echo ${argument} | cut -d ',' -f2)" \ | |
| 202 | "$(echo ${argument} | cut -d ',' -f3-)") | |
| 203 | ||
| 204 | duplicates+=("${arg[0]}") | |
| 205 | ||
| 206 | printf " -%s, --%-${LEN}s%s\n" "${arg[0]}" "${arg[1]}" "${arg[2]}" >&2 | |
| 207 | done | |
| 208 | ||
| 209 | # Sort the arguments to make sure no duplicates exist. | |
| 210 | duplicates=$(echo "${duplicates[@]}" | tr ' ' '\n' | sort | uniq -c -d) | |
| 211 | ||
| 212 | # Warn the developer that there's a duplicate command-line option. | |
| 213 | if [ -n "${duplicates}" ]; then | |
| 214 | # Trim all the whitespaces | |
| 215 | duplicates=$(echo "${duplicates}" | xargs echo -n) | |
| 216 | error "Duplicate command-line argument exists: ${duplicates}" | |
| 217 | fi | |
| 218 | ||
| 219 | return 0 | |
| 220 | } | |
| 221 | ||
| 222 | # ----------------------------------------------------------------------------- | |
| 223 | # Write coloured text to standard output. | |
| 224 | # | |
| 225 | # $1 - Text to write | |
| 226 | # $2 - Text's colour | |
| 227 | # ----------------------------------------------------------------------------- | |
| 228 | coloured_text() { | |
| 229 | printf "%b%s%b\n" "$2" "$1" "${COLOUR_OFF}" | |
| 230 | } | |
| 231 | ||
| 232 | # ----------------------------------------------------------------------------- | |
| 233 | # Write a warning message to standard output. | |
| 234 | # | |
| 235 | # $1 - Text to write | |
| 236 | # ----------------------------------------------------------------------------- | |
| 237 | warning() { | |
| 238 | coloured_text "$1" "${COLOUR_WARNING}" | |
| 239 | } | |
| 240 | ||
| 241 | # ----------------------------------------------------------------------------- | |
| 242 | # Write an error message to standard output. | |
| 243 | # | |
| 244 | # $1 - Text to write | |
| 245 | # ----------------------------------------------------------------------------- | |
| 246 | error() { | |
| 247 | coloured_text "$1" "${COLOUR_ERROR}" | |
| 248 | } | |
| 249 | ||
| 250 | # ----------------------------------------------------------------------------- | |
| 251 | # Write a timestamp and message to standard output. | |
| 252 | # | |
| 253 | # $1 - Text to write | |
| 254 | # ----------------------------------------------------------------------------- | |
| 255 | utile_log() { | |
| 256 | printf "[%s] " "$(date +%H:%M:%S.%4N)" | |
| 257 | coloured_text "$1" "${COLOUR_LOGGING}" | |
| 258 | } | |
| 259 | ||
| 260 | # ----------------------------------------------------------------------------- | |
| 261 | # Perform no operations. | |
| 262 | # | |
| 263 | # return 1 - Success | |
| 264 | # ----------------------------------------------------------------------------- | |
| 265 | noop() { | |
| 266 | return 1 | |
| 267 | } | |
| 268 | ||
| 269 | # ----------------------------------------------------------------------------- | |
| 270 | # Exit the program with a given exit code. | |
| 271 | # | |
| 272 | # $1 - Exit code | |
| 273 | # ----------------------------------------------------------------------------- | |
| 274 | terminate() { | |
| 275 | exit "$1" | |
| 276 | } | |
| 277 | ||
| 278 | # ----------------------------------------------------------------------------- | |
| 279 | # Set global variables from command-line arguments. | |
| 280 | # ----------------------------------------------------------------------------- | |
| 281 | arguments() { | |
| 282 | while [ "$#" -gt "0" ]; do | |
| 283 | local consume=1 | |
| 284 | ||
| 285 | case "$1" in | |
| 286 | -V|--verbose) | |
| 287 | log=utile_log | |
| 288 | ;; | |
| 289 | -h|-\?|--help) | |
| 290 | usage=utile_usage | |
| 291 | ;; | |
| 292 | *) | |
| 293 | set +e | |
| 294 | argument "$@" | |
| 295 | consume=$? | |
| 296 | set -e | |
| 297 | ;; | |
| 298 | esac | |
| 299 | ||
| 300 | shift ${consume} | |
| 301 | done | |
| 302 | } | |
| 303 | ||
| 304 | # ----------------------------------------------------------------------------- | |
| 305 | # Parses a single command-line argument. This must return a value greater | |
| 306 | # than or equal to 1, otherwise parsing the command-line arguments will | |
| 307 | # loop indefinitely. | |
| 308 | # | |
| 309 | # @return The number of arguments to consume (1 by default). | |
| 310 | # ----------------------------------------------------------------------------- | |
| 311 | argument() { | |
| 312 | return 1 | |
| 313 | } | |
| 314 | ||
| 315 | # ANSI colour escape sequences. | |
| 316 | readonly COLOUR_BLUE='\033[1;34m' | |
| 317 | readonly COLOUR_PINK='\033[1;35m' | |
| 318 | readonly COLOUR_DKGRAY='\033[30m' | |
| 319 | readonly COLOUR_DKRED='\033[31m' | |
| 320 | readonly COLOUR_LTRED='\033[1;31m' | |
| 321 | readonly COLOUR_YELLOW='\033[1;33m' | |
| 322 | readonly COLOUR_OFF='\033[0m' | |
| 323 | ||
| 324 | # Colour definitions used by script. | |
| 325 | COLOUR_LOGGING=${COLOUR_BLUE} | |
| 326 | COLOUR_WARNING=${COLOUR_YELLOW} | |
| 327 | COLOUR_ERROR=${COLOUR_LTRED} | |
| 328 | ||
| 329 | # Define required commands to check when script starts. | |
| 330 | DEPENDENCIES=( | |
| 331 | "awk,https://www.gnu.org/software/gawk/manual/gawk.html" | |
| 332 | "cut,https://www.gnu.org/software/coreutils" | |
| 333 | ) | |
| 334 | ||
| 335 | # Define help for command-line arguments. | |
| 336 | ARGUMENTS=( | |
| 337 | "V,verbose,Log messages while processing" | |
| 338 | "h,help,Show this help message then exit" | |
| 339 | ) | |
| 340 | ||
| 341 | # These functions may be set to utile delegates while parsing arguments. | |
| 342 | usage=noop | |
| 343 | log=noop | |
| 344 | ||
| 1 | 345 |
| 1 | #!/usr/bin/env bash | |
| 2 | ||
| 3 | # Outputs font names for all font files. | |
| 4 | ||
| 5 | find src/main/resources/fonts -type f \( -name "*otf" -o -name "*ttf" \) -exec \ | |
| 6 | fc-scan --format "%{foundry}: %{family}\n" {} \; | uniq | sort | |
| 7 | ||
| 1 | 8 |
| 1 | #!/bin/bash | |
| 2 | ||
| 3 | INKSCAPE="/usr/bin/inkscape" | |
| 4 | PNG_COMPRESS="optipng" | |
| 5 | PNG_COMPRESS_OPTS="-o9 *png" | |
| 6 | ||
| 7 | declare -a SIZES=("16" "32" "64" "128" "256" "512") | |
| 8 | ||
| 9 | for i in "${SIZES[@]}"; do | |
| 10 | # -y: export background opacity 0 | |
| 11 | $INKSCAPE -y 0 -w "${i}" --export-overwrite --export-type=png -o "logo${i}.png" "logo.svg" | |
| 12 | done | |
| 13 | ||
| 14 | # Compess the PNG images. | |
| 15 | which $PNG_COMPRESS && $PNG_COMPRESS $PNG_COMPRESS_OPTS | |
| 16 | ||
| 1 | 17 |
| 1 | @echo off | |
| 2 | set "OWNPATH=%~dp0" | |
| 3 | set "PLATFORM=mswin" | |
| 4 | ||
| 5 | if defined ProgramFiles(x86) set "PLATFORM=win64" | |
| 6 | if "%PROCESSOR_ARCHITECTURE%"=="AMD64" set "PLATFORM=win64" | |
| 7 | if exist "%OWNPATH%tex\texmf-mswin\bin\context.exe" set "PLATFORM=mswin" | |
| 8 | if exist "%OWNPATH%tex\texmf-win64\bin\context.exe" set "PLATFORM=win64" | |
| 9 | ||
| 10 | set "TeXPath=%OWNPATH%tex\texmf-%PLATFORM%\bin" | |
| 11 | ||
| 12 | echo %PATH% | findstr "texmf-%PLATFORM%" > nul | |
| 13 | ||
| 14 | rem Only update the PATH if not previously updated | |
| 15 | if ERRORLEVEL 1 ( | |
| 16 | setlocal enabledelayedexpansion | |
| 17 | set "Exists=false" | |
| 18 | set "Key=HKCU\Environment" | |
| 19 | ||
| 20 | for /F "USEBACKQ tokens=2*" %%A in (`reg query %%Key%% /v PATH 2^>nul`) do ( | |
| 21 | if not "%%~B" == "" ( | |
| 22 | set "Exists=true" | |
| 23 | ||
| 24 | rem Preserve the existing PATH | |
| 25 | echo %%B > currpath.txt | |
| 26 | ||
| 27 | rem Change the PATH environment variable | |
| 28 | setx PATH "%%B;%TeXPath%" | |
| 29 | ) | |
| 30 | ) | |
| 31 | ||
| 32 | rem The user-defined PATH does not exist, create it | |
| 33 | if "!Exists!" == "false" ( | |
| 34 | rem Change the user PATH environment variable | |
| 35 | setx PATH "%TeXPath%" | |
| 36 | ) | |
| 37 | ||
| 38 | endlocal | |
| 39 | ||
| 40 | rem Update the current session | |
| 41 | set "PATH=%PATH%;%TeXPath%" | |
| 42 | ) | |
| 43 | ||
| 1 | 44 |
| 1 | #!/usr/bin/env bash | |
| 2 | ||
| 3 | # TODO: This file does not work with Picocli and there are other issues. | |
| 4 | # TODO: Revisit after replacing Picocli and using FastR instead of Renjin. | |
| 5 | ||
| 6 | MODULES="${JAVA_HOME}/jmods/" | |
| 7 | LIBS=$(ls -1 ../libs/*jar | sed 's/\(.*\)/-libraryjars \1/g') | |
| 8 | ||
| 9 | java -jar ../tex/lib/proguard.jar \ | |
| 10 | -libraryjars "${MODULES}java.base.jmod/(!**.jar;!module-info.class)" \ | |
| 11 | -libraryjars "${MODULES}java.desktop.jmod/(!**.jar;!module-info.class)" \ | |
| 12 | -libraryjars "${MODULES}java.xml.jmod/(!**.jar;!module-info.class)" \ | |
| 13 | -libraryjars "${MODULES}javafx.controls.jmod/(!**.jar;!module-info.class)" \ | |
| 14 | -libraryjars "${MODULES}javafx.graphics.jmod/(!**.jar;!module-info.class)" \ | |
| 15 | ${LIBS} \ | |
| 16 | -injars ../build/libs/keenwrite.jar \ | |
| 17 | -outjars ../build/libs/keenwrite-min.jar \ | |
| 18 | -keep 'class com.keenwrite.** { *; }' \ | |
| 19 | -keep 'class com.whitemagicsoftware.tex.** { *; }' \ | |
| 20 | -keep 'class org.renjin.** { *; }' \ | |
| 21 | -keep 'class picocli.** { *; }' \ | |
| 22 | -keep 'interface picocli.** { *; }' \ | |
| 23 | -keep 'class picocli.CommandLine { *; }' \ | |
| 24 | -keep 'class picocli.CommandLine$* { *; }' \ | |
| 25 | -keepattributes '*Annotation*, Signature, Exception' \ | |
| 26 | -keepclassmembers 'class * extends java.util.concurrent.Callable { | |
| 27 | public java.lang.Integer call(); | |
| 28 | }' \ | |
| 29 | -keepclassmembers 'class * { | |
| 30 | @javax.inject.Inject <init>(...); | |
| 31 | @picocli.CommandLine$Option *; | |
| 32 | }' \ | |
| 33 | -keepclassmembers 'class * extends java.lang.Enum { | |
| 34 | <fields>; | |
| 35 | public static **[] values(); | |
| 36 | public static ** valueOf(java.lang.String); | |
| 37 | }' \ | |
| 38 | -keepnames \ | |
| 39 | 'class org.apache.lucene.analysis.tokenattributes.KeywordAttributeImpl' \ | |
| 40 | -dontnote \ | |
| 41 | -dontwarn \ | |
| 42 | -dontoptimize \ | |
| 43 | -dontobfuscate | |
| 44 | ||
| 1 | 45 |
| 1 | 1 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite; | |
| 6 | ||
| 7 | import com.keenwrite.cmdline.Arguments; | |
| 8 | import com.keenwrite.commands.ConcatenateCommand; | |
| 9 | import com.keenwrite.io.SysFile; | |
| 10 | import com.keenwrite.processors.Processor; | |
| 11 | import com.keenwrite.processors.ProcessorContext; | |
| 12 | import com.keenwrite.processors.r.RBootstrapProcessor; | |
| 13 | ||
| 14 | import java.io.IOException; | |
| 15 | import java.nio.file.Path; | |
| 16 | import java.util.concurrent.Callable; | |
| 17 | import java.util.concurrent.CompletableFuture; | |
| 18 | import java.util.concurrent.ExecutorService; | |
| 19 | import java.util.concurrent.Future; | |
| 20 | import java.util.concurrent.atomic.AtomicInteger; | |
| 21 | ||
| 22 | import static com.keenwrite.Launcher.terminate; | |
| 23 | import static com.keenwrite.events.StatusEvent.clue; | |
| 24 | import static com.keenwrite.io.MediaType.TEXT_R_MARKDOWN; | |
| 25 | import static com.keenwrite.processors.ProcessorFactory.createProcessors; | |
| 26 | import static java.nio.charset.StandardCharsets.UTF_8; | |
| 27 | import static java.nio.file.Files.readString; | |
| 28 | import static java.nio.file.Files.writeString; | |
| 29 | import static java.util.concurrent.Executors.newFixedThreadPool; | |
| 30 | import static org.apache.commons.io.FilenameUtils.getExtension; | |
| 31 | ||
| 32 | /** | |
| 33 | * Responsible for executing common commands. These commands are shared by | |
| 34 | * both the graphical and the command-line interfaces. | |
| 35 | */ | |
| 36 | public class AppCommands { | |
| 37 | private static final ExecutorService sExecutor = newFixedThreadPool( 1 ); | |
| 38 | ||
| 39 | private AppCommands() { | |
| 40 | } | |
| 41 | ||
| 42 | public static void run( final Arguments args ) { | |
| 43 | final var exitCode = new AtomicInteger(); | |
| 44 | ||
| 45 | final var future = new CompletableFuture<Path>() { | |
| 46 | @Override | |
| 47 | public boolean complete( final Path path ) { | |
| 48 | return super.complete( path ); | |
| 49 | } | |
| 50 | ||
| 51 | @Override | |
| 52 | public boolean completeExceptionally( final Throwable ex ) { | |
| 53 | clue( ex ); | |
| 54 | exitCode.set( 1 ); | |
| 55 | ||
| 56 | return super.completeExceptionally( ex ); | |
| 57 | } | |
| 58 | }; | |
| 59 | ||
| 60 | file_export( args, future ); | |
| 61 | sExecutor.shutdown(); | |
| 62 | future.join(); | |
| 63 | terminate( exitCode.get() ); | |
| 64 | } | |
| 65 | ||
| 66 | /** | |
| 67 | * Converts one or more files into the given file format. If {@code dir} | |
| 68 | * is set to true, this will first append all files in the same directory | |
| 69 | * as the actively edited file. | |
| 70 | * | |
| 71 | * @param future Indicates whether the export succeeded or failed. | |
| 72 | * @return The path to the exported file as a {@link Future}. | |
| 73 | */ | |
| 74 | @SuppressWarnings( "UnusedReturnValue" ) | |
| 75 | private static Future<Path> file_export( | |
| 76 | final Arguments args, final CompletableFuture<Path> future ) { | |
| 77 | assert args != null; | |
| 78 | assert future != null; | |
| 79 | ||
| 80 | final Callable<Path> callableTask = () -> { | |
| 81 | try { | |
| 82 | final var context = args.createProcessorContext(); | |
| 83 | final var outputPath = context.getTargetPath(); | |
| 84 | final var chain = createProcessors( context ); | |
| 85 | final var processor = createBootstrapProcessor( chain, context ); | |
| 86 | final var inputDoc = read( context ); | |
| 87 | final var outputDoc = processor.apply( inputDoc ); | |
| 88 | ||
| 89 | // Processors can export binary files. In such cases, processors will | |
| 90 | // return null to prevent further processing. | |
| 91 | final var result = outputDoc == null | |
| 92 | ? null | |
| 93 | : writeString( outputPath, outputDoc, UTF_8 ); | |
| 94 | ||
| 95 | future.complete( outputPath ); | |
| 96 | return result; | |
| 97 | } catch( final Throwable ex ) { | |
| 98 | future.completeExceptionally( ex ); | |
| 99 | return null; | |
| 100 | } | |
| 101 | }; | |
| 102 | ||
| 103 | // Prevent the application from blocking while the processor executes. | |
| 104 | return sExecutor.submit( callableTask ); | |
| 105 | } | |
| 106 | ||
| 107 | private static Processor<String> createBootstrapProcessor( | |
| 108 | final Processor<String> chain, final ProcessorContext context ) { | |
| 109 | ||
| 110 | return context.getSourceType() == TEXT_R_MARKDOWN | |
| 111 | ? new RBootstrapProcessor( chain, context ) | |
| 112 | : chain; | |
| 113 | } | |
| 114 | ||
| 115 | /** | |
| 116 | * Concatenates all the files in the same directory as the given file into | |
| 117 | * a string. The extension is determined by the given file name pattern; the | |
| 118 | * order files are concatenated is based on their numeric sort order (this | |
| 119 | * avoids lexicographic sorting). | |
| 120 | * <p> | |
| 121 | * If the parent path to the file being edited in the text editor cannot | |
| 122 | * be found then this will return the editor's text, without iterating through | |
| 123 | * the parent directory. (Should never happen, but who knows?) | |
| 124 | * </p> | |
| 125 | * <p> | |
| 126 | * New lines are automatically appended to separate each file. | |
| 127 | * </p> | |
| 128 | * | |
| 129 | * @param context The {@link ProcessorContext} containing input path, | |
| 130 | * and other command-line parameters. | |
| 131 | * @return All files in the same directory as the file being edited | |
| 132 | * concatenated into a single string. | |
| 133 | */ | |
| 134 | private static String read( final ProcessorContext context ) | |
| 135 | throws IOException { | |
| 136 | final var concat = context.getConcatenate(); | |
| 137 | final var inputPath = context.getSourcePath(); | |
| 138 | final var parent = inputPath.getParent(); | |
| 139 | final var filename = SysFile.getFileName( inputPath ); | |
| 140 | final var extension = getExtension( filename ); | |
| 141 | ||
| 142 | // Short-circuit because: only one file was requested; there is no parent | |
| 143 | // directory to scan for files; or there's no extension for globbing. | |
| 144 | if( !concat || parent == null || extension.isBlank() ) { | |
| 145 | return readString( inputPath, UTF_8 ); | |
| 146 | } | |
| 147 | ||
| 148 | final var command = new ConcatenateCommand( | |
| 149 | parent, extension, context.getChapters() ); | |
| 150 | return command.call(); | |
| 151 | } | |
| 152 | } | |
| 1 | 153 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite; | |
| 3 | ||
| 4 | import com.keenwrite.constants.Constants; | |
| 5 | import com.keenwrite.io.UserDataDir; | |
| 1 | 6 | |
| 7 | import java.io.File; | |
| 8 | import java.io.InputStream; | |
| 9 | import java.nio.file.Pathio.SysFile.toFilvar appVersion = "0.0.0"; | |
| 10 | vartoFile( |
| 1 | /* Copyright 2020-2024 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite; | |
| 6 | ||
| 7 | import com.keenwrite.io.MediaType; | |
| 8 | import com.keenwrite.io.MediaTypeExtension; | |
| 9 | ||
| 10 | import java.io.File; | |
| 11 | import java.nio.file.Path; | |
| 12 | ||
| 13 | import static com.keenwrite.io.SysFile.toFile; | |
| 14 | import static java.lang.String.format; | |
| 15 | import static org.apache.commons.io.FilenameUtils.removeExtension; | |
| 16 | ||
| 17 | /** | |
| 18 | * Provides controls for processor behaviour when transforming input documents. | |
| 19 | */ | |
| 20 | public enum ExportFormat { | |
| 21 | ||
| 22 | /** | |
| 23 | * For HTML exports, encode TeX as SVG. Treat image links relatively. | |
| 24 | */ | |
| 25 | HTML_TEX_SVG( ".html" ), | |
| 26 | ||
| 27 | /** | |
| 28 | * For HTML exports, encode TeX using {@code $} delimiters, suitable for | |
| 29 | * rendering by an external TeX typesetting engine (or online with KaTeX). | |
| 30 | * Treat image links relatively. | |
| 31 | */ | |
| 32 | HTML_TEX_DELIMITED( ".html" ), | |
| 33 | ||
| 34 | /** | |
| 35 | * For XHTML exports, encode TeX using {@code $} delimiters. | |
| 36 | */ | |
| 37 | XHTML_TEX( ".xhtml" ), | |
| 38 | ||
| 39 | /** | |
| 40 | * For TEXT exports, encode TeX using {@code $} delimiters. | |
| 41 | */ | |
| 42 | TEXT_TEX( ".txt" ), | |
| 43 | ||
| 44 | /** | |
| 45 | * Exports as PDF file format. | |
| 46 | */ | |
| 47 | APPLICATION_PDF( ".pdf" ), | |
| 48 | ||
| 49 | /** | |
| 50 | * Indicates no special export format is to be created. No extension is | |
| 51 | * applicable. Image links must use absolute directories. | |
| 52 | */ | |
| 53 | NONE( "" ); | |
| 54 | ||
| 55 | /** | |
| 56 | * Preferred file name extension for the given file type. | |
| 57 | */ | |
| 58 | private final String mExtension; | |
| 59 | ||
| 60 | /** | |
| 61 | * Looks up the {@link ExportFormat} based on the given path and subtype. | |
| 62 | * | |
| 63 | * @param path The type to find. | |
| 64 | * @param modifier The subtype to find (for HTML). | |
| 65 | * @return An object to control the output file format. | |
| 66 | * @throws IllegalArgumentException The type/subtype could not be found. | |
| 67 | */ | |
| 68 | public static ExportFormat valueFrom( final Path path, final String modifier ) | |
| 69 | throws IllegalArgumentException { | |
| 70 | assert path != null; | |
| 71 | ||
| 72 | return valueFrom( MediaType.fromFilename( path ), modifier ); | |
| 73 | } | |
| 74 | ||
| 75 | /** | |
| 76 | * Looks up the {@link ExportFormat} based on the given path and subtype. | |
| 77 | * | |
| 78 | * @param extension The type to find. | |
| 79 | * @param modifier The subtype to find (for HTML). | |
| 80 | * @return An object to control the output file format. | |
| 81 | * @throws IllegalArgumentException The type/subtype could not be found. | |
| 82 | */ | |
| 83 | public static ExportFormat valueFrom( | |
| 84 | final String extension, final String modifier ) | |
| 85 | throws IllegalArgumentException { | |
| 86 | assert extension != null; | |
| 87 | ||
| 88 | return valueFrom( MediaTypeExtension.fromExtension( extension ), modifier ); | |
| 89 | } | |
| 90 | ||
| 91 | /** | |
| 92 | * Looks up the {@link ExportFormat} based on the given path and subtype. | |
| 93 | * | |
| 94 | * @param type The media type to find. | |
| 95 | * @param modifier The subtype to find (for HTML). | |
| 96 | * @return An object to control the output file format. | |
| 97 | * @throws IllegalArgumentException The type/subtype could not be found. | |
| 98 | */ | |
| 99 | public static ExportFormat valueFrom( | |
| 100 | final MediaType type, final String modifier ) { | |
| 101 | return switch( type ) { | |
| 102 | case TEXT_HTML, TEXT_XHTML -> "svg".equalsIgnoreCase( modifier.trim() ) | |
| 103 | ? HTML_TEX_SVG | |
| 104 | : HTML_TEX_DELIMITED; | |
| 105 | case APP_PDF -> APPLICATION_PDF; | |
| 106 | case TEXT_XML -> XHTML_TEX; | |
| 107 | default -> throw new IllegalArgumentException( format( | |
| 108 | "Unrecognized format type and subtype: '%s' and '%s'", type, modifier | |
| 109 | ) ); | |
| 110 | }; | |
| 111 | } | |
| 112 | ||
| 113 | ExportFormat( final String extension ) { | |
| 114 | mExtension = extension; | |
| 115 | } | |
| 116 | ||
| 117 | /** | |
| 118 | * Returns the given {@link File} with its extension replaced by one that | |
| 119 | * matches this {@link ExportFormat} extension. | |
| 120 | * | |
| 121 | * @param file The file to perform an extension swap. | |
| 122 | * @return The given file with its extension replaced. | |
| 123 | */ | |
| 124 | public File toExportFilename( final File file ) { | |
| 125 | return new File( removeExtension( file.getName() ) + mExtension ); | |
| 126 | } | |
| 127 | ||
| 128 | /** | |
| 129 | * Delegates to {@link #toExportFilename(File)} after converting the given | |
| 130 | * {@link Path} to an instance of {@link File}. | |
| 131 | * | |
| 132 | * @param path The {@link Path} to convert to a {@link File}. | |
| 133 | * @return The given path with its extension replaced. | |
| 134 | */ | |
| 135 | public File toExportFilename( final Path path ) { | |
| 136 | return toExportFilename( toFile( path ) ); | |
| 137 | } | |
| 138 | } | |
| 1 | 139 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite; | |
| 3 | ||
| 4 | import com.keenwrite.cmdline.Arguments; | |
| 5 | import com.keenwrite.cmdline.ColourScheme; | |
| 6 | import com.keenwrite.cmdline.HeadleLaunches the application using the {@link MainApp} clas elseoutSystem.errto standard error, suppresse // TODO: Delete this after JavaFX/GTK 3 no longer barfs useless warnings. | |
| 7 | System.err.closeoutSystem.outout( "%noutMainApp.maimain( args} | |
| 1 | 8 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite; | |
| 3 | ||
| 4 | import com.keenwrite.cmdline.HeadlessApp; | |
| 5 | import com.keenwrite.events.HyperlinkOpenEvent; | |
| 6 | import com.keenwrite.preferences.Workspace; | |
| 7 | import com.keenwrite.preview.MathRenderer; | |
| 8 | import com.keenwrite.spelling.impl.Lexicon; | |
| 9 | import javafx.application.Application; | |
| 10 | import javafx.event.Event; | |
| 11 | import javafx.event.EventType; | |
| 12 | import javafx.scene.input.KeyCode; | |
| 13 | import javafx.scene.input.KeyEvent; | |
| 14 | import javafx.stage.Stage; | |
| 15 | import org.greenrobot.eventbus.Subscribe; | |
| 16 | ||
| 17 | import java.io.PrintStream; | |
| 18 | import java.util.function.BooleanSupplier; | |
| 19 | ||
| 20 | import static com.keenwrite.Bootstrap.APP_TITLE; | |
| 21 | import static com.keenwrite.constants.GraphicsConstants.LOGOS; | |
| 22 | import static com.keenwrite.events.Bus.register; | |
| 23 | import static com.keenwrite.preferences.AppKeys.*; | |
| 24 | import static com.keenwrite.util.FontLoader.initFonts; | |
| 25 | import static javafx.scene.input.KeyCode.F11; | |
| 26 | import static javafx.scene.input.KeyEvent.KEY_PRESSED; | |
| 27 | import static javafx.scene.input.KeyEvent.KEY_RELEASED; | |
| 28 | import static javafx.stage.WindowEvent.WINDOW_SHOWN; | |
| 29 | ||
| 30 | /** | |
| 31 | * Application entry point. The application allows users to edit plain text | |
| 32 | * files in a markup notation and see a real-time preview of the formatted | |
| 33 | * output. | |
| 34 | */ | |
| 35 | public final class MainApp extends Application { | |
| 36 | ||
| 37 | private Workspace mWorkspace; | |
| 38 | ||
| 39 | /** | |
| 40 | * TODO: Delete this after JavaFX/GTK 3 no longer barfs useless warnings. | |
| 41 | */ | |
| 42 | @SuppressWarnings( "SameParameterValue" ) | |
| 43 | private static void stderrRedirect( final PrintStream stream ) { | |
| 44 | System.setErr( stream ); | |
| 45 | } | |
| 46 | ||
| 47 | /** | |
| 48 | * GUI application entry point. See {@link HeadlessApp} for the entry | |
| 49 | * point to the command-line application. | |
| 50 | * | |
| 51 | * @param args Command-line arguments. | |
| 52 | */ | |
| 53 | public static void main( final String[] args ) { | |
| 54 | launch( args ); | |
| 55 | } | |
| 56 | ||
| 57 | /** | |
| 58 | * Creates an instance of {@link KeyEvent} that represents pressing a key. | |
| 59 | * | |
| 60 | * @param code The key to simulate being pressed down. | |
| 61 | * @param shift Whether shift key modifier shall modify the key code. | |
| 62 | * @return An instance of {@link KeyEvent} that may be used to simulate | |
| 63 | * a key being pressed. | |
| 64 | */ | |
| 65 | public static Event keyDown( final KeyCode code, final boolean shift ) { | |
| 66 | return keyEvent( KEY_PRESSED, code, shift ); | |
| 67 | } | |
| 68 | ||
| 69 | /** | |
| 70 | * Creates an instance of {@link KeyEvent} that represents a key released | |
| 71 | * event without any modifier keys held. | |
| 72 | * | |
| 73 | * @param code The key code representing a key to simulate releasing. | |
| 74 | * @return An instance of {@link KeyEvent}. | |
| 75 | */ | |
| 76 | public static Event keyDown( final KeyCode code ) { | |
| 77 | return keyDown( code, false ); | |
| 78 | } | |
| 79 | ||
| 80 | /** | |
| 81 | * Creates an instance of {@link KeyEvent} that represents releasing a key. | |
| 82 | * | |
| 83 | * @param code The key to simulate being released up. | |
| 84 | * @param shift Whether shift key modifier shall modify the key code. | |
| 85 | * @return An instance of {@link KeyEvent} that may be used to simulate | |
| 86 | * a key being released. | |
| 87 | */ | |
| 88 | @SuppressWarnings( "unused" ) | |
| 89 | public static Event keyUp( final KeyCode code, final boolean shift ) { | |
| 90 | return keyEvent( KEY_RELEASED, code, shift ); | |
| 91 | } | |
| 92 | ||
| 93 | private static Event keyEvent( | |
| 94 | final EventType<KeyEvent> type, final KeyCode code, final boolean shift ) { | |
| 95 | return new KeyEvent( | |
| 96 | type, "", "", code, shift, false, false, false | |
| 97 | ); | |
| 98 | } | |
| 99 | ||
| 100 | /** | |
| 101 | * JavaFX entry point. | |
| 102 | * | |
| 103 | * @param stage The primary application stage. | |
| 104 | */ | |
| 105 | @Override | |
| 106 | public void start( final Stage stage ) { | |
| 107 | // Must be instantiated after the UI is initialized (i.e., not in main) | |
| 108 | // because it interacts with GUI properties. | |
| 109 | mWorkspace = new Workspace(); | |
| 110 | ||
| 111 | // The locale was already loaded when the workspace was created. This | |
| 112 | // ensures that when the locale preference changes, a new spellchecker | |
| 113 | // instance will be loaded and applied. | |
| 114 | final var property = mWorkspace.localeProperty( KEY_LANGUAGE_LOCALE ); | |
| 115 | property.addListener( ( _, _, _ ) -> readLexicon() ); | |
| 116 | ||
| 117 | initFonts(); | |
| 118 | initState( stage ); | |
| 119 | initStage( stage ); | |
| 120 | initIcons( stage ); | |
| 121 | initScene( stage ); | |
| 122 | ||
| 123 | MathRenderer.bindSize( mWorkspace.doubleProperty( KEY_UI_FONT_MATH_SIZE ) ); | |
| 124 | ||
| 125 | // Load the lexicon and check all the documents after all files are open. | |
| 126 | stage.addEventFilter( WINDOW_SHOWN, _ -> readLexicon() ); | |
| 127 | stage.show(); | |
| 128 | ||
| 129 | stderrRedirect( System.out ); | |
| 130 | ||
| 131 | register( this ); | |
| 132 | } | |
| 133 | ||
| 134 | private void initState( final Stage stage ) { | |
| 135 | final var enable = createBoundsEnabledSupplier( stage ); | |
| 136 | ||
| 137 | stage.setX( mWorkspace.getDouble( KEY_UI_WINDOW_X ) ); | |
| 138 | stage.setY( mWorkspace.getDouble( KEY_UI_WINDOW_Y ) ); | |
| 139 | stage.setWidth( mWorkspace.getDouble( KEY_UI_WINDOW_W ) ); | |
| 140 | stage.setHeight( mWorkspace.getDouble( KEY_UI_WINDOW_H ) ); | |
| 141 | stage.setMaximized( mWorkspace.getBoolean( KEY_UI_WINDOW_MAX ) ); | |
| 142 | stage.setFullScreen( mWorkspace.getBoolean( KEY_UI_WINDOW_FULL ) ); | |
| 143 | ||
| 144 | mWorkspace.listen( KEY_UI_WINDOW_X, stage.xProperty(), enable ); | |
| 145 | mWorkspace.listen( KEY_UI_WINDOW_Y, stage.yProperty(), enable ); | |
| 146 | mWorkspace.listen( KEY_UI_WINDOW_W, stage.widthProperty(), enable ); | |
| 147 | mWorkspace.listen( KEY_UI_WINDOW_H, stage.heightProperty(), enable ); | |
| 148 | mWorkspace.listen( KEY_UI_WINDOW_MAX, stage.maximizedProperty() ); | |
| 149 | mWorkspace.listen( KEY_UI_WINDOW_FULL, stage.fullScreenProperty() ); | |
| 150 | } | |
| 151 | ||
| 152 | private void initStage( final Stage stage ) { | |
| 153 | stage.setTitle( APP_TITLE ); | |
| 154 | stage.addEventHandler( KEY_PRESSED, event -> { | |
| 155 | if( F11.equals( event.getCode() ) ) { | |
| 156 | stage.setFullScreen( !stage.isFullScreen() ); | |
| 157 | } | |
| 158 | } ); | |
| 159 | } | |
| 160 | ||
| 161 | private void initIcons( final Stage stage ) { | |
| 162 | stage.getIcons().addAll( LOGOS ); | |
| 163 | } | |
| 164 | ||
| 165 | private void initScene( final Stage stage ) { | |
| 166 | final var mainScene = new MainScene( mWorkspace ); | |
| 167 | stage.setScene( mainScene.getScene() ); | |
| 168 | } | |
| 169 | ||
| 170 | /** | |
| 171 | * When a hyperlink website URL is clicked, this method is called to launch | |
| 172 | * the default browser to the event's location. | |
| 173 | * | |
| 174 | * @param event The event called when a hyperlink was clicked. | |
| 175 | */ | |
| 176 | @Subscribe | |
| 177 | public void handle( final HyperlinkOpenEvent event ) { | |
| 178 | getHostServices().showDocument( event.getUri().toString() ); | |
| 179 | } | |
| 180 | ||
| 181 | /** | |
| 182 | * This will load the lexicon for the user's preferred locale and fire | |
| 183 | * an event when the all entries in the lexicon have been loaded. | |
| 184 | */ | |
| 185 | private void readLexicon() { | |
| 186 | Lexicon.read( mWorkspace.getLocale() ); | |
| 187 | } | |
| 188 | ||
| 189 | /** | |
| 190 | * When the window is maximized, full screen, or iconified, prevent updating | |
| 191 | * the window bounds. This is used so that if the user exits the application | |
| 192 | * when full screen (or maximized), restarting the application will recall | |
| 193 | * the previous bounds, allowing for continuity of expected behaviour. | |
| 194 | * | |
| 195 | * @param stage The window to check for "normal" status. | |
| 196 | * @return {@code false} when the bounds must not be changed, ergo persisted. | |
| 197 | */ | |
| 198 | private BooleanSupplier createBoundsEnabledSupplier( final Stage stage ) { | |
| 199 | return () -> | |
| 200 | !(stage.isMaximized() || stage.isFullScreen() || stage.isIconified()); | |
| 201 | } | |
| 202 | } | |
| 1 | 203 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite; | |
| 1 | 3 | |
| 4 | import com.keenwrite.constants.Constants; | |
| 5 | import com.keenwrite.editors.TextDefinition; | |
| 6 | import com.keenwrite.editors.TextEditor; | |
| 7 | import com.keenwrite.editoTR."\{key}prefix"TR."\{key}suffix"TR."\{prefix}.\{suffix}"TR."\{prefix}-\{i}.\{suffix}" |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite; | |
| 1 | 3 | |
| 4 | import com.keenwrite.io.FileModifiedListener; | |
| 5 | import com.keenwrite.io.FileWatchService; | |
| 6 | import com.keenwrite.preferences.Workspace; | |
| 7 | import com.keenwrite.uSCROLL_LOCK |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite; | |
| 1 | 3 | |
| 4 | import com.keenwrite.collections.InterpolatingMap; | |
| 5 | import com.keenwrite.preferences.Key; | |
| 6 | import com.keenwrite.sigils.PropertyKeyOperator; | |
| 7 | import com.keenwnet.URI;public static URI getUriURI.create( get( key |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite; | |
| 3 | ||
| 4 | import java.util.HashMap; | |
| 5 | import java.util.Map; | |
| 6 | import java.util.ServiceLoader; | |
| 1 | 7 | |
| 8 | /** | |
| 9 | * Responsible for loading services. The services are treated as singleton |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.cmdline; | |
| 1 | 6 | |
| 7 | import com.fasterxml.jackson.databind.JsonNode; | |
| 8 | import com.fasterxml.jackson.databind.ObjectMapper; | |
| 9 | import comTR."\{parent}.\{node.getKey()}" |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.cmdline; | |
| 6 | ||
| 7 | import static picocli.CommandLine.Help.Ansi.Style.*; | |
| 8 | import static picocli.CommandLine.Help.ColorScheme; | |
| 9 | import static picocli.CommandLine.Help.ColorScheme.Builder; | |
| 1 | 10 | |
| 11 | /** | |
| 12 | * Responsible for creating the command-line parser's |
| 1 | package com.keenwrite.cmdline; | |
| 2 | ||
| 3 | import com.keenwrite.AppCommands; | |
| 4 | import com.keenwrite.events.StatusEvent; | |
| 5 | import org.greenrobot.eventbus.Subscribe; | |
| 6 | ||
| 7 | import static com.keenwrite.events.Bus.register; | |
| 8 | import static java.lang.String.format; | |
| 1 | 9 | |
| 10 | /** | |
| 11 | * Responsible for running the application in headlassert event != null; | |
| 12 | final var stacktrace = event.getProblem(); | |
| 13 | final var problem = stacktrace.isBlank() | |
| 14 | ? "" | |
| 15 | : format( "%n%s", stacktrace ); | |
| 16 | final var msg = format( "%s%s", event, problem ); | |
| 17 | msg |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.collections; | |
| 3 | ||
| 4 | import java.util.LinkedHashMap; | |
| 5 | import java.util.Map; | |
| 6 | ||
| 7 | /** | |
| 8 | * A map that removes the oldest entry once its capacity (cache size) has | |
| 9 | * been reached. | |
| 10 | * | |
| 11 | * @param <K> The type of key mapped to a value. | |
| 12 | * @param <V> The type of value mapped to a key. | |
| 13 | */ | |
| 14 | public final class BoundedCache<K, V> extends LinkedHashMap<K, V> { | |
| 15 | private final int mCacheSize; | |
| 16 | ||
| 17 | /** | |
| 18 | * Constructs a new instance having a finite size. | |
| 19 | * | |
| 20 | * @param cacheSize The maximum number of entries. | |
| 21 | */ | |
| 22 | public BoundedCache( final int cacheSize ) { | |
| 23 | mCacheSize = cacheSize; | |
| 24 | } | |
| 25 | ||
| 26 | @Override | |
| 27 | protected boolean removeEldestEntry( final Map.Entry<K, V> eldest ) { | |
| 28 | return size() > mCacheSize; | |
| 29 | } | |
| 30 | } | |
| 1 | 31 |
| 1 | /* Copyright 2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.collections; | |
| 3 | ||
| 4 | import org.jetbrains.annotations.NotNull; | |
| 5 | ||
| 6 | import java.util.*; | |
| 7 | ||
| 8 | import static java.lang.Math.min; | |
| 1 | 9 | |
| 10 | /** | |
| 11 | * Responsible for maintaining a circular queue where newly added items will | |
| 12 | * overwri@NotNull |
| 1 | /* Copyright 2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.collections; | |
| 3 | ||
| 4 | import com.keenwrite.sigils.PropertyKeyOperator; | |
| 5 | import com.keenwrite.sigils.SigilKeyOperator; | |
| 1 | 6 | |
| 7 | import java.io.Serial; | |
| 8 | import java.util.HashMap; | |
| 9 | imSTR."Mapped value '\{mapValue}\{keyName}'" |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.commands; | |
| 1 | 6 | |
| 7 | import com.keenwrite.io.SysFile; | |
| 8 | import com.keenwrite.util.AlphanumComparator; | |
| 9 | import com.keenwrite.util.RangeValiSTR."**/*.\{mExtension}" |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.config; | |
| 6 | ||
| 7 | import com.keenwrite.collections.InterpolatingMap; | |
| 8 | ||
| 9 | import java.io.IOException; | |
| 10 | import java.io.Reader; | |
| 11 | import java.util.*; | |
| 12 | ||
| 13 | import static java.util.Arrays.*; | |
| 14 | ||
| 15 | /** | |
| 16 | * Responsible for reading and interpolating properties files. | |
| 17 | */ | |
| 18 | public class PropertiesConfiguration { | |
| 19 | private static final String VALUE_SEPARATOR = ","; | |
| 20 | ||
| 21 | private final InterpolatingMap mMap = new InterpolatingMap(); | |
| 22 | ||
| 23 | public PropertiesConfiguration() {} | |
| 24 | ||
| 25 | public void read( final Reader reader ) throws IOException { | |
| 26 | final var properties = new Properties(); | |
| 27 | properties.load( reader ); | |
| 28 | ||
| 29 | for( final var name : properties.stringPropertyNames() ) { | |
| 30 | mMap.put( name, properties.getProperty( name ) ); | |
| 31 | } | |
| 32 | ||
| 33 | mMap.interpolate(); | |
| 34 | } | |
| 35 | ||
| 36 | /** | |
| 37 | * Returns the value of a string property. | |
| 38 | * | |
| 39 | * @param property The property key. | |
| 40 | * @param defaultValue The value to return if no property key has been set. | |
| 41 | * @return The property key value, or defaultValue when no key found. | |
| 42 | */ | |
| 43 | public String getString( final String property, final String defaultValue ) { | |
| 44 | assert property != null; | |
| 45 | ||
| 46 | return mMap.getOrDefault( property, defaultValue ); | |
| 47 | } | |
| 48 | ||
| 49 | /** | |
| 50 | * Returns the value of a string property. | |
| 51 | * | |
| 52 | * @param property The property key. | |
| 53 | * @param defaultValue The value to return if no property key has been set. | |
| 54 | * @return The property key value, or defaultValue when no key found. | |
| 55 | */ | |
| 56 | public int getInt( final String property, final int defaultValue ) { | |
| 57 | assert property != null; | |
| 58 | ||
| 59 | return parse( mMap.get( property ), defaultValue ); | |
| 60 | } | |
| 61 | ||
| 62 | /** | |
| 63 | * Convert the generic list of property objects into strings. | |
| 64 | * | |
| 65 | * @param property The property value to coerce. | |
| 66 | * @param defaults The values to use should the property be unset. | |
| 67 | * @return The list of properties coerced from objects to strings. | |
| 68 | */ | |
| 69 | public List<String> getList( | |
| 70 | final String property, final List<String> defaults ) { | |
| 71 | assert property != null; | |
| 72 | ||
| 73 | final var value = mMap.get( property ); | |
| 74 | ||
| 75 | return value == null | |
| 76 | ? defaults | |
| 77 | : asList( value.split( VALUE_SEPARATOR ) ); | |
| 78 | } | |
| 79 | ||
| 80 | /** | |
| 81 | * Returns a list of property names that begin with the given prefix. | |
| 82 | * Note that the prefix must be separated from other values with a | |
| 83 | * period. | |
| 84 | * | |
| 85 | * @param prefix The prefix to compare against each property name. When | |
| 86 | * comparing, the prefix value will have a period appended. | |
| 87 | * @return The list of property names that have the given prefix. | |
| 88 | */ | |
| 89 | public Iterator<String> getKeys( final String prefix ) { | |
| 90 | assert prefix != null; | |
| 91 | ||
| 92 | final var result = new HashMap<String, String>(); | |
| 93 | final var prefixDotted = prefix + '.'; | |
| 94 | ||
| 95 | for( final var entry : mMap.entrySet() ) { | |
| 96 | final var key = entry.getKey(); | |
| 97 | ||
| 98 | if( key.startsWith( prefixDotted ) ) { | |
| 99 | final var value = entry.getValue(); | |
| 100 | result.put( key, value ); | |
| 101 | } | |
| 102 | } | |
| 103 | ||
| 104 | return result.keySet().iterator(); | |
| 105 | } | |
| 106 | ||
| 107 | private static int parse( final String s, final int defaultValue ) { | |
| 108 | try { | |
| 109 | return s == null || s.isBlank() ? defaultValue : Integer.parseInt( s ); | |
| 110 | } catch( final NumberFormatException e ) { | |
| 111 | return defaultValue; | |
| 112 | } | |
| 113 | } | |
| 114 | } | |
| 1 | 115 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.constants; | |
| 6 | ||
| 7 | import com.keenwrite.Bootstrap; | |
| 8 | import com.keenwrite.Services; | |
| 9 | import com.keenwrite.service.Settings; | |
| 1 | 10 | |
| 11 | import javTR."file.default.\{suffix}" ) |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.constants; | |
| 6 | ||
| 7 | import javafx.scene.image.Image; | |
| 8 | import javafx.scene.image.ImageView; | |
| 9 | ||
| 10 | import java.util.ArrayList; | |
| 11 | import java.util.List; | |
| 1 | 12 | |
| 13 | import static com.kee |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.dom; | |
| 1 | 6 | |
| 7 | import org.jetbrains.annotations.NotNull; | |
| 8 | import org.jsoup.Jsoup; | |
| 9 | import org.jsoup.helper.W3CDom; | |
| 10 | import org.jsoup.node |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.dom; | |
| 6 | ||
| 7 | import org.w3c.dom.*; | |
| 8 | import org.xml.sax.InputSource; | |
| 9 | import org.xml.sax.SAXException; | |
| 10 | ||
| 11 | import javax.xml.parsers.DocumentBuilder; | |
| 12 | import javax.xml.parsers.DocumentBuilderFactory; | |
| 13 | import javax.xml.transform.Transformer; | |
| 14 | import javax.xml.transform.TransformerException; | |
| 15 | import javax.xml.transform.TransformerFactory; | |
| 16 | import javax.xml.transform.dom.DOMSource; | |
| 17 | import javax.xml.transform.stream.StreamResult; | |
| 18 | import javax.xml.xpath.XPath; | |
| 19 | import javax.xml.xpath.XPathExpression; | |
| 20 | import javax.xml.xpath.XPathExpressionException; | |
| 21 | import javax.xml.xpath.XPathFactory; | |
| 22 | import java.io.*; | |
| 23 | import java.nio.file.Path; | |
| 24 | import java.util.HashMap; | |
| 25 | import java.util.Map; | |
| 26 | import java.util.function.Consumer; | |
| 27 | ||
| 28 | import static com.keenwrite.events.StatusEvent.clue; | |
| 29 | import static com.keenwrite.io.SysFile.toFile; | |
| 30 | import static java.nio.charset.StandardCharsets.UTF_16; | |
| 31 | import static java.nio.charset.StandardCharsets.UTF_8; | |
| 32 | import static java.nio.file.Files.write; | |
| 33 | import static javax.xml.transform.OutputKeys.*; | |
| 34 | import static javax.xml.xpath.XPathConstants.NODESET; | |
| 35 | ||
| 36 | /** | |
| 37 | * Responsible for initializing an XML parser. | |
| 38 | */ | |
| 39 | public class DocumentParser { | |
| 40 | private static final String LOAD_EXTERNAL_DTD = | |
| 41 | "http://apache.org/xml/features/nonvalidating/load-external-dtd"; | |
| 42 | private static final String INDENT_AMOUNT = | |
| 43 | "{http://xml.apache.org/xslt}indent-amount"; | |
| 44 | ||
| 45 | private static final ByteArrayOutputStream sWriter = | |
| 46 | new ByteArrayOutputStream( 65536 ); | |
| 47 | private static final OutputStreamWriter sOutput = | |
| 48 | new OutputStreamWriter( sWriter, UTF_8 ); | |
| 49 | ||
| 50 | /** | |
| 51 | * Caches {@link XPathExpression}s to avoid re-compiling. | |
| 52 | */ | |
| 53 | private static final Map<String, XPathExpression> sXpaths = new HashMap<>(); | |
| 54 | ||
| 55 | private static final DocumentBuilderFactory sDocumentFactory; | |
| 56 | private static DocumentBuilder sDocumentBuilder; | |
| 57 | private static Transformer sTransformer; | |
| 58 | private static final XPath sXpath = XPathFactory.newInstance().newXPath(); | |
| 59 | ||
| 60 | public static final DOMImplementation sDomImplementation; | |
| 61 | ||
| 62 | static { | |
| 63 | sDocumentFactory = DocumentBuilderFactory.newInstance(); | |
| 64 | ||
| 65 | sDocumentFactory.setValidating( false ); | |
| 66 | sDocumentFactory.setAttribute( LOAD_EXTERNAL_DTD, false ); | |
| 67 | sDocumentFactory.setNamespaceAware( true ); | |
| 68 | sDocumentFactory.setIgnoringComments( true ); | |
| 69 | sDocumentFactory.setIgnoringElementContentWhitespace( true ); | |
| 70 | ||
| 71 | DOMImplementation domImplementation; | |
| 72 | ||
| 73 | try { | |
| 74 | sDocumentBuilder = sDocumentFactory.newDocumentBuilder(); | |
| 75 | domImplementation = sDocumentBuilder.getDOMImplementation(); | |
| 76 | sTransformer = TransformerFactory.newInstance().newTransformer(); | |
| 77 | ||
| 78 | // Ensure Unicode characters (emojis) are encoded correctly. | |
| 79 | sTransformer.setOutputProperty( ENCODING, UTF_16.toString() ); | |
| 80 | sTransformer.setOutputProperty( OMIT_XML_DECLARATION, "yes" ); | |
| 81 | sTransformer.setOutputProperty( METHOD, "xml" ); | |
| 82 | sTransformer.setOutputProperty( INDENT, "no" ); | |
| 83 | sTransformer.setOutputProperty( INDENT_AMOUNT, "2" ); | |
| 84 | } catch( final Exception ex ) { | |
| 85 | clue( ex ); | |
| 86 | domImplementation = sDocumentBuilder.getDOMImplementation(); | |
| 87 | } | |
| 88 | ||
| 89 | sDomImplementation = domImplementation; | |
| 90 | } | |
| 91 | ||
| 92 | public static Document newDocument() { | |
| 93 | return sDocumentBuilder.newDocument(); | |
| 94 | } | |
| 95 | ||
| 96 | /** | |
| 97 | * Creates a new document object model based on the given XML document | |
| 98 | * string. This will return an empty document if the document could not | |
| 99 | * be parsed. | |
| 100 | * | |
| 101 | * @param xml The document text to convert into a DOM. | |
| 102 | * @return The DOM that represents the given XML data. | |
| 103 | */ | |
| 104 | public static Document parse( final String xml ) { | |
| 105 | assert xml != null; | |
| 106 | ||
| 107 | final var input = new InputSource(); | |
| 108 | ||
| 109 | try( final var reader = new StringReader( xml ) ) { | |
| 110 | input.setEncoding( UTF_8.toString() ); | |
| 111 | input.setCharacterStream( reader ); | |
| 112 | ||
| 113 | return sDocumentBuilder.parse( input ); | |
| 114 | } catch( final Throwable t ) { | |
| 115 | clue( t ); | |
| 116 | ||
| 117 | return sDocumentBuilder.newDocument(); | |
| 118 | } | |
| 119 | } | |
| 120 | ||
| 121 | /** | |
| 122 | * Parses the given file contents into a document object model. | |
| 123 | * | |
| 124 | * @param doc The source XML document to parse. | |
| 125 | * @return The file as a document object model. | |
| 126 | * @throws IOException Could not open the document. | |
| 127 | * @throws SAXException Could not read the XML file content. | |
| 128 | */ | |
| 129 | public static Document parse( final File doc ) | |
| 130 | throws IOException, SAXException { | |
| 131 | assert doc != null; | |
| 132 | ||
| 133 | try( final var in = new FileInputStream( doc ) ) { | |
| 134 | return parse( in ); | |
| 135 | } | |
| 136 | } | |
| 137 | ||
| 138 | /** | |
| 139 | * Parses the given file contents into a document object model. Callers | |
| 140 | * must close the stream. | |
| 141 | * | |
| 142 | * @param doc The source XML document to parse. | |
| 143 | * @return The {@link InputStream} converted to a document object model. | |
| 144 | * @throws IOException Could not open the document. | |
| 145 | * @throws SAXException Could not read the XML file content. | |
| 146 | */ | |
| 147 | public static Document parse( final InputStream doc ) | |
| 148 | throws IOException, SAXException { | |
| 149 | assert doc != null; | |
| 150 | ||
| 151 | return sDocumentBuilder.parse( doc ); | |
| 152 | } | |
| 153 | ||
| 154 | /** | |
| 155 | * Allows an operation to be applied for every node in the document that | |
| 156 | * matches a given tag name pattern. | |
| 157 | * | |
| 158 | * @param document Document to traverse. | |
| 159 | * @param xpath Document elements to find via {@link XPath} expression. | |
| 160 | * @param consumer The consumer to call for each matching document node. | |
| 161 | */ | |
| 162 | public static void visit( | |
| 163 | final Document document, | |
| 164 | final CharSequence xpath, | |
| 165 | final Consumer<Node> consumer ) { | |
| 166 | assert document != null; | |
| 167 | assert consumer != null; | |
| 168 | ||
| 169 | try { | |
| 170 | final var expr = compile( xpath ); | |
| 171 | final var nodeSet = expr.evaluate( document, NODESET ); | |
| 172 | ||
| 173 | if( nodeSet instanceof NodeList nodes ) { | |
| 174 | for( int i = 0, len = nodes.getLength(); i < len; i++ ) { | |
| 175 | consumer.accept( nodes.item( i ) ); | |
| 176 | } | |
| 177 | } | |
| 178 | } catch( final Exception ex ) { | |
| 179 | clue( ex ); | |
| 180 | } | |
| 181 | } | |
| 182 | ||
| 183 | public static Node createMeta( | |
| 184 | final Document document, final Map.Entry<String, String> entry ) { | |
| 185 | assert document != null; | |
| 186 | assert entry != null; | |
| 187 | ||
| 188 | final var node = document.createElement( "meta" ); | |
| 189 | ||
| 190 | node.setAttribute( "name", entry.getKey() ); | |
| 191 | node.setAttribute( "content", entry.getValue() ); | |
| 192 | ||
| 193 | return node; | |
| 194 | } | |
| 195 | ||
| 196 | public static Node createEncoding( | |
| 197 | final Document document, final String encoding | |
| 198 | ) { | |
| 199 | assert document != null; | |
| 200 | assert encoding != null; | |
| 201 | ||
| 202 | final var node = document.createElement( "meta" ); | |
| 203 | ||
| 204 | node.setAttribute( "charset", encoding ); | |
| 205 | ||
| 206 | return node; | |
| 207 | } | |
| 208 | ||
| 209 | public static Node createElement( | |
| 210 | final Document doc, final String nodeName, final String nodeValue ) { | |
| 211 | assert doc != null; | |
| 212 | assert nodeName != null; | |
| 213 | assert !nodeName.isBlank(); | |
| 214 | ||
| 215 | final var node = doc.createElement( nodeName ); | |
| 216 | ||
| 217 | if( nodeValue != null ) { | |
| 218 | node.setTextContent( nodeValue ); | |
| 219 | } | |
| 220 | ||
| 221 | return node; | |
| 222 | } | |
| 223 | ||
| 224 | public static String toString( final Document xhtml ) { | |
| 225 | assert xhtml != null; | |
| 226 | ||
| 227 | try( final var writer = new StringWriter() ) { | |
| 228 | final var result = new StreamResult( writer ); | |
| 229 | ||
| 230 | transform( xhtml, result ); | |
| 231 | ||
| 232 | return writer.toString(); | |
| 233 | } catch( final Exception ex ) { | |
| 234 | clue( ex ); | |
| 235 | return ""; | |
| 236 | } | |
| 237 | } | |
| 238 | ||
| 239 | public static String transform( final Element root ) | |
| 240 | throws IOException, TransformerException { | |
| 241 | assert root != null; | |
| 242 | ||
| 243 | try( final var writer = new StringWriter() ) { | |
| 244 | transform( root.getOwnerDocument(), new StreamResult( writer ) ); | |
| 245 | ||
| 246 | return writer.toString(); | |
| 247 | } | |
| 248 | } | |
| 249 | ||
| 250 | /** | |
| 251 | * Remove whitespace, comments, and XML/DOCTYPE declarations to make | |
| 252 | * processing work with ConTeXt. | |
| 253 | * | |
| 254 | * @param path The SVG file to process. | |
| 255 | * @throws Exception The file could not be processed. | |
| 256 | */ | |
| 257 | public static void sanitize( final Path path ) throws Exception { | |
| 258 | assert path != null; | |
| 259 | ||
| 260 | // Preprocessing the SVG image is a single-threaded operation, no matter | |
| 261 | // how many SVG images are in the document to typeset. | |
| 262 | sWriter.reset(); | |
| 263 | ||
| 264 | final var target = new StreamResult( sOutput ); | |
| 265 | final var source = sDocumentBuilder.parse( toFile( path ) ); | |
| 266 | ||
| 267 | transform( source, target ); | |
| 268 | write( path, sWriter.toByteArray() ); | |
| 269 | } | |
| 270 | ||
| 271 | /** | |
| 272 | * Converts a string into an {@link XPathExpression}, which may be used to | |
| 273 | * extract elements from a {@link Document} object model. | |
| 274 | * | |
| 275 | * @param cs The string to convert to an {@link XPathExpression}. | |
| 276 | * @return {@code null} if there was an error compiling the xpath. | |
| 277 | */ | |
| 278 | public static XPathExpression compile( final CharSequence cs ) { | |
| 279 | assert cs != null; | |
| 280 | ||
| 281 | final var xpath = cs.toString(); | |
| 282 | ||
| 283 | return sXpaths.computeIfAbsent( xpath, k -> { | |
| 284 | try { | |
| 285 | return sXpath.compile( xpath ); | |
| 286 | } catch( final XPathExpressionException ex ) { | |
| 287 | clue( ex ); | |
| 288 | return null; | |
| 289 | } | |
| 290 | } ); | |
| 291 | } | |
| 292 | ||
| 293 | /** | |
| 294 | * Streams an instance of {@link Document} as a plain text XML document. | |
| 295 | * | |
| 296 | * @param src The source document to transform. | |
| 297 | * @param dst The destination location to write the transformed version. | |
| 298 | * @throws TransformerException Could not transform the document. | |
| 299 | */ | |
| 300 | private static void transform( final Document src, final StreamResult dst ) | |
| 301 | throws TransformerException { | |
| 302 | sTransformer.transform( new DOMSource( src ), dst ); | |
| 303 | } | |
| 304 | ||
| 305 | /** | |
| 306 | * Use the {@code static} constants and methods, not an instance, at least | |
| 307 | * until an iterable sub-interface is written. | |
| 308 | */ | |
| 309 | private DocumentParser() {} | |
| 310 | } | |
| 1 | 311 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.editors; | |
| 1 | 6 | |
| 7 | import com.keenwrite.editors.definition.DefinitionEditor; | |
| 8 | import com.keenwrite.editors.definition.DefinitionTreeItem; | |
| 9 | import com.keenwrite.editors |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.editors; | |
| 1 | 6 | |
| 7 | import com.keenwrite.editors.common.Caret; | |
| 8 | import javafx.scene.control.IndexRange; | |
| 9 | import org.fxmisc.flowless.VirtualizedScrollPane; | |
| 10 | import org.fx |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.editors; | |
| 1 | 6 | |
| 7 | import com.keenwrite.io.MediaType; | |
| 8 | import com.keenwrite.util.EncodingDetector; | |
| 9 | import javafx.beans.property.ReadOnlyBooleanProperty; | |
| 10 | import javafx.scene.Node; | |
| 11 | return new EncodingDetector().detect( bytes |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.editors.common; | |
| 1 | 3 | |
| 4 | import com. | |
| 5 | import java.util.function.Supp/** | |
| 6 | * Sets the {@link Supplier} for the cnumber. | |
| 7 | * | |
| 8 | * @param paragraph Returns the document caret paragraph index. | |
| 9 | *//** | |
| 10 | * Sets the {@link Supplier} for the total number of document paragraphs. | |
| 11 | * | |
| 12 | * @param paragraphs Returns the document paragraph count. | |
| 13 | *//** | |
| 14 | * Sets the {@link Supplier} for the caret's current character offset | |
| 15 | * into the current paragraph. | |
| 16 | * | |
| 17 | * @param paraOffset Returns the caret's paragraph character index. | |
| 18 | *//** | |
| 19 | * Sets the {@link Supplier} for the caret's current document position. | |
| 20 | * A value of 0 represents the start of the document. | |
| 21 | * | |
| 22 | * @param textOffset Returns the tex/** | |
| 23 | * Sets the {@link Supplier} for the document's total character count. | |
| 24 | * | |
| 25 | * @param textLength Returns the total character count |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.editors.common; | |
| 1 | 6 | |
| 7 | import com.keenwrite.events.ScrollLockEvent; | |
| 8 | import javafx.beans.property.BooleanProperty; | |
| 9 | import javafx.beans.property.SimpleBooleanProper |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.editors.common; | |
| 1 | 6 | |
| 7 | import com.keenwrite.editors.TextDefinition; | |
| 8 | import com.keenwrite.editors.TextEditor; | |
| 9 | import com.keenwrite.editors.definition.DefinitionTre |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.editors.definition; | |
| 6 | ||
| 7 | import com.keenwrite.constants.Constants; | |
| 8 | import com.keenwrite.editors.TextDefinition; | |
| 9 | import com.keenwrite.events.InsertDefinitionEvent; | |
| 10 | import com.keenwrite.events.TextDefinitionFocusEvent; | |
| 11 | import com.keenwrite.processors.r.Engine; | |
| 12 | import com.keenwrite.ui.tree.AltTreeView; | |
| 13 | import com.keenwrite.ui.tree.TreeItemConverter; | |
| 14 | import javafx.beans.property.BooleanProperty; | |
| 15 | import javafx.beans.property.ReadOnlyBooleanProperty; | |
| 16 | import javafx.beans.property.SimpleBooleanProperty; | |
| 17 | import javafx.beans.value.ObservableValue; | |
| 18 | import javafx.collections.ObservableList; | |
| 19 | import javafx.event.ActionEvent; | |
| 20 | import javafx.event.Event; | |
| 21 | import javafx.event.EventHandler; | |
| 22 | import javafx.scene.Node; | |
| 23 | import javafx.scene.control.*; | |
| 24 | import javafx.scene.input.KeyEvent; | |
| 25 | import javafx.scene.layout.BorderPane; | |
| 26 | import javafx.scene.layout.HBox; | |
| 27 | ||
| 28 | import java.io.File; | |
| 29 | import java.nio.charset.Charset; | |
| 30 | import java.util.*; | |
| 31 | ||
| 32 | import static com.keenwrite.Messages.get; | |
| 33 | import static com.keenwrite.constants.Constants.*; | |
| 34 | import static com.keenwrite.events.StatusEvent.clue; | |
| 35 | import static com.keenwrite.ui.fonts.IconFactory.createGraphic; | |
| 36 | import static javafx.geometry.Pos.CENTER; | |
| 37 | import static javafx.geometry.Pos.TOP_CENTER; | |
| 38 | import static javafx.scene.control.SelectionMode.MULTIPLE; | |
| 39 | import static javafx.scene.control.TreeItem.childrenModificationEvent; | |
| 40 | import static javafx.scene.control.TreeItem.valueChangedEvent; | |
| 41 | import static javafx.scene.input.KeyEvent.KEY_PRESSED; | |
| 42 | ||
| 43 | /** | |
| 44 | * Provides the user interface that holds a {@link TreeView}, which | |
| 45 | * allows users to interact with key/value pairs loaded from the | |
| 46 | * document parser and adapted using a {@link TreeTransformer}. | |
| 47 | */ | |
| 48 | public final class DefinitionEditor extends BorderPane | |
| 49 | implements TextDefinition { | |
| 50 | ||
| 51 | /** | |
| 52 | * Contains the root that is added to the view. | |
| 53 | */ | |
| 54 | private final DefinitionTreeItem<String> mTreeRoot = createRootTreeItem(); | |
| 55 | ||
| 56 | /** | |
| 57 | * Contains a view of the definitions. | |
| 58 | */ | |
| 59 | private final TreeView<String> mTreeView = | |
| 60 | new AltTreeView<>( mTreeRoot, new TreeItemConverter() ); | |
| 61 | ||
| 62 | /** | |
| 63 | * Used to adapt the structured document into a {@link TreeView}. | |
| 64 | */ | |
| 65 | private final TreeTransformer mTreeTransformer; | |
| 66 | ||
| 67 | /** | |
| 68 | * Handlers for key press events. | |
| 69 | */ | |
| 70 | private final Set<EventHandler<? super KeyEvent>> mKeyEventHandlers | |
| 71 | = new HashSet<>(); | |
| 72 | ||
| 73 | private final Map<String, String> mDefinitions = new HashMap<>(); | |
| 74 | ||
| 75 | /** | |
| 76 | * Opened file's character encoding, or {@link Constants#DEFAULT_CHARSET} if | |
| 77 | * either no encoding could be determined or this is a new (empty) file. | |
| 78 | */ | |
| 79 | private final Charset mEncoding; | |
| 80 | ||
| 81 | /** | |
| 82 | * Tracks whether the in-memory definitions have changed with respect to the | |
| 83 | * persisted definitions. | |
| 84 | */ | |
| 85 | private final BooleanProperty mModified = new SimpleBooleanProperty(); | |
| 86 | ||
| 87 | /** | |
| 88 | * File being edited by this editor instance, which may be renamed. | |
| 89 | */ | |
| 90 | private File mFile; | |
| 91 | ||
| 92 | /** | |
| 93 | * This is provided for unit tests that are not backed by files. | |
| 94 | * | |
| 95 | * @param treeTransformer Responsible for transforming the definitions into | |
| 96 | * {@link TreeItem} instances. | |
| 97 | */ | |
| 98 | public DefinitionEditor( | |
| 99 | final TreeTransformer treeTransformer ) { | |
| 100 | this( DEFINITION_DEFAULT, treeTransformer ); | |
| 101 | } | |
| 102 | ||
| 103 | /** | |
| 104 | * Constructs a definition pane with a given tree view root. | |
| 105 | * | |
| 106 | * @param file The file of definitions to maintain through the UI. | |
| 107 | */ | |
| 108 | public DefinitionEditor( | |
| 109 | final File file, | |
| 110 | final TreeTransformer treeTransformer ) { | |
| 111 | assert file != null; | |
| 112 | assert treeTransformer != null; | |
| 113 | ||
| 114 | mFile = file; | |
| 115 | mTreeTransformer = treeTransformer; | |
| 116 | ||
| 117 | mTreeView.setContextMenu( createContextMenu() ); | |
| 118 | mTreeView.addEventFilter( KEY_PRESSED, this::keyEventFilter ); | |
| 119 | mTreeView.focusedProperty().addListener( this::focused ); | |
| 120 | getSelectionModel().setSelectionMode( MULTIPLE ); | |
| 121 | ||
| 122 | final var buttonBar = new HBox(); | |
| 123 | buttonBar.getChildren().addAll( | |
| 124 | createButton( "create", _ -> createDefinition() ), | |
| 125 | createButton( "rename", _ -> renameDefinition() ), | |
| 126 | createButton( "delete", _ -> deleteDefinitions() ) | |
| 127 | ); | |
| 128 | buttonBar.setAlignment( CENTER ); | |
| 129 | buttonBar.setSpacing( UI_CONTROL_SPACING ); | |
| 130 | setTop( buttonBar ); | |
| 131 | setCenter( mTreeView ); | |
| 132 | setAlignment( buttonBar, TOP_CENTER ); | |
| 133 | ||
| 134 | mEncoding = open( mFile ); | |
| 135 | updateDefinitions( getDefinitions(), getTreeView().getRoot() ); | |
| 136 | ||
| 137 | // After the file is opened, watch for changes, not before. Otherwise, | |
| 138 | // upon saving, users will be prompted to save a file that hasn't had | |
| 139 | // any modifications (from their perspective). | |
| 140 | addTreeChangeHandler( _ -> { | |
| 141 | mModified.set( true ); | |
| 142 | updateDefinitions( getDefinitions(), getTreeView().getRoot() ); | |
| 143 | } ); | |
| 144 | } | |
| 145 | ||
| 146 | /** | |
| 147 | * Replaces the given list of variable definitions with a flat hierarchy | |
| 148 | * of the converted {@link TreeView} root. | |
| 149 | * | |
| 150 | * @param definitions The definition map to update. | |
| 151 | * @param root The values to flatten then insert into the map. | |
| 152 | */ | |
| 153 | private void updateDefinitions( | |
| 154 | final Map<String, String> definitions, | |
| 155 | final TreeItem<String> root ) { | |
| 156 | definitions.clear(); | |
| 157 | definitions.putAll( TreeItemMapper.convert( root ) ); | |
| 158 | Engine.clear(); | |
| 159 | } | |
| 160 | ||
| 161 | /** | |
| 162 | * Returns the variable definitions. | |
| 163 | * | |
| 164 | * @return The definition map. | |
| 165 | */ | |
| 166 | @Override | |
| 167 | public Map<String, String> getDefinitions() { | |
| 168 | return mDefinitions; | |
| 169 | } | |
| 170 | ||
| 171 | @Override | |
| 172 | public void setText( final String document ) { | |
| 173 | final var foster = mTreeTransformer.transform( document ); | |
| 174 | final var biological = getTreeRoot(); | |
| 175 | ||
| 176 | for( final var child : foster.getChildren() ) { | |
| 177 | biological.getChildren().add( child ); | |
| 178 | } | |
| 179 | ||
| 180 | getTreeView().refresh(); | |
| 181 | } | |
| 182 | ||
| 183 | @Override | |
| 184 | public String getText() { | |
| 185 | final var result = new StringBuilder( 32768 ); | |
| 186 | ||
| 187 | try { | |
| 188 | result.append( mTreeTransformer.transform( getTreeView().getRoot() ) ); | |
| 189 | ||
| 190 | final var problem = isTreeWellFormed(); | |
| 191 | problem.ifPresent( node -> clue( "yaml.error.tree.form", node ) ); | |
| 192 | } catch( final Exception ex ) { | |
| 193 | // Catch errors while checking for a well-formed tree (e.g., stack smash). | |
| 194 | // Also catch any transformation exceptions (e.g., Json processing). | |
| 195 | clue( ex ); | |
| 196 | } | |
| 197 | ||
| 198 | return result.toString(); | |
| 199 | } | |
| 200 | ||
| 201 | @Override | |
| 202 | public File getFile() { | |
| 203 | return mFile; | |
| 204 | } | |
| 205 | ||
| 206 | @Override | |
| 207 | public void rename( final File file ) { | |
| 208 | mFile = file; | |
| 209 | } | |
| 210 | ||
| 211 | @Override | |
| 212 | public Charset getEncoding() { | |
| 213 | return mEncoding; | |
| 214 | } | |
| 215 | ||
| 216 | @Override | |
| 217 | public Node getNode() { | |
| 218 | return this; | |
| 219 | } | |
| 220 | ||
| 221 | @Override | |
| 222 | public ReadOnlyBooleanProperty modifiedProperty() { | |
| 223 | return mModified; | |
| 224 | } | |
| 225 | ||
| 226 | @Override | |
| 227 | public void clearModifiedProperty() { | |
| 228 | mModified.setValue( false ); | |
| 229 | } | |
| 230 | ||
| 231 | private Button createButton( | |
| 232 | final String msgKey, final EventHandler<ActionEvent> eventHandler ) { | |
| 233 | final var keyPrefix = STR."\{Constants.ACTION_PREFIX}definition.\{msgKey}"; | |
| 234 | final var button = new Button( get( STR."\{keyPrefix}.text" ) ); | |
| 235 | final var graphic = createGraphic( get( STR."\{keyPrefix}.icon" ) ); | |
| 236 | ||
| 237 | button.setOnAction( eventHandler ); | |
| 238 | button.setGraphic( graphic ); | |
| 239 | button.setTooltip( new Tooltip( get( STR."\{keyPrefix}.tooltip" ) ) ); | |
| 240 | ||
| 241 | return button; | |
| 242 | } | |
| 243 | ||
| 244 | /** | |
| 245 | * Informs the caller of whenever any {@link TreeItem} in the {@link TreeView} | |
| 246 | * is modified. The modifications include: item value changes, item additions, | |
| 247 | * and item removals. | |
| 248 | * <p> | |
| 249 | * Safe to call multiple times; if a handler is already registered, the | |
| 250 | * old handler is used. | |
| 251 | * </p> | |
| 252 | * | |
| 253 | * @param handler The handler to call whenever any {@link TreeItem} changes. | |
| 254 | */ | |
| 255 | public void addTreeChangeHandler( | |
| 256 | final EventHandler<TreeItem.TreeModificationEvent<Event>> handler ) { | |
| 257 | final var root = getTreeView().getRoot(); | |
| 258 | root.addEventHandler( valueChangedEvent(), handler ); | |
| 259 | root.addEventHandler( childrenModificationEvent(), handler ); | |
| 260 | } | |
| 261 | ||
| 262 | /** | |
| 263 | * Answers whether the {@link TreeItem}s in the {@link TreeView} are suitably | |
| 264 | * well-formed for export. A tree is considered well-formed if the following | |
| 265 | * conditions are met: | |
| 266 | * | |
| 267 | * <ul> | |
| 268 | * <li>The root node contains at least one child node having a leaf.</li> | |
| 269 | * <li>There are no leaf nodes with sibling leaf nodes.</li> | |
| 270 | * </ul> | |
| 271 | * | |
| 272 | * @return {@code null} if the document is well-formed, otherwise the | |
| 273 | * problematic child {@link TreeItem}. | |
| 274 | */ | |
| 275 | public Optional<TreeItem<String>> isTreeWellFormed() { | |
| 276 | final var root = getTreeView().getRoot(); | |
| 277 | ||
| 278 | for( final var child : root.getChildren() ) { | |
| 279 | final var problemChild = isWellFormed( child ); | |
| 280 | ||
| 281 | if( child.isLeaf() || problemChild != null ) { | |
| 282 | return Optional.ofNullable( problemChild ); | |
| 283 | } | |
| 284 | } | |
| 285 | ||
| 286 | return Optional.empty(); | |
| 287 | } | |
| 288 | ||
| 289 | /** | |
| 290 | * Determines whether the document is well-formed by ensuring that | |
| 291 | * child branches do not contain multiple leaves. | |
| 292 | * | |
| 293 | * @param item The subtree to check for well-formedness. | |
| 294 | * @return {@code null} when the tree is well-formed, otherwise the | |
| 295 | * problematic {@link TreeItem}. | |
| 296 | */ | |
| 297 | private TreeItem<String> isWellFormed( final TreeItem<String> item ) { | |
| 298 | int childLeafs = 0; | |
| 299 | int childBranches = 0; | |
| 300 | ||
| 301 | for( final var child : item.getChildren() ) { | |
| 302 | if( child.isLeaf() ) { | |
| 303 | childLeafs++; | |
| 304 | } | |
| 305 | else { | |
| 306 | childBranches++; | |
| 307 | } | |
| 308 | ||
| 309 | final var problemChild = isWellFormed( child ); | |
| 310 | ||
| 311 | if( problemChild != null ) { | |
| 312 | return problemChild; | |
| 313 | } | |
| 314 | } | |
| 315 | ||
| 316 | return ((childBranches > 0 && childLeafs == 0) || | |
| 317 | (childBranches == 0 && childLeafs <= 1)) | |
| 318 | ? null | |
| 319 | : item; | |
| 320 | } | |
| 321 | ||
| 322 | @Override | |
| 323 | public DefinitionTreeItem<String> findLeafExact( final String text ) { | |
| 324 | return getTreeRoot().findLeafExact( text ); | |
| 325 | } | |
| 326 | ||
| 327 | @Override | |
| 328 | public DefinitionTreeItem<String> findLeafContains( final String text ) { | |
| 329 | return getTreeRoot().findLeafContains( text ); | |
| 330 | } | |
| 331 | ||
| 332 | @Override | |
| 333 | public DefinitionTreeItem<String> findLeafContainsNoCase( | |
| 334 | final String text ) { | |
| 335 | return getTreeRoot().findLeafContainsNoCase( text ); | |
| 336 | } | |
| 337 | ||
| 338 | @Override | |
| 339 | public DefinitionTreeItem<String> findLeafStartsWith( final String text ) { | |
| 340 | return getTreeRoot().findLeafStartsWith( text ); | |
| 341 | } | |
| 342 | ||
| 343 | public void select( final TreeItem<String> item ) { | |
| 344 | getSelectionModel().clearSelection(); | |
| 345 | getSelectionModel().select( getTreeView().getRow( item ) ); | |
| 346 | } | |
| 347 | ||
| 348 | /** | |
| 349 | * Collapses the tree, recursively. | |
| 350 | */ | |
| 351 | public void collapse() { | |
| 352 | collapse( getTreeRoot().getChildren() ); | |
| 353 | } | |
| 354 | ||
| 355 | /** | |
| 356 | * Collapses the tree, recursively. | |
| 357 | * | |
| 358 | * @param <T> The type of tree item to expand (usually String). | |
| 359 | * @param nodes The nodes to collapse. | |
| 360 | */ | |
| 361 | private <T> void collapse( final ObservableList<TreeItem<T>> nodes ) { | |
| 362 | for( final var node : nodes ) { | |
| 363 | node.setExpanded( false ); | |
| 364 | collapse( node.getChildren() ); | |
| 365 | } | |
| 366 | } | |
| 367 | ||
| 368 | /** | |
| 369 | * @return {@code true} when the user is editing a {@link TreeItem}. | |
| 370 | */ | |
| 371 | private boolean isEditingTreeItem() { | |
| 372 | return getTreeView().editingItemProperty().getValue() != null; | |
| 373 | } | |
| 374 | ||
| 375 | /** | |
| 376 | * Changes to edit mode for the selected item. | |
| 377 | */ | |
| 378 | @Override | |
| 379 | public void renameDefinition() { | |
| 380 | getTreeView().edit( getSelectedItem() ); | |
| 381 | } | |
| 382 | ||
| 383 | /** | |
| 384 | * Removes all selected items from the {@link TreeView}. | |
| 385 | */ | |
| 386 | @Override | |
| 387 | public void deleteDefinitions() { | |
| 388 | for( final var item : getSelectedItems() ) { | |
| 389 | final var parent = item.getParent(); | |
| 390 | ||
| 391 | if( parent != null ) { | |
| 392 | parent.getChildren().remove( item ); | |
| 393 | } | |
| 394 | } | |
| 395 | } | |
| 396 | ||
| 397 | /** | |
| 398 | * Deletes the selected item. | |
| 399 | */ | |
| 400 | private void deleteSelectedItem() { | |
| 401 | final var c = getSelectedItem(); | |
| 402 | getSiblings( c ).remove( c ); | |
| 403 | } | |
| 404 | ||
| 405 | private void insertSelectedItem() { | |
| 406 | if( getSelectedItem() instanceof DefinitionTreeItem<String> node ) { | |
| 407 | if( node.isLeaf() ) { | |
| 408 | InsertDefinitionEvent.fire( node ); | |
| 409 | } | |
| 410 | } | |
| 411 | } | |
| 412 | ||
| 413 | /** | |
| 414 | * Adds a new item under the selected item (or root if nothing is selected). | |
| 415 | * There are a few conditions to consider: when adding to the root, | |
| 416 | * when adding to a leaf, and when adding to a non-leaf. Items added to the | |
| 417 | * root must contain two items: a key and a value. | |
| 418 | */ | |
| 419 | @Override | |
| 420 | public void createDefinition() { | |
| 421 | final var value = createDefinitionTreeItem(); | |
| 422 | getSelectedItem().getChildren().add( value ); | |
| 423 | expand( value ); | |
| 424 | select( value ); | |
| 425 | } | |
| 426 | ||
| 427 | private ContextMenu createContextMenu() { | |
| 428 | final var menu = new ContextMenu(); | |
| 429 | final var items = menu.getItems(); | |
| 430 | ||
| 431 | addMenuItem( items, STR."\{ACTION_PREFIX}definition.create.text" ) | |
| 432 | .setOnAction( _ -> createDefinition() ); | |
| 433 | addMenuItem( items, STR."\{ACTION_PREFIX}definition.rename.text" ) | |
| 434 | .setOnAction( _ -> renameDefinition() ); | |
| 435 | addMenuItem( items, STR."\{ACTION_PREFIX}definition.delete.text" ) | |
| 436 | .setOnAction( _ -> deleteSelectedItem() ); | |
| 437 | addMenuItem( items, STR."\{ACTION_PREFIX}definition.insert.text" ) | |
| 438 | .setOnAction( _ -> insertSelectedItem() ); | |
| 439 | ||
| 440 | return menu; | |
| 441 | } | |
| 442 | ||
| 443 | /** | |
| 444 | * Executes hot-keys for edits to the definition tree. | |
| 445 | * | |
| 446 | * @param event Contains the key code of the key that was pressed. | |
| 447 | */ | |
| 448 | private void keyEventFilter( final KeyEvent event ) { | |
| 449 | if( !isEditingTreeItem() ) { | |
| 450 | switch( event.getCode() ) { | |
| 451 | case ENTER -> { | |
| 452 | expand( getSelectedItem() ); | |
| 453 | event.consume(); | |
| 454 | } | |
| 455 | ||
| 456 | case DELETE -> deleteDefinitions(); | |
| 457 | case INSERT -> createDefinition(); | |
| 458 | ||
| 459 | case R -> { | |
| 460 | if( event.isControlDown() ) { | |
| 461 | renameDefinition(); | |
| 462 | } | |
| 463 | } | |
| 464 | ||
| 465 | default -> {} | |
| 466 | } | |
| 467 | ||
| 468 | for( final var handler : getKeyEventHandlers() ) { | |
| 469 | handler.handle( event ); | |
| 470 | } | |
| 471 | } | |
| 472 | } | |
| 473 | ||
| 474 | /** | |
| 475 | * Called when the editor's input focus changes. This will fire an event | |
| 476 | * for subscribers. | |
| 477 | * | |
| 478 | * @param ignored Not used. | |
| 479 | * @param o The old input focus property value. | |
| 480 | * @param n The new input focus property value. | |
| 481 | */ | |
| 482 | private void focused( | |
| 483 | final ObservableValue<? extends Boolean> ignored, | |
| 484 | final Boolean o, | |
| 485 | final Boolean n ) { | |
| 486 | if( n != null && n ) { | |
| 487 | TextDefinitionFocusEvent.fire( this ); | |
| 488 | } | |
| 489 | } | |
| 490 | ||
| 491 | /** | |
| 492 | * Adds a menu item to a list of menu items. | |
| 493 | * | |
| 494 | * @param items The list of menu items to append to. | |
| 495 | * @param labelKey The resource bundle key name for the menu item's label. | |
| 496 | * @return The menu item added to the list of menu items. | |
| 497 | */ | |
| 498 | private MenuItem addMenuItem( | |
| 499 | final List<MenuItem> items, final String labelKey ) { | |
| 500 | final MenuItem menuItem = createMenuItem( labelKey ); | |
| 501 | items.add( menuItem ); | |
| 502 | return menuItem; | |
| 503 | } | |
| 504 | ||
| 505 | private MenuItem createMenuItem( final String labelKey ) { | |
| 506 | return new MenuItem( get( labelKey ) ); | |
| 507 | } | |
| 508 | ||
| 509 | /** | |
| 510 | * Creates a new {@link TreeItem} that is intended to be the root-level item | |
| 511 | * added to the {@link TreeView}. This allows the root item to be | |
| 512 | * distinguished from the other items so that reference keys do not include | |
| 513 | * "Definition" as part of their name. | |
| 514 | * | |
| 515 | * @return A new {@link TreeItem}, never {@code null}. | |
| 516 | */ | |
| 517 | private RootTreeItem<String> createRootTreeItem() { | |
| 518 | return new RootTreeItem<>( get( "Pane.definition.node.root.title" ) ); | |
| 519 | } | |
| 520 | ||
| 521 | private DefinitionTreeItem<String> createDefinitionTreeItem() { | |
| 522 | return new DefinitionTreeItem<>( get( "Definition.menu.add.default" ) ); | |
| 523 | } | |
| 524 | ||
| 525 | @Override | |
| 526 | public void requestFocus() { | |
| 527 | getTreeView().requestFocus(); | |
| 528 | } | |
| 529 | ||
| 530 | /** | |
| 531 | * Expands the node to the root, recursively. | |
| 532 | * | |
| 533 | * @param <T> The type of tree item to expand (usually String). | |
| 534 | * @param node The node to expand. | |
| 535 | */ | |
| 536 | @Override | |
| 537 | public <T> void expand( final TreeItem<T> node ) { | |
| 538 | if( node != null ) { | |
| 539 | expand( node.getParent() ); | |
| 540 | node.setExpanded( !node.isLeaf() ); | |
| 541 | } | |
| 542 | } | |
| 543 | ||
| 544 | /** | |
| 545 | * Answers whether there are any definitions in the tree. | |
| 546 | * | |
| 547 | * @return {@code true} when there are no definitions; {@code false} when | |
| 548 | * there's at least one definition. | |
| 549 | */ | |
| 550 | @Override | |
| 551 | public boolean isEmpty() { | |
| 552 | return getTreeRoot().isEmpty(); | |
| 553 | } | |
| 554 | ||
| 555 | /** | |
| 556 | * Returns the actively selected item in the tree. | |
| 557 | * | |
| 558 | * @return The selected item, or the tree root item if no item is selected. | |
| 559 | */ | |
| 560 | public TreeItem<String> getSelectedItem() { | |
| 561 | final var item = getSelectionModel().getSelectedItem(); | |
| 562 | return item == null ? getTreeRoot() : item; | |
| 563 | } | |
| 564 | ||
| 565 | /** | |
| 566 | * Returns the {@link TreeView} that contains the definition hierarchy. | |
| 567 | * | |
| 568 | * @return A non-null instance. | |
| 569 | */ | |
| 570 | private TreeView<String> getTreeView() { | |
| 571 | return mTreeView; | |
| 572 | } | |
| 573 | ||
| 574 | /** | |
| 575 | * Returns the root of the tree. | |
| 576 | * | |
| 577 | * @return The first node added to the definition tree. | |
| 578 | */ | |
| 579 | private DefinitionTreeItem<String> getTreeRoot() { | |
| 580 | return mTreeRoot; | |
| 581 | } | |
| 582 | ||
| 583 | private ObservableList<TreeItem<String>> getSiblings( | |
| 584 | final TreeItem<String> item ) { | |
| 585 | final var root = getTreeView().getRoot(); | |
| 586 | final var parent = (item == null || item == root) | |
| 587 | ? root | |
| 588 | : item.getParent(); | |
| 589 | ||
| 590 | return parent.getChildren(); | |
| 591 | } | |
| 592 | ||
| 593 | private MultipleSelectionModel<TreeItem<String>> getSelectionModel() { | |
| 594 | return getTreeView().getSelectionModel(); | |
| 595 | } | |
| 596 | ||
| 597 | /** | |
| 598 | * Returns a copy of all the selected items. | |
| 599 | * | |
| 600 | * @return A list, possibly empty, containing all selected items in the | |
| 601 | * {@link TreeView}. | |
| 602 | */ | |
| 603 | private List<TreeItem<String>> getSelectedItems() { | |
| 604 | return new ArrayList<>( getSelectionModel().getSelectedItems() ); | |
| 605 | } | |
| 606 | ||
| 607 | private Set<EventHandler<? super KeyEvent>> getKeyEventHandlers() { | |
| 608 | return mKeyEventHandlers; | |
| 609 | } | |
| 610 | } | |
| 1 | 611 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.editors.definition; | |
| 6 | ||
| 7 | import com.keenwrite.util.Diacritics; | |
| 8 | import javafx.scene.control.TreeItem; | |
| 1 | 9 | |
| 10 | import java.util.Stack; | |
| 11 | import java.util.function.BiFuncti |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.editors.definition; | |
| 6 | ||
| 7 | import javafx.scene.control.TreeItem; | |
| 8 | import javafx.scene.control.TreeView; | |
| 1 | 9 | |
| 10 | /** | |
| 11 | * Marker interface for top-most {@link TreeItem}. Thi |
| 1 | ||
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.editorskeenwrite.preview.HtmlPreviewutil.InterpolatingMapHashMap; |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.editors.definition; | |
| 6 | ||
| 7 | import javafx.scene.control.TreeItem; | |
| 1 | 8 | |
| 9 | /** | |
| 10 | * |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | ||
| 3 | /** | |
| 4 | * This package contains classes that pertain to hierarchical, structured | |
| 5 | * data formats, which can be used as interpolated variables. | |
| 6 | */ | |
| 7 | package com.keenwrite.editors.definition; | |
| 1 | 8 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.editors.definition.yaml; | |
| 3 | ||
| 4 | import com.fasterxml.jackson.databind.JsonNode; | |
| 5 | import com.fasterxml.jackson.databind.ObjectMapper; | |
| 6 | import com.fasterxml.jackson.databind.node.ObjectNode; | |
| 7 | import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; | |
| 8 | import com.fasterxml.jackson.dataformat.yaml.YAMLMapper; | |
| 9 | import com.keenwrite.editors.definition.DefinitionTreeItem; | |
| 10 | import com.keenwrite.editors.definition.TreeTransformer; | |
| 11 | import javafx.scene.control.TreeItem; | |
| 12 | import javafx.scene.control.TreeView; | |
| 13 | ||
| 14 | import java.util.Map.Entry; | |
| 15 | ||
| 16 | import static com.fasterxml.jackson.dataformat.yaml.YAMLGenerator.Feature.*; | |
| 17 | import static com.keenwrite.events.StatusEvent.clue; | |
| 18 | ||
| 19 | /** | |
| 20 | * Transforms a {@link JsonNode} hierarchy into a tree that can be displayed | |
| 21 | * in a user interface and vice-versa. | |
| 22 | */ | |
| 23 | public final class YamlTreeTransformer implements TreeTransformer { | |
| 24 | private static final YAMLFactory sFactory; | |
| 25 | private static final YAMLMapper sMapper; | |
| 26 | ||
| 27 | static { | |
| 28 | sFactory = new YAMLFactory(); | |
| 29 | sFactory.configure( MINIMIZE_QUOTES, true ); | |
| 30 | sFactory.configure( SPLIT_LINES, false ); | |
| 31 | sMapper = new YAMLMapper( sFactory ); | |
| 32 | } | |
| 33 | ||
| 34 | /** | |
| 35 | * Constructs a new instance that will use the given path to read the object | |
| 36 | * hierarchy from a data source. | |
| 37 | */ | |
| 38 | public YamlTreeTransformer() { | |
| 39 | } | |
| 40 | ||
| 41 | @Override | |
| 42 | public String transform( final TreeItem<String> treeItem ) { | |
| 43 | try { | |
| 44 | final var root = sMapper.createObjectNode(); | |
| 45 | ||
| 46 | // Iterate over the root item's children. The root item is used by the | |
| 47 | // application to ensure definitions can always be added to a tree, as | |
| 48 | // such it is not meant to be exported, only its children. | |
| 49 | for( final var child : treeItem.getChildren() ) { | |
| 50 | transform( child, root ); | |
| 51 | } | |
| 52 | ||
| 53 | return sMapper.writeValueAsString( root ); | |
| 54 | } catch( final Exception ex ) { | |
| 55 | clue( ex ); | |
| 56 | throw new RuntimeException( ex ); | |
| 57 | } | |
| 58 | } | |
| 59 | ||
| 60 | /** | |
| 61 | * Converts a YAML document to a {@link TreeItem} based on the document | |
| 62 | * keys. | |
| 63 | * | |
| 64 | * @param document The YAML document to convert to a hierarchy of | |
| 65 | * {@link TreeItem} instances. | |
| 66 | * @throws StackOverflowError If infinite recursion is encountered. | |
| 67 | */ | |
| 68 | @Override | |
| 69 | public TreeItem<String> transform( final String document ) { | |
| 70 | final var jsonNode = toJson( document ); | |
| 71 | final var rootItem = createTreeItem( "root" ); | |
| 72 | ||
| 73 | transform( jsonNode, rootItem ); | |
| 74 | ||
| 75 | return rootItem; | |
| 76 | } | |
| 77 | ||
| 78 | private JsonNode toJson( final String yaml ) { | |
| 79 | try { | |
| 80 | return new ObjectMapper( sFactory ).readTree( yaml ); | |
| 81 | } catch( final Exception ex ) { | |
| 82 | // Ensure that a document root node exists. | |
| 83 | return new ObjectMapper().createObjectNode(); | |
| 84 | } | |
| 85 | } | |
| 86 | ||
| 87 | /** | |
| 88 | * Recursive method to generate an object hierarchy that represents the | |
| 89 | * given {@link TreeItem} hierarchy. | |
| 90 | * | |
| 91 | * @param item The {@link TreeItem} to reproduce as an object hierarchy. | |
| 92 | * @param node The {@link ObjectNode} to update to reflect the | |
| 93 | * {@link TreeItem} hierarchy. | |
| 94 | */ | |
| 95 | private void transform( final TreeItem<String> item, ObjectNode node ) { | |
| 96 | final var children = item.getChildren(); | |
| 97 | ||
| 98 | // If the current item has more than one non-leaf child, it's an | |
| 99 | // object node and must become a new nested object. | |
| 100 | if( !(children.size() == 1 && children.getFirst().isLeaf()) ) { | |
| 101 | node = node.putObject( item.getValue() ); | |
| 102 | } | |
| 103 | ||
| 104 | for( final var child : children ) { | |
| 105 | if( child.isLeaf() ) { | |
| 106 | node.put( item.getValue(), child.getValue() ); | |
| 107 | } | |
| 108 | else { | |
| 109 | transform( child, node ); | |
| 110 | } | |
| 111 | } | |
| 112 | } | |
| 113 | ||
| 114 | /** | |
| 115 | * Iterate over a given root node (at any level of the tree) and adapt each | |
| 116 | * leaf node. | |
| 117 | * | |
| 118 | * @param node A JSON node (YAML node) to adapt. | |
| 119 | * @param item The tree item to use as the root when processing the node. | |
| 120 | * @throws StackOverflowError If infinite recursion is encountered. | |
| 121 | */ | |
| 122 | private void transform( final JsonNode node, final TreeItem<String> item ) { | |
| 123 | node.fields().forEachRemaining( leaf -> transform( leaf, item ) ); | |
| 124 | } | |
| 125 | ||
| 126 | /** | |
| 127 | * Recursively adapt each rootNode to a corresponding rootItem. | |
| 128 | * | |
| 129 | * @param node The node to adapt. | |
| 130 | * @param item The item to adapt using the node's key. | |
| 131 | * @throws StackOverflowError If infinite recursion is encountered. | |
| 132 | */ | |
| 133 | private void transform( | |
| 134 | final Entry<String, JsonNode> node, final TreeItem<String> item ) { | |
| 135 | final var leafNode = node.getValue(); | |
| 136 | final var key = node.getKey(); | |
| 137 | final var leaf = createTreeItem( key ); | |
| 138 | ||
| 139 | if( leafNode.isValueNode() ) { | |
| 140 | leaf.getChildren().add( createTreeItem( node.getValue().asText() ) ); | |
| 141 | } | |
| 142 | ||
| 143 | item.getChildren().add( leaf ); | |
| 144 | ||
| 145 | if( leafNode.isObject() ) { | |
| 146 | transform( leafNode, leaf ); | |
| 147 | } | |
| 148 | } | |
| 149 | ||
| 150 | /** | |
| 151 | * Creates a new {@link TreeItem} that can be added to the {@link TreeView}. | |
| 152 | * | |
| 153 | * @param value The node's value. | |
| 154 | * @return A new {@link TreeItem}, never {@code null}. | |
| 155 | */ | |
| 156 | private TreeItem<String> createTreeItem( final String value ) { | |
| 157 | return new DefinitionTreeItem<>( value ); | |
| 158 | } | |
| 159 | } | |
| 1 | 160 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | ||
| 3 | /** | |
| 4 | * This package contains classes that can parse YAML documents into a GUI | |
| 5 | * representation. | |
| 6 | */ | |
| 7 | package com.keenwrite.editors.def.yaml; | |
| 1 | 8 |
| 1 | ||
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.editors.markdown; | |
| 1 | 6 | |
| 7 | import com.keenwrite.constants.Constants; | |
| 8 | import com.keenwrite.editors.TextEditor; | |
| 9 | import com.keenwrite.ed |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.events; | |
| 1 | 6 | |
| 7 | import static com.keenwrite. | |
| 8 | /** | |
| 9 | * Marker interface for all application events. | |
| 10 | */ | |
| 11 | public interface AppEvent { |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.events; | |
| 3 | ||
| 4 | import org.greenrobot.eventbus.EventBus; | |
| 1 | 5 | |
| 6 | /** | |
| 7 | * Responsible for delegating interactions to the event bus library. This | |
| 8 | * class decouples the rest | |
| 9 | .builder().logNoSubscriberMessages( false ).installDefaultEventBus |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.events; | |
| 6 | ||
| 7 | import com.keenwrite.editors.common.Caret; | |
| 1 | 8 | |
| 9 | /** | |
| 10 | * Responsible for notifying when the caret has moved, which includes giving | |
| 11 | * focus to a different edi |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.events; | |
| 6 | ||
| 7 | import com.keenwrite.ui.outline.DocumentOutline; | |
| 1 | 8 | |
| 9 | /** | |
| 10 | * Collates information about a caret event, which is typically triggered when | |
| 11 | * the user do |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.events; | |
| 1 | 6 | |
| 7 | /** | |
| 8 | * Col |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.events; | |
| 1 | 6 | |
| 7 | /** | |
| 8 | * Responsible for kicking off an alert message when exporting (e.g., to PDF) | |
| 9 | * fails. This can happen when the executable to typeset the docu |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.events; | |
| 6 | ||
| 7 | import java.net.URI; | |
| 1 | 8 | |
| 9 | /** | |
| 10 | * Collates information about a file requested to be opened. This can be calHTML preview panel |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.events; | |
| 1 | 6 | |
| 7 | /** | |
| 8 | * Collates information about an object that has gained focus. This is typically | |
| 9 | * used by text resource editors (such as text editors and def |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.events; | |
| 6 | ||
| 7 | import java.io.IOException; | |
| 8 | import java.net.URI; | |
| 9 | ||
| 10 | import static com.keenwrite.events.StatusEvent.clue; | |
| 1 | 11 | |
| 12 | /** | |
| 13 | * Collates information about a URL reqpublish() |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.events; | |
| 6 | ||
| 7 | import com.keenwrite.editors.definition.DefinitionTreeItem; | |
| 8 | ||
| 9 | /** | |
| 10 | * Collates information about a request to insert a reference to a | |
| 11 | * definition value into the active document. | |
| 12 | */ | |
| 13 | public class InsertDefinitionEvent<T> implements AppEvent { | |
| 14 | ||
| 15 | private final DefinitionTreeItem<T> mLeaf; | |
| 16 | ||
| 17 | private InsertDefinitionEvent( final DefinitionTreeItem<T> leaf ) { | |
| 18 | mLeaf = leaf; | |
| 19 | } | |
| 20 | ||
| 21 | public static <T> void fire( final DefinitionTreeItem<T> leaf ) { | |
| 22 | assert leaf != null; | |
| 23 | assert leaf.isLeaf(); | |
| 24 | ||
| 25 | new InsertDefinitionEvent<>( leaf ).publish(); | |
| 26 | } | |
| 27 | ||
| 28 | /** | |
| 29 | * Returns the {@link DefinitionTreeItem} that is to be inserted into the | |
| 30 | * active document. | |
| 31 | * | |
| 32 | * @return The item to insert (as a variable). | |
| 33 | */ | |
| 34 | public DefinitionTreeItem<T> getLeaf() { | |
| 35 | return mLeaf; | |
| 36 | } | |
| 37 | } | |
| 1 | 38 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.events; | |
| 6 | ||
| 7 | import com.keenwrite.processors.Processor; | |
| 1 | 8 | |
| 9 | /** | |
| 10 | * Collates information about a document heading that has been parsed, after | |
| 11 | * all pertinent {@lin |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.events; | |
| 6 | ||
| 7 | import static java.awt.Toolkit.getDefaultToolkit; | |
| 8 | import static java.awt.event.KeyEvent.VK_SCROLL_LOCK; | |
| 1 | 9 | |
| 10 | /** | |
| 11 | * Collates information about the scro |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.events; | |
| 6 | ||
| 7 | import java.util.List; | |
| 8 | ||
| 9 | import static com.keenwrite.Messages.get; | |
| 10 | import static com.keenwrite.constants.Constants.NEWLINE; | |
| 11 | import static com.keenwrite.constants.Constants.STATUS_BAR_OK; | |
| 12 | import static java.lang.String.format; | |
| 13 | import static java.lang.String.join; | |
| 14 | import static java.util.Arrays.stream; | |
| 15 | ||
| 16 | /** | |
| 17 | * Collates information about an application issue. The issues can be | |
| 18 | * exceptions, state problems, parsing errors, and so forth. | |
| 19 | */ | |
| 20 | public final class StatusEvent implements AppEvent { | |
| 21 | private static final String ENGLISHIFY = | |
| 22 | "(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])"; | |
| 23 | ||
| 24 | /** | |
| 25 | * Detailed information about a problem. | |
| 26 | */ | |
| 27 | private final String mMessage; | |
| 28 | ||
| 29 | /** | |
| 30 | * Provides stack trace information that isolates the cause. | |
| 31 | */ | |
| 32 | private final Throwable mProblem; | |
| 33 | ||
| 34 | /** | |
| 35 | * Constructs a new event that contains a problem description to help the | |
| 36 | * user resolve an issue encountered while using the application. | |
| 37 | * | |
| 38 | * @param message The human-readable message, typically displayed on-screen. | |
| 39 | */ | |
| 40 | public StatusEvent( final String message ) { | |
| 41 | this( message, null ); | |
| 42 | } | |
| 43 | ||
| 44 | /** | |
| 45 | * Constructs a new event that contains information about an unexpected issue. | |
| 46 | * | |
| 47 | * @param problem The issue encountered by the software, never {@code null}. | |
| 48 | */ | |
| 49 | public StatusEvent( final Throwable problem ) { | |
| 50 | this( problem.getMessage(), problem ); | |
| 51 | } | |
| 52 | ||
| 53 | /** | |
| 54 | * @param message The human-readable message text. | |
| 55 | * @param problem May be {@code null} if no exception was thrown. | |
| 56 | */ | |
| 57 | public StatusEvent( final String message, final Throwable problem ) { | |
| 58 | mMessage = message == null ? "" : message; | |
| 59 | mProblem = problem; | |
| 60 | } | |
| 61 | ||
| 62 | /** | |
| 63 | * Returns the stack trace information for the issue encountered. This is | |
| 64 | * optional because usually a status message isn't an application error. | |
| 65 | * | |
| 66 | * @return Optional stack trace to pinpoint the problem area in the code. | |
| 67 | */ | |
| 68 | public String getProblem() { | |
| 69 | // Arbitrary limit. | |
| 70 | final var sb = new StringBuilder( 1024 ); | |
| 71 | final var trace = mProblem; | |
| 72 | ||
| 73 | if( trace != null ) { | |
| 74 | stream( trace.getStackTrace() ) | |
| 75 | .limit( 150 ) | |
| 76 | .toList() | |
| 77 | .forEach( e -> sb.append( e.toString() ).append( NEWLINE ) ); | |
| 78 | } | |
| 79 | ||
| 80 | return sb.toString(); | |
| 81 | } | |
| 82 | ||
| 83 | @Override | |
| 84 | public String toString() { | |
| 85 | // Not exactly sure how the message can be null, but it happened once! | |
| 86 | final var message = mMessage == null ? "UNKNOWN" : mMessage; | |
| 87 | ||
| 88 | return format( "%s%s%s", | |
| 89 | message, | |
| 90 | message.isBlank() ? "" : " ", | |
| 91 | mProblem == null ? "" : toEnglish( mProblem ) ); | |
| 92 | } | |
| 93 | ||
| 94 | /** | |
| 95 | * Separates the exception class name from TitleCase into lowercase, | |
| 96 | * space-separated words. This makes the exception look a little more like | |
| 97 | * English. Any {@link RuntimeException} instances passed into this method | |
| 98 | * will have the cause extracted, if possible. | |
| 99 | * | |
| 100 | * @param problem The exception that triggered the status event change. | |
| 101 | * @return A human-readable message with the exception name and the | |
| 102 | * exception's message. | |
| 103 | */ | |
| 104 | private static String toEnglish( Throwable problem ) { | |
| 105 | assert problem != null; | |
| 106 | ||
| 107 | // Subclasses of RuntimeException must be subject to Englishification. | |
| 108 | if( problem.getClass().equals( RuntimeException.class ) ) { | |
| 109 | final var cause = problem.getCause(); | |
| 110 | return cause == null ? problem.getMessage() : cause.getMessage(); | |
| 111 | } | |
| 112 | ||
| 113 | final var className = problem.getClass().getSimpleName(); | |
| 114 | final var words = join( " ", className.split( ENGLISHIFY ) ); | |
| 115 | return format( "(%s: %s)", words.toLowerCase(), problem.getMessage() ); | |
| 116 | } | |
| 117 | ||
| 118 | /** | |
| 119 | * Returns the message used to construct the event. | |
| 120 | * | |
| 121 | * @return The message for this event. | |
| 122 | */ | |
| 123 | public String getMessage() { | |
| 124 | return mMessage; | |
| 125 | } | |
| 126 | ||
| 127 | /** | |
| 128 | * Resets the status bar to a default message. Indicates that there are no | |
| 129 | * issues to bring to the user's attention. | |
| 130 | */ | |
| 131 | public static void clue() { | |
| 132 | fire( get( STATUS_BAR_OK, "OK" ) ); | |
| 133 | } | |
| 134 | ||
| 135 | /** | |
| 136 | * Notifies listeners of a series of messages. This is useful when providing | |
| 137 | * users feedback of how third-party executables have failed. | |
| 138 | * | |
| 139 | * @param messages The lines of text to display. | |
| 140 | */ | |
| 141 | public static void clue( final List<String> messages ) { | |
| 142 | messages.forEach( StatusEvent::fire ); | |
| 143 | } | |
| 144 | ||
| 145 | /** | |
| 146 | * Notifies listeners of an error. | |
| 147 | * | |
| 148 | * @param key The message bundle key to look up. | |
| 149 | * @param t The exception that caused the error. | |
| 150 | */ | |
| 151 | public static void clue( final String key, final Throwable t ) { | |
| 152 | fire( get( key ), t ); | |
| 153 | } | |
| 154 | ||
| 155 | /** | |
| 156 | * Notifies listeners of a custom message. | |
| 157 | * | |
| 158 | * @param key The property key having a value to populate with arguments. | |
| 159 | * @param args The placeholder values to substitute into the key's value. | |
| 160 | */ | |
| 161 | public static void clue( final String key, final Object... args ) { | |
| 162 | fire( get( key, args ) ); | |
| 163 | } | |
| 164 | ||
| 165 | /** | |
| 166 | * Notifies listeners of a custom message. | |
| 167 | * | |
| 168 | * @param ex The exception that warranted calling this method. | |
| 169 | * @param fmt The string format specifier. | |
| 170 | * @param args The arguments to weave into the format specifier. | |
| 171 | */ | |
| 172 | public static void clue( | |
| 173 | final Exception ex, | |
| 174 | final String fmt, | |
| 175 | final Object... args ) { | |
| 176 | final var msg = format( fmt, args ); | |
| 177 | clue( msg, ex ); | |
| 178 | } | |
| 179 | ||
| 180 | /** | |
| 181 | * Notifies listeners of an exception occurs that warrants the user's | |
| 182 | * attention. | |
| 183 | * | |
| 184 | * @param problem The exception with a message to display to the user. | |
| 185 | */ | |
| 186 | public static void clue( final Throwable problem ) { | |
| 187 | fire( problem ); | |
| 188 | } | |
| 189 | ||
| 190 | public static void fire( final String message ) { | |
| 191 | new StatusEvent( message ).publish(); | |
| 192 | } | |
| 193 | ||
| 194 | private static void fire( final Throwable problem ) { | |
| 195 | new StatusEvent( problem ).publish(); | |
| 196 | } | |
| 197 | ||
| 198 | private static void fire( | |
| 199 | final String message, final Throwable problem ) { | |
| 200 | new StatusEvent( message, problem ).publish(); | |
| 201 | } | |
| 202 | } | |
| 1 | 203 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.events; | |
| 6 | ||
| 7 | import com.keenwrite.editors.TextDefinition; | |
| 1 | 8 | |
| 9 | public class TextDefinitionDefinition> { | |
| 10 | protected TextDefinition |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.events; | |
| 6 | ||
| 7 | import com.keenwrite.editors.TextEditor; | |
| 8 | ||
| 9 | /** | |
| 10 | * Collates information about the text editor that has gained focus. | |
| 11 | */ | |
| 12 | public class TextEditorFocusEvent extends FocusEvent<TextEditor> { | |
| 13 | protected TextEditorFocusEvent( final TextEditor editor ) { | |
| 14 | super( editor ); | |
| 15 | } | |
| 16 | ||
| 17 | /** | |
| 18 | * When the {@link TextEditor} has focus, fire an event so that subscribers | |
| 19 | * may perform an action---such as parsing and rendering the contents. | |
| 20 | * | |
| 21 | * @param editor The instance of editor that has gained input focus. | |
| 22 | */ | |
| 23 | public static void fire( final TextEditor editor ) { | |
| 24 | new TextEditorFocusEvent( editor ).publish(); | |
| 25 | } | |
| 26 | } | |
| 1 | 27 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.events; | |
| 1 | 6 | |
| 7 | /** | |
| 8 | * Collates information about the word count changing. | |
| 9 | */ | |
| 10 | public class WordCountEvent implements AppEvent { | |
| 11 | /** | |
| 12 | * Number of words in the |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.events.spelling; | |
| 6 | ||
| 7 | import com.keenwrite.events.AppEvent; | |
| 8 | ||
| 9 | public abstract class LexiconEvent implements AppEvent { | |
| 10 | } | |
| 1 | 11 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.events.spelling; | |
| 6 | ||
| 7 | import java.util.Map; | |
| 1 | 8 | |
| 9 | /** | |
| 10 | * Collates information about the lexicon. Fired when the lexicon has been | |
| 11 | * fully loaded into memory. | |
| 12 | */ | |
| 13 | public c |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.events.workspace; | |
| 6 | ||
| 7 | import com.keenwrite.events.AppEvent; | |
| 8 | ||
| 9 | /** | |
| 10 | * Superclass of all events related to the workspace. | |
| 11 | */ | |
| 12 | public abstract class WorkspaceEvent implements AppEvent { | |
| 13 | } | |
| 1 | 14 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.events.workspace; | |
| 6 | ||
| 7 | import com.keenwrite.preferences.Workspace; | |
| 8 | ||
| 9 | /** | |
| 10 | * Indicates that the {@link Workspace} has been loaded. | |
| 11 | */ | |
| 12 | public class WorkspaceLoadedEvent extends WorkspaceEvent { | |
| 13 | private final Workspace mWorkspace; | |
| 14 | ||
| 15 | private WorkspaceLoadedEvent( final Workspace workspace ) { | |
| 16 | assert workspace != null; | |
| 17 | ||
| 18 | mWorkspace = workspace; | |
| 19 | } | |
| 20 | ||
| 21 | /** | |
| 22 | * Publishes an event that indicates a new {@link Workspace} has been loaded. | |
| 23 | */ | |
| 24 | public static void fire( final Workspace workspace ) { | |
| 25 | new WorkspaceLoadedEvent( workspace ).publish(); | |
| 26 | } | |
| 27 | ||
| 28 | /** | |
| 29 | * Returns a reference to the {@link Workspace} that was loaded. | |
| 30 | * | |
| 31 | * @return The {@link Workspace} that has loaded user preferences. | |
| 32 | */ | |
| 33 | @SuppressWarnings( "unused" ) | |
| 34 | private Workspace getWorkspace() { | |
| 35 | return mWorkspace; | |
| 36 | } | |
| 37 | } | |
| 1 | 38 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 1 | 4 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | ||
| 3 | /** | |
| 4 | * This package contains classes to help with word count. In logographic, | |
| 5 | * or other non-alphabetic languages, word tokenization cannot rely on | |
| 6 | * spaces. Instead, we need to employ a more sophisticated approach using | |
| 7 | * natural language parsing (NLP). | |
| 8 | */ | |
| 9 | package com.keenwrite.heuristics; | |
| 1 | 10 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.io; | |
| 3 | ||
| 4 | import java.io.FileNotFoundException; | |
| 5 | ||
| 6 | /** | |
| 7 | * Indicates a command could not be found to run. | |
| 8 | */ | |
| 9 | public class CommandNotFoundException extends FileNotFoundException { | |
| 10 | /** | |
| 11 | * Creates a new exception indicating that the given command could not be | |
| 12 | * found (or executed). | |
| 13 | * | |
| 14 | * @param command The binary file's command name that could not be run. | |
| 15 | */ | |
| 16 | public CommandNotFoundException( final String command ) { | |
| 17 | super( command ); | |
| 18 | } | |
| 19 | } | |
| 1 | 20 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.io; | |
| 3 | ||
| 4 | import java.io.File; | |
| 5 | import java.util.EventObject; | |
| 6 | ||
| 7 | /** | |
| 8 | * Responsible for indicating that a file has been modified by the file system. | |
| 9 | */ | |
| 10 | public class FileEvent extends EventObject { | |
| 11 | ||
| 12 | /** | |
| 13 | * Constructs a new event that indicates the source of a file system event. | |
| 14 | * | |
| 15 | * @param file The {@link File} that has succumbed to a file system event. | |
| 16 | */ | |
| 17 | public FileEvent( final File file ) { | |
| 18 | super( file ); | |
| 19 | } | |
| 20 | ||
| 21 | /** | |
| 22 | * Returns the source as an instance of {@link File}. | |
| 23 | * | |
| 24 | * @return The {@link File} being watched. | |
| 25 | */ | |
| 26 | public File getFile() { | |
| 27 | return (File) getSource(); | |
| 28 | } | |
| 29 | } | |
| 1 | 30 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.io; | |
| 3 | ||
| 4 | import java.util.EventListener; | |
| 5 | import java.util.function.Consumer; | |
| 6 | ||
| 7 | /** | |
| 8 | * Responsible for informing listeners when a file has been modified. | |
| 9 | */ | |
| 10 | public interface FileModifiedListener | |
| 11 | extends EventListener, Consumer<FileEvent> { | |
| 12 | } | |
| 1 | 13 |
| 1 | ||
| 1 | /* Copyright 2020-2021 -- All rights reserved. */ | |
| 2 | package com.keenwrite.io {@code | |
| 3 | * settings.properties}- |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.io; | |
| 3 | ||
| 4 | import org.renjin.repackaged.guava.collect.BiMap; | |
| 5 | import org.renjin.repackaged.guava.collect.HashBiMap; | |
| 1 | 6 | |
| 7 | import java.io.File; | |
| 8 | import java.io.IOExceptiocom.keenwrite.io.SysFile.toFiletoFile( |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.io; | |
| 3 | ||
| 4 | import java.io.File; | |
| 5 | import java.io.IOException; | |
| 6 | import java.net.URL; | |
| 7 | import java.nio.file.Path; | |
| 1 | 8 | |
| 9 | import static com.keenwrite.io.MediaType.TypeName.*; | |
| 10 | SysFile.toFiletoFile( directory |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.io; | |
| 3 | ||
| 4 | import org.apache.commons.io.FilenameUtils; | |
| 5 | ||
| 6 | import java.io.File; | |
| 7 | import java.nio.file.Path; | |
| 8 | import java.util.List; | |
| 1 | 9 | |
| 10 | import static com.keenwrite.io.Medcom.keenwrite.io.SysFile.toFiletoFile( path |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.io; | |
| 6 | ||
| 7 | import java.io.*; | |
| 8 | import java.util.LinkedHashMap; | |
| 9 | import java.util.Map; | |
| 10 | ||
| 11 | import static com.keenwrite.io.MediaType.*; | |
| 12 | import static java.lang.Math.min; | |
| 13 | import static java.lang.System.arraycopy; | |
| 14 | import static java.util.Arrays.fill; | |
| 15 | ||
| 16 | /** | |
| 17 | * Associates file signatures with IANA-defined {@link MediaType}s. See: | |
| 18 | * <a href="https://www.garykessler.net/library/file_sigs.html"> | |
| 19 | * Gary Kessler's List | |
| 20 | * </a>, | |
| 21 | * <a href="https://en.wikipedia.org/wiki/List_of_file_signatures"> | |
| 22 | * Wikipedia's List | |
| 23 | * </a>, and | |
| 24 | * <a href="https://github.com/veniware/Space-Maker/blob/master/FileSignatures.cs"> | |
| 25 | * Space Maker's List | |
| 26 | * </a> | |
| 27 | */ | |
| 28 | public class MediaTypeSniffer { | |
| 29 | /** | |
| 30 | * The maximum buffer size of magic bytes to analyze. | |
| 31 | */ | |
| 32 | private static final int BUFFER = 12; | |
| 33 | ||
| 34 | /** | |
| 35 | * The media type data can have any value at a corresponding offset. | |
| 36 | */ | |
| 37 | private static final int ANY = -1; | |
| 38 | ||
| 39 | /** | |
| 40 | * Denotes there are fewer than {@link #BUFFER} bytes to compare. | |
| 41 | */ | |
| 42 | private static final int EOS = -2; | |
| 43 | ||
| 44 | private static final Map<int[], MediaType> FORMAT = new LinkedHashMap<>(); | |
| 45 | ||
| 46 | private static void put( final int[] data, final MediaType mediaType ) { | |
| 47 | FORMAT.put( data, mediaType ); | |
| 48 | } | |
| 49 | ||
| 50 | /* The insertion order attempts to approximate the real-world likelihood of | |
| 51 | * encountering particular file formats in an application. | |
| 52 | */ | |
| 53 | static { | |
| 54 | //@formatter:off | |
| 55 | put( ints( 0x3C, 0x73, 0x76, 0x67, 0x20 ), IMAGE_SVG_XML ); | |
| 56 | put( ints( 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A ), IMAGE_PNG ); | |
| 57 | put( ints( 0xFF, 0xD8, 0xFF, 0xE0 ), IMAGE_JPEG ); | |
| 58 | put( ints( 0xFF, 0xD8, 0xFF, 0xEE ), IMAGE_JPEG ); | |
| 59 | put( ints( 0xFF, 0xD8, 0xFF, 0xE1, ANY, ANY, 0x45, 0x78, 0x69, 0x66, 0x00 ), IMAGE_JPEG ); | |
| 60 | put( ints( 0x3C, 0x21 ), TEXT_HTML ); | |
| 61 | put( ints( 0x3C, 0x68, 0x74, 0x6D, 0x6C ), TEXT_HTML ); | |
| 62 | put( ints( 0x3C, 0x68, 0x65, 0x61, 0x64 ), TEXT_HTML ); | |
| 63 | put( ints( 0x3C, 0x62, 0x6F, 0x64, 0x79 ), TEXT_HTML ); | |
| 64 | put( ints( 0x3C, 0x48, 0x54, 0x4D, 0x4C ), TEXT_HTML ); | |
| 65 | put( ints( 0x3C, 0x48, 0x45, 0x41, 0x44 ), TEXT_HTML ); | |
| 66 | put( ints( 0x3C, 0x42, 0x4F, 0x44, 0x59 ), TEXT_HTML ); | |
| 67 | put( ints( 0x3C, 0x3F, 0x78, 0x6D, 0x6C, 0x20 ), TEXT_XML ); | |
| 68 | put( ints( 0xFE, 0xFF, 0x00, 0x3C, 0x00, 0x3f, 0x00, 0x78 ), TEXT_XML ); | |
| 69 | put( ints( 0xFF, 0xFE, 0x3C, 0x00, 0x3F, 0x00, 0x78, 0x00 ), TEXT_XML ); | |
| 70 | put( ints( 0x47, 0x49, 0x46, 0x38 ), IMAGE_GIF ); | |
| 71 | put( ints( 0x42, 0x4D ), IMAGE_BMP ); | |
| 72 | put( ints( 0x49, 0x49, 0x2A, 0x00 ), IMAGE_TIFF ); | |
| 73 | put( ints( 0x4D, 0x4D, 0x00, 0x2A ), IMAGE_TIFF ); | |
| 74 | put( ints( 0x52, 0x49, 0x46, 0x46, ANY, ANY, ANY, ANY, 0x57, 0x45, 0x42, 0x50 ), IMAGE_WEBP ); | |
| 75 | put( ints( 0x25, 0x50, 0x44, 0x46, 0x2D, 0x31, 0x2E ), APP_PDF ); | |
| 76 | put( ints( 0x25, 0x21, 0x50, 0x53, 0x2D, 0x41, 0x64, 0x6F, 0x62, 0x65, 0x2D ), APP_EPS ); | |
| 77 | put( ints( 0x25, 0x21, 0x50, 0x53 ), APP_PS ); | |
| 78 | put( ints( 0x38, 0x42, 0x50, 0x53, 0x00, 0x01 ), IMAGE_PHOTOSHOP ); | |
| 79 | put( ints( 0xFF, 0xFB, 0x30 ), AUDIO_MP3 ); | |
| 80 | put( ints( 0x49, 0x44, 0x33 ), AUDIO_MP3 ); | |
| 81 | put( ints( 0x8A, 0x4D, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A ), VIDEO_MNG ); | |
| 82 | put( ints( 0x23, 0x64, 0x65, 0x66 ), IMAGE_X_BITMAP ); | |
| 83 | put( ints( 0x21, 0x20, 0x58, 0x50, 0x4D, 0x32 ), IMAGE_X_PIXMAP ); | |
| 84 | put( ints( 0x2E, 0x73, 0x6E, 0x64 ), AUDIO_SIMPLE ); | |
| 85 | put( ints( 0x64, 0x6E, 0x73, 0x2E ), AUDIO_SIMPLE ); | |
| 86 | put( ints( 0x52, 0x49, 0x46, 0x46 ), AUDIO_WAV ); | |
| 87 | put( ints( 0x50, 0x4B ), APP_ZIP ); | |
| 88 | put( ints( 0x41, 0x43, ANY, ANY, ANY, ANY, 0x00, 0x00, 0x00, 0x00, 0x00 ), APP_ACAD ); | |
| 89 | put( ints( 0xCA, 0xFE, 0xBA, 0xBE ), APP_JAVA ); | |
| 90 | put( ints( 0xAC, 0xED ), APP_JAVA_OBJECT ); | |
| 91 | //@formatter:on | |
| 92 | } | |
| 93 | ||
| 94 | /** | |
| 95 | * Returns the {@link MediaType} for a given set of bytes. | |
| 96 | * | |
| 97 | * @param data Binary data to compare against the list of known formats. | |
| 98 | * @return The IANA-defined {@link MediaType}, or | |
| 99 | * {@link MediaType#UNDEFINED} if indeterminate. | |
| 100 | */ | |
| 101 | public static MediaType getMediaType( final byte[] data ) { | |
| 102 | assert data != null; | |
| 103 | assert data.length > 0; | |
| 104 | ||
| 105 | final var source = new int[]{ | |
| 106 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | |
| 107 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | |
| 108 | 0xFF, 0XFF, EOS | |
| 109 | }; | |
| 110 | ||
| 111 | final int length = min( data.length, source.length ); | |
| 112 | ||
| 113 | for( int i = 0; i < length; i++ ) { | |
| 114 | source[ i ] = data[ i ] & 0xFF; | |
| 115 | } | |
| 116 | ||
| 117 | for( final var entry : FORMAT.entrySet() ) { | |
| 118 | final var key = entry.getKey(); | |
| 119 | ||
| 120 | int i = -1; | |
| 121 | boolean matches = true; | |
| 122 | ||
| 123 | while( ++i < BUFFER && key[ i ] != EOS && matches ) { | |
| 124 | matches = key[ i ] == source[ i ] || key[ i ] == ANY; | |
| 125 | } | |
| 126 | ||
| 127 | if( matches ) { | |
| 128 | return entry.getValue(); | |
| 129 | } | |
| 130 | } | |
| 131 | ||
| 132 | return UNDEFINED; | |
| 133 | } | |
| 134 | ||
| 135 | /** | |
| 136 | * Convenience method to return the probed media type for the given | |
| 137 | * {@link SysFile} instance by delegating to | |
| 138 | * {@link #getMediaType(InputStream)}. | |
| 139 | * | |
| 140 | * @param file File to ascertain the {@link MediaType}. | |
| 141 | * @return The IANA-defined {@link MediaType}, or | |
| 142 | * {@link MediaType#UNDEFINED} if indeterminate. | |
| 143 | * @throws IOException Could not read from the {@link File}. | |
| 144 | */ | |
| 145 | public static MediaType getMediaType( final File file ) | |
| 146 | throws IOException { | |
| 147 | try( final var fis = new FileInputStream( file ) ) { | |
| 148 | return getMediaType( fis ); | |
| 149 | } | |
| 150 | } | |
| 151 | ||
| 152 | /** | |
| 153 | * Convenience method to return the probed media type for the given | |
| 154 | * {@link BufferedInputStream} instance. <strong>This resets the stream | |
| 155 | * pointer</strong> making the call idempotent. Prefer calling this | |
| 156 | * method when operating on streams to avoid advancing the stream. | |
| 157 | * | |
| 158 | * @param bis Data source to ascertain the {@link MediaType}. | |
| 159 | * @return The IANA-defined {@link MediaType}, or | |
| 160 | * {@link MediaType#UNDEFINED} if indeterminate. | |
| 161 | * @throws IOException Could not read from the stream. | |
| 162 | */ | |
| 163 | public static MediaType getMediaType( final BufferedInputStream bis ) | |
| 164 | throws IOException { | |
| 165 | bis.mark( BUFFER ); | |
| 166 | final var result = getMediaType( (InputStream) bis ); | |
| 167 | bis.reset(); | |
| 168 | ||
| 169 | return result; | |
| 170 | } | |
| 171 | ||
| 172 | /** | |
| 173 | * Returns the probed media type for the given {@link InputStream} instance. | |
| 174 | * The caller is responsible for closing the stream. <strong>This advances | |
| 175 | * the stream.</strong> Use {@link #getMediaType(BufferedInputStream)} to | |
| 176 | * perform a non-destructive read. | |
| 177 | * | |
| 178 | * @param is Data source to ascertain the {@link MediaType}. | |
| 179 | * @return The IANA-defined {@link MediaType}, or | |
| 180 | * {@link MediaType#UNDEFINED} if indeterminate. | |
| 181 | * @throws IOException Could not read from the {@link InputStream}. | |
| 182 | */ | |
| 183 | private static MediaType getMediaType( final InputStream is ) | |
| 184 | throws IOException { | |
| 185 | final var input = new byte[ BUFFER ]; | |
| 186 | final var count = is.read( input, 0, BUFFER ); | |
| 187 | ||
| 188 | if( count > 1 ) { | |
| 189 | final var available = new byte[ count ]; | |
| 190 | arraycopy( input, 0, available, 0, count ); | |
| 191 | return getMediaType( available ); | |
| 192 | } | |
| 193 | ||
| 194 | return UNDEFINED; | |
| 195 | } | |
| 196 | ||
| 197 | /** | |
| 198 | * Creates an integer array from the given data, padded with {@link #EOS} | |
| 199 | * values up to {@link #BUFFER} in length. | |
| 200 | * | |
| 201 | * @param data The input byte values to pad. | |
| 202 | * @return The data with padding. | |
| 203 | */ | |
| 204 | private static int[] ints( final int... data ) { | |
| 205 | assert data != null; | |
| 206 | ||
| 207 | final var magic = new int[ data.length + 1 ]; | |
| 208 | ||
| 209 | fill( magic, EOS ); | |
| 210 | arraycopy( data, 0, magic, 0, data.length ); | |
| 211 | ||
| 212 | return magic; | |
| 213 | } | |
| 214 | } | |
| 1 | 215 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.io; | |
| 3 | ||
| 4 | import java.nio.file.WatchEvent; | |
| 5 | import java.nio.file.WatchKey; | |
| 6 | import java.nio.file.WatchService; | |
| 7 | import java.nio.file.Watchable; | |
| 8 | import java.util.List; | |
| 9 | import java.util.concurrent.TimeUnit; | |
| 10 | ||
| 11 | /** | |
| 12 | * Responsible for polling the file system to see whether a file has been | |
| 13 | * updated. This is instantiated when an instance of {@link WatchService} | |
| 14 | * cannot be created using the Java API. | |
| 15 | * <p> | |
| 16 | * This is a skeleton class to avoid {@code null} references. In theory, | |
| 17 | * it should never get instantiated. If the application is run on a system | |
| 18 | * that does not support file system events, this should eliminate NPEs. | |
| 19 | * </p> | |
| 20 | */ | |
| 21 | public class PollingWatchService implements WatchService { | |
| 22 | private final WatchKey EMPTY_KEY = new WatchKey() { | |
| 23 | private final Watchable WATCHABLE = new Watchable() { | |
| 24 | @Override | |
| 25 | public WatchKey register( | |
| 26 | final WatchService watcher, | |
| 27 | final WatchEvent.Kind<?>[] events, | |
| 28 | final WatchEvent.Modifier... modifiers ) { | |
| 29 | return EMPTY_KEY; | |
| 30 | } | |
| 31 | ||
| 32 | @Override | |
| 33 | public WatchKey register( | |
| 34 | final WatchService watcher, final WatchEvent.Kind<?>... events ) { | |
| 35 | return EMPTY_KEY; | |
| 36 | } | |
| 37 | }; | |
| 38 | ||
| 39 | @Override | |
| 40 | public boolean isValid() { | |
| 41 | return false; | |
| 42 | } | |
| 43 | ||
| 44 | @Override | |
| 45 | public List<WatchEvent<?>> pollEvents() { | |
| 46 | return List.of(); | |
| 47 | } | |
| 48 | ||
| 49 | @Override | |
| 50 | public boolean reset() { | |
| 51 | return false; | |
| 52 | } | |
| 53 | ||
| 54 | @Override | |
| 55 | public void cancel() { | |
| 56 | } | |
| 57 | ||
| 58 | @Override | |
| 59 | public Watchable watchable() { | |
| 60 | return WATCHABLE; | |
| 61 | } | |
| 62 | }; | |
| 63 | ||
| 64 | @Override | |
| 65 | public void close() { | |
| 66 | } | |
| 67 | ||
| 68 | @Override | |
| 69 | public WatchKey poll() { | |
| 70 | return EMPTY_KEY; | |
| 71 | } | |
| 72 | ||
| 73 | @Override | |
| 74 | public WatchKey poll( final long timeout, final TimeUnit unit ) { | |
| 75 | return EMPTY_KEY; | |
| 76 | } | |
| 77 | ||
| 78 | @Override | |
| 79 | public WatchKey take() { | |
| 80 | return EMPTY_KEY; | |
| 81 | } | |
| 82 | } | |
| 1 | 83 |
| 1 | package com.keenwrite.io; | |
| 2 | ||
| 3 | import java.io.BufferedReader; | |
| 4 | import java.io.IOException; | |
| 5 | import java.io.InputStream; | |
| 6 | import java.io.InputStreamReader; | |
| 7 | import java.util.concurrent.Callable; | |
| 8 | import java.util.function.Consumer; | |
| 9 | ||
| 10 | import static java.nio.charset.StandardCharsets.UTF_8; | |
| 11 | import static java.util.concurrent.Executors.newFixedThreadPool; | |
| 12 | ||
| 13 | /** | |
| 14 | * Consumes the standard output of a {@link Process} created from a | |
| 15 | * {@link ProcessBuilder}. Directs the output to a {@link Consumer} of | |
| 16 | * strings. This will run on its own thread and close the stream when | |
| 17 | * no more data can be processed. | |
| 18 | * <p> | |
| 19 | * <strong>Warning:</strong> Do not use this with binary data, it is only | |
| 20 | * meant for text streams, such as standard out from running command-line | |
| 21 | * applications. | |
| 22 | * </p> | |
| 23 | */ | |
| 24 | public class StreamGobbler implements Callable<Boolean> { | |
| 25 | private final InputStream mInput; | |
| 26 | private final Consumer<String> mConsumer; | |
| 27 | ||
| 28 | /** | |
| 29 | * Constructs a new instance of {@link StreamGobbler} that is capable of | |
| 30 | * reading an {@link InputStream} and passing each line of textual data from | |
| 31 | * that stream over to a string {@link Consumer}. | |
| 32 | * | |
| 33 | * @param input The stream having input to pass to the consumer. | |
| 34 | * @param consumer The {@link Consumer} that receives each line. | |
| 35 | */ | |
| 36 | private StreamGobbler( | |
| 37 | final InputStream input, | |
| 38 | final Consumer<String> consumer ) { | |
| 39 | assert input != null; | |
| 40 | assert consumer != null; | |
| 41 | ||
| 42 | mInput = input; | |
| 43 | mConsumer = consumer; | |
| 44 | } | |
| 45 | ||
| 46 | /** | |
| 47 | * Consumes the input until no more data is available. Closes the stream. | |
| 48 | * | |
| 49 | * @return {@link Boolean#TRUE} always. | |
| 50 | * @throws IOException Could not read from the stream. | |
| 51 | */ | |
| 52 | @Override | |
| 53 | public Boolean call() throws IOException { | |
| 54 | try( final var input = new InputStreamReader( mInput, UTF_8 ); | |
| 55 | final var buffer = new BufferedReader( input ) ) { | |
| 56 | buffer.lines().forEach( mConsumer ); | |
| 57 | } | |
| 58 | ||
| 59 | return Boolean.TRUE; | |
| 60 | } | |
| 61 | ||
| 62 | /** | |
| 63 | * Reads the given {@link InputStream} on a separate thread and passes | |
| 64 | * each line of text input to the given {@link Consumer}. | |
| 65 | * | |
| 66 | * @param inputStream The stream having input to pass to the consumer. | |
| 67 | * @param consumer The {@link Consumer} that receives each line. | |
| 68 | */ | |
| 69 | public static void gobble( | |
| 70 | final InputStream inputStream, final Consumer<String> consumer ) { | |
| 71 | try( final var executor = newFixedThreadPool( 1 ) ) { | |
| 72 | executor.submit( new StreamGobbler( inputStream, consumer ) ); | |
| 73 | } | |
| 74 | } | |
| 75 | } | |
| 1 | 76 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.io; | |
| 3 | ||
| 4 | import org.jetbrains.annotations.NotNull; | |
| 1 | 5 | |
| 6 | import java.io.File; | |
| 7 | import java.io.FileInputStream; | |
| 8 | import java.io.IOException; | |
| 9 | import java.nio.file.Path; | |
| 10 | }; | |
| 11 | _ | |
| 12 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.io; | |
| 6 | ||
| 7 | import java.nio.file.Path; | |
| 8 | ||
| 9 | import static com.keenwrite.io.SysFile.toFile; | |
| 10 | import static com.keenwrite.util.SystemUtils.*; | |
| 11 | import static java.lang.System.getProperty; | |
| 12 | import static java.lang.System.getenv; | |
| 13 | ||
| 14 | /** | |
| 15 | * Responsible for determining the directory to write application data, across | |
| 16 | * multiple platforms. See also: | |
| 17 | * | |
| 18 | * <ul> | |
| 19 | * <li> | |
| 20 | * <a href="https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html"> | |
| 21 | * Linux: XDG Base Directory Specification | |
| 22 | * </a> | |
| 23 | * </li> | |
| 24 | * <li> | |
| 25 | * <a href="https://learn.microsoft.com/en-us/windows/deployment/usmt/usmt-recognized-environment-variables"> | |
| 26 | * Windows: Recognized environment variables | |
| 27 | * </a> | |
| 28 | * </li> | |
| 29 | * <li> | |
| 30 | * <a href="https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html"> | |
| 31 | * macOS: File System Programming Guide | |
| 32 | * </a> | |
| 33 | * </li> | |
| 34 | * </ul> | |
| 35 | * </p> | |
| 36 | */ | |
| 37 | public final class UserDataDir { | |
| 38 | ||
| 39 | private static final Path UNDEFINED = Path.of( "/" ); | |
| 40 | ||
| 41 | private static final String PROP_USER_HOME = getProperty( "user.home" ); | |
| 42 | private static final String PROP_USER_DIR = getProperty( "user.dir" ); | |
| 43 | private static final String PROP_OS_VERSION = getProperty( "os.version" ); | |
| 44 | private static final String ENV_APPDATA = getenv( "AppData" ); | |
| 45 | private static final String ENV_XDG_DATA_HOME = getenv( "XDG_DATA_HOME" ); | |
| 46 | ||
| 47 | private UserDataDir() { } | |
| 48 | ||
| 49 | public static String getUserHome() { | |
| 50 | return PROP_USER_HOME; | |
| 51 | } | |
| 52 | ||
| 53 | /** | |
| 54 | * Makes a valiant attempt at determining where to create application-specific | |
| 55 | * files, regardless of operating system. | |
| 56 | * | |
| 57 | * @param appName The application name that seeks to create files. | |
| 58 | * @return A fully qualified {@link Path} to a directory wherein files may | |
| 59 | * be created that are user- and application-specific. | |
| 60 | */ | |
| 61 | public static Path getAppPath( final String appName ) { | |
| 62 | final var osPath = isWindows() | |
| 63 | ? getWinAppPath() | |
| 64 | : isMacOs() | |
| 65 | ? getMacAppPath() | |
| 66 | : isUnix() | |
| 67 | ? getUnixAppPath() | |
| 68 | : UNDEFINED; | |
| 69 | ||
| 70 | final var path = osPath.equals( UNDEFINED ) | |
| 71 | ? getDefaultAppPath( appName ) | |
| 72 | : osPath.resolve( appName ); | |
| 73 | ||
| 74 | final var alternate = Path.of( PROP_USER_DIR, appName ); | |
| 75 | ||
| 76 | return ensureExists( path ) | |
| 77 | ? path | |
| 78 | : ensureExists( alternate ) | |
| 79 | ? alternate | |
| 80 | : Path.of( PROP_USER_DIR ); | |
| 81 | } | |
| 82 | ||
| 83 | private static Path getWinAppPath() { | |
| 84 | return isValid( ENV_APPDATA ) | |
| 85 | ? Path.of( ENV_APPDATA ) | |
| 86 | : home( getWinVerAppPath() ); | |
| 87 | } | |
| 88 | ||
| 89 | /** | |
| 90 | * Gets the application path with respect to the Windows version. | |
| 91 | * | |
| 92 | * @return The directory name paths relative to the user's home directory. | |
| 93 | */ | |
| 94 | private static String[] getWinVerAppPath() { | |
| 95 | return PROP_OS_VERSION.startsWith( "5." ) | |
| 96 | ? new String[]{"Application Data"} | |
| 97 | : new String[]{"AppData", "Roaming"}; | |
| 98 | } | |
| 99 | ||
| 100 | private static Path getMacAppPath() { | |
| 101 | final var path = home( "Library", "Application Support" ); | |
| 102 | ||
| 103 | return ensureExists( path ) ? path : UNDEFINED; | |
| 104 | } | |
| 105 | ||
| 106 | private static Path getUnixAppPath() { | |
| 107 | // Fallback in case the XDG data directory is undefined. | |
| 108 | var path = home( ".local", "share" ); | |
| 109 | ||
| 110 | if( isValid( ENV_XDG_DATA_HOME ) ) { | |
| 111 | final var xdgPath = Path.of( ENV_XDG_DATA_HOME ); | |
| 112 | ||
| 113 | path = ensureExists( xdgPath ) ? xdgPath : path; | |
| 114 | } | |
| 115 | ||
| 116 | return path; | |
| 117 | } | |
| 118 | ||
| 119 | /** | |
| 120 | * Returns a hidden directory relative to the user's home directory. | |
| 121 | * | |
| 122 | * @param appName The application name. | |
| 123 | * @return A suitable directory for storing application files. | |
| 124 | */ | |
| 125 | private static Path getDefaultAppPath( final String appName ) { | |
| 126 | return home( '.' + appName ); | |
| 127 | } | |
| 128 | ||
| 129 | private static Path home( final String... paths ) { | |
| 130 | return Path.of( PROP_USER_HOME, paths ); | |
| 131 | } | |
| 132 | ||
| 133 | /** | |
| 134 | * Verifies whether the path exists or was created. | |
| 135 | * | |
| 136 | * @param path The directory to verify. | |
| 137 | * @return {@code true} if the path already exists or was created, | |
| 138 | * {@code false} if the directory doesn't exist and couldn't be created. | |
| 139 | */ | |
| 140 | private static boolean ensureExists( final Path path ) { | |
| 141 | final var file = toFile( path ); | |
| 142 | return file.exists() || file.mkdirs(); | |
| 143 | } | |
| 144 | ||
| 145 | /** | |
| 146 | * Answers whether the given string contains content. | |
| 147 | * | |
| 148 | * @param s The string to check, may be {@code null}. | |
| 149 | * @return {@code true} if the string is neither {@code null} nor blank. | |
| 150 | */ | |
| 151 | private static boolean isValid( final String s ) { | |
| 152 | return !(s == null || s.isBlank()); | |
| 153 | } | |
| 154 | ||
| 155 | private static boolean isWindows() { | |
| 156 | return IS_OS_WINDOWS; | |
| 157 | } | |
| 158 | ||
| 159 | private static boolean isMacOs() { | |
| 160 | return IS_OS_MAC; | |
| 161 | } | |
| 162 | ||
| 163 | private static boolean isUnix() { | |
| 164 | return IS_OS_UNIX; | |
| 165 | } | |
| 166 | } | |
| 1 | 167 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.io; | |
| 3 | ||
| 4 | import java.io.IOException; | |
| 5 | import java.util.function.Function; | |
| 6 | import java.util.regex.Pattern; | |
| 1 | 7 | |
| 8 | import static java.io.File.pathSeparator; | |
| 9 | import static jav.* |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.io; | |
| 1 | 6 | |
| 7 | import java.io.IOException; | |
| 8 | import java.io.UncheckedIOException; | |
| 9 | import java.nio.charset.StandardCharsets; | |
| 10 | import java.nio.file.Files; | |
| 11 | import java.nio.file. |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.io.downloads; | |
| 6 | ||
| 7 | import com.keenwrite.io.MediaType; | |
| 8 | import com.keenwrite.io.MediaTypeSniffer; | |
| 9 | import com.keenwrite.io.SysFile; | |
| 10 | import javafx.concurrent.Task; | |
| 11 | ||
| 12 | import java.io.*; | |
| 13 | import java.net.HttpURLConnection; | |
| 14 | import java.net.URI; | |
| 15 | import java.net.URISyntaxException; | |
| 16 | import java.net.URL; | |
| 17 | import java.nio.file.Paths; | |
| 18 | import java.time.Duration; | |
| 19 | import java.util.concurrent.Callable; | |
| 20 | import java.util.zip.GZIPInputStream; | |
| 21 | ||
| 22 | import static java.lang.Math.toIntExact; | |
| 23 | import static java.lang.String.format; | |
| 24 | import static java.lang.System.getProperty; | |
| 25 | import static java.lang.System.setProperty; | |
| 26 | import static java.net.HttpURLConnection.HTTP_OK; | |
| 27 | import static java.net.HttpURLConnection.setFollowRedirects; | |
| 28 | ||
| 29 | /** | |
| 30 | * Responsible for downloading files and publishing status updates. This will | |
| 31 | * download a resource provided by an instance of {@link URL} into a given | |
| 32 | * {@link OutputStream}. | |
| 33 | */ | |
| 34 | public final class DownloadManager { | |
| 35 | static { | |
| 36 | setProperty( "http.keepAlive", "false" ); | |
| 37 | setFollowRedirects( true ); | |
| 38 | } | |
| 39 | ||
| 40 | /** | |
| 41 | * Number of bytes to read at a time. | |
| 42 | */ | |
| 43 | private static final int BUFFER_SIZE = 16384; | |
| 44 | ||
| 45 | /** | |
| 46 | * HTTP request timeout. | |
| 47 | */ | |
| 48 | private static final Duration TIMEOUT = Duration.ofSeconds( 30 ); | |
| 49 | ||
| 50 | /** | |
| 51 | * Use any of the static methods for opening by URI, URL, or string. | |
| 52 | */ | |
| 53 | private DownloadManager() {} | |
| 54 | ||
| 55 | @FunctionalInterface | |
| 56 | public interface ProgressListener { | |
| 57 | /** | |
| 58 | * Called when a chunk of data has been read. This is called synchronously | |
| 59 | * when downloading the data; do not execute long-running tasks in this | |
| 60 | * method (a few milliseconds is fine). | |
| 61 | * | |
| 62 | * @param percentage A value between 0 and 100, inclusive, represents the | |
| 63 | * percentage of bytes downloaded relative to the total. | |
| 64 | * A value of -1 means the total number of bytes to | |
| 65 | * download is unknown. | |
| 66 | * @param bytes When {@code percentage} is greater than or equal to | |
| 67 | * zero, this is the total number of bytes. When {@code | |
| 68 | * percentage} equals -1, this is the number of bytes | |
| 69 | * read so far. | |
| 70 | */ | |
| 71 | void update( int percentage, long bytes ); | |
| 72 | } | |
| 73 | ||
| 74 | /** | |
| 75 | * Callers may check the value of isSuccessful | |
| 76 | */ | |
| 77 | public static final class DownloadToken implements Closeable { | |
| 78 | private final HttpURLConnection mConn; | |
| 79 | private final BufferedInputStream mInput; | |
| 80 | private final MediaType mMediaType; | |
| 81 | private final long mBytesTotal; | |
| 82 | ||
| 83 | private DownloadToken( | |
| 84 | final HttpURLConnection conn, | |
| 85 | final BufferedInputStream input, | |
| 86 | final MediaType mediaType | |
| 87 | ) { | |
| 88 | assert conn != null; | |
| 89 | assert input != null; | |
| 90 | assert mediaType != null; | |
| 91 | ||
| 92 | mConn = conn; | |
| 93 | mInput = input; | |
| 94 | mMediaType = mediaType; | |
| 95 | mBytesTotal = conn.getContentLength(); | |
| 96 | } | |
| 97 | ||
| 98 | /** | |
| 99 | * Provides the ability to download remote files asynchronously while | |
| 100 | * being updated regarding the download progress. The given {@link File} | |
| 101 | * will have the contents of the URL to download upon completion. | |
| 102 | * | |
| 103 | * @param file Where to write the file contents. | |
| 104 | * @param listener Receives download progress status updates. | |
| 105 | * @return A {@link Runnable} task that can be executed in the background | |
| 106 | * to download the resource for this {@link DownloadToken}. | |
| 107 | */ | |
| 108 | public Runnable download( | |
| 109 | final File file, | |
| 110 | final ProgressListener listener ) { | |
| 111 | return () -> { | |
| 112 | final var buffer = new byte[ BUFFER_SIZE ]; | |
| 113 | final var stream = getInputStream(); | |
| 114 | final var bytesTotal = mBytesTotal; | |
| 115 | ||
| 116 | long bytesTally = 0; | |
| 117 | int bytesRead; | |
| 118 | ||
| 119 | try( final var output = new FileOutputStream( file ) ) { | |
| 120 | while( (bytesRead = stream.read( buffer )) != -1 ) { | |
| 121 | if( Thread.currentThread().isInterrupted() ) { | |
| 122 | throw new InterruptedException(); | |
| 123 | } | |
| 124 | ||
| 125 | bytesTally += bytesRead; | |
| 126 | ||
| 127 | if( bytesTotal > 0 ) { | |
| 128 | listener.update( | |
| 129 | toIntExact( bytesTally * 100 / bytesTotal ), | |
| 130 | bytesTotal | |
| 131 | ); | |
| 132 | } | |
| 133 | else { | |
| 134 | listener.update( -1, bytesRead ); | |
| 135 | } | |
| 136 | ||
| 137 | output.write( buffer, 0, bytesRead ); | |
| 138 | } | |
| 139 | } catch( final Exception ex ) { | |
| 140 | throw new RuntimeException( ex ); | |
| 141 | } finally { | |
| 142 | close(); | |
| 143 | } | |
| 144 | }; | |
| 145 | } | |
| 146 | ||
| 147 | public void close() { | |
| 148 | try { | |
| 149 | getInputStream().close(); | |
| 150 | } catch( final Exception ignored ) { | |
| 151 | } finally { | |
| 152 | mConn.disconnect(); | |
| 153 | } | |
| 154 | } | |
| 155 | ||
| 156 | /** | |
| 157 | * Returns the input stream to the resource to download. | |
| 158 | * | |
| 159 | * @return The stream to read. | |
| 160 | */ | |
| 161 | public BufferedInputStream getInputStream() { | |
| 162 | return mInput; | |
| 163 | } | |
| 164 | ||
| 165 | public MediaType getMediaType() { | |
| 166 | return mMediaType; | |
| 167 | } | |
| 168 | ||
| 169 | /** | |
| 170 | * Answers whether the type of content associated with the download stream | |
| 171 | * is a scalable vector graphic. | |
| 172 | * | |
| 173 | * @return {@code true} if the given {@link MediaType} has SVG contents. | |
| 174 | */ | |
| 175 | public boolean isSvg() { | |
| 176 | return getMediaType().isSvg(); | |
| 177 | } | |
| 178 | } | |
| 179 | ||
| 180 | /** | |
| 181 | * Opens the input stream for the resource to download. | |
| 182 | * | |
| 183 | * @param uri The {@link URI} resource to download. | |
| 184 | * @return A token that can be used for downloading the content with | |
| 185 | * periodic updates or retrieving the stream for downloading the content. | |
| 186 | * @throws IOException The stream could not be opened. | |
| 187 | * @throws URISyntaxException Invalid URI. | |
| 188 | */ | |
| 189 | public static DownloadToken open( final String uri ) | |
| 190 | throws IOException, URISyntaxException { | |
| 191 | // Pass an undefined media type so that any type of file can be retrieved. | |
| 192 | return open( new URI( uri ) ); | |
| 193 | } | |
| 194 | ||
| 195 | public static DownloadToken open( final URI uri ) | |
| 196 | throws IOException { | |
| 197 | return open( uri.toURL() ); | |
| 198 | } | |
| 199 | ||
| 200 | /** | |
| 201 | * Opens the input stream for the resource to download and verifies that | |
| 202 | * the given {@link MediaType} matches the requested type. Callers are | |
| 203 | * responsible for closing the {@link DownloadManager} to close the | |
| 204 | * underlying stream and the HTTP connection. Connections must be closed by | |
| 205 | * callers if {@link DownloadToken#download(File, ProgressListener)} | |
| 206 | * isn't called (i.e., {@link DownloadToken#getMediaType()} is called | |
| 207 | * after the transport layer's Content-Type is requested but not contents | |
| 208 | * are downloaded). | |
| 209 | * | |
| 210 | * @param url The {@link URL} resource to download. | |
| 211 | * @return A token that can be used for downloading the content with | |
| 212 | * periodic updates or retrieving the stream for downloading the content. | |
| 213 | * @throws IOException The resource could not be downloaded. | |
| 214 | */ | |
| 215 | public static DownloadToken open( final URL url ) throws IOException { | |
| 216 | final var conn = connect( url ); | |
| 217 | final var contentType = conn.getContentType(); | |
| 218 | ||
| 219 | MediaType remoteType; | |
| 220 | ||
| 221 | try { | |
| 222 | remoteType = MediaType.valueFrom( contentType ); | |
| 223 | } catch( final Exception ex ) { | |
| 224 | // If the media type couldn't be detected, try using the stream. | |
| 225 | remoteType = MediaType.UNDEFINED; | |
| 226 | } | |
| 227 | ||
| 228 | final var input = open( conn ); | |
| 229 | ||
| 230 | // Peek at the magic header bytes to determine the media type. | |
| 231 | final var magicType = MediaTypeSniffer.getMediaType( input ); | |
| 232 | ||
| 233 | // If the transport protocol's Content-Type doesn't align with the | |
| 234 | // media type for the magic header, defer to the transport protocol (so | |
| 235 | // long as the content type was sent from the remote side). | |
| 236 | final MediaType mediaType = remoteType.equals( magicType ) | |
| 237 | ? remoteType | |
| 238 | : contentType != null && !contentType.isBlank() | |
| 239 | ? remoteType | |
| 240 | : magicType.isUndefined() | |
| 241 | ? remoteType | |
| 242 | : magicType; | |
| 243 | ||
| 244 | return new DownloadToken( conn, input, mediaType ); | |
| 245 | } | |
| 246 | ||
| 247 | /** | |
| 248 | * Establishes a connection to the remote {@link URL} resource. | |
| 249 | * | |
| 250 | * @param url The {@link URL} representing a resource to download. | |
| 251 | * @return The connection manager for the {@link URL}. | |
| 252 | * @throws IOException Could not establish a connection. | |
| 253 | * @throws ArithmeticException Could not compute a timeout value (this | |
| 254 | * should never happen because the timeout is | |
| 255 | * less than a minute). | |
| 256 | * @see #TIMEOUT | |
| 257 | */ | |
| 258 | private static HttpURLConnection connect( final URL url ) | |
| 259 | throws IOException, ArithmeticException { | |
| 260 | // Both HTTP and HTTPS are covered by this condition. | |
| 261 | if( url.openConnection() instanceof HttpURLConnection conn ) { | |
| 262 | conn.setUseCaches( false ); | |
| 263 | conn.setInstanceFollowRedirects( true ); | |
| 264 | conn.setRequestProperty( "Accept-Encoding", "gzip" ); | |
| 265 | conn.setRequestProperty( "User-Agent", getProperty( "http.agent" ) ); | |
| 266 | conn.setRequestMethod( "GET" ); | |
| 267 | conn.setConnectTimeout( toIntExact( TIMEOUT.toMillis() ) ); | |
| 268 | conn.setRequestProperty( "connection", "close" ); | |
| 269 | conn.connect(); | |
| 270 | ||
| 271 | final var code = conn.getResponseCode(); | |
| 272 | ||
| 273 | if( code != HTTP_OK ) { | |
| 274 | final var message = format( | |
| 275 | "%s [HTTP %d: %s]", | |
| 276 | url.getFile(), | |
| 277 | code, | |
| 278 | conn.getResponseMessage() | |
| 279 | ); | |
| 280 | ||
| 281 | throw new IOException( message ); | |
| 282 | } | |
| 283 | ||
| 284 | return conn; | |
| 285 | } | |
| 286 | ||
| 287 | throw new UnsupportedOperationException( url.toString() ); | |
| 288 | } | |
| 289 | ||
| 290 | /** | |
| 291 | * Returns a stream in an open state. Callers are responsible for closing. | |
| 292 | * | |
| 293 | * @param conn The connection to open, which could be compressed. | |
| 294 | * @return The open stream. | |
| 295 | * @throws IOException Could not open the stream. | |
| 296 | */ | |
| 297 | private static BufferedInputStream open( final HttpURLConnection conn ) | |
| 298 | throws IOException { | |
| 299 | return open( conn.getContentEncoding(), conn.getInputStream() ); | |
| 300 | } | |
| 301 | ||
| 302 | /** | |
| 303 | * Returns a stream in an open state. Callers are responsible for closing. | |
| 304 | * The input stream may be compressed. | |
| 305 | * | |
| 306 | * @param encoding The content encoding for the stream. | |
| 307 | * @param is The stream to wrap with a suitable decoder. | |
| 308 | * @return The open stream, with any gzip content-encoding decoded. | |
| 309 | * @throws IOException Could not open the stream. | |
| 310 | */ | |
| 311 | private static BufferedInputStream open( | |
| 312 | final String encoding, final InputStream is ) throws IOException { | |
| 313 | return new BufferedInputStream( | |
| 314 | "gzip".equalsIgnoreCase( encoding ) | |
| 315 | ? new GZIPInputStream( is ) | |
| 316 | : is | |
| 317 | ); | |
| 318 | } | |
| 319 | ||
| 320 | public static <T> Task<T> createTask( final Callable<T> callable ) { | |
| 321 | return new Task<>() { | |
| 322 | @Override | |
| 323 | protected T call() throws Exception { | |
| 324 | return callable.call(); | |
| 325 | } | |
| 326 | }; | |
| 327 | } | |
| 328 | ||
| 329 | public static <T> Thread createThread( final Task<T> task ) { | |
| 330 | final var thread = new Thread( task ); | |
| 331 | thread.setDaemon( true ); | |
| 332 | return thread; | |
| 333 | } | |
| 334 | ||
| 335 | /** | |
| 336 | * Downloads a resource to a local file in a separate {@link Thread}. | |
| 337 | * | |
| 338 | * @param uri The resource to download. | |
| 339 | * @param file The destination mTarget for the resource. | |
| 340 | * @param listener Receives updates as the download proceeds. | |
| 341 | */ | |
| 342 | public static Task<Void> downloadAsync( | |
| 343 | final URI uri, | |
| 344 | final File file, | |
| 345 | final ProgressListener listener ) { | |
| 346 | final Task<Void> task = createTask( () -> { | |
| 347 | try( final var token = DownloadManager.open( uri ) ) { | |
| 348 | token.download( file, listener ).run(); | |
| 349 | } | |
| 350 | ||
| 351 | return null; | |
| 352 | } ); | |
| 353 | ||
| 354 | createThread( task ).start(); | |
| 355 | return task; | |
| 356 | } | |
| 357 | ||
| 358 | public static String toFilename( final URI uri ) { | |
| 359 | return toFile( uri ).getName(); | |
| 360 | } | |
| 361 | ||
| 362 | public static File toFile( final URI uri ) { | |
| 363 | return SysFile.toFile( Paths.get( uri.getPath() ) ); | |
| 364 | } | |
| 365 | } | |
| 1 | 366 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.io.downloads.events; | |
| 6 | ||
| 7 | import java.net.URL; | |
| 1 | 8 | |
| 9 | /** | |
| 10 | * Collates information about an HTTP connection that could not be established. | |
| 11 | */ | |
| 12 | public class DownloadConnecti |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.io.downloads.events; | |
| 6 | ||
| 7 | import com.keenwrite.events.AppEvent; | |
| 8 | ||
| 9 | import java.net.URL; | |
| 10 | import java.time.Instant; | |
| 1 | 11 | |
| 12 | /** | |
| 13 | * The parent class to all download-related stat |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.io.downloads.events; | |
| 6 | ||
| 7 | import java.net.URL; | |
| 8 | ||
| 9 | public class DownloadFailedEvent extends DownloadEvent { | |
| 10 | ||
| 11 | private final int mResponseCode; | |
| 12 | ||
| 13 | /** | |
| 14 | * Constructs a new event that indicates downloading a file was not | |
| 15 | * successful. | |
| 16 | * | |
| 17 | * @param url The {@link URL} that has triggered a download event. | |
| 18 | * @param responseCode The HTTP response code associated with the failure. | |
| 19 | */ | |
| 20 | public DownloadFailedEvent( final URL url, final int responseCode ) { | |
| 21 | super( url ); | |
| 22 | ||
| 23 | mResponseCode = responseCode; | |
| 24 | } | |
| 25 | ||
| 26 | public static void fire( final URL url, final int responseCode ) { | |
| 27 | new DownloadFailedEvent( url, responseCode ).publish(); | |
| 28 | } | |
| 29 | ||
| 30 | /** | |
| 31 | * Returns the HTTP response code for a failed download. | |
| 32 | * | |
| 33 | * @return An HTTP response code. | |
| 34 | */ | |
| 35 | public int getResponseCode() { | |
| 36 | return mResponseCode; | |
| 37 | } | |
| 38 | } | |
| 1 | 39 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.io.downloads.events; | |
| 6 | ||
| 7 | import java.net.URL; | |
| 8 | ||
| 9 | /** | |
| 10 | * Collates information about a document that has started downloading. | |
| 11 | */ | |
| 12 | public class DownloadStartedEvent extends DownloadEvent { | |
| 13 | ||
| 14 | public DownloadStartedEvent( final URL url ) { | |
| 15 | super( url ); | |
| 16 | } | |
| 17 | ||
| 18 | public static void fire( final URL url ) { | |
| 19 | new DownloadStartedEvent( url ).publish(); | |
| 20 | } | |
| 21 | } | |
| 1 | 22 |
| 1 | ||
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved.final |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.preferences; | |
| 3 | ||
| 4 | import static com.keenwrite.preferences.Key.key; | |
| 5 | ||
| 6 | /** | |
| 7 | * Responsible for defining constants used throughout the application that | |
| 8 | * represent persisted preferences. | |
| 9 | */ | |
| 10 | public final class AppKeys { | |
| 11 | //@formatter:off | |
| 12 | private static final Key KEY_ROOT = key( "workspace" ); | |
| 13 | ||
| 14 | public static final Key KEY_META = key( KEY_ROOT, "meta" ); | |
| 15 | public static final Key KEY_META_NAME = key( KEY_META, "name" ); | |
| 16 | public static final Key KEY_META_VERSION = key( KEY_META, "version" ); | |
| 17 | ||
| 18 | public static final Key KEY_DOC = key( KEY_ROOT, "document" ); | |
| 19 | public static final Key KEY_DOC_META = key( KEY_DOC, "meta" ); | |
| 20 | ||
| 21 | public static final Key KEY_EDITOR = key( KEY_ROOT, "editor" ); | |
| 22 | public static final Key KEY_EDITOR_AUTOSAVE = key( KEY_EDITOR, "autosave" ); | |
| 23 | ||
| 24 | public static final Key KEY_R = key( KEY_ROOT, "r" ); | |
| 25 | public static final Key KEY_R_SCRIPT = key( KEY_R, "script" ); | |
| 26 | public static final Key KEY_R_DIR = key( KEY_R, "dir" ); | |
| 27 | public static final Key KEY_R_DELIM = key( KEY_R, "delimiter" ); | |
| 28 | public static final Key KEY_R_DELIM_BEGAN = key( KEY_R_DELIM, "began" ); | |
| 29 | public static final Key KEY_R_DELIM_ENDED = key( KEY_R_DELIM, "ended" ); | |
| 30 | ||
| 31 | ||
| 32 | public static final Key KEY_IMAGE = key( KEY_ROOT, "images" ); | |
| 33 | public static final Key KEY_CACHE_DIR = key( KEY_IMAGE, "cache" ); | |
| 34 | public static final Key KEY_IMAGE_DIR = key( KEY_IMAGE, "dir" ); | |
| 35 | public static final Key KEY_IMAGE_ORDER = key( KEY_IMAGE, "order" ); | |
| 36 | public static final Key KEY_IMAGE_RESIZE = key( KEY_IMAGE, "resize" ); | |
| 37 | public static final Key KEY_IMAGE_SERVER = key( KEY_IMAGE, "server" ); | |
| 38 | ||
| 39 | public static final Key KEY_DEF = key( KEY_ROOT, "definition" ); | |
| 40 | public static final Key KEY_DEF_PATH = key( KEY_DEF, "path" ); | |
| 41 | public static final Key KEY_DEF_DELIM = key( KEY_DEF, "delimiter" ); | |
| 42 | public static final Key KEY_DEF_DELIM_BEGAN = key( KEY_DEF_DELIM, "began" ); | |
| 43 | public static final Key KEY_DEF_DELIM_ENDED = key( KEY_DEF_DELIM, "ended" ); | |
| 44 | ||
| 45 | public static final Key KEY_UI = key( KEY_ROOT, "ui" ); | |
| 46 | ||
| 47 | public static final Key KEY_UI_RECENT = key( KEY_UI, "recent" ); | |
| 48 | public static final Key KEY_UI_RECENT_DIR = key( KEY_UI_RECENT, "dir" ); | |
| 49 | public static final Key KEY_UI_RECENT_DOCUMENT = key( KEY_UI_RECENT, "document" ); | |
| 50 | public static final Key KEY_UI_RECENT_OFFSET = key( KEY_UI_RECENT, "offset" ); | |
| 51 | public static final Key KEY_UI_RECENT_DEFINITION = key( KEY_UI_RECENT, "definition" ); | |
| 52 | public static final Key KEY_UI_RECENT_EXPORT = key( KEY_UI_RECENT, "export" ); | |
| 53 | public static final Key KEY_UI_RECENT_OPEN = key( KEY_UI_RECENT, "files" ); | |
| 54 | public static final Key KEY_UI_RECENT_OPEN_PATH = key( KEY_UI_RECENT_OPEN, "path" ); | |
| 55 | ||
| 56 | public static final Key KEY_UI_FONT = key( KEY_UI, "font" ); | |
| 57 | public static final Key KEY_UI_FONT_EDITOR = key( KEY_UI_FONT, "editor" ); | |
| 58 | public static final Key KEY_UI_FONT_EDITOR_NAME = key( KEY_UI_FONT_EDITOR, "name" ); | |
| 59 | public static final Key KEY_UI_FONT_EDITOR_SIZE = key( KEY_UI_FONT_EDITOR, "size" ); | |
| 60 | public static final Key KEY_UI_FONT_PREVIEW = key( KEY_UI_FONT, "preview" ); | |
| 61 | public static final Key KEY_UI_FONT_PREVIEW_NAME = key( KEY_UI_FONT_PREVIEW, "name" ); | |
| 62 | public static final Key KEY_UI_FONT_PREVIEW_SIZE = key( KEY_UI_FONT_PREVIEW, "size" ); | |
| 63 | public static final Key KEY_UI_FONT_PREVIEW_MONO = key( KEY_UI_FONT_PREVIEW, "mono" ); | |
| 64 | public static final Key KEY_UI_FONT_PREVIEW_MONO_NAME = key( KEY_UI_FONT_PREVIEW_MONO, "name" ); | |
| 65 | public static final Key KEY_UI_FONT_PREVIEW_MONO_SIZE = key( KEY_UI_FONT_PREVIEW_MONO, "size" ); | |
| 66 | public static final Key KEY_UI_FONT_MATH = key( KEY_UI_FONT, "math" ); | |
| 67 | public static final Key KEY_UI_FONT_MATH_SIZE = key( KEY_UI_FONT_MATH, "size" ); | |
| 68 | ||
| 69 | public static final Key KEY_UI_WINDOW = key( KEY_UI, "window" ); | |
| 70 | public static final Key KEY_UI_WINDOW_X = key( KEY_UI_WINDOW, "x" ); | |
| 71 | public static final Key KEY_UI_WINDOW_Y = key( KEY_UI_WINDOW, "y" ); | |
| 72 | public static final Key KEY_UI_WINDOW_W = key( KEY_UI_WINDOW, "width" ); | |
| 73 | public static final Key KEY_UI_WINDOW_H = key( KEY_UI_WINDOW, "height" ); | |
| 74 | public static final Key KEY_UI_WINDOW_MAX = key( KEY_UI_WINDOW, "maximized" ); | |
| 75 | public static final Key KEY_UI_WINDOW_FULL = key( KEY_UI_WINDOW, "full" ); | |
| 76 | ||
| 77 | public static final Key KEY_UI_SKIN = key( KEY_UI, "skin" ); | |
| 78 | public static final Key KEY_UI_SKIN_SELECTION = key( KEY_UI_SKIN, "selection" ); | |
| 79 | public static final Key KEY_UI_SKIN_CUSTOM = key( KEY_UI_SKIN, "custom" ); | |
| 80 | ||
| 81 | public static final Key KEY_UI_PREVIEW = key( KEY_UI, "preview" ); | |
| 82 | public static final Key KEY_UI_PREVIEW_STYLESHEET = key( KEY_UI_PREVIEW, "stylesheet" ); | |
| 83 | ||
| 84 | public static final Key KEY_LANGUAGE = key( KEY_ROOT, "language" ); | |
| 85 | public static final Key KEY_LANGUAGE_LOCALE = key( KEY_LANGUAGE, "locale" ); | |
| 86 | ||
| 87 | public static final Key KEY_TYPESET = key( KEY_ROOT, "typeset" ); | |
| 88 | public static final Key KEY_TYPESET_CONTEXT = key( KEY_TYPESET, "context" ); | |
| 89 | public static final Key KEY_TYPESET_CONTEXT_FONTS = key( KEY_TYPESET_CONTEXT, "fonts" ); | |
| 90 | public static final Key KEY_TYPESET_CONTEXT_FONTS_DIR = key( KEY_TYPESET_CONTEXT_FONTS, "dir" ); | |
| 91 | public static final Key KEY_TYPESET_CONTEXT_THEMES = key( KEY_TYPESET_CONTEXT, "themes" ); | |
| 92 | public static final Key KEY_TYPESET_CONTEXT_THEMES_PATH = key( KEY_TYPESET_CONTEXT_THEMES, "path" ); | |
| 93 | public static final Key KEY_TYPESET_CONTEXT_THEME_SELECTION = key( KEY_TYPESET_CONTEXT_THEMES, "selection" ); | |
| 94 | public static final Key KEY_TYPESET_CONTEXT_CLEAN = key( KEY_TYPESET_CONTEXT, "clean" ); | |
| 95 | public static final Key KEY_TYPESET_CONTEXT_CHAPTERS = key( KEY_TYPESET_CONTEXT, "chapters" ); | |
| 96 | public static final Key KEY_TYPESET_TYPOGRAPHY = key( KEY_TYPESET, "typography" ); | |
| 97 | public static final Key KEY_TYPESET_TYPOGRAPHY_QUOTES = key( KEY_TYPESET_TYPOGRAPHY, "quotes" ); | |
| 98 | public static final Key KEY_TYPESET_MODES = key( KEY_TYPESET, "modes" ); | |
| 99 | public static final Key KEY_TYPESET_MODES_ENABLED = key( KEY_TYPESET_MODES, "enabled" ); | |
| 100 | //@formatter:on | |
| 101 | ||
| 102 | /** | |
| 103 | * Only for constants, do not instantiate. | |
| 104 | */ | |
| 105 | private AppKeys() { } | |
| 106 | } | |
| 1 | 107 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.preferences; | |
| 3 | ||
| 4 | import javafx.beans.property.SimpleObjectProperty; | |
| 5 | ||
| 6 | import java.io.File; | |
| 1 | 7 | |
| 8 | public final class FileProperty extends SimpleObjectProperty<File |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.preferences; | |
| 3 | ||
| 4 | import java.util.Stack; | |
| 5 | import java.util.function.Consumer; | |
| 6 | ||
| 7 | /** | |
| 8 | * Responsible for creating a type hierarchy of preference storage keys. | |
| 9 | */ | |
| 10 | public class Key { | |
| 11 | private final Key mParent; | |
| 12 | private fin; | |
| 13 | assert !name.isBlank(); | |
| 14 | Answers whether more {@link Key}s exist above this one in the hierarchy. | |
| 15 | * | |
| 16 | * @return {@code true} means this {@link Key} has a parent {@link Key}. | |
| 17 | */ | |
| 18 | public boolean hasP != null; | |
| 19 | } | |
| 20 | ||
| 21 | /** | |
| 22 | * Visits every key in the hierarchy, starting at the topmost {@link Key} and | |
| 23 | * ending with the current {@link Key}. | |
| 24 | * | |
| 25 | * @param consumer Receives the name of each visited node. | |
| 26 | * @param separator Characters to insert between each node. | |
| 27 | */ | |
| 28 | public void walk( final Consumer<String> consumer, final String separator ) { | |
| 29 | var key = this; | |
| 30 | ||
| 31 | final var stack = new Stack<String>(); | |
| 32 | ||
| 33 | while( key != null ) { | |
| 34 | stack.push( key.name() ); | |
| 35 | key = key.parent(); | |
| 36 | } | |
| 37 | ||
| 38 | var sep = ""; | |
| 39 | ||
| 40 | while( !stack.empty() ) { | |
| 41 | consumer.accept( sep + stack.pop() ); | |
| 42 | sep = separator; | |
| 43 | } | |
| 44 | } | |
| 45 | ||
| 46 | public void walk( final Consumer<String> consumer ) { | |
| 47 | walk( consumer, "" ); | |
| 48 | } | |
| 49 | ||
| 50 | public Key parent() { | |
| 51 | returublicfinal var sb = new StringBuilder( 128 ); | |
| 52 | ||
| 53 | walk( sb::append, "." ); | |
| 54 | ||
| 55 | return sb.toString(); | |
| 56 | } | |
| 57 | } | |
| 1 | 58 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.preferences; | |
| 3 | ||
| 4 | import javafx.beans.property.SimpleObjectProperty; | |
| 5 | import javafx.collections.ObservableList; | |
| 1 | 6 | |
| 7 | import java.util.LinkedHashMap; | |
| 8 | import java.utilThe {@link Locale}s are used for multiple purposes, including: | |
| 9 | * | |
| 10 | * <ul> | |
| 11 | * <li>supported text editor font listing in preferences dialog;</li> | |
| 12 | * <li>text editor CSS;</li> | |
| 13 | * <li>preview window CSS; and</li> | |
| 14 | * <li>lexicon to load for spellcheck.</li> | |
| 15 | * </ul> | |
| 16 | *www.9-suported-9 Supported@SuppressWarnings( "SpellCheckingInspection" )// English// German | |
| 17 | "de-Latn-AT", | |
| 18 | "de-Latn-DE", | |
| 19 | "de-Latn-LU", | |
| 20 | "de-Latn-CH", | |
| 21 | // Spanish | |
| 22 | "es-Latn-AR", | |
| 23 | "es-Latn-BO", | |
| 24 | "es-Latn-CL", | |
| 25 | "es-Latn-CO", | |
| 26 | "es-Latn-CR", | |
| 27 | "es-Latn-DO", | |
| 28 | "es-Latn-EC", | |
| 29 | "es-Latn-SV", | |
| 30 | "es-Latn-GT", | |
| 31 | "es-Latn-HN", | |
| 32 | "es-Latn-MX", | |
| 33 | "es-Latn-NI", | |
| 34 | "es-Latn-PA", | |
| 35 | "es-Latn-PY", | |
| 36 | "es-Latn-PE", | |
| 37 | "es-Latn-PR", | |
| 38 | "es-Latn-ES", | |
| 39 | "es-Latn-US", | |
| 40 | "es-Latn-UY", | |
| 41 | "es-Latn-VE", | |
| 42 | // French | |
| 43 | "fr-Latn-BE", | |
| 44 | "fr-Latn-CA", | |
| 45 | "fr-Latn-FR", | |
| 46 | "fr-Latn-LU", | |
| 47 | "fr-Latn-CH", | |
| 48 | // Hebrew | |
| 49 | //"iw-Hebr-IL", | |
| 50 | // Italian | |
| 51 | "it-Latn-IT", | |
| 52 | "it-Latn-CH", | |
| 53 | // Japanese | |
| 54 | "ja-Jpan-JP", | |
| 55 | // Korean | |
| 56 | "ko-Kore-KR", | |
| 57 | // Chineseund |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.preferences; | |
| 3 | ||
| 4 | import java.util.Collections; | |
| 5 | import java.util.HashMap; | |
| 6 | import java.util.Locale; | |
| 7 | import java.util.Map; | |
| 1 | 8 | |
| 9 | import static java.util.Arrays.asList;key |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.preferences; | |
| 1 | 3 | |
| 4 | import com.dlsc.formsfx.model.structure.StringField; | |
| 5 | import com.dlsc.preferencesfx.PreferencesFx; | |
| 6 | import com.dlsc.preferencesfx.model.CategoryTR."\{key.toString()}.desc"TR."\{key.toString()}.title" |
| 1 | /* Copyright 2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.preferences; | |
| 3 | ||
| 4 | import com.dlsc.formsfx.model.structure.StringField; | |
| 5 | import com.dlsc.preferencesfx.formsfx.view.controls.SimpleControl; | |
| 6 | import javafx.beans.property.DoubleProperty; | |
| 7 | import javafx.beans.property.SimpleDoubleProperty; | |
| 8 | import javafx.scene.control.Button; | |
| 9 | import javafx.scene.control.ListView; | |
| 10 | import javafx.scene.control.TextField; | |
| 11 | import javafx.scene.input.KeyEvent; | |
| 12 | import javafx.scene.layout.HBox; | |
| 13 | import javafx.scene.layout.Region; | |
| 14 | import javafx.scene.layout.StackPane; | |
| 15 | import javafx.scene.text.Font; | |
| 16 | import javafx.stage.Stage; | |
| 17 | import org.controlsfx.dialog.FontSelectorDialog; | |
| 18 | ||
| 19 | import static com.keenwrite.constants.GraphicsConstants.ICON_DIALOG; | |
| 20 | import static com.keenwrite.events.StatusEvent.clue; | |
| 21 | import static java.lang.System.currentTimeMillis; | |
| 22 | import static javafx.geometry.Pos.CENTER_LEFT; | |
| 23 | import static javafx.scene.control.ButtonType.CANCEL; | |
| 24 | import static javafx.scene.control.ButtonType.OK; | |
| 25 | import static javafx.scene.input.KeyCode.ENTER; | |
| 26 | import static javafx.scene.input.KeyCode.ESCAPE; | |
| 27 | import static javafx.scene.layout.Priority.ALWAYS; | |
| 28 | import static javafx.scene.text.Font.font; | |
| 29 | import static javafx.scene.text.Font.getDefault; | |
| 30 | ||
| 31 | /** | |
| 32 | * Responsible for provide users the ability to select a font using a friendly | |
| 33 | * font dialog. | |
| 34 | */ | |
| 35 | public class SimpleFontControl extends SimpleControl<StringField, StackPane> { | |
| 36 | private final Button mButton = new Button(); | |
| 37 | private final String mButtonText; | |
| 38 | private final DoubleProperty mFontSize = new SimpleDoubleProperty(); | |
| 39 | private final TextField mFontName = new TextField(); | |
| 40 | ||
| 41 | public SimpleFontControl( final String buttonText ) { | |
| 42 | mButtonText = buttonText; | |
| 43 | } | |
| 44 | ||
| 45 | @Override | |
| 46 | public void initializeParts() { | |
| 47 | super.initializeParts(); | |
| 48 | ||
| 49 | mFontName.setText( field.getValue() ); | |
| 50 | mFontName.setPromptText( field.placeholderProperty().getValue() ); | |
| 51 | ||
| 52 | final var fieldProperty = field.valueProperty(); | |
| 53 | if( fieldProperty.get().equals( "null" ) ) { | |
| 54 | fieldProperty.set( "" ); | |
| 55 | } | |
| 56 | ||
| 57 | mButton.setText( mButtonText ); | |
| 58 | mButton.setOnAction( event -> { | |
| 59 | final var selected = !fieldProperty.get().trim().isEmpty(); | |
| 60 | var initialFont = getDefault(); | |
| 61 | if( selected ) { | |
| 62 | final var previousValue = fieldProperty.get(); | |
| 63 | initialFont = font( previousValue ); | |
| 64 | } | |
| 65 | ||
| 66 | createFontSelectorDialog( initialFont ) | |
| 67 | .showAndWait() | |
| 68 | .ifPresent( font -> { | |
| 69 | mFontName.setText( font.getFamily() ); | |
| 70 | mFontSize.set( font.getSize() ); | |
| 71 | } ); | |
| 72 | } ); | |
| 73 | ||
| 74 | node = new StackPane(); | |
| 75 | } | |
| 76 | ||
| 77 | @Override | |
| 78 | public void layoutParts() { | |
| 79 | node.getStyleClass().add( "simple-text-control" ); | |
| 80 | fieldLabel.getStyleClass().addAll( field.getStyleClass() ); | |
| 81 | fieldLabel.getStyleClass().add( "read-only-label" ); | |
| 82 | ||
| 83 | final var box = new HBox(); | |
| 84 | HBox.setHgrow( mFontName, ALWAYS ); | |
| 85 | box.setAlignment( CENTER_LEFT ); | |
| 86 | box.getChildren().addAll( fieldLabel, mFontName, mButton ); | |
| 87 | ||
| 88 | node.getChildren().add( box ); | |
| 89 | } | |
| 90 | ||
| 91 | @Override | |
| 92 | public void setupBindings() { | |
| 93 | super.setupBindings(); | |
| 94 | mFontName.textProperty().bindBidirectional( field.userInputProperty() ); | |
| 95 | } | |
| 96 | ||
| 97 | public DoubleProperty fontSizeProperty() { | |
| 98 | return mFontSize; | |
| 99 | } | |
| 100 | ||
| 101 | /** | |
| 102 | * Creates a dialog that displays a list of available font families, | |
| 103 | * sizes, and a button for font selection. | |
| 104 | * | |
| 105 | * @param font The default font to select initially. | |
| 106 | * @return A dialog to help the user select a different {@link Font}. | |
| 107 | */ | |
| 108 | private FontSelectorDialog createFontSelectorDialog( final Font font ) { | |
| 109 | final var dialog = new FontSelectorDialog( font ); | |
| 110 | final var pane = dialog.getDialogPane(); | |
| 111 | final var buttonOk = (Button) pane.lookupButton( OK ); | |
| 112 | final var buttonCancel = (Button) pane.lookupButton( CANCEL ); | |
| 113 | ||
| 114 | buttonOk.setDefaultButton( true ); | |
| 115 | buttonCancel.setCancelButton( true ); | |
| 116 | pane.setOnKeyReleased( keyEvent -> { | |
| 117 | switch( keyEvent.getCode() ) { | |
| 118 | case ENTER -> buttonOk.fire(); | |
| 119 | case ESCAPE -> buttonCancel.fire(); | |
| 120 | default -> { } | |
| 121 | } | |
| 122 | } ); | |
| 123 | ||
| 124 | final var stage = (Stage) pane.getScene().getWindow(); | |
| 125 | stage.getIcons().add( ICON_DIALOG ); | |
| 126 | ||
| 127 | final var frontPanel = (Region) pane.getContent(); | |
| 128 | for( final var node : frontPanel.getChildrenUnmodifiable() ) { | |
| 129 | if( node instanceof final ListView<?> listView ) { | |
| 130 | final var handler = new ListViewHandler<>( listView ); | |
| 131 | listView.setOnKeyPressed( handler::handle ); | |
| 132 | } | |
| 133 | } | |
| 134 | ||
| 135 | return dialog; | |
| 136 | } | |
| 137 | ||
| 138 | /** | |
| 139 | * Responsible for handling key presses when selecting a font. Based on | |
| 140 | * <a href="https://stackoverflow.com/a/43604223/59087">Martin Široký</a>'s | |
| 141 | * answer. | |
| 142 | * | |
| 143 | * @param <T> The type of {@link ListView} to search. | |
| 144 | */ | |
| 145 | private static final class ListViewHandler<T> { | |
| 146 | /** | |
| 147 | * Amount of time to wait between key presses that typing a subsequent | |
| 148 | * key is considered part of the same search, in milliseconds. | |
| 149 | */ | |
| 150 | private static final int RESET_DELAY_MS = 1250; | |
| 151 | ||
| 152 | private String mNeedle = ""; | |
| 153 | private int mSearchSkip = 0; | |
| 154 | private long mLastTyped = currentTimeMillis(); | |
| 155 | private final ListView<T> mHaystack; | |
| 156 | ||
| 157 | private ListViewHandler( final ListView<T> listView ) { | |
| 158 | mHaystack = listView; | |
| 159 | } | |
| 160 | ||
| 161 | private void handle( final KeyEvent key ) { | |
| 162 | var ch = key.getText(); | |
| 163 | final var code = key.getCode(); | |
| 164 | ||
| 165 | if( ch == null || ch.isEmpty() || code == ESCAPE || code == ENTER ) { | |
| 166 | return; | |
| 167 | } | |
| 168 | ||
| 169 | ch = ch.toUpperCase(); | |
| 170 | ||
| 171 | if( mNeedle.equals( ch ) ) { | |
| 172 | mSearchSkip++; | |
| 173 | } | |
| 174 | else { | |
| 175 | mNeedle = currentTimeMillis() - mLastTyped > RESET_DELAY_MS | |
| 176 | ? ch : mNeedle + ch; | |
| 177 | } | |
| 178 | ||
| 179 | mLastTyped = currentTimeMillis(); | |
| 180 | ||
| 181 | boolean found = false; | |
| 182 | int skipped = 0; | |
| 183 | ||
| 184 | for( final T item : mHaystack.getItems() ) { | |
| 185 | final var straw = item.toString().toUpperCase(); | |
| 186 | ||
| 187 | if( straw.startsWith( mNeedle ) ) { | |
| 188 | if( mSearchSkip > skipped ) { | |
| 189 | skipped++; | |
| 190 | continue; | |
| 191 | } | |
| 192 | ||
| 193 | mHaystack.getSelectionModel().select( item ); | |
| 194 | final int index = mHaystack.getSelectionModel().getSelectedIndex(); | |
| 195 | mHaystack.getFocusModel().focus( index ); | |
| 196 | mHaystack.scrollTo( index ); | |
| 197 | found = true; | |
| 198 | break; | |
| 199 | } | |
| 200 | } | |
| 201 | ||
| 202 | if( !found ) { | |
| 203 | clue( "Main.status.font.search.missing", mNeedle ); | |
| 204 | mSearchSkip = 0; | |
| 205 | } | |
| 206 | } | |
| 207 | } | |
| 208 | } | |
| 1 | 209 |
| 1 | /* Copyright 2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.preferences; | |
| 3 | ||
| 4 | import com.dlsc.preferencesfx.formsfx.view.controls.SimpleControl; | |
| 5 | import com.keenwrite.ui.cells.AltTableCell; | |
| 6 | import javafx.beans.property.SimpleO field = getField(); | |
| 7 | final var table = field.createTableView(field } | |
| 8 | } | |
| 1 | 9 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.preferences; | |
| 3 | ||
| 4 | import com.dlsc.preferencesfx.PreferencesFx; | |
| 5 | import com.dlsc.preferencesfx.util.StorageHandler; | |
| 6 | import javafx.collections.ObservableList; | |
| 7 | ||
| 8 | import java.util.prefs.Preferences; | |
| 9 | ||
| 10 | /** | |
| 11 | * Prevents {@link PreferencesFx} from saving. Saving and loading preferences | |
| 12 | * and application window state is accomplished by the {@link Workspace}. This | |
| 13 | * is required to change the user preferences file location and data format. | |
| 14 | * | |
| 15 | * @see XmlStore | |
| 16 | * @see Workspace | |
| 17 | */ | |
| 18 | public final class SkeletonStorageHandler implements StorageHandler { | |
| 19 | @Override | |
| 20 | public void saveSelectedCategory( final String breadcrumb ) {} | |
| 21 | ||
| 22 | @Override | |
| 23 | public String loadSelectedCategory() { | |
| 24 | return ""; | |
| 25 | } | |
| 26 | ||
| 27 | @Override | |
| 28 | public void saveDividerPosition( final double dividerPosition ) {} | |
| 29 | ||
| 30 | @Override | |
| 31 | public double loadDividerPosition() { | |
| 32 | return 0; | |
| 33 | } | |
| 34 | ||
| 35 | @Override | |
| 36 | public void saveWindowWidth( final double windowWidth ) {} | |
| 37 | ||
| 38 | @Override | |
| 39 | public double loadWindowWidth() { | |
| 40 | return 0; | |
| 41 | } | |
| 42 | ||
| 43 | @Override | |
| 44 | public void saveWindowHeight( final double windowHeight ) {} | |
| 45 | ||
| 46 | @Override | |
| 47 | public double loadWindowHeight() { | |
| 48 | return 0; | |
| 49 | } | |
| 50 | ||
| 51 | @Override | |
| 52 | public void saveWindowPosX( final double windowPosX ) {} | |
| 53 | ||
| 54 | @Override | |
| 55 | public double loadWindowPosX() { | |
| 56 | return 0; | |
| 57 | } | |
| 58 | ||
| 59 | @Override | |
| 60 | public void saveWindowPosY( final double windowPosY ) {} | |
| 61 | ||
| 62 | @Override | |
| 63 | public double loadWindowPosY() { | |
| 64 | return 0; | |
| 65 | } | |
| 66 | ||
| 67 | @Override | |
| 68 | public void saveObject( final String breadcrumb, final Object object ) {} | |
| 69 | ||
| 70 | @Override | |
| 71 | public Object loadObject( | |
| 72 | final String breadcrumb, final Object defaultObject ) { | |
| 73 | return defaultObject; | |
| 74 | } | |
| 75 | ||
| 76 | @Override | |
| 77 | public <T> T loadObject( | |
| 78 | final String breadcrumb, final Class<T> type, final T defaultObject ) { | |
| 79 | return defaultObject; | |
| 80 | } | |
| 81 | ||
| 82 | @Override | |
| 83 | @SuppressWarnings( "rawtypes" ) | |
| 84 | public ObservableList loadObservableList( | |
| 85 | final String breadcrumb, final ObservableList defaultObservableList ) { | |
| 86 | return defaultObservableList; | |
| 87 | } | |
| 88 | ||
| 89 | @Override | |
| 90 | public <T> ObservableList<T> loadObservableList( | |
| 91 | final String breadcrumb, | |
| 92 | final Class<T> type, | |
| 93 | final ObservableList<T> defaultObservableList ) { | |
| 94 | return defaultObservableList; | |
| 95 | } | |
| 96 | ||
| 97 | @Override | |
| 98 | public boolean clearPreferences() { | |
| 99 | return false; | |
| 100 | } | |
| 101 | ||
| 102 | public Preferences getPreferences() { | |
| 103 | return null; | |
| 104 | } | |
| 105 | } | |
| 1 | 106 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.preferences; | |
| 3 | ||
| 4 | import com.keenwrite.constants.Constants; | |
| 5 | import javafx.beans.property.SimpleObjectProperty; | |
| 6 | import javafx.collections.ObservableList; | |
| 1 | 7 | |
| 8 | import"Monokai |
| 1 | /* Copyright 2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.preferences; | |
| 3 | ||
| 4 | import com.dlsc.formsfx.model.structure.Field; | |
| 5 | import com.dlsc.formsfx.model.util.BindingMode; | |
| 6 | import javafx.beans.property.ListProperty; | |
| 7 | import javafx.beans.property.Property; | |
| 8 | import javafx.beans.property.SimpleListProperty; | |
| 9 | import javafx.scene.control.TableView; | |
| 10 | ||
| 11 | import java.util.ArrayList; | |
| 12 | ||
| 13 | import static com.dlsc.formsfx.model.util.BindingMode.CONTINUOUS; | |
| 14 | import static javafx.collections.FXCollections.observableList; | |
| 15 | ||
| 16 | /** | |
| 17 | * Responsible for binding a form field to a map of values that, ultimately, | |
| 18 | * users may edit. | |
| 19 | * | |
| 20 | * @param <P> The type of {@link Property} to store in the list. | |
| 21 | */ | |
| 22 | public class TableField<P> extends Field<TableField<P>> { | |
| 23 | ||
| 24 | /** | |
| 25 | * Create a writeable list as the data model. | |
| 26 | */ | |
| 27 | private final ListProperty<P> mViewProperty = new SimpleListProperty<>( | |
| 28 | observableList( new ArrayList<>() ) | |
| 29 | ); | |
| 30 | ||
| 31 | /** | |
| 32 | * Contains the data model entries to persist. | |
| 33 | */ | |
| 34 | private final ListProperty<P> mSaveProperty; | |
| 35 | ||
| 36 | /** | |
| 37 | * Creates a new {@link TableField} with a reference to the list that is to | |
| 38 | * be persisted. | |
| 39 | * | |
| 40 | * @param persist A list of items that will be persisted. | |
| 41 | * @param <P> The type of elements in the list to persist. | |
| 42 | * @return A new {@link TableField} used to help render a UI widget. | |
| 43 | */ | |
| 44 | public static <P> TableField<P> ofListType( final ListProperty<P> persist ) { | |
| 45 | return new TableField<>( persist ); | |
| 46 | } | |
| 47 | ||
| 48 | private TableField( final ListProperty<P> property ) { | |
| 49 | mSaveProperty = property; | |
| 50 | } | |
| 51 | ||
| 52 | public TableView<P> createTableView() { | |
| 53 | return new TableView<>( mViewProperty ); | |
| 54 | } | |
| 55 | ||
| 56 | public void add( final P entry ) { | |
| 57 | mViewProperty.add( entry ); | |
| 58 | } | |
| 59 | ||
| 60 | /** | |
| 61 | * Called when a new UI instance is opened. | |
| 62 | * | |
| 63 | * @param bindingMode Indicates how the view data model is bound to the | |
| 64 | * persistence data model. | |
| 65 | */ | |
| 66 | @Override | |
| 67 | public void setBindingMode( final BindingMode bindingMode ) { | |
| 68 | if( CONTINUOUS.equals( bindingMode ) ) { | |
| 69 | mViewProperty.addAll( mSaveProperty ); | |
| 70 | } | |
| 71 | } | |
| 72 | ||
| 73 | /** | |
| 74 | * Answers whether the user input is valid. | |
| 75 | * | |
| 76 | * @return {@code true} Users may provide any key or value strings. | |
| 77 | */ | |
| 78 | @Override | |
| 79 | protected boolean validate() { | |
| 80 | return true; | |
| 81 | } | |
| 82 | ||
| 83 | /** | |
| 84 | * Update the properties to save by copying the properties updated in the | |
| 85 | * user interface (i.e., the view). To be clear, the properties are not | |
| 86 | * persisted after calling this method, merely moved out of the UI data | |
| 87 | * model and into the to-be-saved data model. | |
| 88 | */ | |
| 89 | @Override | |
| 90 | public void persist() { | |
| 91 | mSaveProperty.clear(); | |
| 92 | mSaveProperty.addAll( mViewProperty ); | |
| 93 | } | |
| 94 | ||
| 95 | /** | |
| 96 | * The {@link TableField} doesn't bind values, as such the reset can be | |
| 97 | * a no-op because only {@link #persist()} will update the properties to | |
| 98 | * save. | |
| 99 | */ | |
| 100 | @Override | |
| 101 | public void reset() {} | |
| 102 | } | |
| 1 | 103 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.preferences; | |
| 3 | ||
| 4 | import com.keenwrite.events.workspace.WorkspaceLoadedEvent; | |
| 5 | import javafx.application.Platform; | |
| 6 | import javafx.beans.property.*; | |
| 7 | import javafx.collections.ObservableList; | |
| 8 | ||
| 9 | import java.io.File; | |
| 10 | import java.nio.file.Path; | |
| 11 | import java.util.*; | |
| 12 | import java.util.Map.Entry; | |
| 13 | import java.util.function.BooleanSupplier; | |
| 14 | import java.util.function.Function; | |
| 15 | ||
| 16 | import static com.keenwrite.Bootstrap.*; | |
| 17 | import static com.keenwrite.Launcher.getVersion; | |
| 18 | import static com.keenwrite.constants.Constants.*; | |
| 19 | import static com.keenwrite.events.StatusEvent.clue; | |
| 20 | import static com.keenwrite.preferences.AppKeys.*; | |
| 21 | import static java.util.Map.entry; | |
| 22 | import static javafx.application.Platform.runLater; | |
| 23 | import static javafx.collections.FXCollections.observableArrayList; | |
| 24 | import static javafx.collections.FXCollections.observableSet; | |
| 25 | ||
| 26 | /** | |
| 27 | * Responsible for defining behaviours for separate projects. A workspace has | |
| 28 | * the ability to save and restore a session, including the window dimensions, | |
| 29 | * tab setup, files, and user preferences. | |
| 30 | * <p> | |
| 31 | * The configuration must support hierarchical (nested) configuration nodes | |
| 32 | * to persist the user interface state. Although possible with a flat | |
| 33 | * configuration file, it's not nearly as simple or elegant. | |
| 34 | * </p> | |
| 35 | * <p> | |
| 36 | * Neither JSON nor HOCON support schema validation and versioning, which makes | |
| 37 | * XML the more suitable configuration file format. Schema validation and | |
| 38 | * versioning provide future-proofing and ease of reading and upgrading previous | |
| 39 | * versions of the configuration file. | |
| 40 | * </p> | |
| 41 | * <p> | |
| 42 | * Persistent preferences may be set directly by the user or indirectly by | |
| 43 | * the act of using the application. | |
| 44 | * </p> | |
| 45 | * <p> | |
| 46 | * Note the following definitions: | |
| 47 | * </p> | |
| 48 | * <dl> | |
| 49 | * <dt>File</dt> | |
| 50 | * <dd>References a file name (no path), path, or directory.</dd> | |
| 51 | * <dt>Path</dt> | |
| 52 | * <dd>Fully qualified file name, which includes all parent directories.</dd> | |
| 53 | * <dt>Dir</dt> | |
| 54 | * <dd>Directory without file name ({@link File#isDirectory()} is true).</dd> | |
| 55 | * </dl> | |
| 56 | */ | |
| 57 | public final class Workspace { | |
| 58 | ||
| 59 | /** | |
| 60 | * Main configuration values, single text strings. | |
| 61 | */ | |
| 62 | private final Map<Key, Property<?>> mValues = Map.ofEntries( | |
| 63 | entry( KEY_META_VERSION, asStringProperty( getVersion() ) ), | |
| 64 | entry( KEY_META_NAME, asStringProperty( "default" ) ), | |
| 65 | ||
| 66 | entry( KEY_EDITOR_AUTOSAVE, asIntegerProperty( 30 ) ), | |
| 67 | ||
| 68 | entry( KEY_R_SCRIPT, asStringProperty( "" ) ), | |
| 69 | entry( KEY_R_DIR, asFileProperty( USER_DIRECTORY ) ), | |
| 70 | entry( KEY_R_DELIM_BEGAN, asStringProperty( R_DELIM_BEGAN_DEFAULT ) ), | |
| 71 | entry( KEY_R_DELIM_ENDED, asStringProperty( R_DELIM_ENDED_DEFAULT ) ), | |
| 72 | ||
| 73 | entry( KEY_CACHE_DIR, asFileProperty( USER_CACHE_DIR ) ), | |
| 74 | entry( KEY_IMAGE_DIR, asFileProperty( USER_DIRECTORY ) ), | |
| 75 | entry( KEY_IMAGE_ORDER, asStringProperty( PERSIST_IMAGES_DEFAULT ) ), | |
| 76 | entry( KEY_IMAGE_RESIZE, asBooleanProperty( true ) ), | |
| 77 | entry( KEY_IMAGE_SERVER, asStringProperty( DIAGRAM_SERVER_NAME ) ), | |
| 78 | ||
| 79 | entry( KEY_DEF_PATH, asFileProperty( DEFINITION_DEFAULT ) ), | |
| 80 | entry( KEY_DEF_DELIM_BEGAN, asStringProperty( DEF_DELIM_BEGAN_DEFAULT ) ), | |
| 81 | entry( KEY_DEF_DELIM_ENDED, asStringProperty( DEF_DELIM_ENDED_DEFAULT ) ), | |
| 82 | ||
| 83 | entry( KEY_UI_RECENT_DIR, asFileProperty( USER_DIRECTORY ) ), | |
| 84 | entry( KEY_UI_RECENT_OFFSET, asIntegerProperty( DOCUMENT_OFFSET ) ), | |
| 85 | entry( KEY_UI_RECENT_DOCUMENT, asFileProperty( DOCUMENT_DEFAULT ) ), | |
| 86 | entry( KEY_UI_RECENT_DEFINITION, asFileProperty( DEFINITION_DEFAULT ) ), | |
| 87 | entry( KEY_UI_RECENT_EXPORT, asFileProperty( PDF_DEFAULT ) ), | |
| 88 | ||
| 89 | //@formatter:off | |
| 90 | entry( | |
| 91 | KEY_UI_FONT_EDITOR_NAME, | |
| 92 | asStringProperty( FONT_NAME_EDITOR_DEFAULT ) | |
| 93 | ), | |
| 94 | entry( | |
| 95 | KEY_UI_FONT_EDITOR_SIZE, | |
| 96 | asDoubleProperty( FONT_SIZE_EDITOR_DEFAULT ) | |
| 97 | ), | |
| 98 | entry( | |
| 99 | KEY_UI_FONT_PREVIEW_NAME, | |
| 100 | asStringProperty( FONT_NAME_PREVIEW_DEFAULT ) | |
| 101 | ), | |
| 102 | entry( | |
| 103 | KEY_UI_FONT_PREVIEW_SIZE, | |
| 104 | asDoubleProperty( FONT_SIZE_PREVIEW_DEFAULT ) | |
| 105 | ), | |
| 106 | entry( | |
| 107 | KEY_UI_FONT_PREVIEW_MONO_NAME, | |
| 108 | asStringProperty( FONT_NAME_PREVIEW_MONO_NAME_DEFAULT ) | |
| 109 | ), | |
| 110 | entry( | |
| 111 | KEY_UI_FONT_PREVIEW_MONO_SIZE, | |
| 112 | asDoubleProperty( FONT_SIZE_PREVIEW_MONO_SIZE_DEFAULT ) | |
| 113 | ), | |
| 114 | entry( | |
| 115 | KEY_UI_FONT_MATH_SIZE, | |
| 116 | asDoubleProperty( FONT_SIZE_MATH_DEFAULT ) | |
| 117 | ), | |
| 118 | ||
| 119 | entry( KEY_UI_WINDOW_X, asDoubleProperty( WINDOW_X_DEFAULT ) ), | |
| 120 | entry( KEY_UI_WINDOW_Y, asDoubleProperty( WINDOW_Y_DEFAULT ) ), | |
| 121 | entry( KEY_UI_WINDOW_W, asDoubleProperty( WINDOW_W_DEFAULT ) ), | |
| 122 | entry( KEY_UI_WINDOW_H, asDoubleProperty( WINDOW_H_DEFAULT ) ), | |
| 123 | entry( KEY_UI_WINDOW_MAX, asBooleanProperty() ), | |
| 124 | entry( KEY_UI_WINDOW_FULL, asBooleanProperty() ), | |
| 125 | ||
| 126 | entry( KEY_UI_SKIN_SELECTION, asSkinProperty( SKIN_DEFAULT ) ), | |
| 127 | entry( KEY_UI_SKIN_CUSTOM, asFileProperty( SKIN_CUSTOM_DEFAULT ) ), | |
| 128 | ||
| 129 | entry( | |
| 130 | KEY_UI_PREVIEW_STYLESHEET, asFileProperty( PREVIEW_CUSTOM_DEFAULT ) | |
| 131 | ), | |
| 132 | ||
| 133 | entry( KEY_LANGUAGE_LOCALE, asLocaleProperty( LOCALE_DEFAULT ) ), | |
| 134 | ||
| 135 | entry( KEY_TYPESET_CONTEXT_CLEAN, asBooleanProperty( true ) ), | |
| 136 | entry( KEY_TYPESET_CONTEXT_FONTS_DIR, asFileProperty( getFontDirectory() ) ), | |
| 137 | entry( KEY_TYPESET_CONTEXT_THEMES_PATH, asFileProperty( USER_DIRECTORY ) ), | |
| 138 | entry( KEY_TYPESET_CONTEXT_THEME_SELECTION, asStringProperty( "boschet" ) ), | |
| 139 | entry( KEY_TYPESET_CONTEXT_CHAPTERS, asStringProperty( "" ) ), | |
| 140 | entry( KEY_TYPESET_TYPOGRAPHY_QUOTES, asBooleanProperty( true ) ), | |
| 141 | entry( KEY_TYPESET_MODES_ENABLED, asStringProperty( "" ) ) | |
| 142 | //@formatter:on | |
| 143 | ); | |
| 144 | ||
| 145 | /** | |
| 146 | * Sets of configuration values, all the same type (e.g., file names), | |
| 147 | * where the key name doesn't change per set. | |
| 148 | */ | |
| 149 | private final Map<Key, SetProperty<?>> mSets = Map.ofEntries( | |
| 150 | entry( | |
| 151 | KEY_UI_RECENT_OPEN_PATH, | |
| 152 | createSetProperty( new HashSet<String>() ) | |
| 153 | ) | |
| 154 | ); | |
| 155 | ||
| 156 | /** | |
| 157 | * Lists of configuration values, such as key-value pairs where both the | |
| 158 | * key name and the value must be preserved per list. | |
| 159 | */ | |
| 160 | private final Map<Key, ListProperty<?>> mLists = Map.ofEntries( | |
| 161 | entry( | |
| 162 | KEY_DOC_META, | |
| 163 | createListProperty( new LinkedList<Entry<String, String>>() ) | |
| 164 | ) | |
| 165 | ); | |
| 166 | ||
| 167 | /** | |
| 168 | * Helps instantiate {@link Property} instances for XML configuration items. | |
| 169 | */ | |
| 170 | private static final Map<Class<?>, Function<String, Object>> UNMARSHALL = | |
| 171 | Map.of( | |
| 172 | LocaleProperty.class, LocaleProperty::parseLocale, | |
| 173 | SimpleBooleanProperty.class, Boolean::parseBoolean, | |
| 174 | SimpleIntegerProperty.class, Integer::parseInt, | |
| 175 | SimpleDoubleProperty.class, Double::parseDouble, | |
| 176 | SimpleFloatProperty.class, Float::parseFloat, | |
| 177 | SimpleStringProperty.class, String::new, | |
| 178 | SimpleObjectProperty.class, String::new, | |
| 179 | SkinProperty.class, String::new, | |
| 180 | FileProperty.class, File::new | |
| 181 | ); | |
| 182 | ||
| 183 | /** | |
| 184 | * The asymmetry with respect to {@link #UNMARSHALL} is because most objects | |
| 185 | * can simply call {@link Object#toString()} to convert the value to a string. | |
| 186 | */ | |
| 187 | private static final Map<Class<?>, Function<String, Object>> MARSHALL = | |
| 188 | Map.of( | |
| 189 | LocaleProperty.class, LocaleProperty::toLanguageTag | |
| 190 | ); | |
| 191 | ||
| 192 | /** | |
| 193 | * Converts the given {@link Property} value to a string. | |
| 194 | * | |
| 195 | * @param property The {@link Property} to convert. | |
| 196 | * @return A string representation of the given property, or the empty | |
| 197 | * string if no conversion was possible. | |
| 198 | */ | |
| 199 | private static String marshall( final Property<?> property ) { | |
| 200 | final var v = property.getValue(); | |
| 201 | ||
| 202 | return v == null | |
| 203 | ? "" | |
| 204 | : MARSHALL | |
| 205 | .getOrDefault( property.getClass(), _ -> property.getValue() ) | |
| 206 | .apply( v.toString() ) | |
| 207 | .toString(); | |
| 208 | } | |
| 209 | ||
| 210 | private static Object unmarshall( | |
| 211 | final Property<?> property, final Object configValue ) { | |
| 212 | final var v = configValue.toString(); | |
| 213 | ||
| 214 | return UNMARSHALL | |
| 215 | .getOrDefault( property.getClass(), _ -> property.getValue() ) | |
| 216 | .apply( v ); | |
| 217 | } | |
| 218 | ||
| 219 | /** | |
| 220 | * Creates an instance of {@link ObservableList} that is based on a | |
| 221 | * modifiable observable array list for the given items. | |
| 222 | * | |
| 223 | * @param items The items to wrap in an observable list. | |
| 224 | * @param <E> The type of items to add to the list. | |
| 225 | * @return An observable property that can have its contents modified. | |
| 226 | */ | |
| 227 | public static <E> ObservableList<E> listProperty( final Set<E> items ) { | |
| 228 | return new SimpleListProperty<>( observableArrayList( items ) ); | |
| 229 | } | |
| 230 | ||
| 231 | private static <E> SetProperty<E> createSetProperty( final Set<E> set ) { | |
| 232 | return new SimpleSetProperty<>( observableSet( set ) ); | |
| 233 | } | |
| 234 | ||
| 235 | private static <E> ListProperty<E> createListProperty( final List<E> list ) { | |
| 236 | return new SimpleListProperty<>( observableArrayList( list ) ); | |
| 237 | } | |
| 238 | ||
| 239 | private static StringProperty asStringProperty( final String value ) { | |
| 240 | return new SimpleStringProperty( value ); | |
| 241 | } | |
| 242 | ||
| 243 | private static BooleanProperty asBooleanProperty() { | |
| 244 | return new SimpleBooleanProperty(); | |
| 245 | } | |
| 246 | ||
| 247 | /** | |
| 248 | * @param value Default value. | |
| 249 | */ | |
| 250 | @SuppressWarnings( "SameParameterValue" ) | |
| 251 | private static BooleanProperty asBooleanProperty( final boolean value ) { | |
| 252 | return new SimpleBooleanProperty( value ); | |
| 253 | } | |
| 254 | ||
| 255 | /** | |
| 256 | * @param value Default value. | |
| 257 | */ | |
| 258 | @SuppressWarnings( "SameParameterValue" ) | |
| 259 | private static IntegerProperty asIntegerProperty( final int value ) { | |
| 260 | return new SimpleIntegerProperty( value ); | |
| 261 | } | |
| 262 | ||
| 263 | /** | |
| 264 | * @param value Default value. | |
| 265 | */ | |
| 266 | private static DoubleProperty asDoubleProperty( final double value ) { | |
| 267 | return new SimpleDoubleProperty( value ); | |
| 268 | } | |
| 269 | ||
| 270 | /** | |
| 271 | * @param value Default value. | |
| 272 | */ | |
| 273 | private static FileProperty asFileProperty( final File value ) { | |
| 274 | return new FileProperty( value ); | |
| 275 | } | |
| 276 | ||
| 277 | /** | |
| 278 | * @param value Default value. | |
| 279 | */ | |
| 280 | @SuppressWarnings( "SameParameterValue" ) | |
| 281 | private static LocaleProperty asLocaleProperty( final Locale value ) { | |
| 282 | return new LocaleProperty( value ); | |
| 283 | } | |
| 284 | ||
| 285 | /** | |
| 286 | * @param value Default value. | |
| 287 | */ | |
| 288 | @SuppressWarnings( "SameParameterValue" ) | |
| 289 | private static SkinProperty asSkinProperty( final String value ) { | |
| 290 | return new SkinProperty( value ); | |
| 291 | } | |
| 292 | ||
| 293 | /** | |
| 294 | * Creates a new {@link Workspace} that will attempt to load the users' | |
| 295 | * preferences. If the configuration file cannot be loaded, the workspace | |
| 296 | * settings returns default values. | |
| 297 | */ | |
| 298 | public Workspace() { | |
| 299 | load(); | |
| 300 | } | |
| 301 | ||
| 302 | /** | |
| 303 | * Attempts to load the app's configuration file. | |
| 304 | */ | |
| 305 | private void load() { | |
| 306 | final var store = createXmlStore(); | |
| 307 | store.load( FILE_PREFERENCES ); | |
| 308 | ||
| 309 | mValues.keySet().forEach( key -> { | |
| 310 | try { | |
| 311 | final var storeValue = store.getValue( key ); | |
| 312 | final var property = valuesProperty( key ); | |
| 313 | final var unmarshalled = unmarshall( property, storeValue ); | |
| 314 | ||
| 315 | property.setValue( unmarshalled ); | |
| 316 | } catch( final NoSuchElementException ex ) { | |
| 317 | // When no configuration (item), use the default value. | |
| 318 | clue( ex ); | |
| 319 | } | |
| 320 | } ); | |
| 321 | ||
| 322 | mSets.keySet().forEach( key -> { | |
| 323 | final var set = store.getSet( key ); | |
| 324 | final SetProperty<String> property = setsProperty( key ); | |
| 325 | ||
| 326 | property.setValue( observableSet( set ) ); | |
| 327 | } ); | |
| 328 | ||
| 329 | mLists.keySet().forEach( key -> { | |
| 330 | final var map = store.getMap( key ); | |
| 331 | final ListProperty<Entry<String, String>> property = listsProperty( key ); | |
| 332 | final var list = map | |
| 333 | .entrySet() | |
| 334 | .stream() | |
| 335 | .toList(); | |
| 336 | ||
| 337 | property.setValue( observableArrayList( list ) ); | |
| 338 | } ); | |
| 339 | ||
| 340 | WorkspaceLoadedEvent.fire( this ); | |
| 341 | } | |
| 342 | ||
| 343 | /** | |
| 344 | * Saves the current workspace. | |
| 345 | */ | |
| 346 | public void save() { | |
| 347 | final var store = createXmlStore(); | |
| 348 | ||
| 349 | try { | |
| 350 | // Update the string values to include the application version. | |
| 351 | valuesProperty( KEY_META_VERSION ).setValue( getVersion() ); | |
| 352 | ||
| 353 | mValues.forEach( ( k, v ) -> store.setValue( k, marshall( v ) ) ); | |
| 354 | mSets.forEach( store::setSet ); | |
| 355 | mLists.forEach( store::setMap ); | |
| 356 | ||
| 357 | store.save( FILE_PREFERENCES ); | |
| 358 | } catch( final Exception ex ) { | |
| 359 | clue( ex ); | |
| 360 | } | |
| 361 | } | |
| 362 | ||
| 363 | /** | |
| 364 | * Returns a value that represents a setting in the application that the user | |
| 365 | * may configure, either directly or indirectly. | |
| 366 | * | |
| 367 | * @param key The reference to the users' preference stored in deference | |
| 368 | * of app reëntrance. | |
| 369 | * @return An observable property to be persisted. | |
| 370 | */ | |
| 371 | @SuppressWarnings( "unchecked" ) | |
| 372 | public <T, U extends Property<T>> U valuesProperty( final Key key ) { | |
| 373 | assert key != null; | |
| 374 | return (U) mValues.get( key ); | |
| 375 | } | |
| 376 | ||
| 377 | /** | |
| 378 | * Returns a set of values that represent a setting in the application that | |
| 379 | * the user may configure, either directly or indirectly. The property | |
| 380 | * returned is backed by a {@link Set}. | |
| 381 | * | |
| 382 | * @param key The {@link Key} associated with a preference value. | |
| 383 | * @return An observable property to be persisted. | |
| 384 | */ | |
| 385 | @SuppressWarnings( "unchecked" ) | |
| 386 | public <T> SetProperty<T> setsProperty( final Key key ) { | |
| 387 | assert key != null; | |
| 388 | return (SetProperty<T>) mSets.get( key ); | |
| 389 | } | |
| 390 | ||
| 391 | /** | |
| 392 | * Returns a list of values that represent a setting in the application that | |
| 393 | * the user may configure, either directly or indirectly. The property | |
| 394 | * returned is backed by a mutable {@link List}. | |
| 395 | * | |
| 396 | * @param key The {@link Key} associated with a preference value. | |
| 397 | * @return An observable property to be persisted. | |
| 398 | */ | |
| 399 | @SuppressWarnings( "unchecked" ) | |
| 400 | public <K, V> ListProperty<Entry<K, V>> listsProperty( final Key key ) { | |
| 401 | assert key != null; | |
| 402 | return (ListProperty<Entry<K, V>>) mLists.get( key ); | |
| 403 | } | |
| 404 | ||
| 405 | /** | |
| 406 | * Returns the {@link String} {@link Property} associated with the given | |
| 407 | * {@link Key} from the internal list of preference values. The caller | |
| 408 | * must be sure that the given {@link Key} is associated with a {@link File} | |
| 409 | * {@link Property}. | |
| 410 | * | |
| 411 | * @param key The {@link Key} associated with a preference value. | |
| 412 | * @return The value associated with the given {@link Key}. | |
| 413 | */ | |
| 414 | public StringProperty stringProperty( final Key key ) { | |
| 415 | assert key != null; | |
| 416 | return valuesProperty( key ); | |
| 417 | } | |
| 418 | ||
| 419 | /** | |
| 420 | * Returns the {@link Boolean} {@link Property} associated with the given | |
| 421 | * {@link Key} from the internal list of preference values. The caller | |
| 422 | * must be sure that the given {@link Key} is associated with a {@link File} | |
| 423 | * {@link Property}. | |
| 424 | * | |
| 425 | * @param key The {@link Key} associated with a preference value. | |
| 426 | * @return The value associated with the given {@link Key}. | |
| 427 | */ | |
| 428 | public BooleanProperty booleanProperty( final Key key ) { | |
| 429 | assert key != null; | |
| 430 | return valuesProperty( key ); | |
| 431 | } | |
| 432 | ||
| 433 | /** | |
| 434 | * Returns the {@link Integer} {@link Property} associated with the given | |
| 435 | * {@link Key} from the internal list of preference values. The caller | |
| 436 | * must be sure that the given {@link Key} is associated with a {@link File} | |
| 437 | * {@link Property}. | |
| 438 | * | |
| 439 | * @param key The {@link Key} associated with a preference value. | |
| 440 | * @return The value associated with the given {@link Key}. | |
| 441 | */ | |
| 442 | public IntegerProperty integerProperty( final Key key ) { | |
| 443 | assert key != null; | |
| 444 | return valuesProperty( key ); | |
| 445 | } | |
| 446 | ||
| 447 | /** | |
| 448 | * Returns the {@link Double} {@link Property} associated with the given | |
| 449 | * {@link Key} from the internal list of preference values. The caller | |
| 450 | * must be sure that the given {@link Key} is associated with a {@link File} | |
| 451 | * {@link Property}. | |
| 452 | * | |
| 453 | * @param key The {@link Key} associated with a preference value. | |
| 454 | * @return The value associated with the given {@link Key}. | |
| 455 | */ | |
| 456 | public DoubleProperty doubleProperty( final Key key ) { | |
| 457 | assert key != null; | |
| 458 | return valuesProperty( key ); | |
| 459 | } | |
| 460 | ||
| 461 | /** | |
| 462 | * Returns the {@link File} {@link Property} associated with the given | |
| 463 | * {@link Key} from the internal list of preference values. The caller | |
| 464 | * must be sure that the given {@link Key} is associated with a {@link File} | |
| 465 | * {@link Property}. | |
| 466 | * | |
| 467 | * @param key The {@link Key} associated with a preference value. | |
| 468 | * @return The value associated with the given {@link Key}. | |
| 469 | */ | |
| 470 | public ObjectProperty<File> fileProperty( final Key key ) { | |
| 471 | assert key != null; | |
| 472 | return valuesProperty( key ); | |
| 473 | } | |
| 474 | ||
| 475 | /** | |
| 476 | * Returns the {@link Locale} {@link Property} associated with the given | |
| 477 | * {@link Key} from the internal list of preference values. The caller | |
| 478 | * must be sure that the given {@link Key} is associated with a {@link File} | |
| 479 | * {@link Property}. | |
| 480 | * | |
| 481 | * @param key The {@link Key} associated with a preference value. | |
| 482 | * @return The value associated with the given {@link Key}. | |
| 483 | */ | |
| 484 | public LocaleProperty localeProperty( final Key key ) { | |
| 485 | assert key != null; | |
| 486 | return valuesProperty( key ); | |
| 487 | } | |
| 488 | ||
| 489 | public ObjectProperty<String> skinProperty( final Key key ) { | |
| 490 | assert key != null; | |
| 491 | return valuesProperty( key ); | |
| 492 | } | |
| 493 | ||
| 494 | public String getString( final Key key ) { | |
| 495 | assert key != null; | |
| 496 | return stringProperty( key ).get(); | |
| 497 | } | |
| 498 | ||
| 499 | /** | |
| 500 | * Returns the {@link Boolean} preference value associated with the given | |
| 501 | * {@link Key}. The caller must be sure that the given {@link Key} is | |
| 502 | * associated with a value that matches the return type. | |
| 503 | * | |
| 504 | * @param key The {@link Key} associated with a preference value. | |
| 505 | * @return The value associated with the given {@link Key}. | |
| 506 | */ | |
| 507 | public boolean getBoolean( final Key key ) { | |
| 508 | assert key != null; | |
| 509 | return booleanProperty( key ).get(); | |
| 510 | } | |
| 511 | ||
| 512 | /** | |
| 513 | * Returns the {@link Integer} preference value associated with the given | |
| 514 | * {@link Key}. The caller must be sure that the given {@link Key} is | |
| 515 | * associated with a value that matches the return type. | |
| 516 | * | |
| 517 | * @param key The {@link Key} associated with a preference value. | |
| 518 | * @return The value associated with the given {@link Key}. | |
| 519 | */ | |
| 520 | @SuppressWarnings( "unused" ) | |
| 521 | public int getInteger( final Key key ) { | |
| 522 | assert key != null; | |
| 523 | return integerProperty( key ).get(); | |
| 524 | } | |
| 525 | ||
| 526 | /** | |
| 527 | * Returns the {@link Double} preference value associated with the given | |
| 528 | * {@link Key}. The caller must be sure that the given {@link Key} is | |
| 529 | * associated with a value that matches the return type. | |
| 530 | * | |
| 531 | * @param key The {@link Key} associated with a preference value. | |
| 532 | * @return The value associated with the given {@link Key}. | |
| 533 | */ | |
| 534 | public double getDouble( final Key key ) { | |
| 535 | assert key != null; | |
| 536 | return doubleProperty( key ).get(); | |
| 537 | } | |
| 538 | ||
| 539 | /** | |
| 540 | * Returns the {@link File} preference value associated with the given | |
| 541 | * {@link Key}. The caller must be sure that the given {@link Key} is | |
| 542 | * associated with a value that matches the return type. | |
| 543 | * | |
| 544 | * @param key The {@link Key} associated with a preference value. | |
| 545 | * @return The value associated with the given {@link Key}. | |
| 546 | */ | |
| 547 | public File getFile( final Key key ) { | |
| 548 | assert key != null; | |
| 549 | return fileProperty( key ).get(); | |
| 550 | } | |
| 551 | ||
| 552 | /** | |
| 553 | * Returns the language locale setting for the | |
| 554 | * {@link AppKeys#KEY_LANGUAGE_LOCALE} key. | |
| 555 | * | |
| 556 | * @return The user's current locale setting. | |
| 557 | */ | |
| 558 | public Locale getLocale() { | |
| 559 | return localeProperty( KEY_LANGUAGE_LOCALE ).toLocale(); | |
| 560 | } | |
| 561 | ||
| 562 | @SuppressWarnings( "unchecked" ) | |
| 563 | public <K, V> Map<K, V> getMetadata() { | |
| 564 | final var metadata = listsProperty( KEY_DOC_META ); | |
| 565 | final HashMap<K, V> map; | |
| 566 | ||
| 567 | if( metadata != null ) { | |
| 568 | map = new HashMap<>( metadata.size() ); | |
| 569 | ||
| 570 | metadata.forEach( | |
| 571 | entry -> map.put( (K) entry.getKey(), (V) entry.getValue() ) | |
| 572 | ); | |
| 573 | } | |
| 574 | else { | |
| 575 | map = new HashMap<>(); | |
| 576 | } | |
| 577 | ||
| 578 | return map; | |
| 579 | } | |
| 580 | ||
| 581 | public Path getThemesPath() { | |
| 582 | final var dir = getFile( KEY_TYPESET_CONTEXT_THEMES_PATH ); | |
| 583 | final var name = getString( KEY_TYPESET_CONTEXT_THEME_SELECTION ); | |
| 584 | ||
| 585 | return Path.of( dir.toString(), name ); | |
| 586 | } | |
| 587 | ||
| 588 | /** | |
| 589 | * Delegates to {@link #listen(Key, ReadOnlyProperty, BooleanSupplier)}, | |
| 590 | * providing a value of {@code true} for the {@link BooleanSupplier} to | |
| 591 | * indicate the property changes always take effect. | |
| 592 | * | |
| 593 | * @param key The value to bind to the internal key property. | |
| 594 | * @param property The external property value that sets the internal value. | |
| 595 | */ | |
| 596 | public <T> void listen( final Key key, final ReadOnlyProperty<T> property ) { | |
| 597 | assert key != null; | |
| 598 | assert property != null; | |
| 599 | ||
| 600 | listen( key, property, () -> true ); | |
| 601 | } | |
| 602 | ||
| 603 | /** | |
| 604 | * Binds a read-only property to a value in the preferences. This allows | |
| 605 | * user interface properties to change and the preferences will be | |
| 606 | * synchronized automatically. | |
| 607 | * <p> | |
| 608 | * This calls {@link Platform#runLater(Runnable)} to ensure that all pending | |
| 609 | * application window states are finished before assessing whether property | |
| 610 | * changes should be applied. Without this, exiting the application while the | |
| 611 | * window is maximized would persist the window's maximum dimensions, | |
| 612 | * preventing restoration to its prior, non-maximum size. | |
| 613 | * | |
| 614 | * @param key The value to bind to the internal key property. | |
| 615 | * @param property The external property value that sets the internal value. | |
| 616 | * @param enabled Indicates whether property changes should be applied. | |
| 617 | */ | |
| 618 | public <T> void listen( | |
| 619 | final Key key, | |
| 620 | final ReadOnlyProperty<T> property, | |
| 621 | final BooleanSupplier enabled ) { | |
| 622 | assert key != null; | |
| 623 | assert property != null; | |
| 624 | assert enabled != null; | |
| 625 | ||
| 626 | property.addListener( | |
| 627 | ( _, _, n ) -> runLater( () -> { | |
| 628 | if( enabled.getAsBoolean() ) { | |
| 629 | valuesProperty( key ).setValue( n ); | |
| 630 | } | |
| 631 | } ) | |
| 632 | ); | |
| 633 | } | |
| 634 | ||
| 635 | /** | |
| 636 | * Creates a lightweight persistence mechanism for user preferences. | |
| 637 | * | |
| 638 | * @return The {@link XmlStore} that helps with persisting application state. | |
| 639 | */ | |
| 640 | private XmlStore createXmlStore() { | |
| 641 | // Root-level configuration item is the application name. | |
| 642 | return new XmlStore( APP_TITLE_LOWERCASE ); | |
| 643 | } | |
| 644 | } | |
| 1 | 645 |
| 1 | package com.keenwrite.preferences; | |
| 2 | ||
| 3 | import com.keenwrite.dom.DocumentParser; | |
| 4 | import javafx.beans.property.ListProperty; | |
| 5 | import javafx.beans.property.SetProperty; | |
| 6 | import org.w3c.dom.Document; | |
| 7 | import org.w3c.dom.Element; | |
| 8 | import org.w3c.dom.Node; | |
| 9 | ||
| 10 | import javax.xml.xpath.XPath; | |
| 11 | import javax.xml.xpath.XPathExpression; | |
| 12 | import javax.xml.xpath.XPathExpressionException; | |
| 13 | import java.io.File; | |
| 14 | import java.io.FileWriter; | |
| 15 | import java.io.IOException; | |
| 16 | import java.util.*; | |
| 17 | import java.util.Map.Entry; | |
| 18 | import java.util.function.Consumer; | |
| 19 | ||
| 20 | import static com.keenwrite.events.StatusEvent.clue; | |
| 21 | import static java.nio.charset.StandardCharsets.UTF_8; | |
| 22 | import static javax.xml.xpath.XPathConstants.NODE; | |
| 23 | ||
| 24 | /** | |
| 25 | * Responsible for managing XML documents, which includes reading, writing, | |
| 26 | * retrieving, and setting elements. This is an alternative to Apache | |
| 27 | * Commons Configuration, JAXB, and Jackson. All of them are heavyweight and | |
| 28 | * the latter are difficult to use with dynamic data (because they require | |
| 29 | * annotations). | |
| 30 | * <p> | |
| 31 | * <strong>Note:</strong> It is preferable to use a different instance when | |
| 32 | * loading and saving the documents. Otherwise, old and duplicate data will | |
| 33 | * persist. Using a new instance ensures that elements removed from the | |
| 34 | * user preferences will not persist across XML configuration file versions. | |
| 35 | */ | |
| 36 | public class XmlStore { | |
| 37 | private static final String SEPARATOR = "/"; | |
| 38 | ||
| 39 | private final String mRoot; | |
| 40 | private Document mDocument = DocumentParser.newDocument(); | |
| 41 | ||
| 42 | /** | |
| 43 | * Constructs a new instance with a blank {@link Document}. Call the | |
| 44 | * {@link #load(File)} method to populate the document from a {@link File}, | |
| 45 | * or {@link #save(File)} to persist the current document state. | |
| 46 | * | |
| 47 | * @param root The root-level document element. | |
| 48 | */ | |
| 49 | public XmlStore( final String root ) { | |
| 50 | assert root != null; | |
| 51 | ||
| 52 | mRoot = root; | |
| 53 | } | |
| 54 | ||
| 55 | /** | |
| 56 | * Loads the given configuration file into a document object model. | |
| 57 | * Clients of this class can set and retrieve elements via the requisite | |
| 58 | * access methods. | |
| 59 | * | |
| 60 | * @param config File containing persistent user preferences. | |
| 61 | */ | |
| 62 | public void load( final File config ) { | |
| 63 | assert config != null; | |
| 64 | assert config.isFile(); | |
| 65 | ||
| 66 | try { | |
| 67 | mDocument = DocumentParser.parse( config ); | |
| 68 | } catch( final Exception ignored ) { | |
| 69 | mDocument = DocumentParser.newDocument(); | |
| 70 | } | |
| 71 | } | |
| 72 | ||
| 73 | /** | |
| 74 | * Returns the document value associated with the given key name. | |
| 75 | * | |
| 76 | * @param key {@link Key} name to retrieve. | |
| 77 | * @return The value associated with the key. | |
| 78 | * @throws NoSuchElementException No value could be found for the key. | |
| 79 | */ | |
| 80 | public String getValue( final Key key ) throws NoSuchElementException { | |
| 81 | assert key != null; | |
| 82 | ||
| 83 | try { | |
| 84 | final var node = toNode( key, mDocument ); | |
| 85 | ||
| 86 | if( node != null ) { | |
| 87 | return node.getTextContent(); | |
| 88 | } | |
| 89 | } catch( final XPathExpressionException ignored ) { } | |
| 90 | ||
| 91 | throw new NoSuchElementException( key.toString() ); | |
| 92 | } | |
| 93 | ||
| 94 | /** | |
| 95 | * Returns a set of document values associated with the given key name. This | |
| 96 | * is suitable for basic sets, such as: | |
| 97 | * <pre> | |
| 98 | * {@code | |
| 99 | * <recent> | |
| 100 | * <file>/tmp/filename.txt</file> | |
| 101 | * <file>/home/username/document.md</file> | |
| 102 | * <file>/usr/local/share/app/conf/help.Rmd</file> | |
| 103 | * </recent>} | |
| 104 | * </pre> | |
| 105 | * <p> | |
| 106 | * The {@code file} element name can be ignored. | |
| 107 | * | |
| 108 | * @param key {@link Key} name to retrieve. | |
| 109 | * @return The values associated with the key, or an empty set if none found. | |
| 110 | */ | |
| 111 | public Set<String> getSet( final Key key ) { | |
| 112 | assert key != null; | |
| 113 | ||
| 114 | final var set = new LinkedHashSet<String>(); | |
| 115 | ||
| 116 | visit( key, node -> set.add( node.getTextContent() ) ); | |
| 117 | ||
| 118 | return set; | |
| 119 | } | |
| 120 | ||
| 121 | /** | |
| 122 | * Returns a map of name/value pairs associated with the given key name. | |
| 123 | * This is suitable for mapped values, such as: | |
| 124 | * <pre> | |
| 125 | * {@code | |
| 126 | * <meta> | |
| 127 | * <title>{{book.title}}</title> | |
| 128 | * <author>{{book.author}}</author> | |
| 129 | * <date>{{book.publish.date}}</date> | |
| 130 | * </meta>} | |
| 131 | * </pre> | |
| 132 | * <p> | |
| 133 | * The element names under the {@code meta} node must be preserved along | |
| 134 | * with their values. Resolving the values based on the variable definitions | |
| 135 | * (in moustache syntax) is not a responsibility of this class. | |
| 136 | * | |
| 137 | * @param key {@link Key} name to retrieve (e.g., {@code meta}). | |
| 138 | * @return A map of element names to element values, or an empty map if | |
| 139 | * none found. | |
| 140 | */ | |
| 141 | public Map<String, String> getMap( final Key key ) { | |
| 142 | assert key != null; | |
| 143 | ||
| 144 | // Create a new key that will match all child nodes under the given key, | |
| 145 | // extracting each element as a name/value pair for the resulting map. | |
| 146 | final var all = Key.key( key, "*" ); | |
| 147 | final var map = new LinkedHashMap<String, String>(); | |
| 148 | ||
| 149 | visit( all, node -> map.put( node.getNodeName(), node.getTextContent() ) ); | |
| 150 | ||
| 151 | return map; | |
| 152 | } | |
| 153 | ||
| 154 | /** | |
| 155 | * Call to write the user preferences to a file. | |
| 156 | * | |
| 157 | * @param config The file wherein the preferences are saved. | |
| 158 | * @throws IOException Could not write to the file. | |
| 159 | */ | |
| 160 | public void save( final File config ) throws IOException { | |
| 161 | assert config != null; | |
| 162 | ||
| 163 | try( final var writer = new FileWriter( config, UTF_8 ) ) { | |
| 164 | writer.write( DocumentParser.toString( mDocument ) ); | |
| 165 | } | |
| 166 | } | |
| 167 | ||
| 168 | public void setValue( final Key key, final String value ) { | |
| 169 | assert key != null; | |
| 170 | assert value != null; | |
| 171 | ||
| 172 | try { | |
| 173 | final var node = upsert( key, mDocument ); | |
| 174 | ||
| 175 | node.setTextContent( value ); | |
| 176 | } catch( final XPathExpressionException ex ) { | |
| 177 | clue( ex ); | |
| 178 | } | |
| 179 | } | |
| 180 | ||
| 181 | public void setSet( final Key key, final SetProperty<?> set ) { | |
| 182 | assert key != null; | |
| 183 | assert set != null; | |
| 184 | ||
| 185 | Node node = null; | |
| 186 | ||
| 187 | try { | |
| 188 | for( final var item : set ) { | |
| 189 | if( node == null ) { | |
| 190 | node = upsert( key, mDocument ); | |
| 191 | } | |
| 192 | else { | |
| 193 | final var doc = node.getOwnerDocument(); | |
| 194 | final var sibling = doc.createElement( key.name() ); | |
| 195 | var parent = node.getParentNode(); | |
| 196 | ||
| 197 | if( parent == null ) { | |
| 198 | parent = doc.getDocumentElement(); | |
| 199 | } | |
| 200 | ||
| 201 | parent.appendChild( sibling ); | |
| 202 | node = sibling; | |
| 203 | } | |
| 204 | ||
| 205 | node.setTextContent( item.toString() ); | |
| 206 | } | |
| 207 | } catch( final XPathExpressionException ignored ) { } | |
| 208 | } | |
| 209 | ||
| 210 | /** | |
| 211 | * @param key The application key representing a user preference. | |
| 212 | * @param list List of {@link Entry} items. | |
| 213 | */ | |
| 214 | public void setMap( final Key key, final ListProperty<?> list ) { | |
| 215 | assert key != null; | |
| 216 | assert list != null; | |
| 217 | ||
| 218 | for( final var item : list ) { | |
| 219 | if( item instanceof Entry<?, ?> entry ) { | |
| 220 | try { | |
| 221 | final var child = Key.key( key, entry.getKey().toString() ); | |
| 222 | final var node = upsert( child, mDocument ); | |
| 223 | ||
| 224 | node.setTextContent( entry.getValue().toString() ); | |
| 225 | } catch( final XPathExpressionException ignored ) { } | |
| 226 | } | |
| 227 | } | |
| 228 | } | |
| 229 | ||
| 230 | private Node toNode( final Key key, final Document doc ) | |
| 231 | throws XPathExpressionException { | |
| 232 | final var xpath = toXPath( key ); | |
| 233 | final var expr = DocumentParser.compile( xpath ); | |
| 234 | final var element = expr.evaluate( doc, NODE ); | |
| 235 | ||
| 236 | return element instanceof Node node ? node : null; | |
| 237 | } | |
| 238 | ||
| 239 | /** | |
| 240 | * Provides the equivalent of update-or-insert behaviour provided by some | |
| 241 | * SQL databases. Finds the element in the document represented by the | |
| 242 | * given {@link Key}. If no element is found then the full path to the | |
| 243 | * element is created. In essence, this method converts a hierarchy of | |
| 244 | * {@link Key} names into a hierarchy of {@link Document} {@link Element}s | |
| 245 | * (i.e., {@link Node}s). | |
| 246 | * <p> | |
| 247 | * For example, given a key named {@code workspace.meta.version}, this will | |
| 248 | * produce a document structure that, when exported as XML, resembles: | |
| 249 | * <pre>{@code | |
| 250 | * <root> | |
| 251 | * <workspace> | |
| 252 | * <meta> | |
| 253 | * <version/> | |
| 254 | * </meta> | |
| 255 | * </workspace> | |
| 256 | * </root> | |
| 257 | * }</pre> | |
| 258 | * <p> | |
| 259 | * The calling code is responsible for populating the {@link Node} returned | |
| 260 | * with its particular value. In the example above, the text content of the | |
| 261 | * {@link Node} would be filled with the application version number. | |
| 262 | * | |
| 263 | * @param key The application key representing a user preference. | |
| 264 | * @param doc The document that may contain an xpath for the {@link Key}. | |
| 265 | * @return The existing or new element. | |
| 266 | */ | |
| 267 | private Node upsert( final Key key, final Document doc ) | |
| 268 | throws XPathExpressionException { | |
| 269 | assert key != null; | |
| 270 | assert doc != null; | |
| 271 | ||
| 272 | final var missing = new Stack<Key>(); | |
| 273 | Key visitor = key; | |
| 274 | Node parent = null; | |
| 275 | ||
| 276 | do { | |
| 277 | final var node = toNode( visitor, doc ); | |
| 278 | ||
| 279 | // If an element exists on the first iteration, return it because there | |
| 280 | // is no missing hierarchy to create. | |
| 281 | if( node != null ) { | |
| 282 | if( missing.isEmpty() ) { | |
| 283 | return node; | |
| 284 | } | |
| 285 | ||
| 286 | parent = node; | |
| 287 | } | |
| 288 | else { | |
| 289 | // Track the number of elements in the hierarchy that don't exist. | |
| 290 | missing.push( visitor ); | |
| 291 | ||
| 292 | // Attempt to find the parent xpath in the document. | |
| 293 | visitor = visitor.parent(); | |
| 294 | } | |
| 295 | } | |
| 296 | while( visitor != null && parent == null ); | |
| 297 | ||
| 298 | // If the document is empty, update the top-level document element. | |
| 299 | if( parent == null ) { | |
| 300 | parent = doc.getDocumentElement(); | |
| 301 | ||
| 302 | // If there is still no top-level element, then create it. | |
| 303 | if( parent == null ) { | |
| 304 | parent = doc.createElement( mRoot ); | |
| 305 | doc.appendChild( parent ); | |
| 306 | } | |
| 307 | } | |
| 308 | ||
| 309 | assert parent != null; | |
| 310 | ||
| 311 | // Create the hierarchy. | |
| 312 | while( !missing.isEmpty() ) { | |
| 313 | visitor = missing.pop(); | |
| 314 | ||
| 315 | final var child = doc.createElement( visitor.name() ); | |
| 316 | parent.appendChild( child ); | |
| 317 | parent = child; | |
| 318 | } | |
| 319 | ||
| 320 | return parent; | |
| 321 | } | |
| 322 | ||
| 323 | /** | |
| 324 | * Abstraction for functionality that requires iterating over multiple | |
| 325 | * nodes under a particular xpath. | |
| 326 | * | |
| 327 | * @param key {@link #toXPath(Key) Compiled} into an {@link XPath}. | |
| 328 | * @param consumer Accepts each node that matches the {@link XPath}. | |
| 329 | */ | |
| 330 | private void visit( final Key key, final Consumer<Node> consumer ) { | |
| 331 | assert key != null; | |
| 332 | assert consumer != null; | |
| 333 | ||
| 334 | try { | |
| 335 | final var xpath = toXPath( key ); | |
| 336 | ||
| 337 | DocumentParser.visit( mDocument, xpath, consumer ); | |
| 338 | } catch( final XPathExpressionException ignored ) { | |
| 339 | // Programming error. Triggered by loading a previous config version? | |
| 340 | } | |
| 341 | } | |
| 342 | ||
| 343 | /** | |
| 344 | * Creates an {@link XPathExpression} value based on the given {@link Key}. | |
| 345 | * | |
| 346 | * @param key The {@link Key} to convert to an xpath string. | |
| 347 | * @return The given {@link Key} compiled into an {@link XPathExpression}. | |
| 348 | * @throws XPathExpressionException Could not compile the {@link Key}. | |
| 349 | */ | |
| 350 | private StringBuilder toXPath( final Key key ) | |
| 351 | throws XPathExpressionException { | |
| 352 | assert key != null; | |
| 353 | ||
| 354 | final var sb = new StringBuilder( 128 ); | |
| 355 | ||
| 356 | key.walk( sb::append, SEPARATOR ); | |
| 357 | sb.insert( 0, SEPARATOR ); | |
| 358 | ||
| 359 | if( !mRoot.isBlank() ) { | |
| 360 | sb.insert( 0, SEPARATOR + mRoot ); | |
| 361 | } | |
| 362 | ||
| 363 | return sb; | |
| 364 | } | |
| 365 | ||
| 366 | /** | |
| 367 | * Pretty-prints the XML document into a string. Meant to be used for | |
| 368 | * debugging. To save the configuration, see {@link #save(File)}. | |
| 369 | * | |
| 370 | * @return The document in a well-formed, indented, string format. | |
| 371 | */ | |
| 372 | @Override | |
| 373 | public String toString() { | |
| 374 | return DocumentParser.toString( mDocument ); | |
| 375 | } | |
| 376 | } | |
| 1 | 377 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.preview; | |
| 1 | 3 | |
| 4 | import com.keenwrite.collections.BoundedCache; | |
| 5 | import com.keenwrite.ui.adapters.ReplacedElementAdapter; | |
| 6 | import org.w3c.dom.Element; | |
| 7 | import org.xht |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.preview; | |
| 3 | ||
| 4 | import java.nio.charset.StandardCharsets; | |
| 5 | import java.util.zip.Deflater; | |
| 6 | ||
| 7 | import static java.lang.String.format; | |
| 8 | import static java.util.Base64.getUrlEncoder; | |
| 9 | ||
| 10 | /** | |
| 11 | * Responsible for transforming text-based diagram descriptions into URLs | |
| 12 | * that the HTML renderer can embed as SVG images. | |
| 13 | */ | |
| 14 | public class DiagramUrlGenerator { | |
| 15 | private DiagramUrlGenerator() { | |
| 16 | } | |
| 17 | ||
| 18 | /** | |
| 19 | * Returns a URL that can be embedded as the {@code src} attribute to an HTML | |
| 20 | * {@code img} tag. | |
| 21 | * | |
| 22 | * @param server Name of server to use for diagram conversion. | |
| 23 | * @param diagram Diagram type (e.g., Graphviz, Block, PlantUML). | |
| 24 | * @param text Diagram text that conforms to the diagram type. | |
| 25 | * @return A secure URL string to use as an image {@code src} attribute. | |
| 26 | */ | |
| 27 | public static String toUrl( | |
| 28 | final String server, final String diagram, final String text ) { | |
| 29 | return format( | |
| 30 | "https://%s/%s/svg/%s", server, diagram, encode( text ) | |
| 31 | ); | |
| 32 | } | |
| 33 | ||
| 34 | /** | |
| 35 | * Convert the plain-text version of the diagram into a URL-encoded value | |
| 36 | * suitable for passing to a web server using an HTTP GET request. | |
| 37 | * | |
| 38 | * @param text The diagram text to encode. | |
| 39 | * @return The URL-encoded (and compressed) version of the text. | |
| 40 | */ | |
| 41 | private static String encode( final String text ) { | |
| 42 | return getUrlEncoder().encodeToString( | |
| 43 | compress( text.getBytes( StandardCharsets.UTF_8 ) ) | |
| 44 | ); | |
| 45 | } | |
| 46 | ||
| 47 | /** | |
| 48 | * Compresses a sequence of bytes using ZLIB format. | |
| 49 | * | |
| 50 | * @param source The data to compress. | |
| 51 | * @return A lossless, compressed sequence of bytes. | |
| 52 | */ | |
| 53 | private static byte[] compress( final byte[] source ) { | |
| 54 | final var deflater = new Deflater(); | |
| 55 | deflater.setInput( source ); | |
| 56 | deflater.finish(); | |
| 57 | ||
| 58 | final var compressed = new byte[ Short.MAX_VALUE ]; | |
| 59 | final var size = deflater.deflate( compressed ); | |
| 60 | final var result = new byte[ size ]; | |
| 61 | ||
| 62 | System.arraycopy( compressed, 0, result, 0, size ); | |
| 63 | ||
| 64 | return result; | |
| 65 | } | |
| 66 | } | |
| 1 | 67 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.preview; | |
| 3 | ||
| 4 | import com.keenwrite.events.FileOpenEvent; | |
| 5 | import com.keenwrite.events.HyperlinkOpenEvent; | |
| 6 | import com.keenwrite.ui.adapters.DocumentAdapter; | |
| 7 | import javafx.beans.property.BooleanProperty; | |
| 8 | import javafx.beans.property.SimpleBooleanProperty; | |
| 9 | import org.w3c.dom.Document; | |
| 10 | import org.xhtmlrenderer.layout.SharedContext; | |
| 11 | import org.xhtmlrenderer.render.Box; | |
| 12 | import org.xhtmlrenderer.simple.XHTMLPanel; | |
| 13 | import org.xhtmlrenderer.simple.extend.XhtmlNamespaceHandler; | |
| 14 | import org.xhtmlrenderer.swing.*; | |
| 15 | ||
| 16 | import javax.swing.*; | |
| 17 | import java.awt.*; | |
| 18 | import java.awt.event.ComponentAdapter; | |
| 19 | import java.awt.event.ComponentEvent; | |
| 20 | import java.net.URI; | |
| 21 | ||
| 22 | import static com.keenwrite.events.StatusEvent.clue; | |
| 23 | import static com.keenwrite.util.ProtocolScheme.getProtocol; | |
| 24 | import static java.lang.Boolean.FALSE; | |
| 25 | import static java.lang.Boolean.TRUE; | |
| 26 | import static java.lang.Math.max; | |
| 27 | import static java.lang.Thread.sleep; | |
| 28 | import static javax.swing.SwingUtilities.invokeLater; | |
| 29 | ||
| 30 | /** | |
| 31 | * Responsible for configuring FlyingSaucer's {@link XHTMLPanel}. | |
| 32 | */ | |
| 33 | public final class FlyingSaucerPanel extends XHTMLPanel | |
| 34 | implements HtmlRenderer { | |
| 35 | ||
| 36 | /** | |
| 37 | * Suppresses scroll attempts until after the document has loaded. | |
| 38 | */ | |
| 39 | private static final class DocumentEventHandler extends DocumentAdapter { | |
| 40 | private final BooleanProperty mReadyProperty = new SimpleBooleanProperty(); | |
| 41 | ||
| 42 | @Override | |
| 43 | public void documentStarted() { | |
| 44 | mReadyProperty.setValue( FALSE ); | |
| 45 | } | |
| 46 | ||
| 47 | @Override | |
| 48 | public void documentLoaded() { | |
| 49 | mReadyProperty.setValue( TRUE ); | |
| 50 | } | |
| 51 | } | |
| 52 | ||
| 53 | /** | |
| 54 | * Ensures that the preview panel fills its container's area completely. | |
| 55 | */ | |
| 56 | private final class ComponentEventHandler extends ComponentAdapter { | |
| 57 | /** | |
| 58 | * Invoked when the component's size changes. | |
| 59 | */ | |
| 60 | public void componentResized( final ComponentEvent e ) { | |
| 61 | setPreferredSize( e.getComponent().getPreferredSize() ); | |
| 62 | } | |
| 63 | } | |
| 64 | ||
| 65 | /** | |
| 66 | * Responsible for opening hyperlinks. External hyperlinks are opened in | |
| 67 | * the system's default browser; local file system links are opened in the | |
| 68 | * editor. | |
| 69 | */ | |
| 70 | private static final class HyperlinkListener extends LinkListener { | |
| 71 | @Override | |
| 72 | public void linkClicked( final BasicPanel panel, final String link ) { | |
| 73 | try { | |
| 74 | final var uri = new URI( link ); | |
| 75 | ||
| 76 | switch( getProtocol( uri ) ) { | |
| 77 | case HTTP -> HyperlinkOpenEvent.fire( uri ); | |
| 78 | case FILE -> FileOpenEvent.fire( uri ); | |
| 79 | default -> { } | |
| 80 | } | |
| 81 | } catch( final Exception ex ) { | |
| 82 | clue( ex ); | |
| 83 | } | |
| 84 | } | |
| 85 | } | |
| 86 | ||
| 87 | private static final XhtmlNamespaceHandler XNH = new XhtmlNamespaceHandler(); | |
| 88 | private final ChainedReplacedElementFactory mFactory; | |
| 89 | ||
| 90 | FlyingSaucerPanel() { | |
| 91 | // The order is important: SwingReplacedElementFactory replaces SVG images | |
| 92 | // with a blank image, which will cause the chained factory to cache the | |
| 93 | // image and exit. Instead, the SVG must execute first to rasterize the | |
| 94 | // content. Consequently, the chained factory must maintain insertion order. | |
| 95 | mFactory = new ChainedReplacedElementFactory( | |
| 96 | new ImageReplacedElementFactory(), | |
| 97 | new SwingReplacedElementFactory() | |
| 98 | ); | |
| 99 | ||
| 100 | final var context = getSharedContext(); | |
| 101 | final var textRenderer = context.getTextRenderer(); | |
| 102 | context.setReplacedElementFactory( mFactory ); | |
| 103 | textRenderer.setSmoothingThreshold( 0 ); | |
| 104 | ||
| 105 | addDocumentListener( new DocumentEventHandler() ); | |
| 106 | removeMouseTrackingListeners(); | |
| 107 | addMouseTrackingListener( new HyperlinkListener() ); | |
| 108 | addComponentListener( new ComponentEventHandler() ); | |
| 109 | } | |
| 110 | ||
| 111 | /** | |
| 112 | * Updates the document model displayed by the renderer. Effectively, this | |
| 113 | * updates the HTML document to provide new content. | |
| 114 | * | |
| 115 | * @param doc A complete HTML5 document, including doctype. | |
| 116 | * @param baseUri URI to use for finding relative files, such as images. | |
| 117 | */ | |
| 118 | @Override | |
| 119 | public void render( final Document doc, final String baseUri ) { | |
| 120 | setDocument( doc, baseUri, XNH ); | |
| 121 | } | |
| 122 | ||
| 123 | @Override | |
| 124 | public void clearCache() { | |
| 125 | mFactory.clearCache(); | |
| 126 | } | |
| 127 | ||
| 128 | @Override | |
| 129 | public void scrollTo( final String id, final JScrollPane scrollPane ) { | |
| 130 | int iter = 0; | |
| 131 | Box box = null; | |
| 132 | ||
| 133 | while( iter++ < 3 && ((box = getBoxById( id )) == null) ) { | |
| 134 | try { | |
| 135 | sleep( 10 ); | |
| 136 | } catch( final Exception ex ) { | |
| 137 | clue( ex ); | |
| 138 | } | |
| 139 | } | |
| 140 | ||
| 141 | scrollTo( box, scrollPane ); | |
| 142 | } | |
| 143 | ||
| 144 | /** | |
| 145 | * Scrolls to the location specified by the {@link Box} that corresponds | |
| 146 | * to a point somewhere in the preview pane. If there is no caret, then | |
| 147 | * this will not change the scroll position. Changing the scroll position | |
| 148 | * to the top if the {@link Box} instance is {@code null} will result in | |
| 149 | * jumping around a lot and inconsistent synchronization issues. | |
| 150 | * | |
| 151 | * @param box The rectangular region containing the caret, or {@code null} | |
| 152 | * if the HTML does not have a caret. | |
| 153 | */ | |
| 154 | private void scrollTo( final Box box, final JScrollPane scrollPane ) { | |
| 155 | if( box != null ) { | |
| 156 | invokeLater( () -> { | |
| 157 | scrollTo( createPoint( box, scrollPane ) ); | |
| 158 | scrollPane.repaint(); | |
| 159 | } ); | |
| 160 | } | |
| 161 | } | |
| 162 | ||
| 163 | /** | |
| 164 | * Creates a {@link Point} to use as a reference for scrolling to the area | |
| 165 | * described by the given {@link Box}. The {@link Box} coordinates are used | |
| 166 | * to populate the {@link Point}'s location, with minor adjustments for | |
| 167 | * vertical centering. | |
| 168 | * | |
| 169 | * @param box The {@link Box} that represents a scrolling anchor reference. | |
| 170 | * @return A coordinate suitable for scrolling to. | |
| 171 | */ | |
| 172 | private Point createPoint( final Box box, final JScrollPane scrollPane ) { | |
| 173 | assert box != null; | |
| 174 | ||
| 175 | // Scroll back up by half the height of the scroll bar to keep the typing | |
| 176 | // area within the view port; otherwise, the view port will have jumped too | |
| 177 | // high up and the most recently typed letters won't be visible. | |
| 178 | int y = max( box.getAbsY() - scrollPane.getVerticalScrollBar() | |
| 179 | .getHeight() / 2, 0 ); | |
| 180 | int x = box.getAbsX(); | |
| 181 | ||
| 182 | if( !box.getStyle().isInline() ) { | |
| 183 | final var margin = box.getMargin( getLayoutContext() ); | |
| 184 | y += (int) margin.top(); | |
| 185 | x += (int) margin.left(); | |
| 186 | } | |
| 187 | ||
| 188 | return new Point( x, y ); | |
| 189 | } | |
| 190 | ||
| 191 | /** | |
| 192 | * Delegates to the {@link SharedContext}. | |
| 193 | * | |
| 194 | * @param id The HTML element identifier to retrieve in {@link Box} form. | |
| 195 | * @return The {@link Box} that corresponds to the given element ID, or | |
| 196 | * {@code null} if none found. | |
| 197 | */ | |
| 198 | Box getBoxById( final String id ) { | |
| 199 | return getSharedContext().getBoxById( id ); | |
| 200 | } | |
| 201 | ||
| 202 | /** | |
| 203 | * Suppress scrolling to the top on updates. | |
| 204 | */ | |
| 205 | @Override | |
| 206 | public void resetScrollPosition() { | |
| 207 | } | |
| 208 | ||
| 209 | /** | |
| 210 | * The default mouse click listener attempts navigation within the preview | |
| 211 | * panel. We want to usurp that behaviour to open the link in a | |
| 212 | * platform-specific browser. | |
| 213 | */ | |
| 214 | private void removeMouseTrackingListeners() { | |
| 215 | for( final var listener : getMouseTrackingListeners() ) { | |
| 216 | if( !(listener instanceof HoverListener) ) { | |
| 217 | removeMouseTrackingListener( (FSMouseListener) listener ); | |
| 218 | } | |
| 219 | } | |
| 220 | } | |
| 221 | } | |
| 1 | 222 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.preview; | |
| 3 | ||
| 4 | import java.util.HashMap; | |
| 5 | import java.util.Map; | |
| 6 | ||
| 7 | import static java.awt.RenderingHints.*; | |
| 8 | import static java.awt.Toolkit.getDefaultToolkit; | |
| 9 | ||
| 10 | /** | |
| 11 | * Responsible for initializing settings to produce high-quality image | |
| 12 | * transformations. | |
| 13 | */ | |
| 14 | @SuppressWarnings( "rawtypes" ) | |
| 15 | public class HighQualityRenderingHints { | |
| 16 | /** | |
| 17 | * Default hints for high-quality rendering that may be changed by | |
| 18 | * the system's rendering hints. | |
| 19 | */ | |
| 20 | private static final Map<Object, Object> DEFAULT_HINTS = Map.of( | |
| 21 | KEY_ANTIALIASING, VALUE_ANTIALIAS_ON, | |
| 22 | KEY_ALPHA_INTERPOLATION, VALUE_ALPHA_INTERPOLATION_QUALITY, | |
| 23 | KEY_COLOR_RENDERING, VALUE_COLOR_RENDER_QUALITY, | |
| 24 | KEY_DITHERING, VALUE_DITHER_DISABLE, | |
| 25 | KEY_FRACTIONALMETRICS, VALUE_FRACTIONALMETRICS_ON, | |
| 26 | KEY_INTERPOLATION, VALUE_INTERPOLATION_BICUBIC, | |
| 27 | KEY_RENDERING, VALUE_RENDER_QUALITY, | |
| 28 | KEY_STROKE_CONTROL, VALUE_STROKE_PURE, | |
| 29 | KEY_TEXT_ANTIALIASING, VALUE_TEXT_ANTIALIAS_ON | |
| 30 | ); | |
| 31 | ||
| 32 | /** | |
| 33 | * Shared hints for high-quality rendering. | |
| 34 | */ | |
| 35 | static final Map<Object, Object> RENDERING_HINTS = new HashMap<>( | |
| 36 | DEFAULT_HINTS | |
| 37 | ); | |
| 38 | ||
| 39 | static { | |
| 40 | initializeRenderingHints(); | |
| 41 | } | |
| 42 | ||
| 43 | private static void initializeRenderingHints() { | |
| 44 | final var toolkit = getDefaultToolkit(); | |
| 45 | final var hints = toolkit.getDesktopProperty( "awt.font.desktophints" ); | |
| 46 | ||
| 47 | if( hints instanceof final Map map ) { | |
| 48 | for( final var key : map.keySet() ) { | |
| 49 | final var hint = map.get( key ); | |
| 50 | RENDERING_HINTS.put( key, hint ); | |
| 51 | } | |
| 52 | } | |
| 53 | } | |
| 54 | ||
| 55 | /** | |
| 56 | * Defines a reusable constant, nothing more. | |
| 57 | */ | |
| 58 | private HighQualityRenderingHints() { | |
| 59 | } | |
| 60 | } | |
| 1 | 61 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.preview; | |
| 3 | ||
| 4 | import com.keenwrite.dom.DocumentConverter; | |
| 5 | import com.keenwrite.events.DocumentChangedEvent; | |
| 6 | import com.keenwrite.events.ScrollLockEvent; | |
| 7 | import com.keenwrite.preferences.LocaleProperty; | |
| 8 | import com.keenwrite.preferences.Workspace; | |
| 9 | import jAppConverts a text string to a structured HTMLDocumentConverter CONVERTER = new DocumentConverter(); | |
| 10 | """ | |
| 11 | <!doctype html> | |
| 12 | ""Renderer mPrevScrollPreview = new FlyingSaucer(Component) mPrevScroll | |
| 13 | _ScrollLocked ) | |
| 14 | } ); | |
| 15 | ||
| 16 | Scroll | |
| 17 | () ->ScrollLocked )final var jsoupDoc = DocumentConverter.parse( decorate( html ) ); | |
| 18 | final var doc = CONVERTER.fromJsoup( jsoupDoc ); | |
| 19 | final var uri = getBaseUri(); | |
| 1 | 20 | |
| 21 | doc.setDocumentURI( uri );mPreview.render( doc, uri ) ); | |
| 22 | DocumentChangedEvent.fire( html Preview!mScrollLocked ) { | |
| 23 | mPreview.scrollTo( id, mScrollPane ); | |
| 24 | mScrollPane.repaint(); | |
| 25 | }{@code en-Latn-CA}String.formagetgetBoolean( KEY_IMAGE_RESIZE ) ) { | |
| 26 | mPreview |
| 1 | package com.keenwrite.preview; | |
| 2 | ||
| 3 | import org.w3c.dom.Document; | |
| 4 | ||
| 5 | import javax.swing.*; | |
| 6 | ||
| 7 | /** | |
| 8 | * Denotes the ability to render an HTML document onto a Swing component. | |
| 9 | */ | |
| 10 | public interface HtmlRenderer { | |
| 11 | ||
| 12 | /** | |
| 13 | * Renders an HTML document with respect to a base location. | |
| 14 | * | |
| 15 | * @param doc The document to render. | |
| 16 | * @param baseUri The document's relative URI. | |
| 17 | */ | |
| 18 | void render( final Document doc, final String baseUri ); | |
| 19 | ||
| 20 | /** | |
| 21 | * Scrolls the given {@link JScrollPane} to the first HTML element that | |
| 22 | * has an {@code id} attribute that matches the given identifier. | |
| 23 | * | |
| 24 | * @param id The HTML element identifier. | |
| 25 | * @param scrollPane The GUI widget that controls scrolling. | |
| 26 | */ | |
| 27 | void scrollTo( final String id, final JScrollPane scrollPane ); | |
| 28 | ||
| 29 | /** | |
| 30 | * Clears the cache (e.g., so that images are re-rendered using updated | |
| 31 | * dimensions). | |
| 32 | */ | |
| 33 | void clearCache(); | |
| 34 | } | |
| 1 | 35 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.preview; | |
| 6 | ||
| 7 | import com.keenwrite.io.MediaType; | |
| 8 | import com.keenwrite.ui.adapters.ReplacedElementAdapter; | |
| 9 | import io.sf.carte.echosvg.transcoder.TranscoderException; | |
| 10 | import org.w3c.dom.Element; | |
| 11 | import org.xhtmlrenderer.extend.ReplacedElement; | |
| 12 | import org.xhtmlrenderer.extend.UserAgentCallback; | |
| 13 | import org.xhtmlrenderer.layout.LayoutContext; | |
| 14 | import org.xhtmlrenderer.render.BlockBox; | |
| 15 | import org.xhtmlrenderer.swing.ImageReplacedElement; | |
| 16 | ||
| 17 | import javax.imageio.ImageIO; | |
| 18 | import java.awt.image.BufferedImage; | |
| 19 | import java.io.IOException; | |
| 20 | import java.net.URI; | |
| 21 | import java.net.URISyntaxException; | |
| 22 | import java.nio.file.Files; | |
| 23 | import java.nio.file.Path; | |
| 24 | import java.nio.file.Paths; | |
| 25 | import java.text.ParseException; | |
| 26 | ||
| 27 | import static com.keenwrite.events.StatusEvent.clue; | |
| 28 | import static com.keenwrite.io.downloads.DownloadManager.open; | |
| 29 | import static com.keenwrite.preview.SvgRasterizer.BROKEN_IMAGE_PLACEHOLDER; | |
| 30 | import static com.keenwrite.preview.SvgRasterizer.rasterize; | |
| 31 | import static com.keenwrite.processors.markdown.extensions.tex.TexNode.HTML_TEX; | |
| 32 | import static com.keenwrite.util.ProtocolScheme.getProtocol; | |
| 33 | ||
| 34 | /** | |
| 35 | * Responsible for running {@link SvgRasterizer} on SVG images detected within | |
| 36 | * a document to transform them into rasterized versions. This will fall back | |
| 37 | * to loading rasterized images from a file if not detected as SVG. | |
| 38 | */ | |
| 39 | public final class ImageReplacedElementFactory extends ReplacedElementAdapter { | |
| 40 | ||
| 41 | public static final String HTML_IMAGE = "img"; | |
| 42 | public static final String HTML_IMAGE_SRC = "src"; | |
| 43 | ||
| 44 | private static final ImageReplacedElement BROKEN_IMAGE = | |
| 45 | createElement( BROKEN_IMAGE_PLACEHOLDER ); | |
| 46 | ||
| 47 | @Override | |
| 48 | public ReplacedElement createReplacedElement( | |
| 49 | final LayoutContext c, | |
| 50 | final BlockBox box, | |
| 51 | final UserAgentCallback uac, | |
| 52 | final int cssWidth, | |
| 53 | final int cssHeight ) { | |
| 54 | final var e = box.getElement(); | |
| 55 | ||
| 56 | try { | |
| 57 | final BufferedImage raster = | |
| 58 | switch( e.getNodeName() ) { | |
| 59 | case HTML_IMAGE -> createHtmlImage( box, e, uac ); | |
| 60 | case HTML_TEX -> createTexImage( e ); | |
| 61 | default -> null; | |
| 62 | }; | |
| 63 | ||
| 64 | return createElement( raster ); | |
| 65 | } catch( final Exception ex ) { | |
| 66 | clue( "Main.status.image.request.error.create", ex ); | |
| 67 | } | |
| 68 | ||
| 69 | return BROKEN_IMAGE; | |
| 70 | } | |
| 71 | ||
| 72 | /** | |
| 73 | * Convert an HTML element to a raster graphic. | |
| 74 | */ | |
| 75 | private static BufferedImage createHtmlImage( | |
| 76 | final BlockBox box, | |
| 77 | final Element e, | |
| 78 | final UserAgentCallback uac ) | |
| 79 | throws TranscoderException, URISyntaxException, IOException { | |
| 80 | final var source = e.getAttribute( HTML_IMAGE_SRC ); | |
| 81 | final var mediaType = MediaType.fromFilename( source ); | |
| 82 | ||
| 83 | URI uri = null; | |
| 84 | BufferedImage raster = null; | |
| 85 | ||
| 86 | final var w = box.getContentWidth(); | |
| 87 | ||
| 88 | if( getProtocol( source ).isRemote() ) { | |
| 89 | try( final var response = open( source ); | |
| 90 | final var stream = response.getInputStream() ) { | |
| 91 | ||
| 92 | // Rasterize SVG from URL resource. | |
| 93 | raster = response.isSvg() | |
| 94 | ? rasterize( stream, w ) | |
| 95 | : ImageIO.read( stream ); | |
| 96 | ||
| 97 | clue( "Main.status.image.request.fetch", source ); | |
| 98 | } | |
| 99 | } | |
| 100 | else if( mediaType.isSvg() ) { | |
| 101 | uri = resolve( source, uac, e ); | |
| 102 | } | |
| 103 | ||
| 104 | if( uri != null && w > 0 ) { | |
| 105 | raster = rasterize( uri, w ); | |
| 106 | } | |
| 107 | ||
| 108 | // Not an SVG, attempt to read a local rasterized image. | |
| 109 | if( raster == null && mediaType.isImage() ) { | |
| 110 | uri = resolve( source, uac, e ); | |
| 111 | ||
| 112 | final var path = Paths.get( uri ); | |
| 113 | ||
| 114 | try( final var stream = Files.newInputStream( path ) ) { | |
| 115 | raster = ImageIO.read( stream ); | |
| 116 | } | |
| 117 | } | |
| 118 | ||
| 119 | // Image path resolved; image rendered successfully. | |
| 120 | clue(); | |
| 121 | ||
| 122 | return raster; | |
| 123 | } | |
| 124 | ||
| 125 | /** | |
| 126 | * Attempt to rasterize based on file name. | |
| 127 | * | |
| 128 | * @param source The source URI from the document. | |
| 129 | * @param uac A callback for retrieving the image resource. | |
| 130 | * @param e The HTML element containing a reference to a file. | |
| 131 | * @return The resolved URI to the file. | |
| 132 | * @throws URISyntaxException Could not resolve URI. | |
| 133 | */ | |
| 134 | private static URI resolve( | |
| 135 | final String source, | |
| 136 | final UserAgentCallback uac, | |
| 137 | final Element e ) | |
| 138 | throws URISyntaxException { | |
| 139 | final var nSource = source.replaceAll( "\\\\", "/" ); | |
| 140 | ||
| 141 | try { | |
| 142 | final var baseUri = new URI( uac.getBaseURL() ); | |
| 143 | final var resolved = baseUri.resolve( nSource ); | |
| 144 | final var path = resolved.normalize(); | |
| 145 | clue( "Main.status.image.request.resolve", path ); | |
| 146 | ||
| 147 | return path.isAbsolute() ? path : resolve( nSource, e ); | |
| 148 | } catch( final Exception ex ) { | |
| 149 | clue( "Main.status.image.request.error.resolve", nSource ); | |
| 150 | throw new URISyntaxException( nSource, ex.getMessage() ); | |
| 151 | } | |
| 152 | } | |
| 153 | ||
| 154 | private static URI resolve( final String source, final Element e ) | |
| 155 | throws URISyntaxException { | |
| 156 | final var base = new URI( e.getBaseURI() ).getPath(); | |
| 157 | return Path.of( base, source ).toUri(); | |
| 158 | } | |
| 159 | ||
| 160 | /** | |
| 161 | * Convert the TeX element to a raster graphic. | |
| 162 | */ | |
| 163 | private BufferedImage createTexImage( final Element e ) | |
| 164 | throws TranscoderException, ParseException { | |
| 165 | return rasterize( MathRenderer.toString( e.getTextContent() ) ); | |
| 166 | } | |
| 167 | ||
| 168 | private static ImageReplacedElement createElement( final BufferedImage bi ) { | |
| 169 | return bi == null | |
| 170 | ? BROKEN_IMAGE | |
| 171 | : new ImageReplacedElement( bi, bi.getWidth(), bi.getHeight() ); | |
| 172 | } | |
| 173 | } | |
| 1 | 174 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.preview; | |
| 3 | ||
| 4 | import com.keenwrite.dom.DocumentParser; | |
| 5 | import com.whitemagicsoftware.keentype.lib.KeenType; | |
| 6 | import javafx.beans.property.DoubleProperty; | |
| 7 | import javafx.beans.property.SimpleDoubleProperty; | |
| 8 | import org.w3c.dom.Document; | |
| 9 | ||
| 10 | import static com.keenfinal DoubleProperty sSize = new SimpleDoubleProperty( 2 );public static void bindSize( final DoubleProperty size ) { | |
| 11 | sSize.bind( sizesSize.doubleValue() ); | |
| 12 | } | |
| 13 | } | |
| 1 | 14 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.preview; | |
| 3 | ||
| 4 | import com.keenwrite.preview.images.Lanczos3Filter; | |
| 5 | import com.keenwrite.preview.images.ResampleOp; | |
| 6 | import org.xhtmlrenderer.swing.ImageReplacedElement; | |
| 7 | ||
| 8 | import java.awt.*; | |
| 9 | import java.awt.image.BufferedImage; | |
| 10 | ||
| 11 | /** | |
| 12 | * Responsible for scaling an image using a Lanczos-3 filter, typically for | |
| 13 | * down-sampling. | |
| 14 | */ | |
| 15 | public final class SmoothImageReplacedElement extends ImageReplacedElement { | |
| 16 | private static final Lanczos3Filter FILTER = new Lanczos3Filter(); | |
| 17 | ||
| 18 | /** | |
| 19 | * Creates a high-quality rescaled version of the given image. The | |
| 20 | * aspect ratio is maintained if either width or height is less than 1. | |
| 21 | * | |
| 22 | * @param source An instance of {@link BufferedImage} to rescale. | |
| 23 | * @param width Rescale the given image to this width (px). | |
| 24 | * @param height Rescale the given image to this height (px). | |
| 25 | */ | |
| 26 | public SmoothImageReplacedElement( | |
| 27 | final Image source, final int width, final int height ) { | |
| 28 | super._image = rescale( source, width, height ); | |
| 29 | } | |
| 30 | ||
| 31 | private BufferedImage rescale( | |
| 32 | final Image source, final int w, final int h ) { | |
| 33 | final var bi = (BufferedImage) source; | |
| 34 | final var dim = rescaleDimensions( bi, w, h ); | |
| 35 | ||
| 36 | final var resampleOp = new ResampleOp( FILTER, dim.width, dim.height ); | |
| 37 | return resampleOp.filter( bi, null ); | |
| 38 | } | |
| 39 | ||
| 40 | /** | |
| 41 | * Calculates scaled dimensions while maintaining the image aspect ratio. | |
| 42 | */ | |
| 43 | private Dimension rescaleDimensions( | |
| 44 | final BufferedImage bi, final int width, final int height ) { | |
| 45 | final var oldW = bi.getWidth(); | |
| 46 | final var oldH = bi.getHeight(); | |
| 47 | ||
| 48 | int newW = width; | |
| 49 | int newH = height; | |
| 50 | ||
| 51 | if( newW <= 0 ) { | |
| 52 | newW = (int) (oldW * ((double) newH / oldH)); | |
| 53 | } | |
| 54 | ||
| 55 | if( newH <= 0 ) { | |
| 56 | newH = (int) (oldH * ((double) newW / oldW)); | |
| 57 | } | |
| 58 | ||
| 59 | if( newW <= 0 && newH <= 0 ) { | |
| 60 | newW = oldW; | |
| 61 | newH = oldH; | |
| 62 | } | |
| 63 | ||
| 64 | return new Dimension( newW, newH ); | |
| 65 | } | |
| 66 | } | |
| 1 | 67 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.preview; | |
| 1 | 3 | |
| 4 | import io.sf.carte.echosvg.anim.dom.SAXSVGDocumentFactory; | |
| 5 | import io.sf.carte.echosvg.bridge.BridgeContext; | |
| 6 | import io.sf.carte.echosvg.bridge.Docuunused" ) |
| 1 | /* | |
| 2 | * Copyright 2013, Morten Nobel-Joergensen | |
| 3 | * | |
| 4 | * License: The BSD 3-Clause License | |
| 5 | * http://opensource.org/licenses/BSD-3-Clause | |
| 6 | */ | |
| 7 | package com.keenwrite.preview.images; | |
| 8 | ||
| 9 | import java.awt.*; | |
| 10 | import java.awt.geom.Point2D; | |
| 11 | import java.awt.geom.Rectangle2D; | |
| 12 | import java.awt.image.BufferedImage; | |
| 13 | import java.awt.image.BufferedImageOp; | |
| 14 | import java.awt.image.ColorModel; | |
| 15 | ||
| 16 | /** | |
| 17 | * @author Morten Nobel-Joergensen | |
| 18 | */ | |
| 19 | public abstract class AdvancedResizeOp implements BufferedImageOp { | |
| 20 | private final ConstrainedDimension dimensionConstrain; | |
| 21 | ||
| 22 | public AdvancedResizeOp( ConstrainedDimension dimensionConstrain ) { | |
| 23 | this.dimensionConstrain = dimensionConstrain; | |
| 24 | } | |
| 25 | ||
| 26 | public final BufferedImage filter( BufferedImage src, BufferedImage dest ) { | |
| 27 | Dimension dstDimension = dimensionConstrain.getDimension( | |
| 28 | new Dimension( src.getWidth(), src.getHeight() ) ); | |
| 29 | int dstWidth = dstDimension.width; | |
| 30 | int dstHeight = dstDimension.height; | |
| 31 | ||
| 32 | return doFilter( src, dest, dstWidth, dstHeight ); | |
| 33 | } | |
| 34 | ||
| 35 | protected abstract BufferedImage doFilter( | |
| 36 | BufferedImage src, BufferedImage dest, int dstWidth, int dstHeight ); | |
| 37 | ||
| 38 | @Override | |
| 39 | public final Rectangle2D getBounds2D( BufferedImage src ) { | |
| 40 | return new Rectangle( 0, 0, src.getWidth(), src.getHeight() ); | |
| 41 | } | |
| 42 | ||
| 43 | @Override | |
| 44 | public final BufferedImage createCompatibleDestImage( | |
| 45 | BufferedImage src, ColorModel destCM ) { | |
| 46 | if( destCM == null ) { | |
| 47 | destCM = src.getColorModel(); | |
| 48 | } | |
| 49 | ||
| 50 | return new BufferedImage( | |
| 51 | destCM, | |
| 52 | destCM.createCompatibleWritableRaster( src.getWidth(), src.getHeight() ), | |
| 53 | destCM.isAlphaPremultiplied(), | |
| 54 | null ); | |
| 55 | } | |
| 56 | ||
| 57 | @Override | |
| 58 | public final Point2D getPoint2D( Point2D srcPt, Point2D dstPt ) { | |
| 59 | return (Point2D) srcPt.clone(); | |
| 60 | } | |
| 61 | ||
| 62 | @Override | |
| 63 | public final RenderingHints getRenderingHints() { | |
| 64 | return null; | |
| 65 | } | |
| 66 | } | |
| 1 | 67 |
| 1 | /* | |
| 2 | * Copyright 2013, Morten Nobel-Joergensen | |
| 3 | * | |
| 4 | * SPDX-License-Identifier: BSD-3-Clause | |
| 5 | */ | |
| 6 | package com.keenwrite.preview.images; | |
| 7 | ||
| 8 | import java.awt.*; | |
| 9 | ||
| 10 | /** | |
| 11 | * This class let you create dimension constrains based on an actual image. | |
| 12 | */ | |
| 13 | public class ConstrainedDimension { | |
| 14 | private ConstrainedDimension() { | |
| 15 | } | |
| 16 | ||
| 17 | /** | |
| 18 | * Will always return a dimension with positive width and height; | |
| 19 | * | |
| 20 | * @param dimension of the unscaled image | |
| 21 | * @return the dimension of the scaled image | |
| 22 | */ | |
| 23 | public Dimension getDimension( Dimension dimension ) { | |
| 24 | return dimension; | |
| 25 | } | |
| 26 | ||
| 27 | /** | |
| 28 | * Used when the destination size is fixed. This may not keep the image | |
| 29 | * aspect radio. | |
| 30 | * | |
| 31 | * @param width destination dimension width | |
| 32 | * @param height destination dimension height | |
| 33 | * @return destination dimension (width x height) | |
| 34 | */ | |
| 35 | public static ConstrainedDimension createAbsolutionDimension( | |
| 36 | final int width, final int height ) { | |
| 37 | assert width > 0 : "Width must be positive integer"; | |
| 38 | assert height > 0 : "Height must be positive integer"; | |
| 39 | ||
| 40 | return new ConstrainedDimension() { | |
| 41 | public Dimension getDimension( Dimension dimension ) { | |
| 42 | return new Dimension( width, height ); | |
| 43 | } | |
| 44 | }; | |
| 45 | } | |
| 46 | } | |
| 1 | 47 |
| 1 | /* | |
| 2 | * Copyright 2013, Morten Nobel-Joergensen | |
| 3 | * | |
| 4 | * License: The BSD 3-Clause License | |
| 5 | * http://opensource.org/licenses/BSD-3-Clause | |
| 6 | */ | |
| 7 | package com.keenwrite.preview.images; | |
| 8 | ||
| 9 | import java.awt.*; | |
| 10 | import java.awt.image.BufferedImage; | |
| 11 | import java.awt.image.Raster; | |
| 12 | import java.awt.image.WritableRaster; | |
| 13 | ||
| 14 | import static java.awt.image.BufferedImage.*; | |
| 15 | ||
| 16 | /** | |
| 17 | * @author Heinz Doerr | |
| 18 | * @author Morten Nobel-Joergensen | |
| 19 | */ | |
| 20 | public final class ImageUtils { | |
| 21 | @SuppressWarnings( "DuplicateBranchesInSwitch" ) | |
| 22 | static int nrChannels( final BufferedImage img ) { | |
| 23 | return switch( img.getType() ) { | |
| 24 | case TYPE_3BYTE_BGR -> 3; | |
| 25 | case TYPE_4BYTE_ABGR -> 4; | |
| 26 | case TYPE_BYTE_GRAY -> 1; | |
| 27 | case TYPE_INT_BGR -> 3; | |
| 28 | case TYPE_INT_ARGB -> 4; | |
| 29 | case TYPE_INT_RGB -> 3; | |
| 30 | case TYPE_CUSTOM -> 4; | |
| 31 | case TYPE_4BYTE_ABGR_PRE -> 4; | |
| 32 | case TYPE_INT_ARGB_PRE -> 4; | |
| 33 | case TYPE_USHORT_555_RGB -> 3; | |
| 34 | case TYPE_USHORT_565_RGB -> 3; | |
| 35 | case TYPE_USHORT_GRAY -> 1; | |
| 36 | default -> 0; | |
| 37 | }; | |
| 38 | } | |
| 39 | ||
| 40 | /** | |
| 41 | * returns one row (height == 1) of byte packed image data in BGR or AGBR form | |
| 42 | * | |
| 43 | * @param temp must be either null or an array with length of w*h | |
| 44 | */ | |
| 45 | static void getPixelsBGR( | |
| 46 | BufferedImage img, int y, int w, byte[] array, int[] temp ) { | |
| 47 | final int x = 0; | |
| 48 | final int h = 1; | |
| 49 | ||
| 50 | assert array.length == temp.length * nrChannels( img ); | |
| 51 | assert temp.length == w; | |
| 52 | ||
| 53 | final Raster raster; | |
| 54 | switch( img.getType() ) { | |
| 55 | case TYPE_3BYTE_BGR, TYPE_4BYTE_ABGR, | |
| 56 | TYPE_4BYTE_ABGR_PRE, TYPE_BYTE_GRAY -> { | |
| 57 | raster = img.getRaster(); | |
| 58 | //int ttype= raster.getTransferType(); | |
| 59 | raster.getDataElements( x, y, w, h, array ); | |
| 60 | } | |
| 61 | case TYPE_INT_BGR -> { | |
| 62 | raster = img.getRaster(); | |
| 63 | raster.getDataElements( x, y, w, h, temp ); | |
| 64 | ints2bytes( temp, array, 0, 1, 2 ); // bgr --> bgr | |
| 65 | } | |
| 66 | case TYPE_INT_RGB -> { | |
| 67 | raster = img.getRaster(); | |
| 68 | raster.getDataElements( x, y, w, h, temp ); | |
| 69 | ints2bytes( temp, array, 2, 1, 0 ); // rgb --> bgr | |
| 70 | } | |
| 71 | case TYPE_INT_ARGB, TYPE_INT_ARGB_PRE -> { | |
| 72 | raster = img.getRaster(); | |
| 73 | raster.getDataElements( x, y, w, h, temp ); | |
| 74 | ints2bytes( temp, array, 2, 1, 0, 3 ); // argb --> abgr | |
| 75 | } | |
| 76 | case TYPE_CUSTOM -> { | |
| 77 | // loader, but else ??? | |
| 78 | img.getRGB( x, y, w, h, temp, 0, w ); | |
| 79 | ints2bytes( temp, array, 2, 1, 0, 3 ); // argb --> abgr | |
| 80 | } | |
| 81 | default -> { | |
| 82 | img.getRGB( x, y, w, h, temp, 0, w ); | |
| 83 | ints2bytes( temp, array, 2, 1, 0 ); // rgb --> bgr | |
| 84 | } | |
| 85 | } | |
| 86 | } | |
| 87 | ||
| 88 | /** | |
| 89 | * converts and copies byte packed BGR or ABGR into the img buffer, | |
| 90 | * the img type may vary (e.g. RGB or BGR, int or byte packed) | |
| 91 | * but the number of components (w/o alpha, w alpha, gray) must match | |
| 92 | * <p> | |
| 93 | * does not unmange the image for all (A)RGN and (A)BGR and gray imaged | |
| 94 | */ | |
| 95 | public static void setBGRPixels( byte[] bgrPixels, BufferedImage img, int x, | |
| 96 | int y, int w, int h ) { | |
| 97 | int imageType = img.getType(); | |
| 98 | WritableRaster raster = img.getRaster(); | |
| 99 | ||
| 100 | if( imageType == TYPE_3BYTE_BGR || | |
| 101 | imageType == TYPE_4BYTE_ABGR || | |
| 102 | imageType == TYPE_4BYTE_ABGR_PRE || | |
| 103 | imageType == TYPE_BYTE_GRAY ) { | |
| 104 | raster.setDataElements( x, y, w, h, bgrPixels ); | |
| 105 | } | |
| 106 | else { | |
| 107 | int[] pixels; | |
| 108 | if( imageType == TYPE_INT_BGR ) { | |
| 109 | pixels = bytes2int( bgrPixels, 2, 1, 0 ); // bgr --> bgr | |
| 110 | } | |
| 111 | else if( imageType == TYPE_INT_ARGB || | |
| 112 | imageType == TYPE_INT_ARGB_PRE ) { | |
| 113 | pixels = bytes2int( bgrPixels, 3, 0, 1, 2 ); // abgr --> argb | |
| 114 | } | |
| 115 | else { | |
| 116 | pixels = bytes2int( bgrPixels, 0, 1, 2 ); // bgr --> rgb | |
| 117 | } | |
| 118 | if( w == 0 || h == 0 ) { | |
| 119 | return; | |
| 120 | } | |
| 121 | else if( pixels.length < w * h ) { | |
| 122 | throw new IllegalArgumentException( "pixels array must have a length" + " >= w*h" ); | |
| 123 | } | |
| 124 | if( imageType == TYPE_INT_ARGB || | |
| 125 | imageType == TYPE_INT_RGB || | |
| 126 | imageType == TYPE_INT_ARGB_PRE || | |
| 127 | imageType == TYPE_INT_BGR ) { | |
| 128 | raster.setDataElements( x, y, w, h, pixels ); | |
| 129 | } | |
| 130 | else { | |
| 131 | // Unmanages the image | |
| 132 | img.setRGB( x, y, w, h, pixels, 0, w ); | |
| 133 | } | |
| 134 | } | |
| 135 | } | |
| 136 | ||
| 137 | public static void ints2bytes( int[] in, byte[] out, int index1, int index2, | |
| 138 | int index3 ) { | |
| 139 | for( int i = 0; i < in.length; i++ ) { | |
| 140 | int index = i * 3; | |
| 141 | int value = in[ i ]; | |
| 142 | out[ index + index1 ] = (byte) value; | |
| 143 | value = value >> 8; | |
| 144 | out[ index + index2 ] = (byte) value; | |
| 145 | value = value >> 8; | |
| 146 | out[ index + index3 ] = (byte) value; | |
| 147 | } | |
| 148 | } | |
| 149 | ||
| 150 | public static void ints2bytes( int[] in, byte[] out, int index1, int index2, | |
| 151 | int index3, int index4 ) { | |
| 152 | for( int i = 0; i < in.length; i++ ) { | |
| 153 | int index = i * 4; | |
| 154 | int value = in[ i ]; | |
| 155 | out[ index + index1 ] = (byte) value; | |
| 156 | value = value >> 8; | |
| 157 | out[ index + index2 ] = (byte) value; | |
| 158 | value = value >> 8; | |
| 159 | out[ index + index3 ] = (byte) value; | |
| 160 | value = value >> 8; | |
| 161 | out[ index + index4 ] = (byte) value; | |
| 162 | } | |
| 163 | } | |
| 164 | ||
| 165 | public static int[] bytes2int( byte[] in, int index1, int index2, | |
| 166 | int index3 ) { | |
| 167 | int[] out = new int[ in.length / 3 ]; | |
| 168 | for( int i = 0; i < out.length; i++ ) { | |
| 169 | int index = i * 3; | |
| 170 | int b1 = (in[ index + index1 ] & 0xff) << 16; | |
| 171 | int b2 = (in[ index + index2 ] & 0xff) << 8; | |
| 172 | int b3 = in[ index + index3 ] & 0xff; | |
| 173 | out[ i ] = b1 | b2 | b3; | |
| 174 | } | |
| 175 | return out; | |
| 176 | } | |
| 177 | ||
| 178 | public static int[] bytes2int( byte[] in, int index1, int index2, int index3, | |
| 179 | int index4 ) { | |
| 180 | int[] out = new int[ in.length / 4 ]; | |
| 181 | for( int i = 0; i < out.length; i++ ) { | |
| 182 | int index = i * 4; | |
| 183 | int b1 = (in[ index + index1 ] & 0xff) << 24; | |
| 184 | int b2 = (in[ index + index2 ] & 0xff) << 16; | |
| 185 | int b3 = (in[ index + index3 ] & 0xff) << 8; | |
| 186 | int b4 = in[ index + index4 ] & 0xff; | |
| 187 | out[ i ] = b1 | b2 | b3 | b4; | |
| 188 | } | |
| 189 | return out; | |
| 190 | } | |
| 191 | ||
| 192 | public static BufferedImage convert( BufferedImage src, int bufImgType ) { | |
| 193 | BufferedImage img = new BufferedImage( src.getWidth(), | |
| 194 | src.getHeight(), | |
| 195 | bufImgType ); | |
| 196 | Graphics2D g2d = img.createGraphics(); | |
| 197 | g2d.drawImage( src, 0, 0, null ); | |
| 198 | g2d.dispose(); | |
| 199 | return img; | |
| 200 | } | |
| 201 | } | |
| 1 | 202 |
| 1 | package com.keenwrite.preview.images; | |
| 2 | ||
| 3 | import java.awt.image.BufferedImage; | |
| 4 | ||
| 5 | /** | |
| 6 | * Unused. Needs to extract image data from {@link BufferedImage} and create | |
| 7 | * down-sampled version. | |
| 8 | */ | |
| 9 | public class Lanczos3 { | |
| 10 | static double sinc( double x ) { | |
| 11 | x *= Math.PI; | |
| 12 | ||
| 13 | if( x < 0.01f && x > -0.01f ) { | |
| 14 | return 1.0f + x * x * (-1.0f / 6.0f + x * x * 1.0f / 120.0f); | |
| 15 | } | |
| 16 | ||
| 17 | return Math.sin( x ) / x; | |
| 18 | } | |
| 19 | ||
| 20 | static float clip( double t ) { | |
| 21 | final float eps = .0000125f; | |
| 22 | ||
| 23 | if( Math.abs( t ) < eps ) { return 0.0f; } | |
| 24 | ||
| 25 | return (float) t; | |
| 26 | } | |
| 27 | ||
| 28 | static float lancos( float t ) { | |
| 29 | if( t < 0.0f ) { t = -t; } | |
| 30 | ||
| 31 | if( t < 3.0f ) { return clip( sinc( t ) * sinc( t / 3.0f ) ); } | |
| 32 | else { return 0.0f; } | |
| 33 | } | |
| 34 | ||
| 35 | static float lancos3_resample_x( | |
| 36 | int[][] arr, int src_w, int src_h, int y, int x, float xscale ) { | |
| 37 | float s = 0; | |
| 38 | float coef_sum = 0.0f; | |
| 39 | float coef; | |
| 40 | float pix; | |
| 41 | int i; | |
| 42 | ||
| 43 | int l, r; | |
| 44 | float c; | |
| 45 | float hw; | |
| 46 | ||
| 47 | // For the reduction of the situation hw is equivalent to expanding the | |
| 48 | // number of pixels in the field, if you do not do this, the final | |
| 49 | // reduction of the image effect is not much different from the recent | |
| 50 | // field interpolation method, the effect is equivalent to the first | |
| 51 | // low-pass filtering, and then interpolate | |
| 52 | if( xscale > 1.0f ) { hw = 3.0f; } | |
| 53 | else { hw = 3.0f / xscale; } | |
| 54 | ||
| 55 | c = (float) x / xscale; | |
| 56 | l = (int) Math.floor( c - hw ); | |
| 57 | r = (int) Math.ceil( c + hw ); | |
| 58 | ||
| 59 | if( y < 0 ) { y = 0; } | |
| 60 | if( y >= src_h ) { y = src_h - 1; } | |
| 61 | if( xscale > 1.0f ) { xscale = 1.0f; } | |
| 62 | for( i = l; i <= r; i++ ) { | |
| 63 | x = Math.max( i, 0 ); | |
| 64 | if( i >= src_w ) { x = src_w - 1; } | |
| 65 | pix = arr[ y ][ x ]; | |
| 66 | coef = lancos( (c - i) * xscale ); | |
| 67 | s += pix * coef; | |
| 68 | coef_sum += coef; | |
| 69 | } | |
| 70 | s /= coef_sum; | |
| 71 | return s; | |
| 72 | } | |
| 73 | ||
| 74 | static class uint8_2d { | |
| 75 | int[][] arr; | |
| 76 | int rows; | |
| 77 | int cols; | |
| 78 | ||
| 79 | public uint8_2d( final int h1, final int w1 ) { | |
| 80 | arr = new int[ h1 ][ w1 ]; | |
| 81 | rows = h1; | |
| 82 | cols = w1; | |
| 83 | } | |
| 84 | } | |
| 85 | ||
| 86 | void img_resize_using_lancos3( uint8_2d src, uint8_2d dst ) { | |
| 87 | if( src == null || dst == null ) { return; } | |
| 88 | ||
| 89 | int src_rows, src_cols; | |
| 90 | int dst_rows, dst_cols; | |
| 91 | int i, j; | |
| 92 | int[][] src_arr; | |
| 93 | int[][] dst_arr; | |
| 94 | float xratio; | |
| 95 | float yratio; | |
| 96 | int val; | |
| 97 | int k; | |
| 98 | float hw; | |
| 99 | ||
| 100 | src_arr = src.arr; | |
| 101 | dst_arr = dst.arr; | |
| 102 | src_rows = src.rows; | |
| 103 | src_cols = src.cols; | |
| 104 | dst_rows = dst.rows; | |
| 105 | dst_cols = dst.cols; | |
| 106 | ||
| 107 | xratio = (float) dst_cols / (float) src_cols; | |
| 108 | yratio = (float) dst_rows / (float) src_rows; | |
| 109 | ||
| 110 | float scale; | |
| 111 | ||
| 112 | if( yratio > 1.0f ) { | |
| 113 | hw = 3.0f; | |
| 114 | scale = 1.0f; | |
| 115 | } | |
| 116 | else { | |
| 117 | hw = 3.0f / yratio; | |
| 118 | scale = yratio; | |
| 119 | } | |
| 120 | ||
| 121 | for( i = 0; i < dst_rows; i++ ) { | |
| 122 | for( j = 0; j < dst_cols; j++ ) { | |
| 123 | int t, b; | |
| 124 | float c; | |
| 125 | ||
| 126 | float s = 0; | |
| 127 | float coef_sum = 0.0f; | |
| 128 | float coef; | |
| 129 | float pix; | |
| 130 | ||
| 131 | c = (float) i / yratio; | |
| 132 | t = (int) Math.floor( c - hw ); | |
| 133 | b = (int) Math.ceil( c + hw ); | |
| 134 | // Interpolate in the x direction first, then interpolate in the y | |
| 135 | // direction. | |
| 136 | for( k = t; k <= b; k++ ) { | |
| 137 | pix = lancos3_resample_x( src_arr, src_cols, src_rows, k, j, xratio ); | |
| 138 | coef = lancos( (c - k) * scale ); | |
| 139 | coef_sum += coef; | |
| 140 | pix *= coef; | |
| 141 | s += pix; | |
| 142 | } | |
| 143 | val = (int) (s / coef_sum); | |
| 144 | if( val < 0 ) { val = 0; } | |
| 145 | if( val > 255 ) { val = 255; } | |
| 146 | dst_arr[ i ][ j ] = val; | |
| 147 | } | |
| 148 | } | |
| 149 | } | |
| 150 | ||
| 151 | BufferedImage test_lancos3_resize( BufferedImage img, float factor ) { | |
| 152 | assert img != null; | |
| 153 | ||
| 154 | uint8_2d r = null; | |
| 155 | uint8_2d g = null; | |
| 156 | uint8_2d b = null; | |
| 157 | ||
| 158 | BufferedImage out = null; | |
| 159 | // TODO: Split buffered image into RGB components. | |
| 160 | //split_img_data( img, r, g, b ); | |
| 161 | ||
| 162 | int w, h; | |
| 163 | int w1, h1; | |
| 164 | w = img.getWidth(); | |
| 165 | h = img.getHeight(); | |
| 166 | ||
| 167 | // TODO: Maintain aspect ratio. | |
| 168 | w1 = (int) (factor * w); | |
| 169 | h1 = (int) (factor * h); | |
| 170 | ||
| 171 | uint8_2d r1 = new uint8_2d( h1, w1 ); | |
| 172 | uint8_2d g1 = new uint8_2d( h1, w1 ); | |
| 173 | uint8_2d b1 = new uint8_2d( h1, w1 ); | |
| 174 | ||
| 175 | img_resize_using_lancos3( r, r1 ); | |
| 176 | img_resize_using_lancos3( g, g1 ); | |
| 177 | img_resize_using_lancos3( b, b1 ); | |
| 178 | ||
| 179 | // TODO: Combine rescaled image into RGB components. | |
| 180 | //merge_img_data( r1, g1, b1, out); | |
| 181 | ||
| 182 | return out; | |
| 183 | } | |
| 184 | } | |
| 1 | 185 |
| 1 | /* | |
| 2 | * Copyright 2013, Morten Nobel-Joergensen | |
| 3 | * | |
| 4 | * License: The BSD 3-Clause License | |
| 5 | * http://opensource.org/licenses/BSD-3-Clause | |
| 6 | */ | |
| 7 | package com.keenwrite.preview.images; | |
| 1 | 8 | |
| 9 | public final class Lanczos3Filter implements ResampleFilter { | |
| 10 | private static final |
| 1 | /* | |
| 2 | * Copyright 2013, Morten Nobel-Joergensen | |
| 3 | * | |
| 4 | * License: The BSD 3-Clause License | |
| 5 | * http://opensource.org/licenses/BSD-3-Clause | |
| 6 | */ | |
| 7 | package com.keenwrite.preview.images; | |
| 8 | ||
| 9 | public interface ResampleFilter { | |
| 10 | float getSamplingRadius(); | |
| 11 | ||
| 12 | float apply(float v); | |
| 13 | } | |
| 1 | 14 |
| 1 | /* | |
| 2 | * Copyright 2013, Morten Nobel-Joergensen | |
| 3 | * | |
| 4 | * License: The BSD 3-Clause License | |
| 5 | * http://opensource.org/licenses/BSD-3-Clause | |
| 6 | */ | |
| 7 | package com.keenwrite.preview.images; | |
| 8 | ||
| 9 | import java.awt.image.BufferedImage; | |
| 10 | import java.util.concurrent.atomic.AtomicI* | |
| 11 | final int dstWidth, | |
| 12 | final int dstHeight ) { | |
| 13 | this( filter,stWidth, d free memory | |
| 14 | // | |
| 1 | 15 | |
| 16 | if( dst != null && | |
| 17 | dstWidth == dst.getWidth() && | |
| 18 | dstHeight == d ][ xLoc ][ xLoc ][ xLoc ][ xLoc |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.processors; | |
| 3 | ||
| 4 | import java.util.Optional; | |
| 5 | import java.util.concurrent.atomic.AtomicReference; | |
| 6 | ||
| 7 | /** | |
| 8 | * Responsible for transforming data through a variety of chained handlers. | |
| 9 | * | |
| 10 | * @param <T> The data type to process. | |
| 11 | */ | |
| 12 | public class ExecutorProcessor<T> implements Processor<T> { | |
| 13 | ||
| 14 | /** | |
| 15 | * The next link in the processing chain. | |
| 16 | */ | |
| 17 | private final Processor<T> mNext; | |
| 18 | ||
| 19 | protected ExecutorProcessor() { | |
| 20 | this( null ); | |
| 21 | } | |
| 22 | ||
| 23 | /** | |
| 24 | * Constructs a new processor having a given successor. | |
| 25 | * | |
| 26 | * @param successor The next processor in the chain. | |
| 27 | */ | |
| 28 | public ExecutorProcessor( final Processor<T> successor ) { | |
| 29 | mNext = successor; | |
| 30 | } | |
| 31 | ||
| 32 | /** | |
| 33 | * Calls every link in the chain to process the given data. | |
| 34 | * | |
| 35 | * @param data The data to transform. | |
| 36 | * @return The data after processing by every link in the chain. | |
| 37 | */ | |
| 38 | @Override | |
| 39 | public T apply( final T data ) { | |
| 40 | // Start processing using the first processor after the executor. | |
| 41 | Optional<Processor<T>> handler = next(); | |
| 42 | final var result = new MutableReference( data ); | |
| 43 | ||
| 44 | while( handler.isPresent() ) { | |
| 45 | handler = handler.flatMap( p -> { | |
| 46 | result.set( p.apply( result.get() ) ); | |
| 47 | return p.next(); | |
| 48 | } ); | |
| 49 | } | |
| 50 | ||
| 51 | return result.get(); | |
| 52 | } | |
| 53 | ||
| 54 | @Override | |
| 55 | public Optional<Processor<T>> next() { | |
| 56 | return Optional.ofNullable( mNext ); | |
| 57 | } | |
| 58 | ||
| 59 | /** | |
| 60 | * A minor micro-optimization, since the processors cannot be run in parallel, | |
| 61 | * avoid using an {@link AtomicReference} during processor execution. This | |
| 62 | * is about twice as fast for the first four processor links in the chain. | |
| 63 | */ | |
| 64 | private final class MutableReference { | |
| 65 | private T mObject; | |
| 66 | ||
| 67 | MutableReference( final T object ) { | |
| 68 | set( object ); | |
| 69 | } | |
| 70 | ||
| 71 | void set( final T object ) { | |
| 72 | mObject = object; | |
| 73 | } | |
| 74 | ||
| 75 | T get() { | |
| 76 | return mObject; | |
| 77 | } | |
| 78 | } | |
| 79 | } | |
| 1 | 80 |
| 1 | ||
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.processors; | |
| 6 | ||
| 7 | import com.keenwrite.ExportFormat; | |
| 8 | import com.keenwrite.collections.InterpolatingMap; | |
| 9 | import com.keenwrite.constants.Constants; | |
| 10 | import com.keenwrite.editors.common.Caret; | |
| 11 | import com.keenwrite.io.FileType; | |
| 12 | import com.keenwrite.io.MediaType; | |
| 13 | import com.keenwrite.io.MediaTypeExtension; | |
| 14 | import com.keenwrite.processors.variable.VariableProcessor; | |
| 15 | import com.keenwrite.sigils.PropertyKeyOperator; | |
| 16 | import com.keenwrite.sigils.SigilKeyOperator; | |
| 17 | import com.keenwrite.util.GenericBuilder; | |
| 18 | import org.renjin.repackaged.guava.base.Splitter; | |
| 19 | ||
| 20 | import java.io.File; | |
| 21 | import java.nio.file.Path; | |
| 22 | import java.util.HashMap; | |
| 23 | import java.util.Locale; | |
| 24 | import java.util.Map; | |
| 25 | import java.util.concurrent.Callable; | |
| 26 | import java.util.function.Supplier; | |
| 27 | ||
| 28 | import static com.keenwrite.Bootstrap.USER_CACHE_DIR; | |
| 29 | import static com.keenwrite.Bootstrap.USER_DATA_DIR; | |
| 30 | import static com.keenwrite.constants.Constants.*; | |
| 31 | import static com.keenwrite.io.FileType.UNKNOWN; | |
| 32 | import static com.keenwrite.io.MediaType.TEXT_PROPERTIES; | |
| 33 | import static com.keenwrite.io.SysFile.toFile; | |
| 34 | import static com.keenwrite.predicates.PredicateFactory.createFileTypePredicate; | |
| 35 | import static com.keenwrite.processors.html.IdentityProcessor.IDENTITY; | |
| 36 | import static com.keenwrite.processors.text.TextReplacementFactory.replace; | |
| 37 | import static com.keenwrite.util.Strings.sanitize; | |
| 38 | ||
| 39 | /** | |
| 40 | * Provides a context for configuring a chain of {@link Processor} instances. | |
| 41 | */ | |
| 42 | public final class ProcessorContext { | |
| 43 | ||
| 44 | private final Mutator mMutator; | |
| 45 | ||
| 46 | /** | |
| 47 | * Determines the file type from the path extension. This should only be | |
| 48 | * called when it is known that the file type won't be a definition file | |
| 49 | * (e.g., YAML or other definition source), but rather an editable file | |
| 50 | * (e.g., Markdown, R Markdown, etc.). | |
| 51 | * | |
| 52 | * @param path The path with a file name extension. | |
| 53 | * @return The FileType for the given path. | |
| 54 | */ | |
| 55 | private static FileType lookup( final Path path ) { | |
| 56 | assert path != null; | |
| 57 | ||
| 58 | final var prefix = GLOB_PREFIX_FILE; | |
| 59 | final var keys = sSettings.getKeys( prefix ); | |
| 60 | ||
| 61 | var found = false; | |
| 62 | var fileType = UNKNOWN; | |
| 63 | ||
| 64 | while( keys.hasNext() && !found ) { | |
| 65 | final var key = keys.next(); | |
| 66 | final var patterns = sSettings.getStringSettingList( key ); | |
| 67 | final var predicate = createFileTypePredicate( patterns ); | |
| 68 | ||
| 69 | if( predicate.test( toFile( path ) ) ) { | |
| 70 | // Remove the EXTENSIONS_PREFIX to get the file name extension mapped | |
| 71 | // to a standard name (as defined in the settings.properties file). | |
| 72 | final String suffix = key.replace( prefix + '.', "" ); | |
| 73 | fileType = FileType.from( suffix ); | |
| 74 | found = true; | |
| 75 | } | |
| 76 | } | |
| 77 | ||
| 78 | return fileType; | |
| 79 | } | |
| 80 | ||
| 81 | public boolean isExportFormat( final ExportFormat exportFormat ) { | |
| 82 | return mMutator.mExportFormat == exportFormat; | |
| 83 | } | |
| 84 | ||
| 85 | /** | |
| 86 | * Responsible for populating the instance variables required by the | |
| 87 | * context. | |
| 88 | */ | |
| 89 | public static class Mutator { | |
| 90 | private Path mSourcePath; | |
| 91 | private Path mTargetPath; | |
| 92 | private ExportFormat mExportFormat; | |
| 93 | private Supplier<Boolean> mConcatenate = () -> true; | |
| 94 | private Supplier<String> mChapters = () -> ""; | |
| 95 | ||
| 96 | private Supplier<Path> mThemeDir = USER_DIRECTORY::toPath; | |
| 97 | private Supplier<Locale> mLocale = () -> Locale.ENGLISH; | |
| 98 | ||
| 99 | private Supplier<Map<String, String>> mDefinitions = HashMap::new; | |
| 100 | private Supplier<Map<String, String>> mMetadata = HashMap::new; | |
| 101 | private Supplier<Caret> mCaret = () -> Caret.builder().build(); | |
| 102 | ||
| 103 | private Supplier<Path> mImageDir = USER_DIRECTORY::toPath; | |
| 104 | private Supplier<String> mImageServer = () -> DIAGRAM_SERVER_NAME; | |
| 105 | private Supplier<String> mImageOrder = () -> PERSIST_IMAGES_DEFAULT; | |
| 106 | private Supplier<Path> mCacheDir = USER_CACHE_DIR::toPath; | |
| 107 | private Supplier<Path> mFontDir = () -> getFontDirectory().toPath(); | |
| 108 | ||
| 109 | private Supplier<String> mModesEnabled = () -> ""; | |
| 110 | ||
| 111 | private Supplier<String> mSigilBegan = () -> DEF_DELIM_BEGAN_DEFAULT; | |
| 112 | private Supplier<String> mSigilEnded = () -> DEF_DELIM_ENDED_DEFAULT; | |
| 113 | ||
| 114 | private Supplier<Path> mRWorkingDir = USER_DIRECTORY::toPath; | |
| 115 | private Supplier<String> mRScript = () -> ""; | |
| 116 | ||
| 117 | private Supplier<Boolean> mCurlQuotes = () -> true; | |
| 118 | private Supplier<Boolean> mAutoRemove = () -> true; | |
| 119 | ||
| 120 | public void setSourcePath( final Path sourcePath ) { | |
| 121 | assert sourcePath != null; | |
| 122 | mSourcePath = sourcePath; | |
| 123 | } | |
| 124 | ||
| 125 | public void setTargetPath( final Path outputPath ) { | |
| 126 | assert outputPath != null; | |
| 127 | mTargetPath = outputPath; | |
| 128 | } | |
| 129 | ||
| 130 | public void setThemeDir( final Supplier<Path> themeDir ) { | |
| 131 | assert themeDir != null; | |
| 132 | mThemeDir = themeDir; | |
| 133 | } | |
| 134 | ||
| 135 | public void setCacheDir( final Supplier<File> cacheDir ) { | |
| 136 | assert cacheDir != null; | |
| 137 | ||
| 138 | mCacheDir = () -> { | |
| 139 | final var dir = cacheDir.get(); | |
| 140 | ||
| 141 | return (dir == null ? toFile( USER_DATA_DIR ) : dir).toPath(); | |
| 142 | }; | |
| 143 | } | |
| 144 | ||
| 145 | public void setImageDir( final Supplier<File> imageDir ) { | |
| 146 | assert imageDir != null; | |
| 147 | ||
| 148 | mImageDir = () -> { | |
| 149 | final var dir = imageDir.get(); | |
| 150 | ||
| 151 | return (dir == null ? USER_DIRECTORY : dir).toPath(); | |
| 152 | }; | |
| 153 | } | |
| 154 | ||
| 155 | public void setImageOrder( final Supplier<String> imageOrder ) { | |
| 156 | assert imageOrder != null; | |
| 157 | mImageOrder = imageOrder; | |
| 158 | } | |
| 159 | ||
| 160 | public void setImageServer( final Supplier<String> imageServer ) { | |
| 161 | assert imageServer != null; | |
| 162 | mImageServer = imageServer; | |
| 163 | } | |
| 164 | ||
| 165 | public void setFontDir( final Supplier<File> fontDir ) { | |
| 166 | assert fontDir != null; | |
| 167 | ||
| 168 | mFontDir = () -> { | |
| 169 | final var dir = fontDir.get(); | |
| 170 | ||
| 171 | return (dir == null ? USER_DIRECTORY : dir).toPath(); | |
| 172 | }; | |
| 173 | } | |
| 174 | ||
| 175 | public void setModesEnabled( final Supplier<String> modesEnabled ) { | |
| 176 | assert modesEnabled != null; | |
| 177 | mModesEnabled = modesEnabled; | |
| 178 | } | |
| 179 | ||
| 180 | public void setExportFormat( final ExportFormat exportFormat ) { | |
| 181 | assert exportFormat != null; | |
| 182 | mExportFormat = exportFormat; | |
| 183 | } | |
| 184 | ||
| 185 | public void setConcatenate( final Supplier<Boolean> concatenate ) { | |
| 186 | mConcatenate = concatenate; | |
| 187 | } | |
| 188 | ||
| 189 | public void setChapters( final Supplier<String> chapters ) { | |
| 190 | mChapters = chapters; | |
| 191 | } | |
| 192 | ||
| 193 | public void setLocale( final Supplier<Locale> locale ) { | |
| 194 | assert locale != null; | |
| 195 | mLocale = locale; | |
| 196 | } | |
| 197 | ||
| 198 | /** | |
| 199 | * Sets the list of fully interpolated key-value pairs to use when | |
| 200 | * substituting variable names back into the document as variable values. | |
| 201 | * This uses a {@link Callable} reference so that GUI and command-line | |
| 202 | * usage can insert their respective behaviours. That is, this method | |
| 203 | * prevents coupling the GUI to the CLI. | |
| 204 | * | |
| 205 | * @param supplier Defines how to retrieve the definitions. | |
| 206 | */ | |
| 207 | public void setDefinitions( final Supplier<Map<String, String>> supplier ) { | |
| 208 | assert supplier != null; | |
| 209 | mDefinitions = supplier; | |
| 210 | } | |
| 211 | ||
| 212 | /** | |
| 213 | * Sets metadata to use in the document header. These are made available | |
| 214 | * to the typesetting engine as {@code \documentvariable} values. | |
| 215 | * | |
| 216 | * @param metadata The key/value pairs to publish as document metadata. | |
| 217 | */ | |
| 218 | public void setMetadata( final Supplier<Map<String, String>> metadata ) { | |
| 219 | assert metadata != null; | |
| 220 | mMetadata = metadata.get() == null ? HashMap::new : metadata; | |
| 221 | } | |
| 222 | ||
| 223 | /** | |
| 224 | * Sets document variables to use when building the document. These | |
| 225 | * variables will override existing key/value pairs, or be added as | |
| 226 | * new key/value pairs if not already defined. This allows users to | |
| 227 | * inject variables into the document from the command-line, allowing | |
| 228 | * for dynamic assignment of in-text values when building documents. | |
| 229 | * | |
| 230 | * @param overrides The key/value pairs to add (or override) as variables. | |
| 231 | */ | |
| 232 | public void setOverrides( final Supplier<Map<String, String>> overrides ) { | |
| 233 | assert overrides != null; | |
| 234 | assert mDefinitions != null; | |
| 235 | assert mDefinitions.get() != null; | |
| 236 | ||
| 237 | final var map = overrides.get(); | |
| 238 | ||
| 239 | if( map != null ) { | |
| 240 | mDefinitions.get().putAll( map ); | |
| 241 | } | |
| 242 | } | |
| 243 | ||
| 244 | /** | |
| 245 | * Sets the source for deriving the {@link Caret}. Typically, this is | |
| 246 | * the text editor that has focus. | |
| 247 | * | |
| 248 | * @param caret The source for the currently active caret. | |
| 249 | */ | |
| 250 | public void setCaret( final Supplier<Caret> caret ) { | |
| 251 | assert caret != null; | |
| 252 | mCaret = caret; | |
| 253 | } | |
| 254 | ||
| 255 | public void setSigilBegan( final Supplier<String> sigilBegan ) { | |
| 256 | assert sigilBegan != null; | |
| 257 | mSigilBegan = sigilBegan; | |
| 258 | } | |
| 259 | ||
| 260 | public void setSigilEnded( final Supplier<String> sigilEnded ) { | |
| 261 | assert sigilEnded != null; | |
| 262 | mSigilEnded = sigilEnded; | |
| 263 | } | |
| 264 | ||
| 265 | public void setRWorkingDir( final Supplier<Path> rWorkingDir ) { | |
| 266 | assert rWorkingDir != null; | |
| 267 | mRWorkingDir = rWorkingDir; | |
| 268 | } | |
| 269 | ||
| 270 | public void setRScript( final Supplier<String> rScript ) { | |
| 271 | assert rScript != null; | |
| 272 | mRScript = rScript; | |
| 273 | } | |
| 274 | ||
| 275 | public void setCurlQuotes( final Supplier<Boolean> curlQuotes ) { | |
| 276 | assert curlQuotes != null; | |
| 277 | mCurlQuotes = curlQuotes; | |
| 278 | } | |
| 279 | ||
| 280 | public void setAutoRemove( final Supplier<Boolean> autoRemove ) { | |
| 281 | assert autoRemove != null; | |
| 282 | mAutoRemove = autoRemove; | |
| 283 | } | |
| 284 | ||
| 285 | private boolean isExportFormat( final ExportFormat format ) { | |
| 286 | return mExportFormat == format; | |
| 287 | } | |
| 288 | } | |
| 289 | ||
| 290 | public static GenericBuilder<Mutator, ProcessorContext> builder() { | |
| 291 | return GenericBuilder.of( Mutator::new, ProcessorContext::new ); | |
| 292 | } | |
| 293 | ||
| 294 | /** | |
| 295 | * Creates a new context for use by the {@link ProcessorFactory} when | |
| 296 | * instantiating new {@link Processor} instances. Although all the | |
| 297 | * parameters are required, not all {@link Processor} instances will use | |
| 298 | * all parameters. | |
| 299 | */ | |
| 300 | private ProcessorContext( final Mutator mutator ) { | |
| 301 | assert mutator != null; | |
| 302 | ||
| 303 | mMutator = mutator; | |
| 304 | } | |
| 305 | ||
| 306 | public Path getSourcePath() { | |
| 307 | return mMutator.mSourcePath; | |
| 308 | } | |
| 309 | ||
| 310 | /** | |
| 311 | * Answers what type of input document is to be processed. | |
| 312 | * | |
| 313 | * @return The input document's {@link MediaType}. | |
| 314 | */ | |
| 315 | public MediaType getSourceType() { | |
| 316 | return MediaTypeExtension.fromPath( mMutator.mSourcePath ); | |
| 317 | } | |
| 318 | ||
| 319 | /** | |
| 320 | * Fully qualified file name to use when exporting (e.g., document.pdf). | |
| 321 | * | |
| 322 | * @return Full path to a file name. | |
| 323 | */ | |
| 324 | public Path getTargetPath() { | |
| 325 | return mMutator.mTargetPath; | |
| 326 | } | |
| 327 | ||
| 328 | public ExportFormat getExportFormat() { | |
| 329 | return mMutator.mExportFormat; | |
| 330 | } | |
| 331 | ||
| 332 | public Locale getLocale() { | |
| 333 | return mMutator.mLocale.get(); | |
| 334 | } | |
| 335 | ||
| 336 | /** | |
| 337 | * Returns the variable map of definitions, without interpolation. | |
| 338 | * | |
| 339 | * @return A map to help dereference variables. | |
| 340 | */ | |
| 341 | public Map<String, String> getDefinitions() { | |
| 342 | return mMutator.mDefinitions.get(); | |
| 343 | } | |
| 344 | ||
| 345 | /** | |
| 346 | * Returns the variable map of definitions, with interpolation. | |
| 347 | * | |
| 348 | * @return A map to help dereference variables. | |
| 349 | */ | |
| 350 | public InterpolatingMap getInterpolatedDefinitions() { | |
| 351 | return new InterpolatingMap( | |
| 352 | createDefinitionKeyOperator(), getDefinitions() | |
| 353 | ).interpolate(); | |
| 354 | } | |
| 355 | ||
| 356 | public Map<String, String> getMetadata() { | |
| 357 | return mMutator.mMetadata.get(); | |
| 358 | } | |
| 359 | ||
| 360 | /** | |
| 361 | * Returns the current caret position in the document being edited and is | |
| 362 | * always up-to-date. | |
| 363 | * | |
| 364 | * @return Caret position in the document. | |
| 365 | */ | |
| 366 | public Supplier<Caret> getCaret() { | |
| 367 | return mMutator.mCaret; | |
| 368 | } | |
| 369 | ||
| 370 | /** | |
| 371 | * Returns the directory that contains the file being edited. When | |
| 372 | * {@link Constants#DOCUMENT_DEFAULT} is created, the parent path is | |
| 373 | * {@code null}. This will get absolute path to the file before trying to | |
| 374 | * get te parent path, which should always be a valid path. In the unlikely | |
| 375 | * event that the base path cannot be determined by the path alone, the | |
| 376 | * default user directory is returned. This is necessary for the creation | |
| 377 | * of new files. | |
| 378 | * | |
| 379 | * @return Path to the directory containing a file being edited, or the | |
| 380 | * default user directory if the base path cannot be determined. | |
| 381 | */ | |
| 382 | public Path getBaseDir() { | |
| 383 | final var path = getSourcePath().toAbsolutePath().getParent(); | |
| 384 | return path == null ? DEFAULT_DIRECTORY : path; | |
| 385 | } | |
| 386 | ||
| 387 | FileType getSourceFileType() { | |
| 388 | return lookup( getSourcePath() ); | |
| 389 | } | |
| 390 | ||
| 391 | public Path getThemeDir() { | |
| 392 | return mMutator.mThemeDir.get(); | |
| 393 | } | |
| 394 | ||
| 395 | public Path getImageDir() { | |
| 396 | return mMutator.mImageDir.get(); | |
| 397 | } | |
| 398 | ||
| 399 | public Path getCacheDir() { | |
| 400 | return mMutator.mCacheDir.get(); | |
| 401 | } | |
| 402 | ||
| 403 | public Iterable<String> getImageOrder() { | |
| 404 | assert mMutator.mImageOrder != null; | |
| 405 | ||
| 406 | final var order = mMutator.mImageOrder.get(); | |
| 407 | final var token = order.contains( "," ) ? ',' : ' '; | |
| 408 | ||
| 409 | return Splitter.on( token ).split( token + order ); | |
| 410 | } | |
| 411 | ||
| 412 | public String getImageServer() { | |
| 413 | return mMutator.mImageServer.get(); | |
| 414 | } | |
| 415 | ||
| 416 | public Path getFontDir() { | |
| 417 | return mMutator.mFontDir.get(); | |
| 418 | } | |
| 419 | ||
| 420 | public String getModesEnabled() { | |
| 421 | // Force the processor to select particular sigils. | |
| 422 | final var processor = new VariableProcessor( IDENTITY, this ); | |
| 423 | final var needles = processor.getDefinitions(); | |
| 424 | final var haystack = sanitize( mMutator.mModesEnabled.get() ); | |
| 425 | ||
| 426 | return needles.containsKey( haystack ) | |
| 427 | ? replace( haystack, needles ) | |
| 428 | : processor.hasSigils( haystack ) | |
| 429 | ? "" | |
| 430 | : haystack; | |
| 431 | } | |
| 432 | ||
| 433 | public boolean getAutoRemove() { | |
| 434 | return mMutator.mAutoRemove.get(); | |
| 435 | } | |
| 436 | ||
| 437 | public Path getRWorkingDir() { | |
| 438 | return mMutator.mRWorkingDir.get(); | |
| 439 | } | |
| 440 | ||
| 441 | public String getRScript() { | |
| 442 | return mMutator.mRScript.get(); | |
| 443 | } | |
| 444 | ||
| 445 | public boolean getCurlQuotes() { | |
| 446 | return mMutator.mCurlQuotes.get(); | |
| 447 | } | |
| 448 | ||
| 449 | /** | |
| 450 | * Answers whether to process a single text file or all text files in | |
| 451 | * the same directory as a single text file. See {@link #getSourcePath()} | |
| 452 | * for the file to process (or all files in its directory). | |
| 453 | * | |
| 454 | * @return {@code true} means to process all text files, {@code false} | |
| 455 | * means to process a single file. | |
| 456 | */ | |
| 457 | public boolean getConcatenate() { | |
| 458 | return mMutator.mConcatenate.get(); | |
| 459 | } | |
| 460 | ||
| 461 | public String getChapters() { | |
| 462 | return mMutator.mChapters.get(); | |
| 463 | } | |
| 464 | ||
| 465 | public SigilKeyOperator createKeyOperator() { | |
| 466 | return createKeyOperator( getSourcePath() ); | |
| 467 | } | |
| 468 | ||
| 469 | /** | |
| 470 | * Returns the sigil operator for the given {@link Path}. | |
| 471 | * | |
| 472 | * @param path The type of file being edited, from its extension. | |
| 473 | */ | |
| 474 | private SigilKeyOperator createKeyOperator( final Path path ) { | |
| 475 | assert path != null; | |
| 476 | ||
| 477 | return MediaType.fromFilename( path ) == TEXT_PROPERTIES | |
| 478 | ? createPropertyKeyOperator() | |
| 479 | : createDefinitionKeyOperator(); | |
| 480 | } | |
| 481 | ||
| 482 | private SigilKeyOperator createPropertyKeyOperator() { | |
| 483 | return new PropertyKeyOperator(); | |
| 484 | } | |
| 485 | ||
| 486 | private SigilKeyOperator createDefinitionKeyOperator() { | |
| 487 | final var began = mMutator.mSigilBegan.get(); | |
| 488 | final var ended = mMutator.mSigilEnded.get(); | |
| 489 | ||
| 490 | return new SigilKeyOperator( began, ended ); | |
| 491 | } | |
| 492 | } | |
| 1 | 493 |
| 1 | /* Copyright 2020-2024 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.processors; | |
| 1 | 6 | |
| 7 | import com.keenwrite.processors.html.PreformattedProces |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.processors.html; | |
| 1 | 3 | |
| 4 | import com.keenwrite.preview.HtmlPreview; | |
| 5 | import com.keenwrite.processors.ExecutorProcessor; | |
| 6 | HtmlhtmlP final HtmlPreview htmlPreview ) { | |
| 7 | sHtmlPreview = htmlP | |
| 8 | sHtmlPreview.render( html |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.processors.html; | |
| 3 | ||
| 4 | import com.keenwrite.processors.ExecutorProcessor; | |
| 5 | ||
| 6 | /** | |
| 7 | * Responsible for transforming a string into itself. This is used at the | |
| 8 | * end of a processing chain when no more processing is required. | |
| 9 | */ | |
| 10 | public final class IdentityProcessor extends ExecutorProcessor<String> { | |
| 11 | public static final IdentityProcessor IDENTITY = new IdentityProcessor(); | |
| 12 | ||
| 13 | /** | |
| 14 | * Constructs a new instance having no successor (the default successor is | |
| 15 | * {@code null}). | |
| 16 | */ | |
| 17 | private IdentityProcessor() { | |
| 18 | } | |
| 19 | ||
| 20 | /** | |
| 21 | * Returns the given string without modification. | |
| 22 | * | |
| 23 | * @param s The string to return. | |
| 24 | * @return The value of s. | |
| 25 | */ | |
| 26 | @Override | |
| 27 | public String apply( final String s ) { | |
| 28 | return s; | |
| 29 | } | |
| 30 | } | |
| 1 | 31 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.processors.html; | |
| 6 | ||
| 7 | import com.keenwrite.processors.ExecutorProcessor; | |
| 8 | import com.keenwrite.processors.Processor; | |
| 9 | ||
| 10 | /** | |
| 11 | * TR."<pre>\{t}</pre>"; | |
| 12 | } | |
| 13 | } | |
| 1 | 14 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.processors.html; | |
| 1 | 6 | |
| 7 | import com.keenwrite.dom.DocumentParser; | |
| 8 | import com.keenwrite.io.MediaTypeExtension; | |
| 9 | import com.keenwrCurlCurl |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.processors.markdown; | |
| 1 | 6 | |
| 7 | import com.keenwrite.dom.DocumentConverter; | |
| 8 | import com.keenwrite.processors.ExecutorProcessor; | |
| 9 | imp |
| 1 | /* Copyright 2022 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.processors.markdown; | |
| 1 | 6 | |
| 7 | import com.keenwrite.ExportFormat; | |
| 8 | import com.keenwrite.io.MediaType; | |
| 9 | import com.keenwrite.processors.PImageBlockImage |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.processors.markdown.extensions.captions; | |
| 1 | 6 | |
| 7 | import com.vladsch.flexmark.html.HtmlWriter; | |
| 8 | import com.vladsch.flexmark.parser.Inl |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.processors.markdown.extensions.captions; | |
| 6 | ||
| 7 | import com.vladsch.flexmark.parser.block.AbstractBlockParserFactory; | |
| 8 | import com.vladsch.flexmark.parser.block.BlockStart; | |
| 9 | import com.vladsch.flexmark.parser.block.MatchedBlockParser; | |
| 10 | import com.vladsch.flexmark.parser.block.ParserState; | |
| 11 | import com.vladsch.flexmark.util.data.DataHolder; | |
| 12 | ||
| 13 | class CaptionBlockParserFactory extends AbstractBlockParserFactory { | |
| 14 | CaptionBlockParserFactory( final DataHolder options ) { | |
| 15 | super( options ); | |
| 16 | } | |
| 17 | ||
| 18 | @Override | |
| 19 | public BlockStart tryStart( | |
| 20 | final ParserState state, | |
| 21 | final MatchedBlockParser matchedBlockParser ) { | |
| 22 | ||
| 23 | final var flush = state.getIndent() == 0; | |
| 24 | final var index = state.getNextNonSpaceIndex(); | |
| 25 | final var line = state.getLine(); | |
| 26 | final var length = line.length(); | |
| 27 | final var text = line.subSequence( index, length ); | |
| 28 | ||
| 29 | return flush && CaptionParser.canParse( text ) | |
| 30 | ? BlockStart.of( new CaptionParser( text ) ).atIndex( length ) | |
| 31 | : BlockStart.none(); | |
| 32 | } | |
| 33 | } | |
| 1 | 34 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.processors.markdown.extensions.captions; | |
| 6 | ||
| 7 | import com.keenwrite.processors.markdown.extensions.common.MarkdownCustomBlockParserFactory; | |
| 8 | import com.vladsch.flexmark.parser.block.BlockParserFactory; | |
| 9 | import com.vladsch.flexmark.util.data.DataHolder; | |
| 10 | ||
| 11 | class CaptionCustomBlockParserFactory extends MarkdownCustomBlockParserFactory { | |
| 12 | CaptionCustomBlockParserFactory() {} | |
| 13 | ||
| 14 | @Override | |
| 15 | public BlockParserFactory createBlockParserFactory( | |
| 16 | final DataHolder options ) { | |
| 17 | return new CaptionBlockParserFactory( options ); | |
| 18 | } | |
| 19 | } | |
| 1 | 20 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.processors.markdown.extensions.captions; | |
| 1 | 6 | |
| 7 | import com.keenwrite.processors.markdown.extensions.common.MarkdownRenderarsing and rendering {@link CaptionBlock} instaaptionaptionaptionaption syntax. | |
| 8 | */ | |
| 9 | public static CaptionaptioncustomBlockParserFactory( new CaptionCustomBlockParsepostProcessorFactory( new CaptionPostProcessorFactoryaption |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.processors.markdown.extensions.captions; | |
| 6 | ||
| 7 | import com.keenwrite.processors.markdown.extensions.references.CrossReferenceNode; | |
| 8 | import com.vladsch.flexmark.html.HtmlWriter; | |
| 9 | import com.vladsch.flexmark.html.renderer.CoreNodeRenderer; | |
| 10 | import com.vladsch.flexmark.html.renderer.NodeRendererContext; | |
| 11 | import com.vladsch.flexmark.html.renderer.NodeRenderingHandler; | |
| 12 | import com.vladsch.flexmark.util.ast.Node; | |
| 13 | import com.vladsch.flexmark.util.data.DataHolder; | |
| 14 | ||
| 15 | import java.util.HashSet; | |
| 16 | import java.util.LinkedList; | |
| 17 | import java.util.List; | |
| 18 | import java.util.Set; | |
| 19 | ||
| 20 | /** | |
| 21 | * Responsible for rendering {@link CaptionBlock} instances as HTML (via | |
| 22 | * delegation). | |
| 23 | */ | |
| 24 | class CaptionNodeRenderer extends CoreNodeRenderer { | |
| 25 | CaptionNodeRenderer( final DataHolder options ) { | |
| 26 | super( options ); | |
| 27 | } | |
| 28 | ||
| 29 | @Override | |
| 30 | public Set<NodeRenderingHandler<?>> getNodeRenderingHandlers() { | |
| 31 | return new HashSet<>( List.of( | |
| 32 | new NodeRenderingHandler<>( CaptionBlock.class, this::render ) | |
| 33 | ) ); | |
| 34 | } | |
| 35 | ||
| 36 | private void render( | |
| 37 | final CaptionBlock node, | |
| 38 | final NodeRendererContext context, | |
| 39 | final HtmlWriter html ) { | |
| 40 | final var anchors = new LinkedList<Node>(); | |
| 41 | ||
| 42 | html.raw( "<p>" ); | |
| 43 | node.opening( html ); | |
| 44 | ||
| 45 | if( node.hasChildren() ) { | |
| 46 | for( final var child : node.getChildren() ) { | |
| 47 | if( !child.isOrDescendantOfType( CrossReferenceNode.class ) ) { | |
| 48 | context.render( child ); | |
| 49 | } | |
| 50 | else { | |
| 51 | anchors.add( child ); | |
| 52 | } | |
| 53 | } | |
| 54 | } | |
| 55 | ||
| 56 | node.closing( html ); | |
| 57 | ||
| 58 | for( final var anchor : anchors ) { | |
| 59 | context.render( anchor ); | |
| 60 | } | |
| 61 | ||
| 62 | html.raw( "</p>" ); | |
| 63 | } | |
| 64 | } | |
| 1 | 65 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.processors.markdown.extensions.captions; | |
| 6 | ||
| 7 | import com.keenwrite.processors.markdown.extensions.common.MarkdownaptionaptionNodeRenderer( options ); | |
| 8 | } | |
| 9 | } | |
| 1 | 10 |
| 1 | package com.keenwrite.processors.markdown.extensions.captions; | |
| 2 | ||
| 3 | import com.vladsch.flexmark.parser.InlineParser; | |
| 4 | import com.vladsch.flexmark.parser.block.AbstractBlockParser; | |
| 5 | import com.vladsch.flexmark.parser.block.BlockContinue; | |
| 6 | import com.vladsch.flexmark.parser.block.ParserState; | |
| 7 | import com.vladsch.flexmark.util.ast.Block; | |
| 8 | import com.vladsch.flexmark.util.sequence.BasedSequence; | |
| 9 | ||
| 10 | class CaptionParser extends AbstractBlockParser { | |
| 11 | private final CaptionBlock mBlock; | |
| 12 | ||
| 13 | CaptionParser( final BasedSequence text ) { | |
| 14 | assert text != null; | |
| 15 | assert text.isNotEmpty(); | |
| 16 | assert text.length() > 2; | |
| 17 | ||
| 18 | final var caption = text.subSequence( 2 ); | |
| 19 | ||
| 20 | mBlock = new CaptionBlock( caption.trim() ); | |
| 21 | } | |
| 22 | ||
| 23 | static boolean canParse( final BasedSequence text ) { | |
| 24 | return text.length() > 3 && | |
| 25 | text.charAt( 0 ) == ':' && | |
| 26 | text.charAt( 1 ) == ':' && | |
| 27 | text.charAt( 2 ) != ':'; | |
| 28 | } | |
| 29 | ||
| 30 | @Override | |
| 31 | public Block getBlock() { | |
| 32 | return mBlock; | |
| 33 | } | |
| 34 | ||
| 35 | @Override | |
| 36 | public BlockContinue tryContinue( final ParserState state ) { | |
| 37 | return BlockContinue.none(); | |
| 38 | } | |
| 39 | ||
| 40 | @Override | |
| 41 | public void parseInlines( final InlineParser inlineParser ) { | |
| 42 | assert inlineParser != null; | |
| 43 | ||
| 44 | mBlock.parse( inlineParser ); | |
| 45 | } | |
| 46 | ||
| 47 | @Override | |
| 48 | public void closeBlock( final ParserState state ) {} | |
| 49 | } | |
| 1 | 50 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.processors.markdown.extensions.captions; | |
| 6 | ||
| 7 | import com.keenwrite.processors.markdown.extensions.fences.blocks.ClosingDivBlock; | |
| 8 | import com.keenwrite.processors.markdown.extensions.fences.blocks.OpeningDivBlock; | |
| 9 | import com.vladsch.flexmark.parser.block.NodePostProcessor; | |
| 10 | import com.vladsch.flexmark.util.ast.Node; | |
| 11 | import com.vladsch.flexmark.util.ast.NodeTracker; | |
| 12 | import org.jetbrains.annotations.NotNull; | |
| 13 | ||
| 14 | /** | |
| 15 | * Captions are written most naturally <em>after</em>> the element that they | |
| 16 | * apply to, regardless of whether they are figures, tables, code listings, | |
| 17 | * algorithms, or equations. The typesetting software uses event-based parsing | |
| 18 | * of XML elements, meaning the DOM isn't fully loaded into memory. This means | |
| 19 | * that captions must come <em>before</em> the item being captioned. | |
| 20 | * <p> | |
| 21 | * To reconcile this UX conundrum, we swap captions with the previous node. | |
| 22 | */ | |
| 23 | class CaptionPostProcessor extends NodePostProcessor { | |
| 24 | @Override | |
| 25 | public void process( | |
| 26 | @NotNull final NodeTracker state, | |
| 27 | @NotNull final Node caption ) { | |
| 28 | ||
| 29 | var previous = caption.getPrevious(); | |
| 30 | ||
| 31 | if( previous != null ) { | |
| 32 | swap( previous, caption ); | |
| 33 | } | |
| 34 | } | |
| 35 | ||
| 36 | private void swap( final Node previous, final Node caption ) { | |
| 37 | assert previous != null; | |
| 38 | assert caption != null; | |
| 39 | ||
| 40 | var swap = previous; | |
| 41 | boolean found = true; | |
| 42 | ||
| 43 | if( swap.isOrDescendantOfType( ClosingDivBlock.class ) ) { | |
| 44 | found = false; | |
| 45 | ||
| 46 | while( !found && swap != null ) { | |
| 47 | if( swap.isOrDescendantOfType( OpeningDivBlock.class ) ) { | |
| 48 | found = true; | |
| 49 | } | |
| 50 | else { | |
| 51 | swap = swap.getPrevious(); | |
| 52 | } | |
| 53 | } | |
| 54 | } | |
| 55 | ||
| 56 | if( found ) { | |
| 57 | swap.insertBefore( caption ); | |
| 58 | } | |
| 59 | } | |
| 60 | } | |
| 1 | 61 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.processors.markdown.extensions.captions; | |
| 6 | ||
| 7 | import com.keenwrite.processors.markdown.extensions.common.parser.block.NodePostProcessor; | |
| 8 | import com.vladsch.flexma | |
| 9 | class Captio extend { | |
| 10 | Captio() { | |
| 11 | // The argument isn't used by the Markdown parsing library. | |
| 12 | super( false ); | |
| 13 | ||
| 14 | addNodes( CaptionBlock.class ); | |
| 15 | } | |
| 16 | ||
| 17 | @Override | |
| 18 | protectedfinanew CaptionPostProcessor(); | |
| 19 | } | |
| 20 | } | |
| 1 | 21 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved..extensions.caret; | |
| 2 | ||
| 3 | import com.keenwrite.editors.common.Caret; | |
| 4 | import com.keenwrite.processors.ProcessorContext; | |
| 5 | import com.kee.extensions.common.HtmlRendererAdapterjava.util.function.Supplier.extensions.caret.Builderextends HtmlRendererAdapter { | |
| 6 | ||
| 7 | private final Supplier<Caret>ProcessomCaret = context.getCaret(Processoontext )Builder builder, | |
| 8 | } | |
| 1 | 9 |
| 1 | package com.keenwrite.processors.markdown.extensions.caret; | |
| 1 | 2 | |
| 3 | import com.keenwrite.constants.Constants; | |
| 4 | import com.keenwrite.editors.common.Caret; | |
| 5 | import com.vladsch.flexmark.ext.tables.TableBlock; | |
| 6 | import com.vladsch.flexmark.html.AttributeProvider; | |
| 7 | importfinal |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.processors.markdown.extensions.common; | |
| 3 | ||
| 4 | import com.vladsch.flexmark.util.ast.Node; | |
| 5 | import com.vladsch.flexmark.util.sequence.BasedSequence; | |
| 6 | import org.jetbrains./** | |
| 7 | * Use {@link #EMPTY_NODE}. | |
| 8 | */} | |
| 9 | ||
| 10 | @NotNull | |
| 11 | @Override | |
| 12 | publicasedSequence.EMPTY_SEGMENTS; | |
| 13 | } | |
| 14 | } | |
| 1 | 15 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.processors.markdown.extensions.common; | |
| 3 | ||
| 4 | import com.vladsch.flexmark.util.data.MutableDataHolder; | |
| 5 | import org.jetbrains.annotations.NotNull; | |
| 6 | ||
| 7 | import static com.vladsch.flexmark.html.HtmlRenderer.HtmlRendererExtension; | |
| 8 | ||
| 9 | /** | |
| 10 | * Hides the {@link #rendererOptions(MutableDataHolder)} from subclasses | |
| 11 | * that would otherwise implement the {@link HtmlRendererExtension} interface. | |
| 12 | */ | |
| 13 | public abstract class HtmlRendererAdapter implements HtmlRendererExtension { | |
| 14 | /** | |
| 15 | * Empty, unused. | |
| 16 | * | |
| 17 | * @param options Ignored. | |
| 18 | */ | |
| 19 | @Override | |
| 20 | public void rendererOptions( @NotNull final MutableDataHolder options ) { } | |
| 21 | } | |
| 1 | 22 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.processors.markdown.extensions.common; | |
| 6 | ||
| 7 | import com.vladsch.flexmark.parser.block.BlockParserFactory; | |
| 8 | import com.vladsch.flexmark.parser.block.CustomBlockParserFactory; | |
| 9 | import com.vladsch.flexmark.util.data.DataHolder; | |
| 10 | import org.jetbrains.annotations.NotNull; | |
| 11 | import org.jetbrains.annotations.Nullable; | |
| 12 | ||
| 13 | import java.util.Set; | |
| 14 | ||
| 15 | public abstract class MarkdownCustomBlockParserFactory | |
| 16 | implements CustomBlockParserFactory { | |
| 17 | /** | |
| 18 | * Subclasses must return a new {@link BlockParserFactory} instance. | |
| 19 | * | |
| 20 | * @param options Passed into the new instance constructor. | |
| 21 | * @return The new {@link BlockParserFactory} instance. | |
| 22 | */ | |
| 23 | protected abstract BlockParserFactory createBlockParserFactory( | |
| 24 | DataHolder options ); | |
| 25 | ||
| 26 | @NotNull | |
| 27 | @Override | |
| 28 | public BlockParserFactory apply( @NotNull final DataHolder options ) { | |
| 29 | return createBlockParserFactory( options ); | |
| 30 | } | |
| 31 | ||
| 32 | @Override | |
| 33 | public @Nullable Set<Class<?>> getAfterDependents() { | |
| 34 | return null; | |
| 35 | } | |
| 36 | ||
| 37 | @Override | |
| 38 | public @Nullable Set<Class<?>> getBeforeDependents() { | |
| 39 | return null; | |
| 40 | } | |
| 41 | ||
| 42 | @Override | |
| 43 | public boolean affectsGlobalScope() { | |
| 44 | return false; | |
| 45 | } | |
| 46 | } | |
| 1 | 47 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.processors.markdown.extensions.common; | |
| 6 | ||
| 7 | import com.vladsch.flexmark.html.renderer.NodeRenderer; | |
| 8 | import com.vladsch.flexmark.html.renderer.NodeRenderedata.DataHolderNodeRendererFactory | |
| 9 | implements NodeRendererFactory {Renderer apply( @NotNull final DataHolder options ) { | |
| 10 | return createNodeRenderer( optionsRenderer createNodeRenderer( DataHolder options ); | |
| 11 | } | |
| 1 | 12 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.processors.markdown.extensions.common; | |
| 6 | ||
| 7 | import com.vladsch.flexmark.parser.Parser.ParserExtension; | |
| 8 | import com.vladsch.flexmark.util.data.MutableDataHolder; | |
| 9 | ||
| 10 | /** | |
| 11 | * Provides a default {@link #parserOptions(MutableDataHolder)} implementation. | |
| 12 | */ | |
| 13 | public interface MarkdownParserExtension extends ParserExtension { | |
| 14 | @Override | |
| 15 | default void parserOptions( final MutableDataHolder options ) {} | |
| 16 | } | |
| 1 | 17 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.processors.markdown.extensions.common; | |
| 6 | ||
| 7 | import com.vladsch.flexmark.parser.block.NodePostProcessor; | |
| 8 | import com.vladsch.flexmark.parser.block.NodePostProcessorFactory; | |
| 9 | import com.vladsch.flexmark.util.ast.Document; | |
| 10 | import org.jetbrains.annotations.NotNull; | |
| 11 | ||
| 12 | public abstract class MarkdownPostProcessorFactory | |
| 13 | extends NodePostProcessorFactory { | |
| 14 | public MarkdownPostProcessorFactory( final boolean ignored ) { | |
| 15 | super( ignored ); | |
| 16 | } | |
| 17 | ||
| 18 | @NotNull | |
| 19 | @Override | |
| 20 | public NodePostProcessor apply( @NotNull Document document ) { | |
| 21 | return createPostProcessor( document ); | |
| 22 | } | |
| 23 | ||
| 24 | protected abstract NodePostProcessor createPostProcessor( Document document ); | |
| 25 | } | |
| 1 | 26 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.processors.markdown.extensions.common; | |
| 6 | ||
| 7 | import com.vladsch.flexmark.html.HtmlRenderer.Builder; | |
| 8 | import com.vladsch.flexmark.html.renderer.NodeRenderer; | |
| 9 | import com.vladsch.flexmark.html.renderer.NodeRendererFactory; | |
| 10 | import org.jetbrains.annotations.NotNull; | |
| 11 | ||
| 12 | public abstract class MarkdownRendererExtension extends HtmlRendererAdapter | |
| 13 | implements MarkdownParserExtension { | |
| 14 | ||
| 15 | /** | |
| 16 | * Implemented by subclasses to create the {@link NodeRendererFactory} capable | |
| 17 | * of converting nodes created by an extension into HTML elements. | |
| 18 | * | |
| 19 | * @return The {@link NodeRendererFactory} for producing {@link NodeRenderer} | |
| 20 | * instances. | |
| 21 | */ | |
| 22 | protected abstract NodeRendererFactory createNodeRendererFactory(); | |
| 23 | ||
| 24 | /** | |
| 25 | * Adds an extension for HTML document export types. | |
| 26 | * | |
| 27 | * @param builder The document builder. | |
| 28 | * @param rendererType Indicates the document type to be built. | |
| 29 | */ | |
| 30 | @Override | |
| 31 | public void extend( | |
| 32 | @NotNull final Builder builder, | |
| 33 | @NotNull final String rendererType ) { | |
| 34 | if( "HTML".equalsIgnoreCase( rendererType ) ) { | |
| 35 | builder.nodeRendererFactory( createNodeRendererFactory() ); | |
| 36 | } | |
| 37 | } | |
| 38 | } | |
| 1 | 39 |
| 1 | /* Copyright 2020-2024 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.processors.markdown.extensions.fences; | |
| 3 | ||
| 4 | import com.keenwrite.processors.markdown.extensions.common.MarkdownParserExtension; | |
| 5 | import com.keenwrite.processors.markdown.extensions.common.MarkdownRendererExtension; | |
| 6 | import com.keenwrite.processors.markdown.extensions.fences.factories.CustomDivBlockParserFactory; | |
| 7 | import com.keenwrite.processors.markdown.extensions.fences.factories.FencedDivNodeRendererFactory; | |
| 8 | import com.keenwrite.processors.markdown.extensions.fences.factories.FencedDivPreProcessorFactory; | |
| 9 | import com.vladsch.flexmark.html.renderer.NodeRendererFactory; | |
| 10 | import com.vladsch.flexmark.parser.Parser.Builder; | |
| 11 | ||
| 12 | import java.util.regex.Pattern; | |
| 13 | ||
| 14 | import static java.util.regex.Pattern.UNICODE_CHARACTER_CLASS; | |
| 15 | import static java.util.regex.Pattern.compile; | |
| 16 | ||
| 17 | /** | |
| 18 | * Responsible for parsing div block syntax into HTML div tags. Fenced div | |
| 19 | * blocks start with three or more consecutive colons, followed by a space, | |
| 20 | * followed by attributes. The attributes can be either a single word, or | |
| 21 | * multiple words nested in braces. For example: | |
| 22 | * | |
| 23 | * <p> | |
| 24 | * ::: poem | |
| 25 | * Tyger Tyger, burning bright, | |
| 26 | * In the forests of the night; | |
| 27 | * What immortal hand or eye, | |
| 28 | * Could frame thy fearful symmetry? | |
| 29 | * ::: | |
| 30 | * </p> | |
| 31 | * <p> | |
| 32 | * As well as: | |
| 33 | * </p> | |
| 34 | * <p> | |
| 35 | * ::: {#verse .p .d k=v author="Dickinson"} | |
| 36 | * Because I could not stop for Death -- | |
| 37 | * He kindly stopped for me -- | |
| 38 | * The Carriage held but just Ourselves -- | |
| 39 | * And Immortality. | |
| 40 | * ::: | |
| 41 | * </p> | |
| 42 | * | |
| 43 | * <p> | |
| 44 | * The second example produces the following starting {@code div} element: | |
| 45 | * </p> | |
| 46 | * {@literal <div id="verse" class="p d" data-k="v" data-author="Dickson">} | |
| 47 | * | |
| 48 | * <p> | |
| 49 | * This will parse fenced divs embedded inside of blockquote environments. | |
| 50 | * </p> | |
| 51 | */ | |
| 52 | public class FencedDivExtension extends MarkdownRendererExtension | |
| 53 | implements MarkdownParserExtension { | |
| 54 | /** | |
| 55 | * Matches any number of colons at start of line. This will match both the | |
| 56 | * opening and closing fences, with any number of colons. | |
| 57 | */ | |
| 58 | public static final Pattern FENCE = compile( "^:::+.*" ); | |
| 59 | ||
| 60 | /** | |
| 61 | * After a fenced div is detected, this will match the opening fence. | |
| 62 | */ | |
| 63 | public static final Pattern FENCE_OPENING = compile( | |
| 64 | "^:::+\\s+([\\p{Alnum}\\-_]+|\\{.+})\\s*$", | |
| 65 | UNICODE_CHARACTER_CLASS ); | |
| 66 | ||
| 67 | public static FencedDivExtension create() { | |
| 68 | return new FencedDivExtension(); | |
| 69 | } | |
| 70 | ||
| 71 | @Override | |
| 72 | public void extend( final Builder builder ) { | |
| 73 | builder.customBlockParserFactory( new CustomDivBlockParserFactory() ); | |
| 74 | builder.paragraphPreProcessorFactory( new FencedDivPreProcessorFactory() ); | |
| 75 | } | |
| 76 | ||
| 77 | @Override | |
| 78 | protected NodeRendererFactory createNodeRendererFactory() { | |
| 79 | return new FencedDivNodeRendererFactory(); | |
| 80 | } | |
| 81 | } | |
| 1 | 82 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.processors.markdown.extensions.fences; | |
| 1 | 3 | |
| 4 | import com.keenwrite.preview.DiagramUrlGenerator; | |
| 5 | import com.keenwrite.processors.Processor; | |
| 6 | import com.keenwrite.prImageImageImageImageImage |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.processors.markdown.extensions.fences.blocks; | |
| 1 | 3 | |
| 4 | import com.vladsch.flexmark.html.HtmlWriter; | |
| 5 | import com.vladsch.flexmark.util. closClosublic Closhtml.closeT |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.processors.markdown.extensions.fences.blocks; | |
| 3 | ||
| 4 | import com.vladsch.flexmark.html.HtmlWriter; | |
| 5 | import com.vladsch.flexmark.util.ast.Block; | |
| 6 | import com.vladsch.flexmark.util.sequence.BasedSequence; | |
| 7 | import org.jetbrains.annotations.NotNull; | |
| 8 | ||
| 9 | public abstract class DivBlock extends Block { | |
| 10 | static final CharSequence HTML_DIV = "div"; | |
| 11 | ||
| 12 | public DivBlock( final BasedSequence chars ) { | |
| 13 | super( chars ); | |
| 14 | } | |
| 15 | ||
| 16 | @Override | |
| 17 | @NotNull | |
| 18 | public BasedSequence[] getSegments() { | |
| 19 | return EMPTY_SEGMENTS; | |
| 20 | } | |
| 21 | ||
| 22 | /** | |
| 23 | * Append an opening or closing HTML div element to the given writer. | |
| 24 | * | |
| 25 | * @param html Builds the HTML document to be written. | |
| 26 | */ | |
| 27 | public abstract void write( HtmlWriter html ); | |
| 28 | } | |
| 1 | 29 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.processors.markdown.extensions.fences.blocks; | |
| 3 | ||
| 4 | import com.vladsch.flexmark.html.HtmlWriter; | |
| 5 | import com.vladsch.flexmark.util.html.Attribute; | |
| 6 | import com.vladsch.flexmark.util.sequence.BasedSequence; | |
| 7 | ||
| 8 | import java.util.ArrayList; | |
| 9 | import java.util.List; | |
| 10 | ||
| 11 | /** | |
| 12 | * Responsible for helping to generate an opening {@code div} element. | |
| 13 | */ | |
| 14 | public final class OpeningDivBlock extends DivBlock { | |
| 15 | private final List<Attribute> mAttributes = new ArrayList<>(); | |
| 16 | ||
| 17 | public OpeningDivBlock( final BasedSequence chars, | |
| 18 | final List<Attribute> attrs ) { | |
| 19 | super( chars ); | |
| 20 | assert attrs != null; | |
| 21 | mAttributes.addAll( attrs ); | |
| 22 | } | |
| 23 | ||
| 24 | @Override | |
| 25 | public void write( final HtmlWriter html ) { | |
| 26 | mAttributes.forEach( html::attr ); | |
| 27 | html.withAttr().tag( HTML_DIV ); | |
| 28 | } | |
| 29 | } | |
| 1 | 30 |
| 1 | /* Copyright 2024 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.processors.markdown.extensions.fences.factories; | |
| 6 | ||
| 7 | import com.keenwrite.processors.markdown.extensions.common.MarkdownCustomn instance of {@link}. | |
| 8 | */ | |
| 9 | public class Custom | |
| 10 | extends MarkdownCustomBlockParserFactory { | |
| 11 | @Override | |
| 12 | public BlockParserFactory createBlockParserFactory( | |
| 13 | final DataHreturn new( options ); | |
| 14 | } | |
| 15 | } | |
| 1 | 16 |
| 1 | /* Copyright 2024 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.processors.markdown.extensions.fences.factories; | |
| 6 | ||
| 7 | import com.keenwrite.processors.markdown.extensions.fences.parsers.ClosingParser; | |
| 8 | import com.keenwrite.processors.markdown.extensions.fences.parsers.OpeningParser; | |
| 9 | import com.vladsch.flexmark.parser.block.AbstractBlockParserFactory; | |
| 10 | import com.vladsch.flexmark.parser.block.BlockStart; | |
| 11 | import com.vladsch.flexmark.parser.block.MatchedBlockParser; | |
| 12 | import com.vladsch.flexmark.parser.block.ParserState; | |
| 13 | import com.vladsch.flexmark.util.data.DataHolder; | |
| 14 | ||
| 15 | import static com.keenwrite.processors.markdown.extensions.fences.FencedDivExtension.FENCE; | |
| 16 | import static com.keenwrite.processors.markdown.extensions.fences.FencedDivExtension.FENCE_OPENING; | |
| 17 | ||
| 18 | /** | |
| 19 | * Responsible for creating a fenced div parser that is appropriate for the | |
| 20 | * type of fenced div encountered: opening or closing. | |
| 21 | */ | |
| 22 | public class DivBlockParserFactory extends AbstractBlockParserFactory { | |
| 23 | public DivBlockParserFactory( final DataHolder options ) { | |
| 24 | super( options ); | |
| 25 | } | |
| 26 | ||
| 27 | /** | |
| 28 | * Try to match an opening or closing fenced div. | |
| 29 | * | |
| 30 | * @param state Block parser state. | |
| 31 | * @param blockParser Last matched open block parser. | |
| 32 | * @return Wrapper for the opening or closing parser, upon finding :::. | |
| 33 | */ | |
| 34 | @Override | |
| 35 | public BlockStart tryStart( | |
| 36 | final ParserState state, final MatchedBlockParser blockParser ) { | |
| 37 | return | |
| 38 | state.getIndent() == 0 && FENCE.matcher( state.getLine() ).matches() | |
| 39 | ? parseFence( state ) | |
| 40 | : BlockStart.none(); | |
| 41 | } | |
| 42 | ||
| 43 | /** | |
| 44 | * After finding a fenced div, this will further disambiguate an opening | |
| 45 | * from a closing fence. | |
| 46 | * | |
| 47 | * @param state Block parser state, contains line to parse. | |
| 48 | * @return Wrapper for the opening or closing parser, upon finding :::. | |
| 49 | */ | |
| 50 | private BlockStart parseFence( final ParserState state ) { | |
| 51 | final var line = state.getLine(); | |
| 52 | final var fence = FENCE_OPENING.matcher( line.trim() ); | |
| 53 | ||
| 54 | return BlockStart.of( | |
| 55 | fence.matches() | |
| 56 | ? new OpeningParser( fence.group( 1 ) ) | |
| 57 | : new ClosingParser( line ) | |
| 58 | ).atIndex( state.getIndex() ); | |
| 59 | } | |
| 60 | } | |
| 1 | 61 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.processors.markdown.extensions.fences.factories; | |
| 3 | ||
| 4 | import com.keenwrite.processors.markdown.extensions.common.MarkdownNodeRendererFactory; | |
| 5 | import com.keenwrite.processors.markdown.extensions.fences.renderers.FencedDivRendererhtml.renderer.NodeRendererpublic class FencedDivNodeRendererFactory extends MarkdownNodeRenderrotected NodeRenderer createNodeRenderer(FencedDivRenderer(); | |
| 6 | } | |
| 7 | } | |
| 1 | 8 |
| 1 | /* Copyright 2024 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.processors.markdown.extensions.fences.factories; | |
| 6 | ||
| 7 | import com.keenwrite.processors.markdown.extensions.fences.processors.FencedDivParagraphPreProcessor; | |
| 8 | import com.vladsch.flexmark.parser.block.ParagraphPreProcessor; | |
| 9 | import com.vladsch.flexmark.parser.block.ParagraphPreProcessorFactory; | |
| 10 | import com.vladsch.flexmark.parser.block.ParserState; | |
| 11 | import com.vladsch.flexmark.parser.core.ReferencePreProcessorFactory; | |
| 12 | import org.jetbrains.annotations.Nullable; | |
| 13 | ||
| 14 | import java.util.Set; | |
| 15 | ||
| 16 | public class FencedDivPreProcessorFactory | |
| 17 | implements ParagraphPreProcessorFactory { | |
| 18 | ||
| 19 | @Override | |
| 20 | public ParagraphPreProcessor apply( final ParserState state ) { | |
| 21 | return new FencedDivParagraphPreProcessor( state.getProperties() ); | |
| 22 | } | |
| 23 | ||
| 24 | @Override | |
| 25 | public @Nullable Set<Class<?>> getBeforeDependents() { | |
| 26 | return Set.of(); | |
| 27 | } | |
| 28 | ||
| 29 | @Override | |
| 30 | public @Nullable Set<Class<?>> getAfterDependents() { | |
| 31 | return Set.of( ReferencePreProcessorFactory.class ); | |
| 32 | } | |
| 33 | ||
| 34 | @Override | |
| 35 | public boolean affectsGlobalScope() { | |
| 36 | return false; | |
| 37 | } | |
| 38 | ||
| 39 | } | |
| 1 | 40 |
| 1 | /* Copyright 2024 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.processors.markdown.extensions.fences.parsers; | |
| 6 | ||
| 7 | import com.keenwrite.processors.markdown.extensions.fences.blocks.ClosingDivBClosClosprivate final ClosingDivBlock mBlock; | |
| 1 | 8 | |
| 9 | public ClosingParser( final BasedSequence line ) { | |
| 10 | mBlock = new ClosingDivBlock( line |
| 1 | /* Copyright 2024 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.processors.markdown.extensions.fences.parsers; | |
| 6 | ||
| 7 | import com.vladsch.flexmark.parser.block.AbstractBlockParser; | |
| 8 | import com.vladsch.flexmark.parser.block.BlockContinue; | |
| 9 | import com.vladsch.flexmark.parser.block.ParserState; | |
| 10 | ||
| 11 | /** | |
| 12 | * Abstracts common {@link OpeningParser} and | |
| 13 | * {@link ClosingParser} methods. | |
| 14 | */ | |
| 15 | public abstract class DivBlockParser extends AbstractBlockParser { | |
| 16 | @Override | |
| 17 | public BlockContinue tryContinue( final ParserState state ) { | |
| 18 | return BlockContinue.none(); | |
| 19 | } | |
| 20 | ||
| 21 | @Override | |
| 22 | public void closeBlock( final ParserState state ) {} | |
| 23 | } | |
| 1 | 24 |
| 1 | /* Copyright 2024 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.processors.markdown.extensions.fences.parsers; | |
| 1 | 6 | |
| 7 | import com.keenwrite.processors.markdown.extensions.fences.blocks.OpeningDivBSTR."data-\{}"; |
| 1 | /* Copyright 2024 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.processors.markdown.extensions.fences.processors; | |
| 6 | ||
| 7 | import com.keenwrite.processors.markdown.extensions.fences.parsers.ClosingParser; | |
| 8 | import com.keenwrite.processors.markdown.extensions.fences.parsers.OpeningParser; | |
| 9 | import com.vladsch.flexmark.ast.Paragraph; | |
| 10 | import com.vladsch.flexmark.parser.block.ParagraphPreProcessor; | |
| 11 | import com.vladsch.flexmark.parser.block.ParserState; | |
| 12 | import com.vladsch.flexmark.util.data.MutableDataHolder; | |
| 13 | import com.vladsch.flexmark.util.sequence.BasedSequence; | |
| 14 | ||
| 15 | import java.util.ArrayList; | |
| 16 | ||
| 17 | import static com.keenwrite.processors.markdown.extensions.fences.FencedDivExtension.FENCE; | |
| 18 | import static com.keenwrite.processors.markdown.extensions.fences.FencedDivExtension.FENCE_OPENING; | |
| 19 | ||
| 20 | public class FencedDivParagraphPreProcessor | |
| 21 | implements ParagraphPreProcessor { | |
| 22 | public FencedDivParagraphPreProcessor( final MutableDataHolder unused ) {} | |
| 23 | ||
| 24 | @Override | |
| 25 | public int preProcessBlock( final Paragraph block, | |
| 26 | final ParserState state ) { | |
| 27 | final var lines = block.getContentLines(); | |
| 28 | ||
| 29 | // Stores lines matching opening or closing fenced div sigil. | |
| 30 | final var sigilLines = new ArrayList<BasedSequence>(); | |
| 31 | ||
| 32 | for( final var line : lines ) { | |
| 33 | // Seeks a :::+ sigil. | |
| 34 | final var fence = FENCE.matcher( line ); | |
| 35 | ||
| 36 | if( fence.find() ) { | |
| 37 | // Attributes after the fence are required to detect an open fence. | |
| 38 | final var attrs = FENCE_OPENING.matcher( line.trim() ); | |
| 39 | final var match = attrs.matches(); | |
| 40 | ||
| 41 | final var parser = match | |
| 42 | ? new OpeningParser( attrs.group( 1 ) ) | |
| 43 | : new ClosingParser( line ); | |
| 44 | final var divBlock = parser.getBlock(); | |
| 45 | ||
| 46 | if( match ) { | |
| 47 | block.insertBefore( divBlock ); | |
| 48 | } | |
| 49 | else { | |
| 50 | block.insertAfter( divBlock ); | |
| 51 | } | |
| 52 | ||
| 53 | state.blockAdded( divBlock ); | |
| 54 | ||
| 55 | // Schedule the line for removal (because it has been handled). | |
| 56 | sigilLines.add( line ); | |
| 57 | } | |
| 58 | } | |
| 59 | ||
| 60 | sigilLines.forEach( lines::remove ); | |
| 61 | ||
| 62 | return 0; | |
| 63 | } | |
| 64 | } | |
| 1 | 65 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.processors.markdown.extensions.fences.renderers; | |
| 3 | ||
| 4 | import com.keenwrite.processors.markdown.extensions.fences.blocks.ClosingDivBlock; | |
| 5 | import com.keenwrite.processors.markdown.extensions.fences.blocks.DivBlock; | |
| 6 | import com.keenwrite.processors.markdown.extensions.fences.blocks.OpeningDivBlock; | |
| 7 | import com.vladsch.flexmark.html.HtmlWriter; | |
| 8 | import com.vladsch.flexmark.html.renderer.NodeRenderer; | |
| 9 | import com.vladsch.flexmark.html.renderer.NodeRendererContext; | |
| 10 | import com.vladsch.flexmark.html.renderer.NodeRenderingHandler; | |
| 11 | import org.jetbrains.annotations.Nullable; | |
| 12 | ||
| 13 | import java.util.Set; | |
| 14 | ||
| 15 | /** | |
| 16 | * Responsible for rendering opening and closing fenced div blocks as HTML | |
| 17 | * {@code div} elements. | |
| 18 | */ | |
| 19 | public class FencedDivRenderer implements NodeRenderer { | |
| 20 | @Nullable | |
| 21 | @Override | |
| 22 | public Set<NodeRenderingHandler<?>> getNodeRenderingHandlers() { | |
| 23 | return Set.of( | |
| 24 | new NodeRenderingHandler<>( OpeningDivBlock.class, this::render ), | |
| 25 | new NodeRenderingHandler<>( ClosingDivBlock.class, this::render ) | |
| 26 | ); | |
| 27 | } | |
| 28 | ||
| 29 | /** | |
| 30 | * Renders the fenced div block as an HTML {@code <div></div>} element. | |
| 31 | */ | |
| 32 | void render( | |
| 33 | final DivBlock node, | |
| 34 | final NodeRendererContext context, | |
| 35 | final HtmlWriter html ) { | |
| 36 | node.write( html ); | |
| 37 | } | |
| 38 | } | |
| 1 | 39 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.processors.markdown.extensions.images; | |
| 1 | 3 | |
| 4 | import com.keenwrite.ExportFormat; | |
| 5 | import com.keenwrite.processors.ProcessorContext; | |
| 6 | import com.keenwrite.processorscommonrivate ImageLinkResolver() { |
| 1 | package com.keenwrite.processors.markdown.extensions.outline; | |
| 1 | 2 | |
| 3 | import; | |
| 4 | import com.keenwrite.processors.Processor; | |
| 5 | import com.keenwrite.processors.markdown.extensions.common.MarkdownParserExtension; | |
| 6 | importast.Heading; | |
| 7 | import com.vladsch.flexmark.parser.Parser.Builder; | |
| 8 | import com.vladsch.flexmark.parser.MarkdownREGEXREGEXParseHeadingEvent.fire |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.processors.markdown.extensions.r; | |
| 3 | ||
| 4 | import com.keenwrite.processors.Processor; | |
| 5 | import com.keenwrite.processors.ProcessorContext; | |
| 6 | import com.keenwrite.processors.markdown.BaseMarkdownProcessor; | |
| 7 | import com.keenwrite.processors.markdown.extensions.common.MarkdownParserExtension; | |
| 8 | import com.keenwrite.processors.r.RInlineEvaluator; | |
| 9 | import com.vladsch.flexmark.ast.Paragraph; | |
| 10 | import com.vladsch.flexmark.parser.InlineParserExtensionFactory; | |
| 11 | import com.vladsch.flexmark.parser.delimiter.DelimiterProcessor; | |
| 12 | import com.vladsch.flexmark.parser.internal.InlineParserImpl; | |
| 13 | import com.vladsch.flexmark.parser.internal.LinkRefProcessorData; | |
| 14 | import com.vladsch.flexmark.util.data.DataHolder; | |
| 15 | ||
| 16 | import java.util.BitSet; | |
| 17 | import java.util.List; | |
| 18 | import java.util.Map; | |
| 19 | ||
| 20 | import static com.keenwrite.processors.html.IdentityProcessor.IDENTITY; | |
| 21 | import static com.vladsch.flexmark.parser.Parser.Builder; | |
| 22 | ||
| 23 | /** | |
| 24 | * Responsible for processing inline R statements (denoted using the | |
| 25 | * {@link RInlineEvaluator#PREFIX}) to prevent them from being converted to | |
| 26 | * HTML {@code <code>} elements and stop them from interfering with TeX | |
| 27 | * statements. Note that TeX statements are processed using a Markdown | |
| 28 | * extension, rather than an implementation of {@link Processor}. For this | |
| 29 | * reason, some pre-conversion is necessary. | |
| 30 | */ | |
| 31 | public final class RInlineExtension implements MarkdownParserExtension { | |
| 32 | private final RInlineEvaluator mEvaluator; | |
| 33 | private final BaseMarkdownProcessor mMarkdownProcessor; | |
| 34 | ||
| 35 | private RInlineExtension( | |
| 36 | final RInlineEvaluator evaluator, | |
| 37 | final ProcessorContext context ) { | |
| 38 | mEvaluator = evaluator; | |
| 39 | mMarkdownProcessor = new BaseMarkdownProcessor( IDENTITY, context ); | |
| 40 | } | |
| 41 | ||
| 42 | /** | |
| 43 | * Creates an extension capable of intercepting R code blocks and preventing | |
| 44 | * them from being converted into HTML {@code <code>} elements. | |
| 45 | */ | |
| 46 | public static RInlineExtension create( | |
| 47 | final RInlineEvaluator evaluator, | |
| 48 | final ProcessorContext context ) { | |
| 49 | return new RInlineExtension( evaluator, context ); | |
| 50 | } | |
| 51 | ||
| 52 | @Override | |
| 53 | public void extend( final Builder builder ) { | |
| 54 | builder.customInlineParserFactory( InlineParser::new ); | |
| 55 | } | |
| 56 | ||
| 57 | /** | |
| 58 | * Prevents rendering {@code `r} statements as inline HTML {@code <code>} | |
| 59 | * blocks, which allows the {@link RInlineEvaluator} to post-process the | |
| 60 | * text prior to display in the preview pane. This intervention assists | |
| 61 | * with decoupling the caret from the Markdown content so that the two | |
| 62 | * can vary independently in the architecture while permitting synchronization | |
| 63 | * of the editor and preview pane. | |
| 64 | * <p> | |
| 65 | * The text is therefore processed twice: once by flexmark-java and once by | |
| 66 | * {@link RInlineEvaluator}. | |
| 67 | * </p> | |
| 68 | */ | |
| 69 | private final class InlineParser extends InlineParserImpl { | |
| 70 | private InlineParser( | |
| 71 | final DataHolder options, | |
| 72 | final BitSet specialCharacters, | |
| 73 | final BitSet delimiterCharacters, | |
| 74 | final Map<Character, DelimiterProcessor> delimiterProcessors, | |
| 75 | final LinkRefProcessorData referenceLinkProcessors, | |
| 76 | final List<InlineParserExtensionFactory> inlineParserExtensions ) { | |
| 77 | super( | |
| 78 | options, | |
| 79 | specialCharacters, | |
| 80 | delimiterCharacters, | |
| 81 | delimiterProcessors, | |
| 82 | referenceLinkProcessors, | |
| 83 | inlineParserExtensions | |
| 84 | ); | |
| 85 | } | |
| 86 | ||
| 87 | /** | |
| 88 | * The superclass handles a number backtick parsing edge cases; this method | |
| 89 | * changes the behaviour to retain R code snippets, identified by | |
| 90 | * {@link RInlineEvaluator#PREFIX}, so that subsequent processing can | |
| 91 | * invoke R. If other languages are added, the {@link InlineParser} will | |
| 92 | * have to be rewritten to identify more than merely R. | |
| 93 | * | |
| 94 | * @return The return value from {@link super#parseBackticks()}. | |
| 95 | * @inheritDoc | |
| 96 | */ | |
| 97 | @Override | |
| 98 | protected boolean parseBackticks() { | |
| 99 | final var foundTicks = super.parseBackticks(); | |
| 100 | ||
| 101 | if( foundTicks ) { | |
| 102 | final var blockNode = getBlock(); | |
| 103 | final var codeNode = blockNode.getLastChild(); | |
| 104 | ||
| 105 | if( codeNode != null ) { | |
| 106 | final var code = codeNode.getChars().toString(); | |
| 107 | ||
| 108 | if( mEvaluator.test( code ) ) { | |
| 109 | codeNode.unlink(); | |
| 110 | ||
| 111 | final var rText = mEvaluator.apply( code ); | |
| 112 | var node = mMarkdownProcessor.toNode( rText ); | |
| 113 | ||
| 114 | if( node.getFirstChild() instanceof Paragraph paragraph ) { | |
| 115 | node = paragraph.getFirstChild(); | |
| 116 | } | |
| 117 | ||
| 118 | if( node != null ) { | |
| 119 | blockNode.appendChild( node ); | |
| 120 | } | |
| 121 | } | |
| 122 | } | |
| 123 | } | |
| 124 | ||
| 125 | return foundTicks; | |
| 126 | } | |
| 127 | } | |
| 128 | } | |
| 1 | 129 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.processors.markdown.extensions.references; | |
| 6 | parser.InlineParser; | |
| 7 | import com.vladsch.flexmark.parser.core.delimiter.Delimiter; | |
| 8 | import coimport static com.keenwrite.constants.Constants.DEF_DELIM_BEGAN_DEFAULT; | |
| 9 | ||
| 10 | /** | |
| 11 | * Responsible for processing {@code {@type:id}} anchors. | |
| 12 | */ | |
| 13 | class AnchorNam | |
| 14 | AnchorNameNode({'}' | |
| 15 | text = opener.getNode(); | |
| 1 | 16 | |
| 17 | // Ensure that the default delimiters are respected (not clobbered by | |
| 18 | // transforming them into anchor links). | |
| 19 | return text.getChars().toString().equals( DEF_DELIM_BEGAN_DEFAULT ) ? 0 : 1 | |
| 20 | canBeOpener( | |
| 21 | ||
| 22 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.processors.markdown.extensions.references; | |
| 6 | ||
| 7 | import com.vladsch.flexmark.ast.DelimitedNodeImpl; | |
| 8 | import com.vladsch.flexmark.util.sequence.BasedSequence; | |
| 9 | import org.jetbrains.annotations.NotNull; | |
| 10 | ||
| 11 | /** | |
| 12 | * Responsible for writing HTML anchor names in the form | |
| 13 | * {@code <a data-type="..." name="name" />}, where {@code name} can be | |
| 14 | * referred to by a cross-reference. | |
| 15 | * | |
| 16 | * @see AnchorXrefNode | |
| 17 | */ | |
| 18 | public class AnchorNameNode extends DelimitedNodeImpl implements CrossReferenceNode { | |
| 19 | ||
| 20 | private BasedSequence mOpeningMarker = BasedSequence.EMPTY; | |
| 21 | private BasedSequence mClosingMarker = BasedSequence.EMPTY; | |
| 22 | ||
| 23 | private BasedSequenceNameParser mParser; | |
| 24 | ||
| 25 | public AnchorNameNode() {} | |
| 26 | ||
| 27 | @Override | |
| 28 | public String getTypeName() { | |
| 29 | return mParser.getTypeName(); | |
| 30 | } | |
| 31 | ||
| 32 | @Override | |
| 33 | public String getIdName() { | |
| 34 | return mParser.getIdName(); | |
| 35 | } | |
| 36 | ||
| 37 | @Override | |
| 38 | public String getRefAttrName() { | |
| 39 | return "name"; | |
| 40 | } | |
| 41 | ||
| 42 | @Override | |
| 43 | public BasedSequence getOpeningMarker() { | |
| 44 | return mOpeningMarker; | |
| 45 | } | |
| 46 | ||
| 47 | @NotNull | |
| 48 | @Override | |
| 49 | public BasedSequence getChars() { | |
| 50 | return BasedSequence.EMPTY; | |
| 51 | } | |
| 52 | ||
| 53 | @Override | |
| 54 | public void setOpeningMarker( final BasedSequence openingMarker ) { | |
| 55 | mOpeningMarker = openingMarker; | |
| 56 | } | |
| 57 | ||
| 58 | @Override | |
| 59 | public BasedSequence getText() { | |
| 60 | return BasedSequence.EMPTY; | |
| 61 | } | |
| 62 | ||
| 63 | @Override | |
| 64 | public void setText( final BasedSequence text ) { | |
| 65 | mParser = BasedSequenceNameParser.parse( text ); | |
| 66 | } | |
| 67 | ||
| 68 | @Override | |
| 69 | public BasedSequence getClosingMarker() { | |
| 70 | return mClosingMarker; | |
| 71 | } | |
| 72 | ||
| 73 | @Override | |
| 74 | public void setClosingMarker( final BasedSequence closingMarker ) { | |
| 75 | mClosingMarker = closingMarker; | |
| 76 | } | |
| 77 | } | |
| 1 | 78 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.processors.markdown.extensions.references; | |
| 6 | ||
| 7 | import com.vladsch.flexmark.util.ast.Node; | |
| 8 | import com.vladsch.flexmark.util.sequence.BasedSequence; | |
| 9 | import org.jetbrains.annotations.NotNull; | |
| 10 | ||
| 11 | /** | |
| 12 | * Responsible for writing HTML anchor cross-references in the form | |
| 13 | * {@code <a data-type="..." href="#name" />} where {@code name} refers | |
| 14 | * to an anchor name. | |
| 15 | * | |
| 16 | * @see AnchorNameNode | |
| 17 | */ | |
| 18 | public class AnchorXrefNode extends Node implements CrossReferenceNode { | |
| 19 | private final String mTypeName; | |
| 20 | private final String mIdName; | |
| 21 | ||
| 22 | AnchorXrefNode( final String type, final String id ) { | |
| 23 | mTypeName = type; | |
| 24 | mIdName = STR. "#\{ id }" ; | |
| 25 | } | |
| 26 | ||
| 27 | @Override | |
| 28 | public String getTypeName() { | |
| 29 | return mTypeName; | |
| 30 | } | |
| 31 | ||
| 32 | @Override | |
| 33 | public String getIdName() { | |
| 34 | return mIdName; | |
| 35 | } | |
| 36 | ||
| 37 | @Override | |
| 38 | public String getRefAttrName() { | |
| 39 | return "href"; | |
| 40 | } | |
| 41 | ||
| 42 | @NotNull | |
| 43 | @Override | |
| 44 | public BasedSequence[] getSegments() { | |
| 45 | return BasedSequence.EMPTY_SEGMENTS; | |
| 46 | } | |
| 47 | } | |
| 1 | 48 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.processors.markdown.extensions.references; | |
| 6 | ||
| 7 | import com.vladsch.flexmark.parser.LinkRefProcessor; | |
| 8 | import com.vladsch.flexmark.parser.LinkRefProcessorFactory; | |
| 9 | import com.vladsch.flexmark.util.ast.Document; | |
| 10 | import com.vladsch.flexmark.util.ast.Node; | |
| 11 | import com.vladsch.flexmark.util.data.DataHolder; | |
| 12 | import com.vladsch.flexmark.util.sequence.BasedSequence; | |
| 13 | import org.jetbrains.annotations.NotNull; | |
| 14 | ||
| 15 | /** | |
| 16 | * Responsible for processing {@code [@type:id]} anchors. | |
| 17 | */ | |
| 18 | class AnchorXrefProcessorFactory implements LinkRefProcessorFactory { | |
| 19 | private final LinkRefProcessor mProcessor = new AnchorLinkRefProcessor(); | |
| 20 | ||
| 21 | @Override | |
| 22 | public boolean getWantExclamationPrefix( @NotNull final DataHolder options ) { | |
| 23 | return false; | |
| 24 | } | |
| 25 | ||
| 26 | @Override | |
| 27 | public int getBracketNestingLevel( @NotNull final DataHolder options ) { | |
| 28 | return 0; | |
| 29 | } | |
| 30 | ||
| 31 | @NotNull | |
| 32 | @Override | |
| 33 | public LinkRefProcessor apply( @NotNull final Document document ) { | |
| 34 | return mProcessor; | |
| 35 | } | |
| 36 | ||
| 37 | private static class AnchorLinkRefProcessor implements LinkRefProcessor { | |
| 38 | ||
| 39 | @Override | |
| 40 | public boolean getWantExclamationPrefix() { | |
| 41 | return false; | |
| 42 | } | |
| 43 | ||
| 44 | @Override | |
| 45 | public int getBracketNestingLevel() { | |
| 46 | return 0; | |
| 47 | } | |
| 48 | ||
| 49 | @Override | |
| 50 | public boolean isMatch( @NotNull final BasedSequence nodeChars ) { | |
| 51 | return nodeChars.indexOf( '@' ) == 1; | |
| 52 | } | |
| 53 | ||
| 54 | @NotNull | |
| 55 | @Override | |
| 56 | public Node createNode( @NotNull final BasedSequence nodeChars ) { | |
| 57 | return BasedSequenceXrefParser.parse( nodeChars ).toNode(); | |
| 58 | } | |
| 59 | ||
| 60 | @NotNull | |
| 61 | @Override | |
| 62 | public BasedSequence adjustInlineText( | |
| 63 | @NotNull final Document document, | |
| 64 | @NotNull final Node node ) { | |
| 65 | return BasedSequence.EMPTY; | |
| 66 | } | |
| 67 | ||
| 68 | @Override | |
| 69 | public boolean allowDelimiters( | |
| 70 | @NotNull final BasedSequence chars, | |
| 71 | @NotNull final Document document, | |
| 72 | @NotNull final Node node ) { | |
| 73 | return false; | |
| 74 | } | |
| 75 | ||
| 76 | @Override | |
| 77 | public void updateNodeElements( | |
| 78 | @NotNull final Document document, | |
| 79 | @NotNull final Node node ) {} | |
| 80 | } | |
| 81 | } | |
| 1 | 82 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.processors.markdown.extensions.references; | |
| 6 | ||
| 7 | import com.vladsch.flexmark.util.seque | |
| 8 | @Override | |
| 9 | Pattern getPattern() { | |
| 10 | return PATTERN; | |
| 11 | } | |
| 12 | } | |
| 1 | 13 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.processors.markdown.extensions.references; | |
| 6 | ||
| 7 | import java.util.regex.Matcher; | |
| 8 | import java.util.regex.Pattern; | |
| 9 | ||
| 10 | import static java.util.regex.Pattern.UNICODE_CHARACTER_CLASS; | |
| 11 | ||
| 12 | abstract class BasedSequenceParser { | |
| 13 | /** | |
| 14 | * Shared syntax between subclasses: a letter followed by zero or more | |
| 15 | * alphanumeric characters. | |
| 16 | */ | |
| 17 | static final String REGEX_INNER = | |
| 18 | "(\\p{Alpha}[\\p{Alnum}-_]+):(\\p{Alpha}[\\p{Alnum}-_]+)"; | |
| 19 | ||
| 20 | private final String mTypeName; | |
| 21 | private final String mIdName; | |
| 22 | ||
| 23 | BasedSequenceParser( final String text ) { | |
| 24 | final var matcher = createMatcher( text ); | |
| 25 | ||
| 26 | if( matcher.find() ) { | |
| 27 | mTypeName = matcher.group( 1 ); | |
| 28 | mIdName = matcher.group( 2 ); | |
| 29 | } | |
| 30 | else { | |
| 31 | mTypeName = null; | |
| 32 | mIdName = null; | |
| 33 | } | |
| 34 | } | |
| 35 | ||
| 36 | static Pattern asPattern( final String regex ) { | |
| 37 | return Pattern.compile( regex, UNICODE_CHARACTER_CLASS ); | |
| 38 | } | |
| 39 | ||
| 40 | abstract Pattern getPattern(); | |
| 41 | ||
| 42 | /** | |
| 43 | * Creates a regular expression pattern matcher that can extract the | |
| 44 | * reference elements from text. | |
| 45 | * | |
| 46 | * @param text The text containing an anchor or cross-reference to an anchor. | |
| 47 | * @return The {@link Matcher} to use when extracting the text elements. | |
| 48 | */ | |
| 49 | Matcher createMatcher( final String text ) { | |
| 50 | return getPattern().matcher( text ); | |
| 51 | } | |
| 52 | ||
| 53 | String getTypeName() { | |
| 54 | return mTypeName; | |
| 55 | } | |
| 56 | ||
| 57 | String getIdName() { | |
| 58 | return mIdName; | |
| 59 | } | |
| 60 | } | |
| 1 | 61 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.processors.markdown.extensions.references; | |
| 1 | 6 | |
| 7 | import com.vladsch.flexmark.util.ast.Node; | |
| 8 | import com.vladsch.flexmark.util.sequecommonPattern getPattern() { | |
| 9 | return PATTERN |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.processors.markdown.extensions.references; | |
| 6 | ||
| 7 | import com.keenwrite.processors.markdown.extensions.common.MarkdownRenderhtml.renderer.NodeRendererFactoryBuilderfinalMarkdownRendererExtension { | |
| 8 | /** | |
| 9 | * Use {@link #create()}. | |
| 10 | */ | |
| 11 | private() {} | |
| 12 | ||
| 13 | /** | |
| 14 | * Returns a new {@link}. | |
| 15 | * | |
| 16 | * @return An extension capable of parsing cross-reference syntax. | |
| 17 | */ | |
| 18 | public staticcreate() { | |
| 19 | return(); | |
| 20 | }rotected NodeRendererFactory createNodeRendererFactory() { | |
| 21 | returnFactory(); | |
| 22 | } | |
| 23 | } | |
| 1 | 24 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.processors.markdown.extensions.references; | |
| 6 | ||
| 7 | import com.vladsch.flexmark.html.HtmlWriter; | |
| 8 | ||
| 9 | /** | |
| 10 | * Responsible for generating anchor links, either named or cross-referenced. | |
| 11 | */ | |
| 12 | public interface CrossReferenceNode { | |
| 13 | String getTypeName(); | |
| 14 | ||
| 15 | String getIdName(); | |
| 16 | ||
| 17 | String getRefAttrName(); | |
| 18 | ||
| 19 | /** | |
| 20 | * Writes the HTML representation for this cross-reference node. | |
| 21 | * | |
| 22 | * @param html The HTML tag is written to the {@link HtmlWriter}. | |
| 23 | */ | |
| 24 | default void write( final HtmlWriter html ) { | |
| 25 | final var type = getTypeName(); | |
| 26 | final var id = getIdName(); | |
| 27 | final var attr = getRefAttrName(); | |
| 28 | ||
| 29 | final var clazz = STR. "class=\"\{ attr }\"" ; | |
| 30 | final var dataType = STR. "data-type=\"\{ type }\"" ; | |
| 31 | final var refId = STR. "\{ attr }=\"\{ id }\"" ; | |
| 32 | ||
| 33 | html.raw( STR. "<a \{ clazz } \{ dataType } \{ refId } />" ); | |
| 34 | } | |
| 35 | } | |
| 1 | 36 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.processors.markdown.extensions.references; | |
| 6 | ||
| 7 | import com.vladHtmlWriter; | |
| 8 | import com.vladsch.flexmark.html.renderer.NodeRenderer; | |
| 9 | import com.vlad | |
| 10 | import java.util.Arrays; | |
| 11 | import java.util.HashSet;HTML elements that correspond to cross-references. | |
| 12 | */ | |
| 13 | class CrossReferencesNodenew HashSet<>( Arrays.asListAnchorNameNodeAnchorXrefNode ); | |
| 14 | } | |
| 1 | 15 | |
| 16 | private void render( | |
| 17 | final CrossReferenceNode |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.processors.markdown.extensions.references; | |
| 1 | 6 | |
| 7 | import com.keenwrite.processors.markdown.extensions.common.Markdownh; | |
| 8 | import com.vladsch.flexmark.hextends MarkdownNodeRendererFactory { | |
| 9 | @Override | |
| 10 | protected NodeRenderer createNodeRenderer( |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.processors.markdown.extensions.tex; | |
| 3 | ||
| 4 | import com.keenwrite.ExportFormat; | |
| 5 | import com.keenwrite.processors.ProcessorContext; | |
| 6 | import com.keenwrite.processors.markdown.extensions.common.MarkdownRendererExtension; | |
| 7 | import com.keenwrite.processors.markdown.extensions.tex.TexNodeRenderer.TexNodeRendererFactory; | |
| 8 | import com.vladsch.flexmark.html.renderer.NodeRendererFactory; | |
| 9 | import com.vladsch.flexmark.parser.Parser; | |
| 10 | ||
| 11 | import java.util.function.Function; | |
| 12 | ||
| 13 | /** | |
| 14 | * Responsible for wrapping delimited TeX code in Markdown into an XML element | |
| 15 | * that the HTML renderer can handle. For example, {@code $E=mc^2$} becomes | |
| 16 | * {@code <tex>E=mc^2</tex>} when passed to HTML renderer. The HTML renderer | |
| 17 | * is responsible for converting the TeX code for display. This avoids inserting | |
| 18 | * SVG code into the Markdown document, which the parser would then have to | |
| 19 | * iterate---a <em>very</em> wasteful operation that impacts front-end | |
| 20 | * performance. | |
| 21 | */ | |
| 22 | public class TexExtension extends MarkdownRendererExtension { | |
| 23 | /** | |
| 24 | * Responsible for pre-parsing the input. | |
| 25 | */ | |
| 26 | private final Function<String, String> mEvaluator; | |
| 27 | ||
| 28 | /** | |
| 29 | * Controls how the node renderer produces TeX code within HTML output. | |
| 30 | */ | |
| 31 | private final ExportFormat mExportFormat; | |
| 32 | ||
| 33 | private TexExtension( | |
| 34 | final Function<String, String> evaluator, | |
| 35 | final ProcessorContext context ) { | |
| 36 | mEvaluator = evaluator; | |
| 37 | mExportFormat = context.getExportFormat(); | |
| 38 | } | |
| 39 | ||
| 40 | /** | |
| 41 | * Creates an extension capable of handling delimited TeX code in Markdown. | |
| 42 | * | |
| 43 | * @return The new {@link TexExtension}, never {@code null}. | |
| 44 | */ | |
| 45 | public static TexExtension create( | |
| 46 | final Function<String, String> evaluator, final ProcessorContext context ) { | |
| 47 | return new TexExtension( evaluator, context ); | |
| 48 | } | |
| 49 | ||
| 50 | /** | |
| 51 | * Creates the TeX {@link NodeRendererFactory} for HTML document export types. | |
| 52 | */ | |
| 53 | @Override | |
| 54 | public NodeRendererFactory createNodeRendererFactory() { | |
| 55 | return new TexNodeRendererFactory( mExportFormat, mEvaluator ); | |
| 56 | } | |
| 57 | ||
| 58 | @Override | |
| 59 | public void extend( final Parser.Builder builder ) { | |
| 60 | builder.customDelimiterProcessor( new TexInlineDelimiterProcessor() ); | |
| 61 | } | |
| 62 | } | |
| 1 | 63 |
| 1 | ||
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.processors.markdown.extensions.tex; | |
| 3 | parser.core.delimiter.Delimiter; | |
| 4 | sch.flexmark.parser.core.delimiter.Delimiter; | |
| 5 | class TexInlinTexNode( opener, closer $$/** | |
| 6 | * Allow for $ or $$. | |
| 7 | * | |
| 8 | * @param opener One or more opening delimiter characters. | |
| 9 | * @param closer One or more closing delimiter characters. | |
| 10 | * @return The number of delimiters to use to determine whether a valid | |
| 11 | * opening delimiter expression is found. | |
| 12 | */ |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.processors.markdown.extensions.tex; | |
| 3 | ||
| 4 | import com.vladsch.flexmark.ast.DelimitedNodeImpl; | |
| 5 | import com.vladsch.flexmark.parser.core.delimiter.Delimiter; | |
| 6 | ||
| 7 | public class TexNode extends DelimitedNodeImpl { | |
| 8 | /** | |
| 9 | * A TeX expression wrapped in a {@code <tex>} element. | |
| 10 | */ | |
| 11 | public static final String HTML_TEX = "tex"; | |
| 12 | ||
| 13 | static final String TOKEN_OPEN = "$"; | |
| 14 | static final String TOKEN_CLOSE = "$"; | |
| 15 | ||
| 16 | private final String mOpener; | |
| 17 | private final String mCloser; | |
| 18 | ||
| 19 | /** | |
| 20 | * Creates a new TeX node representation that can distinguish between '$' | |
| 21 | * and '$$' as opening/closing delimiters. The '$' is used for inline | |
| 22 | * TeX statements and '$$' is used for multi-line statements. | |
| 23 | * | |
| 24 | * @param opener The opening delimiter. | |
| 25 | * @param closer The closing delimiter. | |
| 26 | */ | |
| 27 | public TexNode( final Delimiter opener, final Delimiter closer ) { | |
| 28 | mOpener = getDelimiter( opener ); | |
| 29 | mCloser = getDelimiter( closer ); | |
| 30 | } | |
| 31 | ||
| 32 | /** | |
| 33 | * @return Either '$' or '$$'. | |
| 34 | */ | |
| 35 | public String getOpeningDelimiter() { | |
| 36 | return mOpener; | |
| 37 | } | |
| 38 | ||
| 39 | /** | |
| 40 | * @return Either '$' or '$$'. | |
| 41 | */ | |
| 42 | public String getClosingDelimiter() { | |
| 43 | return mCloser; | |
| 44 | } | |
| 45 | ||
| 46 | private String getDelimiter( final Delimiter delimiter ) { | |
| 47 | return delimiter.getInput().subSequence( | |
| 48 | delimiter.getStartIndex(), delimiter.getEndIndex() | |
| 49 | ).toString(); | |
| 50 | } | |
| 51 | } | |
| 1 | 52 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.processors.markdown.extensions.tex; | |
| 3 | ||
| 4 | import com.keenwrite.ExportFormat; | |
| 5 | import com.keenwrite.preview.MathRenderer; | |
| 6 | import com.keenwrite.preview.SvgRasterizer; | |
| 7 | import com.vladsch.flexmark.html.HtmlWriter; | |
| 8 | import com.vladsch.flexmark.html.renderer.NodeRenderer; | |
| 9 | import com.vladsch.flexmark.html.renderer.NodeRendererContext; | |
| 10 | import com.vladsch.flexmark.html.renderer.NodeRendererFactory; | |
| 11 | import com.vladsch.flexmark.html.renderer.NodeRenderingHandler; | |
| 12 | import com.vladsch.flexmark.util.ast.Node; | |
| 13 | import com.vladsch.flexmark.util.data.DataHolder; | |
| 14 | import org.jetbrains.annotations.NotNull; | |
| 15 | import org.jetbrains.annotations.Nullable; | |
| 16 | ||
| 17 | import java.util.Map; | |
| 18 | import java.util.Set; | |
| 19 | import java.util.function.Function; | |
| 20 | ||
| 21 | import static com.keenwrite.ExportFormat.*; | |
| 22 | import static com.keenwrite.processors.markdown.extensions.tex.TexNode.*; | |
| 23 | ||
| 24 | public class TexNodeRenderer { | |
| 25 | private static final RendererFacade RENDERER = | |
| 26 | new TexElementNodeRenderer( false ); | |
| 27 | ||
| 28 | private static final Map<ExportFormat, RendererFacade> EXPORT_RENDERERS = | |
| 29 | Map.of( | |
| 30 | APPLICATION_PDF, new TexElementNodeRenderer( true ), | |
| 31 | HTML_TEX_SVG, new TexSvgNodeRenderer(), | |
| 32 | HTML_TEX_DELIMITED, new TexDelimitedNodeRenderer(), | |
| 33 | XHTML_TEX, new TexElementNodeRenderer( true ), | |
| 34 | TEXT_TEX, new TexElementNodeRenderer( true ), | |
| 35 | NONE, RENDERER | |
| 36 | ); | |
| 37 | ||
| 38 | public static class TexNodeRendererFactory implements NodeRendererFactory { | |
| 39 | private final RendererFacade mNodeRenderer; | |
| 40 | ||
| 41 | public TexNodeRendererFactory( | |
| 42 | final ExportFormat exportFormat, | |
| 43 | final Function<String, String> evaluator ) { | |
| 44 | final var format = exportFormat == null ? NONE : exportFormat; | |
| 45 | ||
| 46 | mNodeRenderer = EXPORT_RENDERERS.getOrDefault( format, RENDERER ); | |
| 47 | mNodeRenderer.setEvaluator( evaluator ); | |
| 48 | } | |
| 49 | ||
| 50 | @NotNull | |
| 51 | @Override | |
| 52 | public NodeRenderer apply( @NotNull final DataHolder options ) { | |
| 53 | return mNodeRenderer; | |
| 54 | } | |
| 55 | } | |
| 56 | ||
| 57 | private static abstract class RendererFacade | |
| 58 | implements NodeRenderer { | |
| 59 | private Function<String, String> mEvaluator; | |
| 60 | ||
| 61 | @Override | |
| 62 | public @Nullable Set<NodeRenderingHandler<?>> getNodeRenderingHandlers() { | |
| 63 | return Set.of( | |
| 64 | new NodeRenderingHandler<>( TexNode.class, this::render ) | |
| 65 | ); | |
| 66 | } | |
| 67 | ||
| 68 | /** | |
| 69 | * Subclasses implement this method to render the content of {@link TexNode} | |
| 70 | * instances as per their associated {@link ExportFormat}. | |
| 71 | * | |
| 72 | * @param node {@link Node} containing text content of a math formula. | |
| 73 | * @param context Configuration information (unused). | |
| 74 | * @param html Where to write the rendered output. | |
| 75 | */ | |
| 76 | abstract void render( final TexNode node, | |
| 77 | final NodeRendererContext context, | |
| 78 | final HtmlWriter html ); | |
| 79 | ||
| 80 | private void setEvaluator( final Function<String, String> evaluator ) { | |
| 81 | mEvaluator = evaluator; | |
| 82 | } | |
| 83 | ||
| 84 | Function<String, String> getEvaluator() { | |
| 85 | return mEvaluator; | |
| 86 | } | |
| 87 | } | |
| 88 | ||
| 89 | /** | |
| 90 | * Responsible for rendering a TeX node as an HTML {@code <tex>} | |
| 91 | * element. This is the default behaviour. | |
| 92 | */ | |
| 93 | private static class TexElementNodeRenderer extends RendererFacade { | |
| 94 | private final boolean mIncludeDelimiter; | |
| 95 | ||
| 96 | private TexElementNodeRenderer( final boolean includeDelimiter ) { | |
| 97 | mIncludeDelimiter = includeDelimiter; | |
| 98 | } | |
| 99 | ||
| 100 | void render( final TexNode node, | |
| 101 | final NodeRendererContext context, | |
| 102 | final HtmlWriter html ) { | |
| 103 | final var text = getEvaluator().apply( node.getText().toString() ); | |
| 104 | final var content = | |
| 105 | mIncludeDelimiter | |
| 106 | ? node.getOpeningDelimiter() + text + node.getClosingDelimiter() | |
| 107 | : text; | |
| 108 | html.tag( HTML_TEX ); | |
| 109 | html.raw( content ); | |
| 110 | html.closeTag( HTML_TEX ); | |
| 111 | } | |
| 112 | } | |
| 113 | ||
| 114 | /** | |
| 115 | * Responsible for rendering a TeX node as an HTML {@code <svg>} | |
| 116 | * element. | |
| 117 | */ | |
| 118 | private static class TexSvgNodeRenderer extends RendererFacade { | |
| 119 | void render( final TexNode node, | |
| 120 | final NodeRendererContext context, | |
| 121 | final HtmlWriter html ) { | |
| 122 | final var tex = node.getText().toStringOrNull(); | |
| 123 | final var doc = MathRenderer.toDocument( | |
| 124 | tex == null ? "" : getEvaluator().apply( tex ) | |
| 125 | ); | |
| 126 | final var svg = SvgRasterizer.toSvg( doc.getDocumentElement() ); | |
| 127 | html.raw( svg ); | |
| 128 | } | |
| 129 | } | |
| 130 | ||
| 131 | /** | |
| 132 | * Responsible for rendering a TeX node as text bracketed by $ tokens. | |
| 133 | */ | |
| 134 | private static class TexDelimitedNodeRenderer extends RendererFacade { | |
| 135 | void render( final TexNode node, | |
| 136 | final NodeRendererContext context, | |
| 137 | final HtmlWriter html ) { | |
| 138 | html.raw( TOKEN_OPEN ); | |
| 139 | html.raw( getEvaluator().apply( node.getText().toString() ) ); | |
| 140 | html.raw( TOKEN_CLOSE ); | |
| 141 | } | |
| 142 | } | |
| 143 | } | |
| 1 | 144 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.processors.pdf; | |
| 3 | ||
| 4 | import com.keenwrite.processors.ExecutorProcessor; | |
| 5 | import com.keenwrite.processors.ProcessorContext; | |
| 6 | import com.keenwrite.typesetting.Typesetter; | |
| 7 | ||
| 8 | import static com.keenwrite.Bootstrap.APP_TITLE_ABBR; | |
| 9 | import static com.keenwrite.events.StatusEvent.clue; | |
| 10 | import static com.keenwrite.io.MediaType.TEXT_XML; | |
| 11 | import static com.keenwrite.io.SysFile.normalize; | |
| 12 | import static com.keenwrite.typesetting.Typesetter.Mutator; | |
| 13 | import static com.keenwrite.util.Strings.sanitize; | |
| 14 | import static java.nio.charset.StandardCharsets.UTF_8; | |
| 15 | import static java.nio.file.Files.deleteIfExists; | |
| 16 | import static java.nio.file.Files.writeString; | |
| 17 | ||
| 18 | /** | |
| 19 | * Responsible for using a typesetting engine to convert an XHTML document | |
| 20 | * into a PDF file. This must not be run from the JavaFX thread. | |
| 21 | */ | |
| 22 | public final class PdfProcessor extends ExecutorProcessor<String> { | |
| 23 | private final ProcessorContext mProcessorContext; | |
| 24 | ||
| 25 | public PdfProcessor( final ProcessorContext context ) { | |
| 26 | assert context != null; | |
| 27 | mProcessorContext = context; | |
| 28 | } | |
| 29 | ||
| 30 | /** | |
| 31 | * Converts a document by calling a third-party application to typeset the | |
| 32 | * given XHTML document. | |
| 33 | * | |
| 34 | * @param xhtml The document to convert to a PDF file. | |
| 35 | * @return {@code null} because there is no valid return value from generating | |
| 36 | * a PDF file. | |
| 37 | */ | |
| 38 | public String apply( final String xhtml ) { | |
| 39 | try { | |
| 40 | clue( "Main.status.typeset.create" ); | |
| 41 | ||
| 42 | final var context = mProcessorContext; | |
| 43 | final var targetPath = context.getTargetPath(); | |
| 44 | clue( "Main.status.typeset.setting", "target", targetPath ); | |
| 45 | ||
| 46 | final var parent = normalize( targetPath.toAbsolutePath().getParent() ); | |
| 47 | ||
| 48 | final var document = TEXT_XML.createTempFile( APP_TITLE_ABBR, parent ); | |
| 49 | final var sourcePath = writeString( document, xhtml, UTF_8 ); | |
| 50 | clue( "Main.status.typeset.setting", "source", sourcePath ); | |
| 51 | ||
| 52 | final var themeDir = normalize( context.getThemeDir() ); | |
| 53 | clue( "Main.status.typeset.setting", "themes", themeDir ); | |
| 54 | ||
| 55 | final var imageDir = normalize( context.getImageDir() ); | |
| 56 | clue( "Main.status.typeset.setting", "images", imageDir ); | |
| 57 | ||
| 58 | final var imageOrder = context.getImageOrder(); | |
| 59 | clue( "Main.status.typeset.setting", "order", imageOrder ); | |
| 60 | ||
| 61 | final var cacheDir = normalize( context.getCacheDir() ); | |
| 62 | clue( "Main.status.typeset.setting", "caches", cacheDir ); | |
| 63 | ||
| 64 | final var fontDir = normalize( context.getFontDir() ); | |
| 65 | clue( "Main.status.typeset.setting", "fonts", fontDir ); | |
| 66 | ||
| 67 | final var rWorkDir = normalize( context.getRWorkingDir() ); | |
| 68 | clue( "Main.status.typeset.setting", "r-work", rWorkDir ); | |
| 69 | ||
| 70 | final var modesEnabled = sanitize( context.getModesEnabled() ); | |
| 71 | clue( "Main.status.typeset.setting", "mode", modesEnabled ); | |
| 72 | ||
| 73 | final var autoRemove = context.getAutoRemove(); | |
| 74 | clue( "Main.status.typeset.setting", "purge", autoRemove ); | |
| 75 | ||
| 76 | final var typesetter = Typesetter | |
| 77 | .builder() | |
| 78 | .with( Mutator::setTargetPath, targetPath ) | |
| 79 | .with( Mutator::setSourcePath, sourcePath ) | |
| 80 | .with( Mutator::setThemeDir, themeDir ) | |
| 81 | .with( Mutator::setImageDir, imageDir ) | |
| 82 | .with( Mutator::setCacheDir, cacheDir ) | |
| 83 | .with( Mutator::setFontDir, fontDir ) | |
| 84 | .with( Mutator::setModesEnabled, modesEnabled ) | |
| 85 | .with( Mutator::setAutoRemove, autoRemove ) | |
| 86 | .build(); | |
| 87 | ||
| 88 | try { | |
| 89 | typesetter.typeset(); | |
| 90 | } | |
| 91 | finally { | |
| 92 | // Smote the temporary file after typesetting the document. | |
| 93 | if( typesetter.autoRemove() ) { | |
| 94 | deleteIfExists( document ); | |
| 95 | } | |
| 96 | } | |
| 97 | } catch( final Exception ex ) { | |
| 98 | // Typesetter runtime exceptions will pass up the call stack. | |
| 99 | clue( "Main.status.typeset.failed", ex ); | |
| 100 | } | |
| 101 | ||
| 102 | // Do not continue processing (the document was typeset into a binary). | |
| 103 | return null; | |
| 104 | } | |
| 105 | } | |
| 1 | 106 |
| 1 | /* Copyright 2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.processors.r; | |
| 3 | ||
| 4 | import com.keenwrite.collections.BoundedCache; | |
| 5 | ||
| 6 | import javax.script.ScriptEngine; | |
| 7 | import javax.script.ScriptEngineManager; | |
| 8 | import java.util.Map; | |
| 9 | ||
| 10 | import static com.keenwrite.Messages.get; | |
| 11 | import static com.keenwrite.events.StatusEvent.clue; | |
| 12 | import static java.lang.Math.min; | |
| 13 | ||
| 14 | /** | |
| 15 | * Responsible for executing R statements, which can also update the engine's | |
| 16 | * state. | |
| 17 | */ | |
| 18 | public final class Engine { | |
| 19 | /** | |
| 20 | * Inline R expressions that have already been evaluated. | |
| 21 | */ | |
| 22 | private static final Map<String, String> sCache = | |
| 23 | new BoundedCache<>( 768 ); | |
| 24 | ||
| 25 | /** | |
| 26 | * Engine for evaluating R expressions. | |
| 27 | */ | |
| 28 | private static final ScriptEngine sEngine = | |
| 29 | new ScriptEngineManager().getEngineByName( "Renjin" ); | |
| 30 | ||
| 31 | /** | |
| 32 | * Empties the cache. | |
| 33 | */ | |
| 34 | public static void clear() { | |
| 35 | sCache.clear(); | |
| 36 | } | |
| 37 | ||
| 38 | /** | |
| 39 | * Look up an R expression from the cache then return the resulting object. | |
| 40 | * If the R expression hasn't been cached, it'll first be evaluated. | |
| 41 | * | |
| 42 | * @param r R expression to evaluate. | |
| 43 | * @return The object resulting from the evaluation. | |
| 44 | */ | |
| 45 | public static String eval( final String r ) { | |
| 46 | return sCache.computeIfAbsent( r, _ -> evaluate( r ) ); | |
| 47 | } | |
| 48 | ||
| 49 | /** | |
| 50 | * Returns the result of an R expression as an object converted to string. | |
| 51 | * | |
| 52 | * @param r R expression to evaluate. | |
| 53 | * @return The object resulting from the evaluation. | |
| 54 | */ | |
| 55 | private static String evaluate( final String r ) { | |
| 56 | try { | |
| 57 | return sEngine.eval( r ).toString(); | |
| 58 | } catch( final Exception ex ) { | |
| 59 | final var expr = r.substring( 0, min( r.length(), 50 ) ); | |
| 60 | clue( get( "Main.status.error.r", expr, ex.getMessage() ), ex ); | |
| 61 | throw new IllegalArgumentException( r ); | |
| 62 | } | |
| 63 | } | |
| 64 | } | |
| 1 | 65 |
| 1 | /* Copyright 2020 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.processors.r; | |
| 6 | ||
| 7 | import com.keenwrite.preferences.Workspace; | |
| 8 | import com.keenwrite.sigils.RKeyOperator; | |
| 9 | ||
| 10 | import java.util.HashMap; | |
| 11 | import java.util.Map; | |
| 12 | import java.util.function.Supplier; | |
| 13 | ||
| 14 | import static com.keenwrite.events.StatusEvent.clue; | |
| 15 | import static com.keenwrite.preferences.AppKeys.KEY_R_DIR; | |
| 16 | import static com.keenwrite.preferences.AppKeys.KEY_R_SCRIPT; | |
| 17 | import static com.keenwrite.processors.variable.RVariableProcessor.escape; | |
| 18 | import static com.keenwrite.processors.text.TextReplacementFactory.replace; | |
| 19 | ||
| 20 | /** | |
| 21 | * Transforms a document containing R statements into Markdown. | |
| 22 | */ | |
| 23 | public final class RBootstrapController { | |
| 24 | ||
| 25 | private static final RKeyOperator KEY_OPERATOR = new RKeyOperator(); | |
| 26 | ||
| 27 | private final Workspace mWorkspace; | |
| 28 | private final Supplier<Map<String, String>> mSupplier; | |
| 29 | ||
| 30 | public RBootstrapController( | |
| 31 | final Workspace workspace, | |
| 32 | final Supplier<Map<String, String>> supplier ) { | |
| 33 | assert workspace != null; | |
| 34 | assert supplier != null; | |
| 35 | ||
| 36 | mWorkspace = workspace; | |
| 37 | mSupplier = supplier; | |
| 38 | ||
| 39 | mWorkspace.stringProperty( KEY_R_SCRIPT ) | |
| 40 | .addListener( ( c, o, n ) -> update() ); | |
| 41 | mWorkspace.fileProperty( KEY_R_DIR ) | |
| 42 | .addListener( ( c, o, n ) -> update() ); | |
| 43 | ||
| 44 | // Add the definitions immediately upon loading them. | |
| 45 | update(); | |
| 46 | } | |
| 47 | ||
| 48 | /** | |
| 49 | * Updates the R code so that R can find imported libraries. Note that | |
| 50 | * any existing R functionality will not be overwritten if this method is | |
| 51 | * called multiple times. | |
| 52 | */ | |
| 53 | public void update() { | |
| 54 | final var bootstrap = getRScript(); | |
| 55 | ||
| 56 | if( !bootstrap.isBlank() ) { | |
| 57 | final var dir = getRWorkingDirectory(); | |
| 58 | final var definitions = mSupplier.get(); | |
| 59 | ||
| 60 | update( bootstrap, dir, definitions ); | |
| 61 | } | |
| 62 | } | |
| 63 | ||
| 64 | public static void update( | |
| 65 | final String bootstrap, | |
| 66 | final String workingDir, | |
| 67 | final Map<String, String> definitions ) { | |
| 68 | ||
| 69 | if( !bootstrap.isBlank() ) { | |
| 70 | final Map<String, String> map; | |
| 71 | ||
| 72 | if( definitions == null ) { | |
| 73 | map = new HashMap<>(); | |
| 74 | } | |
| 75 | else { | |
| 76 | map = new HashMap<>( definitions.size() + 1 ); | |
| 77 | definitions.forEach( | |
| 78 | ( k, v ) -> map.put( KEY_OPERATOR.apply( k ), escape( v ) ) | |
| 79 | ); | |
| 80 | } | |
| 81 | ||
| 82 | map.put( | |
| 83 | KEY_OPERATOR.apply( "application.r.working.directory" ), | |
| 84 | escape( workingDir ) | |
| 85 | ); | |
| 86 | ||
| 87 | try { | |
| 88 | Engine.eval( replace( bootstrap, map ) ); | |
| 89 | } catch( final Exception ex ) { | |
| 90 | clue( ex ); | |
| 91 | } | |
| 92 | } | |
| 93 | } | |
| 94 | ||
| 95 | private String getRScript() { | |
| 96 | return mWorkspace.getString( KEY_R_SCRIPT ); | |
| 97 | } | |
| 98 | ||
| 99 | private String getRWorkingDirectory() { | |
| 100 | final var wd = mWorkspace.getFile( KEY_R_DIR ); | |
| 101 | return wd.toString().replace( '\\', '/' ); | |
| 102 | } | |
| 103 | } | |
| 1 | 104 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.processors.r; | |
| 6 | ||
| 7 | import com.keenwrite.processors.ExecutorProcessor; | |
| 8 | import com.keenwrite.processors.Processor; | |
| 9 | import com.keenwrite.processors.ProcessorContext; | |
| 10 | ||
| 11 | public class RBootstrapProcessor extends ExecutorProcessor<String> { | |
| 12 | private final Processor<String> mSuccessor; | |
| 13 | private final ProcessorContext mContext; | |
| 14 | ||
| 15 | public RBootstrapProcessor( | |
| 16 | final Processor<String> successor, | |
| 17 | final ProcessorContext context ) { | |
| 18 | assert successor != null; | |
| 19 | assert context != null; | |
| 20 | ||
| 21 | mSuccessor = successor; | |
| 22 | mContext = context; | |
| 23 | } | |
| 24 | ||
| 25 | /** | |
| 26 | * Processes the given text document by replacing variables with their values. | |
| 27 | * | |
| 28 | * @param text The document text that includes variables that should be | |
| 29 | * replaced with values when rendered as HTML. | |
| 30 | * @return The text with all variables replaced. | |
| 31 | */ | |
| 32 | @Override | |
| 33 | public String apply( final String text ) { | |
| 34 | assert text != null; | |
| 35 | ||
| 36 | final var bootstrap = mContext.getRScript(); | |
| 37 | final var workingDir = mContext.getRWorkingDir().toString(); | |
| 38 | final var definitions = mContext.getDefinitions(); | |
| 39 | ||
| 40 | RBootstrapController.update( bootstrap, workingDir, definitions ); | |
| 41 | ||
| 42 | return mSuccessor.apply( text ); | |
| 43 | } | |
| 44 | } | |
| 1 | 45 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.processors.r; | |
| 3 | ||
| 4 | import java.util.function.Function; | |
| 5 | ||
| 6 | import static com.keenwrite.constants.Constants.STATUS_PARSE_ERROR; | |
| 7 | import static com.keenwrite.events.StatusEvent.clue; | |
| 8 | ||
| 9 | /** | |
| 10 | * Transforms a document containing R statements into Markdown. The statements | |
| 11 | * are part of an R chunk, <code>```{r}</code>. | |
| 12 | */ | |
| 13 | public final class RChunkEvaluator implements Function<String, String> { | |
| 14 | ||
| 15 | /** | |
| 16 | * Constructs an evaluator capable of executing R statements. | |
| 17 | */ | |
| 18 | public RChunkEvaluator() {} | |
| 19 | ||
| 20 | /** | |
| 21 | * Evaluates the given R statements and returns the result as a string. | |
| 22 | * If an image was produced, the calling code is responsible for persisting | |
| 23 | * and making the file embeddable into the document. | |
| 24 | * | |
| 25 | * @param r The R statements to evaluate. | |
| 26 | * @return The output from the final R statement. | |
| 27 | */ | |
| 28 | @Override | |
| 29 | public String apply( final String r ) { | |
| 30 | try { | |
| 31 | return Engine.eval( r ); | |
| 32 | } catch( final Exception ex ) { | |
| 33 | clue( STATUS_PARSE_ERROR, ex.getMessage() ); | |
| 34 | ||
| 35 | return r; | |
| 36 | } | |
| 37 | } | |
| 38 | } | |
| 1 | 39 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.processors.r; | |
| 3 | ||
| 4 | import com.keenwrite.processors.Processor; | |
| 5 | import com.keenwrite.processors.variable.RVariableProcessor; | |
| 6 | ||
| 7 | import java.util.function.Function; | |
| 8 | import java.util.function.Predicate; | |
| 9 | ||
| 10 | import static com.keenwrite.constants.Constants.STATUS_PARSE_ERROR; | |
| 11 | import static com.keenwrite.events.StatusEvent.clue; | |
| 12 | ||
| 13 | /** | |
| 14 | * Evaluates inline R statements. | |
| 15 | */ | |
| 16 | public final class RInlineEvaluator | |
| 17 | implements Function<String, String>, Predicate<String> { | |
| 18 | public static final String PREFIX = "`r#"; | |
| 19 | public static final String SUFFIX = "`"; | |
| 20 | ||
| 21 | private static final int PREFIX_LENGTH = PREFIX.length(); | |
| 22 | ||
| 23 | private final Processor<String> mProcessor; | |
| 24 | ||
| 25 | /** | |
| 26 | * Constructs an evaluator capable of executing R statements. | |
| 27 | */ | |
| 28 | public RInlineEvaluator( final RVariableProcessor processor ) { | |
| 29 | mProcessor = processor; | |
| 30 | } | |
| 31 | ||
| 32 | /** | |
| 33 | * Evaluates all R statements in the source document and inserts the | |
| 34 | * calculated value into the generated document. | |
| 35 | * | |
| 36 | * @param text The document text that includes variables that should be | |
| 37 | * replaced with values when rendered as HTML. | |
| 38 | * @return The generated document with output from all R statements | |
| 39 | * substituted with value returned from their execution. | |
| 40 | */ | |
| 41 | @Override | |
| 42 | public String apply( final String text ) { | |
| 43 | try { | |
| 44 | final var buffer = new StringBuilder( text.length() ); | |
| 45 | ||
| 46 | int index = 0; | |
| 47 | int began; | |
| 48 | int ended = 0; | |
| 49 | ||
| 50 | while( (began = text.indexOf( PREFIX, index )) >= 0 && ended > -1 ) { | |
| 51 | buffer.append( text, index, began ); | |
| 52 | ||
| 53 | // If the R expression has no definite end, this returns -1. | |
| 54 | ended = text.indexOf( SUFFIX, began + 1 ); | |
| 55 | ||
| 56 | if( ended > began ) { | |
| 57 | final var r = mProcessor.apply( | |
| 58 | text.substring( began + PREFIX_LENGTH, ended ) | |
| 59 | ); | |
| 60 | ||
| 61 | // Return the evaluated R expression for insertion back into the text. | |
| 62 | buffer.append( Engine.eval( r ) ); | |
| 63 | ||
| 64 | index = ended + 1; | |
| 65 | } | |
| 66 | } | |
| 67 | ||
| 68 | buffer.append( text.substring( index ) ); | |
| 69 | ||
| 70 | return buffer.toString(); | |
| 71 | } catch( final Exception ex ) { | |
| 72 | clue( STATUS_PARSE_ERROR, ex.getMessage() ); | |
| 73 | ||
| 74 | // If the string couldn't be parsed using R, append the statement | |
| 75 | // that failed to parse, instead of its evaluated value. | |
| 76 | return text; | |
| 77 | } | |
| 78 | } | |
| 79 | ||
| 80 | /** | |
| 81 | * Answers whether the engine associated with this evaluator may attempt to | |
| 82 | * evaluate the given source code statement. | |
| 83 | * | |
| 84 | * @param code The source code to verify. | |
| 85 | * @return {@code true} if the code may be evaluated. | |
| 86 | */ | |
| 87 | @Override | |
| 88 | public boolean test( final String code ) { | |
| 89 | return code.startsWith( PREFIX ); | |
| 90 | } | |
| 91 | } | |
| 1 | 92 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.processors.text; | |
| 3 | ||
| 4 | import java.util.Map; | |
| 5 | ||
| 6 | /** | |
| 7 | * Responsible for common behaviour across all text replacer implementations. | |
| 8 | */ | |
| 9 | public abstract class Abstrac = new String[ 0 ] = new String[ 0 ]private final Object mMutex = new Object()synchronized( mMutex ) { | |
| 10 | return mKeys; | |
| 11 | }synchronized( mMutex ) { | |
| 12 | return mValues; | |
| 13 | }synchronized( mMutex ) { | |
| 14 | } | |
| 15 | } | |
| 16 | } | |
| 17 | } | |
| 1 | 18 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.processors.text; | |
| 3 | ||
| 4 | import java.util.Map; | |
| 5 | ||
| 6 | import static org.ahocorasick.trie.Trie.builder; | |
| 7 | ||
| 8 | /** | |
| 9 | * Replaces text using an Aho-Corasick algorithm. | |
| 10 | */ | |
| 11 | public final var keySet = keys( map ); | |
| 1 | 12 | |
| 13 | if( keySet != null ) { | |
| 14 | } |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.processors.text; | |
| 3 | ||
| 4 | import java.util.Map; | |
| 5 | ||
| 6 | import static com.keenwrite.util.Strings.replaceEach; | |
| 7 | ||
| 8 | /** | |
| 9 | * Replaces text using a brute-force replacement method. | |
| 10 | */ | |
| 11 | public class StringUtilsReplacer extends AbstractTextReplacer { | |
| 12 | ||
| 13 | /** | |
| 14 | * Default (empty) constructor. | |
| 15 | */ | |
| 16 | protected StringUtilsReplacer() {} | |
| 17 | ||
| 18 | @Override | |
| 19 | public String replace( final String text, final Map<String, String> map ) { | |
| 20 | return replaceEach( text, keys( map ), values( map ) ); | |
| 21 | } | |
| 22 | } | |
| 1 | 23 |
| 1 | /* Copyright 2024 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.processors.text; | |
| 6 | io.MediaType; | |
| 7 | import com.keenwrite.processors.ExecutorPconverting documents to plain text files. This will | |
| 8 | * perform interpolated variable substitutions and execute R commands | |
| 9 | * as necessary. | |
| 10 | */ | |
| 11 | public class TextProcessor extends ExecutorProcessor<String> { | |
| 12 | privatemEvaluator; | |
| 13 | ||
| 14 | public Text | |
| 15 | ); | |
| 16 | m} | |
| 17 | else { | |
| 18 | mEvaluat} | |
| 19 | } | |
| 20 | ||
| 21 | @Override | |
| 22 | public String apply( final String document ) { | |
| 23 | return mEvaluator.apply( document ); | |
| 24 | } | |
| 25 | } | |
| 1 | 26 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.processors.text; | |
| 3 | ||
| 4 | import com.keenwrite.util.Strings; | |
| 5 | ||
| 6 | import java.util.Map; | |
| 7 | ||
| 8 | /** | |
| 9 | * Used to generate a class capable of efficiently replacing variable | |
| 10 | * definitions with their values. | |
| 11 | */ | |
| 12 | public final class TextReplacementFactory { | |
| 13 | ||
| 14 | private static final TextReplacer APACHE = new StringUtilsReplacer(); | |
| 15 | private static final TextReplacer AHO_CORASICK = new AhoCorasickReplacer(); | |
| 16 | ||
| 17 | /** | |
| 18 | * Returns a text search/replacement instance that is reasonably optimal for | |
| 19 | * the given length of text. | |
| 20 | * | |
| 21 | * @param length The length of text that requires some search and replacing. | |
| 22 | * @return A class that can search and replace text with utmost expediency. | |
| 23 | */ | |
| 24 | public static TextReplacer getTextReplacer( final int length ) { | |
| 25 | // After about 1,500 characters, the Aho-Corsick algorithm is faster. | |
| 26 | return length < 1500 ? APACHE : AHO_CORASICK; | |
| 27 | } | |
| 28 | ||
| 29 | /** | |
| 30 | * Convenience method to instantiate a suitable text replacer algorithm and | |
| 31 | * perform a replacement using the given map. At this point, the values should | |
| 32 | * be already dereferenced and ready to be substituted verbatim; any | |
| 33 | * recursively defined values must have been interpolated previously. | |
| 34 | * | |
| 35 | * @param text The text containing zero or more variables to replace. | |
| 36 | * @param needles The map of variables to their dereferenced values. | |
| 37 | * @return The text with all variables replaced. | |
| 38 | */ | |
| 39 | public static String replace( | |
| 40 | final String text, final Map<String, String> needles ) { | |
| 41 | final String haystack = Strings.sanitize( text ); | |
| 42 | assert needles != null; | |
| 43 | ||
| 44 | return getTextReplacer( haystack.length() ).replace( haystack, needles ); | |
| 45 | } | |
| 46 | } | |
| 1 | 47 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.processors.text; | |
| 3 | ||
| 4 | import java.util.Map; | |
| 5 | ||
| 6 | /** | |
| 7 | * Defines the ability to replace text given a set of keys and values. | |
| 8 | */ | |
| 9 | public interface TextReplacer { | |
| 10 | ||
| 11 | /** | |
| 12 | * Searches through the given text for any of the keys given in the map and | |
| 13 | * replaces the keys that appear in the text with the key's corresponding | |
| 14 | * value. | |
| 15 | * | |
| 16 | * @param text The text that contains zero or more keys. | |
| 17 | * @param map The set of keys mapped to replacement values. | |
| 18 | * @return The given text with all keys replaced with corresponding values. | |
| 19 | */ | |
| 20 | String replace( String text, Map<String, String> map ); | |
| 21 | } | |
| 1 | 22 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.processors.variable; | |
| 1 | 6 | |
| 7 | import com.keenwrite.processors.Processor; | |
| 8 | import com.keenwrite.processors.ProcessorContext; | |
| 9 | import com.keenwrite. |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.processors.variable; | |
| 3 | ||
| 4 | import com.keenwrite.processors.ExecutorProcessor; | |
| 5 | import com.keenwrite.processors.Processor; | |
| 6 | import com.keenwrite.processors.ProcessorContext; | |
| 7 | import com.keenwrite.sigils.SigilKeyOperator; | |
| 8 | ||
| 9 | import java.util.HashMap; | |
| 10 | import java.util.Map; | |
| 11 | import java.util.function.Function; | |
| 12 | ||
| 13 | import static com.keenwrite.processors.text.TextReplacementFactory.replace; | |
| 14 | ||
| 15 | /** | |
| 16 | * Processes interpolated string definitions in the document and inserts | |
| 17 | * their values into the post-processed text. The default variable syntax is | |
| 18 | * <pre>{{variable}}</pre> (a.k.a., moustache syntax). | |
| 19 | */ | |
| 20 | public class VariableProcessor | |
| 21 | extends ExecutorProcessor<String> implements Function<String, String> { | |
| 22 | ||
| 23 | private final ProcessorContext mContext; | |
| 24 | private final SigilKeyOperator mSigilOperator; | |
| 25 | ||
| 26 | /** | |
| 27 | * Constructs a processor capable of interpolating string definitions. | |
| 28 | * | |
| 29 | * @param successor Subsequent link in the processing chain. | |
| 30 | * @param context Contains resolved definitions map. | |
| 31 | */ | |
| 32 | public VariableProcessor( | |
| 33 | final Processor<String> successor, | |
| 34 | final ProcessorContext context ) { | |
| 35 | super( successor ); | |
| 36 | ||
| 37 | mContext = context; | |
| 38 | mSigilOperator = createKeyOperator( context ); | |
| 39 | } | |
| 40 | ||
| 41 | /** | |
| 42 | * Subclasses may change the type of operation performed on keys, such as | |
| 43 | * wrapping key names in sigils. | |
| 44 | * | |
| 45 | * @param context Provides the name of the file being edited. | |
| 46 | * @return An operator for transforming key names. | |
| 47 | */ | |
| 48 | protected SigilKeyOperator createKeyOperator( | |
| 49 | final ProcessorContext context ) { | |
| 50 | return context.createKeyOperator(); | |
| 51 | } | |
| 52 | ||
| 53 | /** | |
| 54 | * Returns the map to use for variable substitution. | |
| 55 | * | |
| 56 | * @return A map of variable names to values, with keys wrapped in sigils. | |
| 57 | */ | |
| 58 | public Map<String, String> getDefinitions() { | |
| 59 | return entoken( mContext.getInterpolatedDefinitions() ); | |
| 60 | } | |
| 61 | ||
| 62 | /** | |
| 63 | * Subclasses may override this method to change how keys are wrapped | |
| 64 | * in sigils. | |
| 65 | * | |
| 66 | * @param key The key to enwrap. | |
| 67 | * @return The wrapped key. | |
| 68 | */ | |
| 69 | protected String processKey( final String key ) { | |
| 70 | return mSigilOperator.apply( key ); | |
| 71 | } | |
| 72 | ||
| 73 | /** | |
| 74 | * Subclasses may override this method to modify values prior to use. This | |
| 75 | * can be used, for example, to escape values prior to evaluating by a | |
| 76 | * scripting engine. | |
| 77 | * | |
| 78 | * @param value The value to process. | |
| 79 | * @return The processed value. | |
| 80 | */ | |
| 81 | protected String processValue( final String value ) { | |
| 82 | return value; | |
| 83 | } | |
| 84 | ||
| 85 | /** | |
| 86 | * Answers whether the given key is wrapped in sigil tokens. | |
| 87 | * | |
| 88 | * @param key The key to analyze. | |
| 89 | * @return {@code true} if the key is wrapped in sigils. | |
| 90 | */ | |
| 91 | public boolean hasSigils( final String key ) { | |
| 92 | return mSigilOperator.match( key ).find(); | |
| 93 | } | |
| 94 | ||
| 95 | /** | |
| 96 | * Processes the given text document by replacing variables with their values. | |
| 97 | * | |
| 98 | * @param text The document text that includes variables that should be | |
| 99 | * replaced with values when rendered as HTML. | |
| 100 | * @return The text with all variables replaced. | |
| 101 | */ | |
| 102 | @Override | |
| 103 | public String apply( final String text ) { | |
| 104 | assert text != null; | |
| 105 | ||
| 106 | return replace( text, getDefinitions() ); | |
| 107 | } | |
| 108 | ||
| 109 | /** | |
| 110 | * Converts the given map from regular variables to processor-specific | |
| 111 | * variables. | |
| 112 | * | |
| 113 | * @param map Map of variable names to values. | |
| 114 | * @return Map of variables with the keys and values subjected to | |
| 115 | * post-processing. | |
| 116 | */ | |
| 117 | protected Map<String, String> entoken( final Map<String, String> map ) { | |
| 118 | assert map != null; | |
| 119 | ||
| 120 | final var result = new HashMap<String, String>( map.size() ); | |
| 121 | ||
| 122 | map.forEach( ( k, v ) -> result.put( processKey( k ), processValue( v ) ) ); | |
| 123 | ||
| 124 | return result; | |
| 125 | } | |
| 126 | } | |
| 1 | 127 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.search; | |
| 1 | 3 | |
| 4 | import com.keenwrite.util.CyclicIterator; | |
| 5 | import javafx.beans.property.ObjectProperty; | |
| 6 | import javafx.beans.property.SimpleObjectProperty; | |
| 7 | import ja |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.security; | |
| 3 | ||
| 4 | import javax.net.ssl.*; | |
| 5 | import java.security.KeyManagementException; | |
| 6 | import java.security.NoSuchAlgorithmException; | |
| 7 | import java.security.SecureRandom; | |
| 8 | import java.security.cert.X509Certificate; | |
| 9 | ||
| 10 | import static javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier; | |
| 11 | import static javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory; | |
| 12 | ||
| 13 | /** | |
| 14 | * Responsible for trusting all certificate chains. The purpose of this class | |
| 15 | * is to work-around certificate issues caused by software that blocks | |
| 16 | * HTTP requests. For example, Zscaler may block HTTP requests to kroki.io | |
| 17 | * when generating diagrams. | |
| 18 | */ | |
| 19 | public final class PermissiveCertificate { | |
| 20 | /** | |
| 21 | * Create a trust manager that does not validate certificate chains. | |
| 22 | */ | |
| 23 | private static final TrustManager[] TRUST_ALL_CERTS = new TrustManager[]{ | |
| 24 | new X509TrustManager() { | |
| 25 | @Override | |
| 26 | public X509Certificate[] getAcceptedIssuers() { | |
| 27 | return new X509Certificate[ 0 ]; | |
| 28 | } | |
| 29 | ||
| 30 | @Override | |
| 31 | public void checkClientTrusted( | |
| 32 | X509Certificate[] certs, String authType ) { | |
| 33 | } | |
| 34 | ||
| 35 | @Override | |
| 36 | public void checkServerTrusted( | |
| 37 | X509Certificate[] certs, String authType ) { | |
| 38 | } | |
| 39 | } | |
| 40 | }; | |
| 41 | ||
| 42 | /** | |
| 43 | * Responsible for permitting all hostnames for making HTTP requests. | |
| 44 | */ | |
| 45 | private static class PermissiveHostNameVerifier implements HostnameVerifier { | |
| 46 | @Override | |
| 47 | public boolean verify( final String hostname, final SSLSession session ) { | |
| 48 | return true; | |
| 49 | } | |
| 50 | } | |
| 51 | ||
| 52 | /** | |
| 53 | * Install the all-trusting trust manager. If this fails it means that in | |
| 54 | * certain situations the HTML preview may fail to render diagrams. A way | |
| 55 | * to work around the issue is to install a local server for generating | |
| 56 | * diagrams. | |
| 57 | */ | |
| 58 | public static boolean installTrustManager() { | |
| 59 | try { | |
| 60 | final var context = SSLContext.getInstance( "SSL" ); | |
| 61 | context.init( null, TRUST_ALL_CERTS, new SecureRandom() ); | |
| 62 | setDefaultSSLSocketFactory( context.getSocketFactory() ); | |
| 63 | setDefaultHostnameVerifier( new PermissiveHostNameVerifier() ); | |
| 64 | return true; | |
| 65 | } catch( NoSuchAlgorithmException | KeyManagementException e ) { | |
| 66 | return false; | |
| 67 | } | |
| 68 | } | |
| 69 | ||
| 70 | /** | |
| 71 | * Use {@link #installTrustManager()}. | |
| 72 | */ | |
| 73 | private PermissiveCertificate() { | |
| 74 | } | |
| 75 | } | |
| 1 | 76 |
| 1 | ||
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. |
| 1 | ||
| 1 | /* Copyright 2020-2021 | |
| 2 | * All rights reserved. | |
| 3 | * -- All rights reserved. |
| 1 | ||
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. |
| 1 | /* Copyright 2020-2021 -- All rights reserved. */ | |
| 2 | package com.keenwritenio.file.PathPath path, | |
| 3 | String titleKey, | |
| 4 | Path path, | |
| 5 | String title, | |
| 1 | 6 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.service.events.impl; | |
| 3 | ||
| 4 | import javafx.scene.Node; | |
| 5 | import javafx.scene.control.ButtonBar; | |
| 6 | import javafx.scene.control.DialogPane; | |
| 7 | ||
| 8 | import static com.keenwrite.constants.Constants.sSettings; | |
| 9 | import static javafx.scene.control.ButtonBar.BUTTON_ORDER_WINDOWS; | |
| 10 | ||
| 11 | /** | |
| 12 | * Ensures a consistent button order for alert dialogs across platforms (because | |
| 13 | * the default button order on Linux defies all logic). | |
| 14 | */ | |
| 15 | public class ButtonOrderPane extends DialogPane { | |
| 16 | public ButtonOrderPane() { | |
| 17 | } | |
| 18 | ||
| 19 | @Override | |
| 20 | protected Node createButtonBar() { | |
| 21 | final var node = (ButtonBar) super.createButtonBar(); | |
| 22 | node.setButtonOrder( getButtonOrder() ); | |
| 23 | return node; | |
| 24 | } | |
| 25 | ||
| 26 | private String getButtonOrder() { | |
| 27 | return sSettings.getSetting( | |
| 28 | "dialog.alert.button.order.windows", BUTTON_ORDER_WINDOWS ); | |
| 29 | } | |
| 30 | } | |
| 1 | 31 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.service.events.impl; | |
| 3 | ||
| 4 | import com.keenwrite.service.events.Notification; | |
| 5 | ||
| 6 | import java.text.MessageFormat; | |
| 7 | ||
| 8 | /** | |
| 9 | * Responsible for alerting the user to prominmTitle;mCmTitle = title; | |
| 10 | mCmTmContent; | |
| 11 | } | |
| 12 | ||
| 13 | } | |
| 1 | 14 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.service.events.impl; | |
| 1 | 3 | |
| 4 | import com.keenwrite.service.events.Notification; | |
| 5 | import com.keenwrite.service.events.Notifier; | |
| 6 | import javafx.scene.control.Alert; | |
| 7 | impconstants |
| 1 | /* Copyright 2020-2021 -- All rights reserved. */ | |
| 2 | package com.keenwritecom.keenwrite.config.; | |
| 3 | import com.keenwrite.service.Settings; | |
| 4 | ||
| 5 | import static com.keenwrite.constants.Constants.PATH_PROPERTIES_SETTINGS/ | |
| 6 | public final | |
| 7 | privatemProperties = loadProperties() { loadProperties() { | |
| 8 | final varvar final var encoding = getDefaultEncodingvar reade | |
| 9 | url.openStream(), encodingread( reader ); | |
| 10 | } catch( final exPATH_PROPERTIES_SETTINGSmProperties; | |
| 11 | } | |
| 12 | } | |
| 1 | 13 |
| 1 | /* Copyright 2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.sigils; | |
| 3 | ||
| 4 | /** | |
| 5 | * Responsible for defining sigils used within property files. | |
| 6 | */ | |
| 7 | public class PropertyKeyOperator extends SigilKeyOperator { | |
| 8 | public static final String BEGAN = "${"; | |
| 9 | public static final String ENDED = "}"; | |
| 10 | ||
| 11 | /** | |
| 12 | * Constructs a new {@link SigilKeyOperator} subclass with <code>${</code> | |
| 13 | * and <code>}</code> used for the beginning and ending sigils. | |
| 14 | */ | |
| 15 | public PropertyKeyOperator() { | |
| 16 | super( BEGAN, ENDED ); | |
| 17 | } | |
| 18 | } | |
| 1 | 19 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.sigils; | |
| 3 | ||
| 4 | import com.keenwrite.collections.BoundedCache; | |
| 5 | ||
| 6 | /** | |
| 7 | * Converts dot-separated variable names into names compatible with R. That is, | |
| 8 | * {@code variable.name.qualified} becomes {@code v$variable$name$qualified}. | |
| 9 | */ | |
| 10 | public final class RKeyOperator extends SigilKeyOperator { | |
| 11 | private static final char KEY_SEPARATOR_DEF = '.'; | |
| 12 | private static final char KEY_SEPARATOR_R = '$'; | |
| 13 | ||
| 14 | /** Minor optimization to avoid recreating an object. */ | |
| 15 | private final StringBuilder mVarName = new StringBuilder( 128 ); | |
| 16 | ||
| 17 | /** Optimization to avoid re-converting variable names into R format. */ | |
| 18 | private final BoundedCache<String, String> mVariables = new BoundedCache<>( | |
| 19 | 2048 | |
| 20 | ); | |
| 21 | ||
| 22 | /** | |
| 23 | * Constructs a new instance capable of converting dot-separated variable | |
| 24 | * names into R's dollar-symbol-separated names. | |
| 25 | */ | |
| 26 | public RKeyOperator() { | |
| 27 | // The keys are not delimited. | |
| 28 | super( "", "" ); | |
| 29 | } | |
| 30 | ||
| 31 | /** | |
| 32 | * Transforms a definition key name into the expected format for an R | |
| 33 | * variable key name. | |
| 34 | * <p> | |
| 35 | * This algorithm is faster than {@link String#replace(char, char)}. Faster | |
| 36 | * still would be to cache the values, but that would mean managing the | |
| 37 | * cache when the user changes the beginning and ending of the R delimiters. | |
| 38 | * This code gives about a 2% performance boost when scrolling using | |
| 39 | * cursor keys. After the JIT warms up, this super-minor bottleneck vanishes. | |
| 40 | * | |
| 41 | * @param key The variable name to transform, neither blank nor {@code null}. | |
| 42 | * @return The transformed variable name. | |
| 43 | */ | |
| 44 | @Override | |
| 45 | public String apply( final String key ) { | |
| 46 | assert key != null; | |
| 47 | assert !key.isBlank(); | |
| 48 | ||
| 49 | return mVariables.computeIfAbsent( key, this::convert ); | |
| 50 | } | |
| 51 | ||
| 52 | private String convert( final String key ) { | |
| 53 | mVarName.setLength( 0 ); | |
| 54 | mVarName.append( "v" ); | |
| 55 | mVarName.append( KEY_SEPARATOR_R ); | |
| 56 | mVarName.append( key ); | |
| 57 | ||
| 58 | // The 3 is for v$ + first char, which cannot be a separator. | |
| 59 | for( int i = mVarName.length() - 1; i >= 3; i-- ) { | |
| 60 | if( mVarName.charAt( i ) == KEY_SEPARATOR_DEF ) { | |
| 61 | mVarName.setCharAt( i, KEY_SEPARATOR_R ); | |
| 62 | } | |
| 63 | } | |
| 64 | ||
| 65 | return mVarName.toString(); | |
| 66 | } | |
| 67 | } | |
| 1 | 68 |
| 1 | /* Copyright 2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.sigils; | |
| 3 | ||
| 4 | import java.util.function.UnaryOperator; | |
| 5 | import java.util.regex.Matcher; | |
| 6 | import java.util.regex.Pattern; | |
| 7 | ||
| 8 | import static java.lang.String.format; | |
| 9 | import static java.util.regex.Pattern.compile; | |
| 10 | import static java.util.regex.Pattern.quote; | |
| 11 | ||
| 12 | /** | |
| 13 | * Responsible for bracketing definition keys with token delimiters. | |
| 14 | */ | |
| 15 | public class SigilKeyOperator implements UnaryOperator<String> { | |
| 16 | private final String mBegan; | |
| 17 | private final String mEnded; | |
| 18 | private final Pattern mPattern; | |
| 19 | ||
| 20 | public SigilKeyOperator( final String began, final String ended ) { | |
| 21 | assert began != null; | |
| 22 | assert ended != null; | |
| 23 | ||
| 24 | mBegan = began; | |
| 25 | mEnded = ended; | |
| 26 | mPattern = compile( format( "%s(.*?)%s", quote( began ), quote( ended ) ) ); | |
| 27 | } | |
| 28 | ||
| 29 | @Override | |
| 30 | public String apply( final String key ) { | |
| 31 | assert key != null; | |
| 32 | assert !key.startsWith( mBegan ); | |
| 33 | assert !key.endsWith( mEnded ); | |
| 34 | ||
| 35 | return mBegan + key + mEnded; | |
| 36 | } | |
| 37 | ||
| 38 | public Matcher match( final String text ) { | |
| 39 | return mPattern.matcher( text ); | |
| 40 | } | |
| 41 | } | |
| 1 | 42 |
| 1 | ||
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. |
| 1 | ||
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | ||
| 3 | /** | |
| 4 | * This package contains interfaces for spell checking implementations. | |
| 5 | */ | |
| 6 | package com.keenwrite.spelling.api; | |
| 1 | 7 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.spelling.impl; | |
| 6 | ||
| 7 | import com.keenwrite.events.spelling.LexiconLoadedEvent; | |
| 8 | import com.keenwrite.exceptions.MissingFileExceptionSTR.\{s}", count ); | |
| 9 | } | |
| 10 | } | |
| 1 | 11 |
| 1 | ||
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved.final |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.spelling.impl; | |
| 3 | ||
| 4 | import com.keenwrite.spelling.api.SpellCheckListener; | |
| 5 | import com.keenwrite.spelling.api.SpellChecker; | |
| 6 | import io.gitlab.rxp90.jsymspell.SymSpexceptions.NotInitializedException | |
| 7 | throws NotInitializedExceptionfinal var symSpell =.build(); | |
| 1 | 8 | |
| 9 | symSpell ); |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | ||
| 3 | /** | |
| 4 | * This package contains classes for spell checking implementations. | |
| 5 | */ | |
| 6 | package com.keenwrite.spelling.impl; | |
| 1 | 7 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.typesetting; | |
| 1 | 3 | |
| 4 | import com.keenwrite.io.CommandNotFoundException; | |
| 5 | import com.keenwrite.io.StreamGobbler; | |
| 6 | import com.keenwrite.io.SysFile; | |
| 7 | import com.keenwriteTR."\{TYPESETTER_EXE} --version > /dev/null"TR."\{TYPESETTER_VERSION}; echo $?" |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.typesetting; | |
| 6 | ||
| 7 | import com.keenwrite.collections.CircularQueue; | |
| 8 | import com.keenwrite.io.StreamGobbler; | |
| 9 | import com.keenwrite.io.SysFile; | |
| 10 | ||
| 11 | import java.io.io.IOTEMPORARYio.SysFile.toFilecharset.StandardCharsets.UTF_8 | |
| 12 | TargeAll( optionsCircularQueue<toFile( mDirectory ); | |
| 13 | ||
| 14 | // Slurp page numbers in a separate thread while typesetting. | |
| 15 | StreamGobbler.gobble(, line -> { | |
| 16 | listener.accept( line ); | |
| 17 | stdout.add( line ); | |
| 18 | } SysFile.getFileName( getSourcePath()srcName = SysFile.getFileName( getTargetPath()RemoveTarge, UTF_8@SuppressWarnings( "SpellCheckingInspection" )TEMPORARY_DIRECTORYtoFile( cache )Booleantask = new HostTypesetter.TypesetTask(); | |
| 19 | return task.typeset(); | |
| 20 | } | |
| 21 | } | |
| 1 | 22 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.typesetting; | |
| 3 | ||
| 4 | import java.function.Consumimplements Consumer<String>int mPageCount = 1; | |
| 5 | private int mPassCount = 1; | |
| 6 | private int mPageTotal = 0) {accept( final String line ) { | |
| 7 | if( page < mPmPassCount++; | |
| 8 | mPageTotal = mPageCount; | |
| 9 | } | |
| 10 | ||
| 11 | mPmPageCount, mPmPageTotal, mPassCount | |
| 12 | ); | |
| 13 | } | |
| 14 | } | |
| 15 | } | |
| 1 | 16 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.typesetting; | |
| 6 | ||
| 7 | import com.keenwrite.util.GenericBuilder; | |
| 8 | import com.keenwrite.util.Time; | |
| 1 | 9 | |
| 10 | import java.nio.file.Path; | |
| 11 | import jaSTR."\{prefix}began"STR."\{prefix}ended.\{suffix}" |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.typesetting; | |
| 3 | ||
| 4 | /** | |
| 5 | * Responsible for creating an alternate execution path when a typesetter | |
| 6 | * cannot be found. | |
| 7 | */ | |
| 8 | public class TypesetterNotFoundException extends RuntimeException { | |
| 9 | /** | |
| 10 | * Constructs a new exception that indicates the typesetting engine cannot | |
| 11 | * be found anywhere along the PATH. | |
| 12 | * | |
| 13 | * @param name Typesetter executable file name. | |
| 14 | */ | |
| 15 | public TypesetterNotFoundException( final String name ) { | |
| 16 | super( name ); | |
| 17 | } | |
| 18 | } | |
| 1 | 19 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.typesetting.containerization; | |
| 6 | ||
| 7 | import com.keenwrite.io.CommandNotFoundException; | |
| 8 | ||
| 9 | import java.io.File; | |
| 10 | import java.io.IOException; | |
| 11 | import java.util.List; | |
| 1 | 12 | |
| 13 | public |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.typesetting.containerization; | |
| 6 | ||
| 7 | import com.keenwrite.Messages; | |
| 8 | import com.keenwrite.io.CommandNotFoundException; | |
| 9 | import com.keenwrite.io.SysFile; | |
| 10 | ||
| 11 | import java.io.File; | |
| 12 | import java.nio.file.Files; | |
| 13 | import java.nio.file.Path; | |
| 14 | import java.util.LinkedList; | |
| 15 | import java.util.List; | |
| 16 | ||
| 17 | import static com.keenwrite.events.StatusEvent.clue; | |
| 18 | import static com.keenwrite.io.SysFile.toFile; | |
| 19 | import static com.keenwrite.util.SystemUtils.IS_OS_WINDOWS; | |
| 20 | import static java.lang.String.format; | |
| 21 | import static java.lang.String.join; | |
| 22 | import static java.lang.System.arraycopy; | |
| 23 | import static java.util.Arrays.copyOf; | |
| 24 | ||
| 25 | /** | |
| 26 | * Provides facilities for interacting with a container environment. | |
| 27 | */ | |
| 28 | public final class Podman implements ContainerManager { | |
| 29 | private static final String BINARY = "podman"; | |
| 30 | private static final Path BINARY_PATH = | |
| 31 | Path.of( | |
| 32 | format( IS_OS_WINDOWS | |
| 33 | ? "C:\\Program Files\\RedHat\\Podman\\%s.exe" | |
| 34 | : "/usr/bin/%s", | |
| 35 | BINARY | |
| 36 | ) | |
| 37 | ); | |
| 38 | private static final SysFile MANAGER = new SysFile( BINARY ); | |
| 39 | ||
| 40 | private final List<String> mMountPoints = new LinkedList<>(); | |
| 41 | ||
| 42 | public Podman() { } | |
| 43 | ||
| 44 | /** | |
| 45 | * Answers whether the container is installed and runnable on the host. | |
| 46 | * | |
| 47 | * @return {@code true} if the container is available. | |
| 48 | */ | |
| 49 | public static boolean canRun() { | |
| 50 | try { | |
| 51 | return toFile( getExecutable() ).isFile(); | |
| 52 | } catch( final Exception ex ) { | |
| 53 | clue( "Wizard.container.executable.run.error", ex ); | |
| 54 | ||
| 55 | // If the binary couldn't be found, then indicate that it cannot run. | |
| 56 | return false; | |
| 57 | } | |
| 58 | } | |
| 59 | ||
| 60 | private static Path getExecutable() { | |
| 61 | final var executable = Files.isExecutable( BINARY_PATH ); | |
| 62 | ||
| 63 | clue( "Wizard.container.executable.run.scan", BINARY_PATH, executable ); | |
| 64 | ||
| 65 | return executable | |
| 66 | ? BINARY_PATH | |
| 67 | : MANAGER.locate().orElseThrow(); | |
| 68 | } | |
| 69 | ||
| 70 | @Override | |
| 71 | public int install( final File exe ) { | |
| 72 | // This monstrosity runs the installer in the background without displaying | |
| 73 | // a secondary command window, while blocking until the installer completes | |
| 74 | // and an exit code can be determined. I hate Windows. | |
| 75 | final var cmd = format( | |
| 76 | "start /b /high /wait cmd /c %s /quiet /install & exit ^!errorlevel^!", | |
| 77 | exe.getAbsolutePath() | |
| 78 | ); | |
| 79 | ||
| 80 | clue( "Wizard.container.install.command", cmd ); | |
| 81 | ||
| 82 | final var builder = processBuilder( "cmd", "/c", cmd ); | |
| 83 | ||
| 84 | try { | |
| 85 | clue( "Wizard.container.install.await", cmd ); | |
| 86 | ||
| 87 | // Wait for installation to finish (successfully or not). | |
| 88 | return wait( builder.start() ); | |
| 89 | } catch( final Exception ignored ) { | |
| 90 | return -1; | |
| 91 | } | |
| 92 | } | |
| 93 | ||
| 94 | @Override | |
| 95 | public void start( final StreamProcessor processor ) | |
| 96 | throws CommandNotFoundException { | |
| 97 | machine( processor, "stop" ); | |
| 98 | podman( processor, "system", "prune", "--force" ); | |
| 99 | machine( processor, "rm", "--force" ); | |
| 100 | machine( processor, "init" ); | |
| 101 | machine( processor, "start" ); | |
| 102 | } | |
| 103 | ||
| 104 | @Override | |
| 105 | public void load( final StreamProcessor processor ) | |
| 106 | throws CommandNotFoundException { | |
| 107 | final var url = Messages.get( "Wizard.typesetter.container.image.url" ); | |
| 108 | ||
| 109 | podman( processor, "load", "-i", url ); | |
| 110 | } | |
| 111 | ||
| 112 | /** | |
| 113 | * Runs: | |
| 114 | * <p> | |
| 115 | * <code>podman run --network=host --rm -t IMAGE /bin/sh -lc</code> | |
| 116 | * </p> | |
| 117 | * followed by the given arguments. | |
| 118 | * | |
| 119 | * @param args The command and arguments to run against the container. | |
| 120 | * @return The exit code from running the container manager (not the | |
| 121 | * exit code from running the command). | |
| 122 | * @throws CommandNotFoundException Container manager couldn't be found. | |
| 123 | */ | |
| 124 | @Override | |
| 125 | public int run( | |
| 126 | final StreamProcessor processor, | |
| 127 | final String... args ) throws CommandNotFoundException { | |
| 128 | final var tag = Messages.get( "Wizard.typesetter.container.image.tag" ); | |
| 129 | ||
| 130 | final var options = new LinkedList<String>(); | |
| 131 | options.add( "run" ); | |
| 132 | options.add( "--rm" ); | |
| 133 | options.add( "--network=host" ); | |
| 134 | options.addAll( mMountPoints ); | |
| 135 | options.add( "-t" ); | |
| 136 | options.add( tag ); | |
| 137 | options.add( "/bin/sh" ); | |
| 138 | options.add( "-lc" ); | |
| 139 | ||
| 140 | final var command = toArray( toArray( options ), args ); | |
| 141 | return podman( processor, command ); | |
| 142 | } | |
| 143 | ||
| 144 | /** | |
| 145 | * Generates a command-line argument representing a mount point between | |
| 146 | * the host and guest systems. | |
| 147 | * | |
| 148 | * @param hostDir The host directory to mount in the container. | |
| 149 | * @param guestDir The guest directory to map from the container to host. | |
| 150 | * @param readonly Set {@code true} to make the mount point read-only. | |
| 151 | */ | |
| 152 | public void mount( | |
| 153 | final Path hostDir, final String guestDir, final boolean readonly ) { | |
| 154 | assert hostDir != null; | |
| 155 | assert guestDir != null; | |
| 156 | assert !guestDir.isBlank(); | |
| 157 | assert toFile( hostDir ).isDirectory(); | |
| 158 | ||
| 159 | mMountPoints.add( | |
| 160 | format( "-v%s:%s:%s", hostDir, guestDir, readonly ? "ro" : "Z" ) | |
| 161 | ); | |
| 162 | } | |
| 163 | ||
| 164 | private static void machine( | |
| 165 | final StreamProcessor processor, | |
| 166 | final String... args ) | |
| 167 | throws CommandNotFoundException { | |
| 168 | podman( processor, toArray( "machine", args ) ); | |
| 169 | } | |
| 170 | ||
| 171 | private static int podman( | |
| 172 | final StreamProcessor processor, final String... args ) | |
| 173 | throws CommandNotFoundException { | |
| 174 | try { | |
| 175 | final var path = getExecutable(); | |
| 176 | final var joined = join( ",", args ); | |
| 177 | ||
| 178 | clue( "Wizard.container.process.enter", path, joined ); | |
| 179 | ||
| 180 | final var builder = processBuilder( path, args ); | |
| 181 | final var process = builder.start(); | |
| 182 | ||
| 183 | processor.start( process.getInputStream() ); | |
| 184 | ||
| 185 | return wait( process ); | |
| 186 | } catch( final Exception ex ) { | |
| 187 | clue( ex ); | |
| 188 | throw new CommandNotFoundException( MANAGER.toString() ); | |
| 189 | } | |
| 190 | } | |
| 191 | ||
| 192 | /** | |
| 193 | * Performs a blocking wait until the {@link Process} completes. | |
| 194 | * | |
| 195 | * @param process The {@link Process} to await completion. | |
| 196 | * @return The exit code from running a command. | |
| 197 | * @throws InterruptedException The {@link Process} was interrupted. | |
| 198 | */ | |
| 199 | private static int wait( final Process process ) throws InterruptedException { | |
| 200 | final var exitCode = process.waitFor(); | |
| 201 | ||
| 202 | clue( "Wizard.container.process.exit", exitCode ); | |
| 203 | ||
| 204 | process.destroy(); | |
| 205 | ||
| 206 | return exitCode; | |
| 207 | } | |
| 208 | ||
| 209 | private static ProcessBuilder processBuilder( final String... args ) { | |
| 210 | final var builder = new ProcessBuilder( args ); | |
| 211 | builder.redirectErrorStream( true ); | |
| 212 | ||
| 213 | return builder; | |
| 214 | } | |
| 215 | ||
| 216 | private static ProcessBuilder processBuilder( | |
| 217 | final File file, final String... s ) { | |
| 218 | return processBuilder( toArray( file.getAbsolutePath(), s ) ); | |
| 219 | } | |
| 220 | ||
| 221 | private static ProcessBuilder processBuilder( | |
| 222 | final Path path, final String... s ) { | |
| 223 | return processBuilder( toFile( path ), s ); | |
| 224 | } | |
| 225 | ||
| 226 | /** | |
| 227 | * Merges two arrays into a single array. | |
| 228 | * | |
| 229 | * @param first The first array to merge before the second array. | |
| 230 | * @param second The second array to merge after the first array. | |
| 231 | * @param <T> The type of arrays to merge. | |
| 232 | * @return The merged arrays, with the first array elements preceding the | |
| 233 | * second array's elements. | |
| 234 | */ | |
| 235 | private static <T> T[] toArray( final T[] first, final T[] second ) { | |
| 236 | assert first != null; | |
| 237 | assert second != null; | |
| 238 | assert first.length > 0; | |
| 239 | assert second.length > 0; | |
| 240 | ||
| 241 | final var merged = copyOf( first, first.length + second.length ); | |
| 242 | arraycopy( second, 0, merged, first.length, second.length ); | |
| 243 | return merged; | |
| 244 | } | |
| 245 | ||
| 246 | /** | |
| 247 | * Convenience method to merge a single string with an array of strings. | |
| 248 | * | |
| 249 | * @param first The first item to prepend to the secondary items. | |
| 250 | * @param second The second item to combine with the first item. | |
| 251 | * @return A new array with the first element at index 0 and the second | |
| 252 | * elements starting at index 1. | |
| 253 | */ | |
| 254 | private static String[] toArray( final String first, String... second ) { | |
| 255 | assert first != null; | |
| 256 | assert second != null; | |
| 257 | assert second.length > 0; | |
| 258 | ||
| 259 | return toArray( new String[]{first}, second ); | |
| 260 | } | |
| 261 | } | |
| 1 | 262 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.typesetting.containerization; | |
| 3 | ||
| 4 | import java.io.InputStream; | |
| 5 | import java.io.PipedInputStream; | |
| 6 | import java.io.PipedOutputStream; | |
| 7 | ||
| 8 | /** | |
| 9 | * Implementations receive an {@link InputStream} for reading, which happens | |
| 10 | * on a separate thread. Implementations are responsible for starting the | |
| 11 | * thread. This class helps avoid relying on {@link PipedInputStream} and | |
| 12 | * {@link PipedOutputStream} to connect the {@link InputStream} from an | |
| 13 | * instance of {@link ProcessBuilder} to process standard output and standard | |
| 14 | * error for a running command. | |
| 15 | */ | |
| 16 | @FunctionalInterface | |
| 17 | public interface StreamProcessor { | |
| 18 | /** | |
| 19 | * Processes the given {@link InputStream} on a separate thread. | |
| 20 | */ | |
| 21 | void start( InputStream in ); | |
| 22 | } | |
| 1 | 23 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.typesetting.installer; | |
| 6 | ||
| 7 | import com.keenwrite.events.ExportFailedEvent; | |
| 8 | import com.keenwrite.preferences.AppKeys; | |
| 9 | import com.keenwrite.preferences.Workspace; | |
| 10 | import com.keenwrite.typesetting.installer.panes.*; | |
| 11 | import org.controlsfx.dialog.Wizard; | |
| 12 | import org.greenrobot.eventbus.Subscribe; | |
| 13 | ||
| 14 | import java.util.LinkedList; | |
| 15 | ||
| 16 | import static com.keenwrite.Messages.get; | |
| 17 | import static com.keenwrite.events.Bus.register; | |
| 18 | import static com.keenwrite.util.SystemUtils.*; | |
| 19 | ||
| 20 | /** | |
| 21 | * Responsible for installing the typesetting system and all its requirements. | |
| 22 | */ | |
| 23 | public final class TypesetterInstaller { | |
| 24 | private final Workspace mWorkspace; | |
| 25 | ||
| 26 | /** | |
| 27 | * Registers for the {@link ExportFailedEvent}, which, when received, | |
| 28 | * indicates that the typesetting software must be installed. | |
| 29 | * | |
| 30 | * @param workspace To set {@link AppKeys#KEY_TYPESET_CONTEXT_THEMES_PATH} via | |
| 31 | * {@link TypesetterThemesDownloadPane}. | |
| 32 | */ | |
| 33 | public TypesetterInstaller( final Workspace workspace ) { | |
| 34 | assert workspace != null; | |
| 35 | ||
| 36 | mWorkspace = workspace; | |
| 37 | ||
| 38 | register( this ); | |
| 39 | } | |
| 40 | ||
| 41 | @Subscribe | |
| 42 | @SuppressWarnings( "unused" ) | |
| 43 | public void handle( final ExportFailedEvent failedEvent ) { | |
| 44 | final var wizard = wizard(); | |
| 45 | ||
| 46 | wizard.showAndWait(); | |
| 47 | } | |
| 48 | ||
| 49 | private Wizard wizard() { | |
| 50 | final var title = get( "Wizard.typesetter.all.1.install.title" ); | |
| 51 | final var wizard = new Wizard( this, title ); | |
| 52 | final var wizardFlow = wizardFlow(); | |
| 53 | ||
| 54 | wizard.setFlow( wizardFlow ); | |
| 55 | ||
| 56 | return wizard; | |
| 57 | } | |
| 58 | ||
| 59 | private Wizard.Flow wizardFlow() { | |
| 60 | final var panels = wizardPanes(); | |
| 61 | return new Wizard.LinearFlow( panels ); | |
| 62 | } | |
| 63 | ||
| 64 | private InstallerPane[] wizardPanes() { | |
| 65 | final var panes = new LinkedList<InstallerPane>(); | |
| 66 | ||
| 67 | // STEP 1: Introduction panel (all) | |
| 68 | panes.add( new IntroductionPane() ); | |
| 69 | ||
| 70 | if( IS_OS_WINDOWS ) { | |
| 71 | // STEP 2 a: Download container (Windows) | |
| 72 | panes.add( new WindowsManagerDownloadPane() ); | |
| 73 | // STEP 2 b: Install container (Windows) | |
| 74 | panes.add( new WindowsManagerInstallPane() ); | |
| 75 | } | |
| 76 | else if( IS_OS_UNIX ) { | |
| 77 | // STEP 2: Install container (Unix) | |
| 78 | panes.add( new UnixManagerInstallPane() ); | |
| 79 | } | |
| 80 | else { | |
| 81 | // STEP 2: Install container (other) | |
| 82 | panes.add( new UniversalManagerInstallPane() ); | |
| 83 | } | |
| 84 | ||
| 85 | if( !IS_OS_LINUX ) { | |
| 86 | // STEP 3: Initialize container (all except Linux) | |
| 87 | panes.add( new ManagerInitializationPane() ); | |
| 88 | } | |
| 89 | ||
| 90 | // STEP 4: Install typesetter container image (all) | |
| 91 | panes.add( new TypesetterImageDownloadPane() ); | |
| 92 | ||
| 93 | // STEP 5: Download and install typesetter themes (all) | |
| 94 | panes.add( new TypesetterThemesDownloadPane( mWorkspace ) ); | |
| 95 | ||
| 96 | return panes.toArray( InstallerPane[]::new ); | |
| 97 | } | |
| 98 | } | |
| 1 | 99 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.typesetting.installer.panes; | |
| 1 | 6 | |
| 7 | import com.keenwrite.io.SysFile; | |
| 8 | import javafx.collections.ObservableMap; | |
| 9 | import javafx.concurrSTR."\{getPrefix()}.download.link.url" STR."\{getPrefix()}.paths", mFilename, directorySTR."\{getPrefix()}\{STATUS}.progress", 0, 0STR."\{STATUS}.checksum\{suffix}"STR."\{getPrefix()}.header"STR."\{STATUS}.success"STR."\{STATUS}.failure" |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.typesetting.installer.panes; | |
| 1 | 6 | |
| 7 | import com.keenwrite.events.HyperlinkOpenEvent; | |
| 8 | import com.keenwrite.typesetting.containerizatiTR."\{prefix}.lbl"TR."\{prefix}.url" |
| 1 | ||
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.typesetting.installer.panescti/** | |
| 6 | * Responsible for informing the user as to what will happen next. | |
| 7 | */ionPanePREFIX = | |
| 8 | extends Installer |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.typesetting.installer.panes; | |
| 6 | ||
| 7 | import com.keenwrite.typesetting.containerization.ContainerManager; | |
| 8 | ||
| 9 | /** | |
| 10 | * Responsible for initializing the container manager on all platforms except | |
| 11 | * for Linux. | |
| 12 | */ | |
| 13 | public final class ManagerInitializationPane extends ManagerOutputPane { | |
| 14 | ||
| 15 | private static final String PREFIX = | |
| 16 | "Wizard.typesetter.all.3.install.container"; | |
| 17 | ||
| 18 | public ManagerInitializationPane() { | |
| 19 | super( | |
| 20 | PREFIX + ".correct", | |
| 21 | PREFIX + ".missing", | |
| 22 | ContainerManager::start, | |
| 23 | 35 | |
| 24 | ); | |
| 25 | } | |
| 26 | ||
| 27 | @Override | |
| 28 | public String getHeaderKey() { | |
| 29 | return PREFIX + ".header"; | |
| 30 | } | |
| 31 | } | |
| 1 | 32 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.typesetting.installer.panes; | |
| 1 | 6 | |
| 7 | import com.keenwrite.io.CommandNotFoundException; | |
| 8 | import com.keenwrite.io.downloads.DownloadManfinal static |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.typesetting.installer.panes; | |
| 6 | ||
| 7 | import com.keenwrite.typesetting.containerization.ContainerManager; | |
| 8 | typesetter's image via the container managerTypesetterImageDownloadPane extends ManagerOutputPane {all.4.download.image"; | |
| 1 | 9 | |
| 10 | public TypesetterImageDownloadPane() { | |
| 11 | super( | |
| 12 | PREFIX + ".correct", | |
| 13 | PREFIX + ".missing", | |
| 14 | ContainerManager::load, | |
| 15 | 45 | |
| 16 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.typesetting.installer.panes; | |
| 6 | ||
| 7 | import com.keenwrite.io.UserDataDir; | |
| 8 | import com.keenwrite.io.Zip; | |
| 9 | import com.keenwrite.preferences.Workspace; | |
| 10 | import javafx.collections.ObservableMap; | |
| 11 | import org.controlsfx.dialog.Wizard; | |
| 12 | ||
| 13 | import java.io.File; | |
| 14 | import java.io.IOException; | |
| 15 | ||
| 16 | import static com.keenwrite.Messages.get; | |
| 17 | import static com.keenwrite.events.StatusEvent.clue; | |
| 18 | import static com.keenwrite.io.SysFile.toFile; | |
| 19 | import static com.keenwrite.preferences.AppKeys.KEY_TYPESET_CONTEXT_THEMES_PATH; | |
| 20 | ||
| 21 | /** | |
| 22 | * Responsible for downloading themes into the application's data directory. | |
| 23 | * The data directory differs between platforms, which is handled | |
| 24 | * transparently by the {@link UserDataDir} class. | |
| 25 | */ | |
| 26 | public class TypesetterThemesDownloadPane extends AbstractDownloadPane { | |
| 27 | private static final String PREFIX = | |
| 28 | "Wizard.typesetter.all.5.download.themes"; | |
| 29 | ||
| 30 | private final Workspace mWorkspace; | |
| 31 | ||
| 32 | public TypesetterThemesDownloadPane( final Workspace workspace ) { | |
| 33 | assert workspace != null; | |
| 34 | mWorkspace = workspace; | |
| 35 | } | |
| 36 | ||
| 37 | @Override | |
| 38 | public void onEnteringPage( final Wizard wizard ) { | |
| 39 | // Delete the target themes file to force re-download so that unzipping | |
| 40 | // the file takes place. This side-steps checksum validation, which would | |
| 41 | // be best implemented after downloading. | |
| 42 | deleteTarget(); | |
| 43 | super.onEnteringPage( wizard ); | |
| 44 | } | |
| 45 | ||
| 46 | @Override | |
| 47 | protected void onDownloadSucceeded( | |
| 48 | final String threadName, final ObservableMap<Object, Object> properties ) { | |
| 49 | super.onDownloadSucceeded( threadName, properties ); | |
| 50 | ||
| 51 | try { | |
| 52 | process( getTarget() ); | |
| 53 | } catch( final Exception ex ) { | |
| 54 | clue( ex ); | |
| 55 | } | |
| 56 | } | |
| 57 | ||
| 58 | private void process( final File target ) throws IOException { | |
| 59 | Zip.extract( target.toPath() ); | |
| 60 | ||
| 61 | // Replace the default themes directory with the downloaded version. | |
| 62 | final var root = toFile( Zip.root( target.toPath() ) ); | |
| 63 | ||
| 64 | // Make sure the typesetter will know where to find the themes. | |
| 65 | mWorkspace.fileProperty( KEY_TYPESET_CONTEXT_THEMES_PATH ).set( root ); | |
| 66 | mWorkspace.save(); | |
| 67 | ||
| 68 | // The themes pack is no longer needed. | |
| 69 | deleteTarget(); | |
| 70 | } | |
| 71 | ||
| 72 | @Override | |
| 73 | protected String getPrefix() { | |
| 74 | return PREFIX; | |
| 75 | } | |
| 76 | ||
| 77 | @Override | |
| 78 | protected String getChecksum() { | |
| 79 | return get( "Wizard.typesetter.themes.checksum" ); | |
| 80 | } | |
| 81 | } | |
| 1 | 82 |
| 1 | ||
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.typesetting.installer.panes; | |
| 6 | u/** | |
| 7 | * Responsible for installing the container manager for any operating system | |
| 8 | * that was not explicitly detected. | |
| 9 | */ | |
| 10 | publil |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.typesetting.installer.panes; | |
| 1 | 6 | |
| 7 | import com.keenwrite.ui.clipboard.SystemClipboard; | |
| 8 | import javafx.geometry.Insets; | |
| 9 | import javafxSTR."\{PREFIX}.copy.began"STR."\{PREFIX}.copy.ended"STR."\{PREFIX}.header"STR."\{PREFIX}.command"STR."\{prefix}.distros"STR."\{prefix}.os.name\{suffix}"STR."\{prefix}.os.text\{suffix}" |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.typesetting.installer.panes; | |
| 6 | ||
| 7 | import typesetting.installer.panes.WindowsManagerInstallPane.WIN_BIN container manager software on Windows. | |
| 8 | */ | |
| 9 | public final class WindowsManagerwin.2.download.container";void updateProperties( | |
| 10 | properties.put( WIN_BIN, getTarget() container.checksum" ); | |
| 11 | } | |
| 12 | } | |
| 1 | 13 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.typesetting.installer.panes; | |
| 6 | ||
| 7 | import com.keenwrite.typesetting.containerization.ContainerManager; | |
| 8 | import javafx.scene.controlTR."\{PREFIX}.status.running"TR."\{PREFIX}.step.0"TR."\{PREFIX}.step.1"TR."\{PREFIX}.step.2"TR."\{PREFIX}.step.3"TR."\{PREFIX}.status"TR."\{key}.success" ) | |
| 9 | : get( STR."\{key}.failure"TR."\{PREFIX}.unknown"TR."\{PREFIX}.header"; | |
| 10 | } | |
| 11 | } | |
| 1 | 12 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.ui.actions; | |
| 3 | ||
| 4 | import com.keenwrite.Messages; | |
| 5 | import com.keenwrite.util.GenericBuilder; | |
| 6 | import com.keenwrite.constants.Constants.ACTION_PREFIX; | |
| 7 | import static com.keenwrite.ui.fonts.IconFactory.createGraphicfinalStringSTR."\{ACTION_PREFIX}\{id}."; | |
| 8 | final var text = STR."\{prefix}STR."\{prefix}STR."\{prefix}/// If there's no icon associated with the icon key name, don't attempt | |
| 9 | // to create a graphic for the icon, because it won't exist. | |
| 10 | final var iconNam mIcon = iconKey.equals( iconName ) ? "" : iconName; | |
| 11 | private static Button createIconButton( final String icon ) { | |
| 12 | return new Button( null, createGraphic( icon ) ); | |
| 13 | } | |
| 14 | ||
| 15 | publfinal String text, | |
| 16 | final String icon, | |
| 17 | createGraphic mIcon // Do not display mnemonic accelerator character in tooltip text. | |
| 18 | // The accelerator key will still be available, this is display-only. | |
| 19 | tooltip = tooltip.replace( "_", "" );STR." (\{}\{')'}"} | |
| 1 | 20 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.ui.actions; | |
| 6 | ||
| 7 | import com.keenwrite.ui.controls.EventedStatusBar; | |
| 8 | import javafx.event.ActionEvent; | |
| 9 | import javafx.event.EventHandler; | |
| 10 | import javafx.scene.Node; | |
| 11 | import javafx.scene.control.Menu; | |
| 12 | import javafx.scene.control.MenuBar; | |
| 13 | import javafx.scene.control.MenuItem; | |
| 14 | import javafx.scene.control.ToolBar; | |
| 15 | import org.controlsfx.control.StatusBar; | |
| 16 | import org.jetbrains.annotations.NotNull; | |
| 17 | ||
| 18 | import java.util.HashMap; | |
| 19 | import java.util.Map; | |
| 20 | ||
| 21 | import static com.keenwrite.Messages.get; | |
| 22 | ||
| 23 | /** | |
| 24 | * Responsible for wiring all application actions to menus, toolbar buttons, | |
| 25 | * and keyboard shortcuts. | |
| 26 | */ | |
| 27 | public final class ApplicationBars { | |
| 28 | ||
| 29 | private static final Map<String, Action> sMap = new HashMap<>( 64 ); | |
| 30 | ||
| 31 | /** | |
| 32 | * Empty constructor. | |
| 33 | */ | |
| 34 | public ApplicationBars() { | |
| 35 | } | |
| 36 | ||
| 37 | /** | |
| 38 | * Creates the main application affordances. | |
| 39 | * | |
| 40 | * @param actions The {@link GuiCommands} that map user interface | |
| 41 | * selections to executable code. | |
| 42 | * @return An instance of {@link MenuBar} that contains the menu. | |
| 43 | */ | |
| 44 | public static MenuBar createMenuBar( final GuiCommands actions ) { | |
| 45 | final var SEPARATOR = new SeparatorAction(); | |
| 46 | ||
| 47 | return new MenuBar( | |
| 48 | createMenuFile( actions, SEPARATOR ), | |
| 49 | createMenuEdit( actions, SEPARATOR ), | |
| 50 | createMenuFormat( actions ), | |
| 51 | createMenuInsert( actions, SEPARATOR ), | |
| 52 | createMenuVariable( actions, SEPARATOR ), | |
| 53 | createMenuView( actions, SEPARATOR ), | |
| 54 | createMenuHelp( actions ) | |
| 55 | ); | |
| 56 | } | |
| 57 | ||
| 58 | @NotNull | |
| 59 | private static Menu createMenuFile( | |
| 60 | final GuiCommands actions, final SeparatorAction SEPARATOR ) { | |
| 61 | // @formatter:off | |
| 62 | return createMenu( | |
| 63 | get( "Main.menu.file" ), | |
| 64 | addAction( "file.new", _ -> actions.file_new() ), | |
| 65 | addAction( "file.open", _ -> actions.file_open() ), | |
| 66 | addAction( "file.open_url", _ -> actions.file_open_url() ), | |
| 67 | SEPARATOR, | |
| 68 | addAction( "file.close", _ -> actions.file_close() ), | |
| 69 | addAction( "file.close_all", _ -> actions.file_close_all() ), | |
| 70 | SEPARATOR, | |
| 71 | addAction( "file.save", _ -> actions.file_save() ), | |
| 72 | addAction( "file.save_as", _ -> actions.file_save_as() ), | |
| 73 | addAction( "file.save_all", _ -> actions.file_save_all() ), | |
| 74 | SEPARATOR, | |
| 75 | addAction( "file.export", _ -> { } ) | |
| 76 | .addSubActions( | |
| 77 | addAction( "file.export.pdf", _ -> actions.file_export_pdf() ), | |
| 78 | addAction( "file.export.pdf.dir", _ -> actions.file_export_pdf_dir() ), | |
| 79 | addAction( "file.export.pdf.repeat", _ -> actions.file_export_repeat() ), | |
| 80 | addAction( "file.export.html.dir", _ -> actions.file_export_html_dir() ), | |
| 81 | addAction( "file.export.text_tex.dir", _ -> actions.file_export_text_tex_dir() ), | |
| 82 | addAction( "file.export.html_svg", _ -> actions.file_export_html_svg() ), | |
| 83 | addAction( "file.export.html_tex", _ -> actions.file_export_html_tex() ), | |
| 84 | addAction( "file.export.text_tex", _ -> actions.file_export_text_tex() ), | |
| 85 | addAction( "file.export.xhtml_tex", _ -> actions.file_export_xhtml_tex() ) | |
| 86 | ), | |
| 87 | SEPARATOR, | |
| 88 | addAction( "file.exit", _ -> actions.file_exit() ) | |
| 89 | ); | |
| 90 | // @formatter:on | |
| 91 | } | |
| 92 | ||
| 93 | @NotNull | |
| 94 | private static Menu createMenuEdit( | |
| 95 | final GuiCommands actions, final SeparatorAction SEPARATOR ) { | |
| 96 | return createMenu( | |
| 97 | get( "Main.menu.edit" ), | |
| 98 | SEPARATOR, | |
| 99 | addAction( "edit.undo", _ -> actions.edit_undo() ), | |
| 100 | addAction( "edit.redo", _ -> actions.edit_redo() ), | |
| 101 | SEPARATOR, | |
| 102 | addAction( "edit.cut", _ -> actions.edit_cut() ), | |
| 103 | addAction( "edit.copy", _ -> actions.edit_copy() ), | |
| 104 | addAction( "edit.paste", _ -> actions.edit_paste() ), | |
| 105 | addAction( "edit.select_all", _ -> actions.edit_select_all() ), | |
| 106 | SEPARATOR, | |
| 107 | addAction( "edit.find", _ -> actions.edit_find() ), | |
| 108 | addAction( "edit.find_next", _ -> actions.edit_find_next() ), | |
| 109 | addAction( "edit.find_prev", _ -> actions.edit_find_prev() ), | |
| 110 | SEPARATOR, | |
| 111 | addAction( "edit.preferences", _ -> actions.edit_preferences() ) | |
| 112 | ); | |
| 113 | } | |
| 114 | ||
| 115 | @NotNull | |
| 116 | private static Menu createMenuFormat( final GuiCommands actions ) { | |
| 117 | return createMenu( | |
| 118 | get( "Main.menu.format" ), | |
| 119 | addAction( "format.bold", _ -> actions.format_bold() ), | |
| 120 | addAction( "format.italic", _ -> actions.format_italic() ), | |
| 121 | addAction( "format.monospace", _ -> actions.format_monospace() ), | |
| 122 | addAction( "format.superscript", _ -> actions.format_superscript() ), | |
| 123 | addAction( "format.subscript", _ -> actions.format_subscript() ), | |
| 124 | addAction( "format.strikethrough", _ -> actions.format_strikethrough() ) | |
| 125 | ); | |
| 126 | } | |
| 127 | ||
| 128 | @NotNull | |
| 129 | private static Menu createMenuInsert( | |
| 130 | final GuiCommands actions, | |
| 131 | final SeparatorAction SEPARATOR ) { | |
| 132 | // @formatter:off | |
| 133 | return createMenu( | |
| 134 | get( "Main.menu.insert" ), | |
| 135 | addAction( "insert.blockquote", _ -> actions.insert_blockquote() ), | |
| 136 | addAction( "insert.code", _ -> actions.insert_code() ), | |
| 137 | addAction( "insert.fenced_code_block", _ -> actions.insert_fenced_code_block() ), | |
| 138 | SEPARATOR, | |
| 139 | addAction( "insert.link", _ -> actions.insert_link() ), | |
| 140 | addAction( "insert.image", _ -> actions.insert_image() ), | |
| 141 | SEPARATOR, | |
| 142 | addAction( "insert.heading_1", _ -> actions.insert_heading_1() ), | |
| 143 | addAction( "insert.heading_2", _ -> actions.insert_heading_2() ), | |
| 144 | addAction( "insert.heading_3", _ -> actions.insert_heading_3() ), | |
| 145 | SEPARATOR, | |
| 146 | addAction( "insert.unordered_list", _ -> actions.insert_unordered_list() ), | |
| 147 | addAction( "insert.ordered_list", _ -> actions.insert_ordered_list() ), | |
| 148 | addAction( "insert.horizontal_rule", _ -> actions.insert_horizontal_rule() ) | |
| 149 | ); | |
| 150 | // @formatter:on | |
| 151 | } | |
| 152 | ||
| 153 | @NotNull | |
| 154 | private static Menu createMenuVariable( | |
| 155 | final GuiCommands actions, final SeparatorAction SEPARATOR ) { | |
| 156 | return createMenu( | |
| 157 | get( "Main.menu.definition" ), | |
| 158 | addAction( "definition.insert", _ -> actions.definition_autoinsert() ), | |
| 159 | SEPARATOR, | |
| 160 | addAction( "definition.create", _ -> actions.definition_create() ), | |
| 161 | addAction( "definition.rename", _ -> actions.definition_rename() ), | |
| 162 | addAction( "definition.delete", _ -> actions.definition_delete() ) | |
| 163 | ); | |
| 164 | } | |
| 165 | ||
| 166 | @NotNull | |
| 167 | private static Menu createMenuView( | |
| 168 | final GuiCommands actions, final SeparatorAction SEPARATOR ) { | |
| 169 | return createMenu( | |
| 170 | get( "Main.menu.view" ), | |
| 171 | addAction( "view.refresh", _ -> actions.view_refresh() ), | |
| 172 | SEPARATOR, | |
| 173 | addAction( "view.preview", _ -> actions.view_preview() ), | |
| 174 | addAction( "view.outline", _ -> actions.view_outline() ), | |
| 175 | addAction( "view.statistics", _ -> actions.view_statistics() ), | |
| 176 | addAction( "view.files", _ -> actions.view_files() ), | |
| 177 | SEPARATOR, | |
| 178 | addAction( "view.menubar", _ -> actions.view_menubar() ), | |
| 179 | addAction( "view.toolbar", _ -> actions.view_toolbar() ), | |
| 180 | addAction( "view.statusbar", _ -> actions.view_statusbar() ), | |
| 181 | SEPARATOR, | |
| 182 | addAction( "view.log", _ -> actions.view_log() ) | |
| 183 | ); | |
| 184 | } | |
| 185 | ||
| 186 | @NotNull | |
| 187 | private static Menu createMenuHelp( final GuiCommands actions ) { | |
| 188 | return createMenu( | |
| 189 | get( "Main.menu.help" ), | |
| 190 | addAction( "help.about", _ -> actions.help_about() ) | |
| 191 | ); | |
| 192 | } | |
| 193 | ||
| 194 | public static Node createToolBar() { | |
| 195 | final var SEPARATOR = new SeparatorAction(); | |
| 196 | ||
| 197 | return createToolBar( | |
| 198 | getAction( "file.new" ), | |
| 199 | getAction( "file.open" ), | |
| 200 | getAction( "file.save" ), | |
| 201 | SEPARATOR, | |
| 202 | getAction( "file.export.pdf" ), | |
| 203 | SEPARATOR, | |
| 204 | getAction( "edit.undo" ), | |
| 205 | getAction( "edit.redo" ), | |
| 206 | getAction( "edit.cut" ), | |
| 207 | getAction( "edit.copy" ), | |
| 208 | getAction( "edit.paste" ), | |
| 209 | SEPARATOR, | |
| 210 | getAction( "format.bold" ), | |
| 211 | getAction( "format.italic" ), | |
| 212 | getAction( "format.superscript" ), | |
| 213 | getAction( "format.subscript" ), | |
| 214 | getAction( "insert.blockquote" ), | |
| 215 | getAction( "insert.code" ), | |
| 216 | getAction( "insert.fenced_code_block" ), | |
| 217 | SEPARATOR, | |
| 218 | getAction( "insert.link" ), | |
| 219 | getAction( "insert.image" ), | |
| 220 | SEPARATOR, | |
| 221 | getAction( "insert.heading_1" ), | |
| 222 | SEPARATOR, | |
| 223 | getAction( "insert.unordered_list" ), | |
| 224 | getAction( "insert.ordered_list" ) | |
| 225 | ); | |
| 226 | } | |
| 227 | ||
| 228 | public static StatusBar createStatusBar() { | |
| 229 | return new EventedStatusBar(); | |
| 230 | } | |
| 231 | ||
| 232 | /** | |
| 233 | * Adds a new action to the list of actions. | |
| 234 | * | |
| 235 | * @param key The name of the action to register in {@link #sMap}. | |
| 236 | * @param handler Performs the action upon request. | |
| 237 | * @return The newly registered action. | |
| 238 | */ | |
| 239 | private static Action addAction( | |
| 240 | final String key, final EventHandler<ActionEvent> handler ) { | |
| 241 | assert key != null; | |
| 242 | assert handler != null; | |
| 243 | ||
| 244 | final var action = Action | |
| 245 | .builder() | |
| 246 | .setId( key ) | |
| 247 | .setHandler( handler ) | |
| 248 | .build(); | |
| 249 | ||
| 250 | sMap.put( key, action ); | |
| 251 | ||
| 252 | return action; | |
| 253 | } | |
| 254 | ||
| 255 | private static Action getAction( final String key ) { | |
| 256 | return sMap.get( key ); | |
| 257 | } | |
| 258 | ||
| 259 | public static Menu createMenu( | |
| 260 | final String text, final MenuAction... actions ) { | |
| 261 | return new Menu( text, null, createMenuItems( actions ) ); | |
| 262 | } | |
| 263 | ||
| 264 | public static MenuItem[] createMenuItems( final MenuAction... actions ) { | |
| 265 | final var menuItems = new MenuItem[ actions.length ]; | |
| 266 | ||
| 267 | for( var i = 0; i < actions.length; i++ ) { | |
| 268 | menuItems[ i ] = actions[ i ].createMenuItem(); | |
| 269 | } | |
| 270 | ||
| 271 | return menuItems; | |
| 272 | } | |
| 273 | ||
| 274 | private static ToolBar createToolBar( final MenuAction... actions ) { | |
| 275 | return new ToolBar( createToolBarButtons( actions ) ); | |
| 276 | } | |
| 277 | ||
| 278 | private static Node[] createToolBarButtons( final MenuAction... actions ) { | |
| 279 | final var len = actions.length; | |
| 280 | final var nodes = new Node[ len ]; | |
| 281 | ||
| 282 | for( var i = 0; i < len; i++ ) { | |
| 283 | nodes[ i ] = actions[ i ].createToolBarNode(); | |
| 284 | } | |
| 285 | ||
| 286 | return nodes; | |
| 287 | } | |
| 288 | } | |
| 1 | 289 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.ui.actions; | |
| 1 | 6 | |
| 7 | import com.keenwrite.ExportFormat; | |
| 8 | import com.keenwrite.MainPane; | |
| 9 | import com.keenwrite.MainScene; | |
| 10 | import com.keeTR."\{prefix}title"TR."\{prefix}header"TR."\{prefix}content" |
| 1 | package com.keenwrite.ui.actions; | |
| 2 | ||
| 3 | import javafx.scene.input.KeyCodeCombination; | |
| 4 | import javafx.scene.input.KeyEvent; | |
| 5 | ||
| 6 | import static javafx.scene.input.KeyCode.C; | |
| 7 | import static javafx.scene.input.KeyCode.INSERT; | |
| 8 | import static javafx.scene.input.KeyCombination.CONTROL_ANY; | |
| 9 | ||
| 10 | public class Keyboard { | |
| 11 | public static final KeyCodeCombination CTRL_C = | |
| 12 | new KeyCodeCombination( C, CONTROL_ANY ); | |
| 13 | public static final KeyCodeCombination CTRL_INSERT = | |
| 14 | new KeyCodeCombination( INSERT, CONTROL_ANY ); | |
| 15 | ||
| 16 | /** | |
| 17 | * Answers whether the user issued a copy request via the keyboard. | |
| 18 | * | |
| 19 | * @param event The keyboard event to examine. | |
| 20 | * @return {@code true} if the user pressed Ctrl+C or Ctrl+Insert. | |
| 21 | */ | |
| 22 | public static boolean isCopy( final KeyEvent event ) { | |
| 23 | return CTRL_C.match( event ) || CTRL_INSERT.match( event ); | |
| 24 | } | |
| 25 | } | |
| 1 | 26 |
| 1 | ||
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.ui.actions; | |
| 3 | ||
| 4 | import javafx.scene.Node; | |
| 5 | import javafx.scene.control.*; | |
| 1 | 6 | |
| 7 | /** | |
| 8 | * Represents a {@link MenuBar} or {@link ToolBar} action that has no | |
| 9 | * operatiofinal |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | ||
| 3 | /** | |
| 4 | * This package contains classes that define commands as executable actions. | |
| 5 | */ | |
| 6 | package com.keenwrite.ui.actions; | |
| 1 | 7 |
| 1 | ||
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved.events.StatusEvent |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.ui.adapters; | |
| 3 | ||
| 4 | import org.w3c.dom.Element; | |
| 5 | import org.xhtmlrenderer.extend.ReplacedElementFactory; | |
| 6 | import org.xhtmlrenderer.simple.extend.FormSubmissionListener; | |
| 7 | ||
| 8 | /** | |
| 9 | * Allows subclasses to implement only specific events of interest. | |
| 10 | */ | |
| 11 | public abstract class ReplacedElementAdapter implements ReplacedElementFactory { | |
| 12 | @Override | |
| 13 | public void reset() { | |
| 14 | } | |
| 15 | ||
| 16 | @Override | |
| 17 | public void remove( final Element e ) { | |
| 18 | } | |
| 19 | ||
| 20 | @Override | |
| 21 | public void setFormSubmissionListener( | |
| 22 | final FormSubmissionListener listener ) { | |
| 23 | } | |
| 24 | } | |
| 1 | 25 |
| 1 | package com.keenwrite.ui.cells; | |
| 1 | 2 | |
| 3 | import javafx.scene.control.cell.TextFieldTableCell; | |
| 4 | import javafx.uti |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.ui.cells; | |
| 1 | 3 |
| 1 | package com.keenwrite.ui.cells; | |
| 2 | ||
| 3 | import javafx.beans.property.ObjectProperty; | |
| 4 | import javafx.beans.property.Property; | |
| 5 | import javafx.beans.property.SimpleStringProperty; | |
| 6 | import javafx.beans.value.ChangeListener; | |
| 7 | import javafx.beans.value.ObservableValue; | |
| 8 | import javafx.event.EventHandler; | |
| 9 | import javafx.scene.Node; | |
| 10 | import javafx.scene.control.TableCell; | |
| 11 | import javafx.scene.control.TextField; | |
| 12 | import javafx.scene.control.TreeCell; | |
| 13 | import javafx.scene.input.KeyEvent; | |
| 14 | ||
| 15 | import java.util.function.Consumer; | |
| 16 | ||
| 17 | import static javafx.application.Platform.runLater; | |
| 18 | import static javafx.scene.input.KeyCode.ENTER; | |
| 19 | import static javafx.scene.input.KeyCode.TAB; | |
| 20 | import static javafx.scene.input.KeyEvent.KEY_RELEASED; | |
| 21 | ||
| 22 | public class CellEditor { | |
| 23 | private FocusListener mFocusListener; | |
| 24 | private final KeyHandler mKeyHandler = new KeyHandler(); | |
| 25 | private final Property<String> mInputText = new SimpleStringProperty(); | |
| 26 | private final Consumer<String> mConsumer; | |
| 27 | ||
| 28 | /** | |
| 29 | * Responsible for accepting the text when users press the Enter or Tab key. | |
| 30 | */ | |
| 31 | private class KeyHandler implements EventHandler<KeyEvent> { | |
| 32 | @Override | |
| 33 | public void handle( final KeyEvent event ) { | |
| 34 | if( event.getCode() == ENTER || event.getCode() == TAB ) { | |
| 35 | commitEdit(); | |
| 36 | event.consume(); | |
| 37 | } | |
| 38 | } | |
| 39 | } | |
| 40 | ||
| 41 | /** | |
| 42 | * Responsible for committing edits when focus is lost. This will also | |
| 43 | * deselect the input field when focus is gained so that typing text won't | |
| 44 | * overwrite the entire existing text. | |
| 45 | */ | |
| 46 | private class FocusListener implements ChangeListener<Boolean> { | |
| 47 | private final TextField mInput; | |
| 48 | ||
| 49 | private FocusListener( final TextField input ) { | |
| 50 | mInput = input; | |
| 51 | } | |
| 52 | ||
| 53 | @Override | |
| 54 | public void changed( | |
| 55 | final ObservableValue<? extends Boolean> c, | |
| 56 | final Boolean endedFocus, final Boolean beganFocus ) { | |
| 57 | ||
| 58 | if( beganFocus ) { | |
| 59 | runLater( mInput::deselect ); | |
| 60 | } | |
| 61 | else if( endedFocus ) { | |
| 62 | commitEdit(); | |
| 63 | } | |
| 64 | } | |
| 65 | } | |
| 66 | ||
| 67 | /** | |
| 68 | * Generalized cell editor suitable for use with {@link TableCell} or | |
| 69 | * {@link TreeCell} instances. | |
| 70 | * | |
| 71 | * @param consumer Converts the field input text to the required | |
| 72 | * data type. | |
| 73 | * @param graphicProperty Defines the graphical user input field. | |
| 74 | */ | |
| 75 | public CellEditor( | |
| 76 | final Consumer<String> consumer, | |
| 77 | final ObjectProperty<Node> graphicProperty ) { | |
| 78 | assert consumer != null; | |
| 79 | mConsumer = consumer; | |
| 80 | ||
| 81 | init( graphicProperty ); | |
| 82 | } | |
| 83 | ||
| 84 | private void init( final ObjectProperty<Node> graphicProperty ) { | |
| 85 | // When the text field is added as the graphics context, we hook into | |
| 86 | // the changed value to get a handle on the text field. From there it is | |
| 87 | // possible to add change the keyboard and focus behaviours. | |
| 88 | graphicProperty.addListener( ( c, o, n ) -> { | |
| 89 | if( o instanceof TextField ) { | |
| 90 | o.removeEventHandler( KEY_RELEASED, mKeyHandler ); | |
| 91 | o.focusedProperty().removeListener( mFocusListener ); | |
| 92 | } | |
| 93 | ||
| 94 | if( n instanceof final TextField input ) { | |
| 95 | n.addEventFilter( KEY_RELEASED, mKeyHandler ); | |
| 96 | mInputText.bind( input.textProperty() ); | |
| 97 | mFocusListener = new FocusListener( input ); | |
| 98 | n.focusedProperty().addListener( mFocusListener ); | |
| 99 | } | |
| 100 | } ); | |
| 101 | } | |
| 102 | ||
| 103 | private void commitEdit() { | |
| 104 | mConsumer.accept( mInputText.getValue() ); | |
| 105 | } | |
| 106 | } | |
| 1 | 107 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.ui.clipboard; | |
| 6 | ||
| 7 | import javafx.scene.control.TableView; | |
| 8 | import javafx.scene.input.ClipboardContent; | |
| 9 | ||
| 10 | import java.util.TreeSet; | |
| 11 | ||
| 12 | import static javafx.scene.input.Clipboard.getSystemClipboard; | |
| 13 | ||
| 14 | /** | |
| 15 | * Responsible for pasting into the computer's clipboard. | |
| 16 | */ | |
| 17 | public class SystemClipboard { | |
| 18 | /** | |
| 19 | * Copies the given text into the clipboard, overwriting all data. | |
| 20 | * | |
| 21 | * @param text The text to insert into the clipboard. | |
| 22 | */ | |
| 23 | public static void write( final String text ) { | |
| 24 | final var contents = new ClipboardContent(); | |
| 25 | contents.putString( text ); | |
| 26 | getSystemClipboard().setContent( contents ); | |
| 27 | } | |
| 28 | ||
| 29 | /** | |
| 30 | * Delegates to {@link #write(String)}. | |
| 31 | * | |
| 32 | * @see #write(String) | |
| 33 | */ | |
| 34 | public static void write( final StringBuilder text ) { | |
| 35 | write( text.toString() ); | |
| 36 | } | |
| 37 | ||
| 38 | /** | |
| 39 | * Copies the contents of the selected rows into the clipboard; code is from | |
| 40 | * <a href="https://stackoverflow.com/a/48126059/59087">StackOverflow</a>. | |
| 41 | * | |
| 42 | * @param table The {@link TableView} having selected rows to copy. | |
| 43 | */ | |
| 44 | public static <T> void write( final TableView<T> table ) { | |
| 45 | final var sb = new StringBuilder( 2048 ); | |
| 46 | final var rows = new TreeSet<Integer>(); | |
| 47 | final var cols = table.getColumns(); | |
| 48 | ||
| 49 | for( final var position : table.getSelectionModel().getSelectedCells() ) { | |
| 50 | rows.add( position.getRow() ); | |
| 51 | } | |
| 52 | ||
| 53 | String rSep = ""; | |
| 54 | ||
| 55 | for( final var row : rows ) { | |
| 56 | sb.append( rSep ); | |
| 57 | ||
| 58 | String cSep = ""; | |
| 59 | ||
| 60 | for( final var column : cols ) { | |
| 61 | sb.append( cSep ); | |
| 62 | ||
| 63 | final var data = column.getCellData( row ); | |
| 64 | sb.append( data == null ? "" : data.toString() ); | |
| 65 | ||
| 66 | cSep = "\t"; | |
| 67 | } | |
| 68 | ||
| 69 | rSep = "\n"; | |
| 70 | } | |
| 71 | ||
| 72 | write( sb ); | |
| 73 | } | |
| 74 | } | |
| 1 | 75 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.ui.controls; | |
| 6 | ||
| 7 | import com.keenwrite.Messages; | |
| 8 | import javafx.event.ActionEvent; | |
| 9 | import javafx.scene.control.Button; | |
| 10 | import javafx.stage.DirectoryChooser; | |
| 11 | ||
| 12 | import java.io.File; | |
| 13 | import java.util.function.Consumer; | |
| 14 | ||
| 15 | import static com.keenwrite.ui.fonts.IconFactory.createGraphic; | |
| 16 | import static org.controlsfx.glyphfont.FontAwesome.Glyph.FILE_ALT; | |
| 17 | ||
| 18 | /** | |
| 19 | * Responsible for browsing directories. | |
| 20 | */ | |
| 21 | public class BrowseButton extends Button { | |
| 22 | /** | |
| 23 | * Initial directory. | |
| 24 | */ | |
| 25 | private final File mDirectory; | |
| 26 | ||
| 27 | /** | |
| 28 | * Called when the user accepts a directory. | |
| 29 | */ | |
| 30 | private final Consumer<File> mConsumer; | |
| 31 | ||
| 32 | public BrowseButton( final File directory, final Consumer<File> consumer ) { | |
| 33 | assert directory != null; | |
| 34 | assert consumer != null; | |
| 35 | ||
| 36 | mDirectory = directory; | |
| 37 | mConsumer = consumer; | |
| 38 | ||
| 39 | setGraphic( createGraphic( FILE_ALT ) ); | |
| 40 | setOnAction( this::browse ); | |
| 41 | } | |
| 42 | ||
| 43 | public void browse( final ActionEvent ignored ) { | |
| 44 | final var chooser = new DirectoryChooser(); | |
| 45 | chooser.setTitle( Messages.get( "BrowseDirectoryButton.chooser.title" ) ); | |
| 46 | chooser.setInitialDirectory( mDirectory ); | |
| 47 | ||
| 48 | final var result = chooser.showDialog( getScene().getWindow() ); | |
| 49 | ||
| 50 | if( result != null ) { | |
| 51 | mConsumer.accept( result ); | |
| 52 | } | |
| 53 | } | |
| 54 | } | |
| 1 | 55 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.ui.controls; | |
| 3 | ||
| 4 | import com.keenwrite.events.StatusEvent; | |
| 5 | import org.controlsfx.control.StatusBar; | |
| 6 | import org.greenrobot.eventbus.Subscribe; | |
| 1 | 7 | |
| 8 | import static comtoString |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.ui.controls; | |
| 3 | ||
| 4 | import javafx.beansstaticstaticstaticstatic | |
| 5 | } | |
| 1 | 6 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.ui.dialogs; | |
| 6 | ||
| 7 | import com.keenwrite.service.events.impl.ButtonOrderPane; | |
| 8 | import javafx.scene.control.Dialog; | |
| 9 | import javafx.stage.Stage; | |
| 10 | import javafx.stage.Window; | |
| 11 | ||
| 12 | import static com.keenwrite.constants.GraphicsConstants.ICON_DIALOG; | |
| 13 | import static com.keenwrite.Messages.get; | |
| 14 | import static com.keenwrite.util.Strings.validate; | |
| 15 | import static javafx.scene.control.ButtonType.CANCEL; | |
| 16 | import static javafx.scene.control.ButtonType.OK; | |
| 17 | ||
| 18 | /** | |
| 19 | * Superclass that abstracts common behaviours for all dialogs. | |
| 20 | * | |
| 21 | * @param <T> The type of dialog to create (usually String). | |
| 22 | */ | |
| 23 | public abstract class AbstractDialog<T> extends Dialog<T> { | |
| 24 | ||
| 25 | /** | |
| 26 | * Ensures that all dialogs can be closed. | |
| 27 | * | |
| 28 | * @param owner The parent window of this dialog. | |
| 29 | * @param title The messages title to display in the title bar. | |
| 30 | */ | |
| 31 | public AbstractDialog( final Window owner, final String title ) { | |
| 32 | assert owner != null; | |
| 33 | assert validate( title ); | |
| 34 | ||
| 35 | setTitle( get( title ) ); | |
| 36 | setResizable( true ); | |
| 37 | ||
| 38 | initOwner( owner ); | |
| 39 | initCloseAction(); | |
| 40 | initDialogPane(); | |
| 41 | initDialogButtons(); | |
| 42 | initComponents(); | |
| 43 | ||
| 44 | if( owner instanceof Stage stage ) { | |
| 45 | initIcon( stage ); | |
| 46 | } | |
| 47 | } | |
| 48 | ||
| 49 | /** | |
| 50 | * Initialize the component layout. | |
| 51 | */ | |
| 52 | protected abstract void initComponents(); | |
| 53 | ||
| 54 | /** | |
| 55 | * Set the dialog to use a button order pane with an OK and a CANCEL button. | |
| 56 | */ | |
| 57 | protected void initDialogPane() { | |
| 58 | setDialogPane( new ButtonOrderPane() ); | |
| 59 | } | |
| 60 | ||
| 61 | /** | |
| 62 | * Set an OK and CANCEL button on the dialog. | |
| 63 | */ | |
| 64 | protected void initDialogButtons() { | |
| 65 | getDialogPane().getButtonTypes().addAll( OK, CANCEL ); | |
| 66 | } | |
| 67 | ||
| 68 | /** | |
| 69 | * Attaches a close request to the dialog's [X] button so that the user | |
| 70 | * can always close the window, even if there's an error. | |
| 71 | */ | |
| 72 | protected final void initCloseAction() { | |
| 73 | final var window = getDialogPane().getScene().getWindow(); | |
| 74 | window.setOnCloseRequest( _ -> window.hide() ); | |
| 75 | } | |
| 76 | ||
| 77 | private void initIcon( final Stage owner ) { | |
| 78 | owner.getIcons().add( ICON_DIALOG ); | |
| 79 | } | |
| 80 | } | |
| 1 | 81 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.ui.dialogs; | |
| 6 | ||
| 7 | import com.keenwrite.Messages; | |
| 8 | import com.keenwrite.service.events.impl.ButtonOrderPane; | |
| 9 | import javafx.application.Platform; | |
| 10 | import javafx.beans.value.ChangeListener; | |
| 11 | import javafx.geometry.Insets; | |
| 12 | import javafx.scene.control.ButtonBar.ButtonData; | |
| 13 | import javafx.scene.control.Dialog; | |
| 14 | import javafx.scene.control.Label; | |
| 15 | import javafx.scene.control.TextField; | |
| 16 | import javafx.scene.layout.ColumnConstraints; | |
| 17 | import javafx.scene.layout.GridPane; | |
| 18 | import javafx.stage.Window; | |
| 19 | ||
| 20 | import java.util.LinkedList; | |
| 21 | import java.util.List; | |
| 22 | ||
| 23 | import static com.keenwrite.Messages.get; | |
| 24 | import static com.keenwrite.util.Strings.validate; | |
| 25 | import static javafx.scene.control.ButtonType.CANCEL; | |
| 26 | import static javafx.scene.control.ButtonType.OK; | |
| 27 | import static javafx.scene.layout.Priority.ALWAYS; | |
| 28 | import static javafx.scene.layout.Priority.NEVER; | |
| 29 | ||
| 30 | /** | |
| 31 | * TODO: This class could be combined with {@link AbstractDialog}, either | |
| 32 | * directly or through inheritance. | |
| 33 | * | |
| 34 | * @param <T> The type of data returned from the dialog upon acceptance. | |
| 35 | */ | |
| 36 | public abstract class CustomDialog<T> extends Dialog<T> { | |
| 37 | private final GridPane mContentPane = new GridPane( 10, 10 ); | |
| 38 | private final List<TextField> mInputFields = new LinkedList<>(); | |
| 39 | ||
| 40 | public CustomDialog( final Window owner, final String title ) { | |
| 41 | assert owner != null; | |
| 42 | assert validate( title ); | |
| 43 | ||
| 44 | initOwner( owner ); | |
| 45 | setTitle( get( title ) ); | |
| 46 | setResizable( true ); | |
| 47 | } | |
| 48 | ||
| 49 | /** | |
| 50 | * Allows for late binding so that input fields can be populated after | |
| 51 | * the constructor is called. | |
| 52 | */ | |
| 53 | protected void initialize() { | |
| 54 | initDialogPane(); | |
| 55 | initDialogButtons(); | |
| 56 | initInputFields(); | |
| 57 | initContentPane(); | |
| 58 | ||
| 59 | assert !mInputFields.isEmpty(); | |
| 60 | ||
| 61 | final var first = mInputFields.getFirst(); | |
| 62 | assert first != null; | |
| 63 | ||
| 64 | Platform.runLater( first::requestFocus ); | |
| 65 | ||
| 66 | setResultConverter( button -> { | |
| 67 | final ButtonData data = button == null ? null : button.getButtonData(); | |
| 68 | return data == ButtonData.OK_DONE ? handleAccept() : null; | |
| 69 | } ); | |
| 70 | } | |
| 71 | ||
| 72 | /** | |
| 73 | * Invoked when the user selects the OK button to confirm the input values. | |
| 74 | * | |
| 75 | * @return The type of data provided by using the dialog. | |
| 76 | */ | |
| 77 | protected abstract T handleAccept(); | |
| 78 | ||
| 79 | /** | |
| 80 | * Subclasses must call this method at least once. | |
| 81 | * | |
| 82 | * @param id The unique identifier for the input field. | |
| 83 | * @param label The input field's label property key. | |
| 84 | * @param prompt The prompt property key, which provides context. | |
| 85 | * @param value The initial value to provide for the field. | |
| 86 | * @see Messages#get(String) | |
| 87 | */ | |
| 88 | protected void addInputField( | |
| 89 | final String id, | |
| 90 | final String label, | |
| 91 | final String prompt, | |
| 92 | final String value, | |
| 93 | final ChangeListener<String> listener ) { | |
| 94 | assert validate( id ); | |
| 95 | assert validate( label ); | |
| 96 | assert validate( prompt ); | |
| 97 | assert validate( value ); | |
| 98 | ||
| 99 | final int row = mInputFields.size(); | |
| 100 | final Label fieldLabel = new Label( get( label ) ); | |
| 101 | final TextField fieldInput = new TextField(); | |
| 102 | ||
| 103 | fieldInput.setPromptText( get( prompt ) ); | |
| 104 | fieldInput.setId( id ); | |
| 105 | fieldInput.textProperty().addListener( listener ); | |
| 106 | fieldInput.setText( value ); | |
| 107 | ||
| 108 | mContentPane.add( fieldLabel, 0, row ); | |
| 109 | mContentPane.add( fieldInput, 1, row ); | |
| 110 | mInputFields.add( fieldInput ); | |
| 111 | } | |
| 112 | ||
| 113 | /** | |
| 114 | * Subclasses must add at least one input field. | |
| 115 | */ | |
| 116 | protected abstract void initInputFields(); | |
| 117 | ||
| 118 | /** | |
| 119 | * Set the dialog to use a button order pane with an OK and a CANCEL button. | |
| 120 | */ | |
| 121 | protected void initDialogPane() { | |
| 122 | setDialogPane( new ButtonOrderPane() ); | |
| 123 | } | |
| 124 | ||
| 125 | /** | |
| 126 | * Set an OK and CANCEL button on the dialog. | |
| 127 | */ | |
| 128 | protected void initDialogButtons() { | |
| 129 | getDialogPane().getButtonTypes().addAll( OK, CANCEL ); | |
| 130 | } | |
| 131 | ||
| 132 | /** | |
| 133 | * Called after the input fields have been added. This adds the input | |
| 134 | * fields to the main dialog pane. | |
| 135 | */ | |
| 136 | protected void initContentPane() { | |
| 137 | mContentPane.setPadding( new Insets( 20, 10, 10, 10 ) ); | |
| 138 | ||
| 139 | final var cc1 = new ColumnConstraints(); | |
| 140 | final var cc2 = new ColumnConstraints(); | |
| 141 | ||
| 142 | cc1.setHgrow( NEVER ); | |
| 143 | cc2.setHgrow( ALWAYS ); | |
| 144 | cc2.setMinWidth( 250 ); | |
| 145 | mContentPane.getColumnConstraints().addAll( cc1, cc2 ); | |
| 146 | ||
| 147 | getDialogPane().setContent( mContentPane ); | |
| 148 | } | |
| 149 | } | |
| 1 | 150 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.ui.dialogs; | |
| 1 | 6 | |
| 7 | import com.keenwrite.events.ExportFailedEvent; | |
| 8 | import com.keenwrite.io.SysFile; | |
| 9 | import com.keenwrite.util.DiacriTR."\{get( key )}:" |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.ui.dialogs; | |
| 6 | ||
| 7 | import com.keenwrite.util.GenericBuilder; | |
| 8 | import javafx.beans.property.StringProperty; | |
| 1 | 9 | |
| 10 | /** | |
| 11 | * Provides export settings such as the selected theme a |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.ui.dialogs; | |
| 6 | ||
| 7 | import com.keenwrite.ui.models.HyperlinkModel; | |
| 8 | import javafx.stage.Window; | |
| 1 | 9 | |
| 10 | /** | |
| 11 | * Dialog to insert or edit a MaTR."\{PREFIX}title"TR."\{PREFIX}label.text", STR."\{PREFIX}prompt.text"TR."\{PREFIX}label.url", STR."\{PREFIX}prompt.url"TR."\{PREFIX}label.title", STR."\{PREFIX}prompt.title" |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.ui.dialogs; | |
| 6 | ||
| 7 | import com.keenwrite.ui.models.ImageModel; | |
| 8 | import javafx.stage.Window; | |
| 9 | ||
| 10 | /** | |
| 11 | * Dialog to enter a MaimageImageimage."; | |
| 12 | ||
| 13 | private final ImageModel mModel; | |
| 1 | 14 | |
| 15 | public ImageImage |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.ui.dialogs; | |
| 6 | ||
| 7 | import com.keenwrite.events.FileOpenEvent; | |
| 8 | import javafx.stage.Window; | |
| 1 | 9 | |
| 10 | import java.io.File; | |
| 11 | import java.net.URITR."\{DOWNLOAD}status."TR."\{PREFIX}title"TR."\{PREFIX}label.url", STR."\{PREFIX}prompt.url"TR."\{DOWNLOAD}fetch"TR."\{DOWNLOAD}exists"TR."\{STATUS}\{suffix}"TR."\{DOWNLOAD}success" STR."\{DOWNLOAD}failure", uri ) |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.ui.explorer; | |
| 3 | ||
| 4 | import java.io.File; | |
| 5 | import java.nio.file.Path; | |
| 6 | import java.util.List; | |
| 7 | import java.util.Optional; | |
| 1 | 8 | |
| 9 | /** | |
| 10 | * Responsible for providing the user w; |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.ui.explorer; | |
| 1 | 3 | |
| 4 | import com.keenwrite.Messages; | |
| 5 | import com.keenwrite.Workspace; | |
| 6 | import javafx.beans.mDirectory.get().toPath() |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.ui.explorer; | |
| 1 | 3 | |
| 4 | import com.keenwrite.events.FileOpenEvent; | |
| 5 | import com.keenwrite.io.SysFile; | |
| 6 | import com.keenwrite.ui.controls.BrowseButton; | |
| 7 | import javafx.beansio.SysFile.toFiltoFile( path toFile( path.normalize() ) );toFile( path |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.ui.fonts; | |
| 1 | 3 | |
| 4 | import com.keenwrite.io.MediaType; | |
| 5 | import com.keenwrite.io.MediaTypeExtension; | |
| 6 | import com.keenwrite.io.SysFile; | |
| 7 | import javafx.scene.Node; | |
| 8 | import fromFilename |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.ui.heuristics; | |
| 3 | ||
| 4 | import com.keenwrite.events.DocumentChangedEvent; | |
| 5 | import com.keenwrite.; | |
| 6 | import com.keenwrite.preferences.Workspace; | |
| 7 | import com.keenwrite.ui.actions.Keyboard; | |
| 8 | import com.keenwrite.ui.clipboard.SystemClipboardkeenAppAppui.heuristics.DocumentStatistics.StatEntrySelectionMode.MULTIPLE extends TableView<StatEntry> { | |
| 9 | ||
| 10 | private WordCounter mWordCounter;mWordCounter = WordCounter.create( workspace.getLocale for rendering, the parsed | |
| 11 | * If that text differs in its hash code | |
| 12 | * implication | |
| 13 | * replaced. | |
| 14 | * outsidefinal var document = event.getDocument(); | |
| 15 | final var wordCount = mWordCounter.count( | |
| 16 | document, ( k, count ) -> | |
| 17 | ); | |
| 1 | 18 | |
| 19 | WordCountEvent.fire( wordCount ); | |
| 20 | } );_FLEX_LAST_COLUMNinitLocaleListener( workspace ); | |
| 21 | initFontListener( workspace ); | |
| 22 | initKeyboardListener(ocaleListenermWordCounter = WordCounter.createFontListenerKeyboardListener() { | |
| 23 | getSelectionModel().setSelectionMode( MULTIPLE ); | |
| 24 | setOnKeyPressed( event -> { | |
| 25 | if( Keyboard.isCopy( event ) ) { | |
| 26 | SystemClipboard.write( this ); | |
| 27 | } | |
| 28 | } |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.ui.heuristics; | |
| 3 | ||
| 4 | import com.whitemagicsoftware.keencount.Tokenizer; | |
| 5 | import com.whitemagicsoftware.keencount.TokenizerFactory; | |
| 6 | ||
| 7 | import java.util.Locale; | |
| 8 | import java.util.function.BiConsumer; | |
| 9 | ||
| 10 | /** | |
| 11 | * Responsible for counting unique words as well as total words in a document. | |
| 12 | */ | |
| 13 | public class WordCounter { | |
| 14 | /** | |
| 15 | * Parses documents into word counts. | |
| 16 | */ | |
| 17 | private final Tokenizer mTokenizer; | |
| 18 | ||
| 19 | /** | |
| 20 | * Constructs a new {@link WordCounter} instance using the given tokenizer. | |
| 21 | * | |
| 22 | * @param tokenizer The class responsible for parsing a document into unique | |
| 23 | * and total word counts. | |
| 24 | */ | |
| 25 | private WordCounter( final Tokenizer tokenizer ) { | |
| 26 | mTokenizer = tokenizer; | |
| 27 | } | |
| 28 | ||
| 29 | /** | |
| 30 | * Counts the number of unique words in the document. | |
| 31 | * | |
| 32 | * @param document The document to tally. | |
| 33 | * @return The total number of words in the document. | |
| 34 | */ | |
| 35 | public int count( final String document ) { | |
| 36 | return count( document, ( k, count ) -> {} ); | |
| 37 | } | |
| 38 | ||
| 39 | /** | |
| 40 | * Counts the number of unique words in the document. | |
| 41 | * | |
| 42 | * @param document The document to tally. | |
| 43 | * @param consumer The action to take for each unique word/count pair. | |
| 44 | * @return The total number of words in the document. | |
| 45 | */ | |
| 46 | public int count( | |
| 47 | final String document, final BiConsumer<String, Integer> consumer ) { | |
| 48 | final var tokens = mTokenizer.tokenize( document ); | |
| 49 | final var sum = new int[]{0}; | |
| 50 | ||
| 51 | tokens.forEach( ( k, v ) -> { | |
| 52 | final var count = v[ 0 ]; | |
| 53 | consumer.accept( k, count ); | |
| 54 | sum[ 0 ] += count; | |
| 55 | } ); | |
| 56 | ||
| 57 | return sum[ 0 ]; | |
| 58 | } | |
| 59 | ||
| 60 | /** | |
| 61 | * Constructs a new {@link WordCounter} capable of tokenizing a document | |
| 62 | * into words using the given {@link Locale}. | |
| 63 | * | |
| 64 | * @param locale The {@link Tokenizer}'s language settings. | |
| 65 | */ | |
| 66 | public static WordCounter create( final Locale locale ) { | |
| 67 | return new WordCounter( createTokenizer( locale ) ); | |
| 68 | } | |
| 69 | ||
| 70 | /** | |
| 71 | * Creates a tokenizer for English text (can handle most Latin languages). | |
| 72 | * | |
| 73 | * @return An English-based tokenizer for counting words. | |
| 74 | */ | |
| 75 | private static Tokenizer createTokenizer( final Locale language ) { | |
| 76 | return TokenizerFactory.create( language ); | |
| 77 | } | |
| 78 | } | |
| 1 | 79 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.ui.listeners; | |
| 3 | ||
| 4 | import com.keenwrite.editors.common.Caret; | |
| 5 | import com.keenwrite.events.CaretMovedEvent; | |
| 6 | import com.keenwrite.events.WordCountEvent; | |
| 7 | import javafx.scene.control.Label; | |
| 8 | import javafx.scene.layout.VBox; | |
| 9 | import org.greenrobot.eventbus.Subscribe; | |
| 10 | ||
| 11 | import static com.keenwrite.events.Bus.register; | |
| 12 | import static javafx.application.Platform.runLater; | |
| 13 | import static javafx.geometry.Pos.BASELINE_CENTER; | |
| 14 | ||
| 15 | /** | |
| 16 | * Responsible for updating the UI whenever the caret changes position. | |
| 17 | * Only one instance of {@link CaretStatus} is allowed, which prevents | |
| 18 | * duplicate adds to the observable property. | |
| 19 | */ | |
| 20 | public class CaretStatus extends VBox { | |
| 21 | ||
| 22 | /** | |
| 23 | * Use an instance of {@link Label} for its built-in CSS style class. | |
| 24 | */ | |
| 25 | private final Label mStatusText = new Label(); | |
| 26 | ||
| 27 | /** | |
| 28 | * Contains caret position information within an editor. | |
| 29 | */ | |
| 30 | private volatile Caret mCaret = Caret.builder().build(); | |
| 31 | ||
| 32 | /** | |
| 33 | * Approximate number of words in the document. | |
| 34 | */ | |
| 35 | private volatile int mCount; | |
| 36 | ||
| 37 | public CaretStatus() { | |
| 38 | setAlignment( BASELINE_CENTER ); | |
| 39 | getChildren().add( mStatusText ); | |
| 40 | register( this ); | |
| 41 | } | |
| 42 | ||
| 43 | @Subscribe | |
| 44 | public void handle( final WordCountEvent event ) { | |
| 45 | mCount = event.getCount(); | |
| 46 | updateStatus( mCaret, mCount ); | |
| 47 | } | |
| 48 | ||
| 49 | @Subscribe | |
| 50 | public void handle( final CaretMovedEvent event ) { | |
| 51 | mCaret = event.getCaret(); | |
| 52 | updateStatus( mCaret, mCount ); | |
| 53 | } | |
| 54 | ||
| 55 | private void updateStatus( final Caret caret, final int count ) { | |
| 56 | assert caret != null; | |
| 57 | runLater( () -> mStatusText.setText( caret + " | " + count ) ); | |
| 58 | } | |
| 59 | } | |
| 1 | 60 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.ui.logging; | |
| 3 | ||
| 4 | import com.keenwrite.events.StatusEvent; | |
| 5 | import com.keenwrite.ui.actions.Keyboard; | |
| 6 | import com.keenwrite.ui.clipboard.SystemClipboard; | |
| 7 | import javafx.beans.property.SimpleStringProperty; | |
| 8 | import// Display the entire date by default. | |
| 9 | colDate.setPrefWidth( 135 ); | |
| 10 | ||
| 11 | // Display most of the message by default. | |
| 12 | colMessage.setPrefWidth( 425 ); | |
| 13 | ||
| 14 | // Display a large portion of the stack trace. | |
| 15 | colTrace.setPrefWidth( 600 ); | |
| 16 | ||
| 17 | mTable.200Keyboard.isCopy( event ) ) { | |
| 18 | SystemClipboard.write default -> { }getClass().getSimpleName() + "} | |
| 1 | 19 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.ui.models; | |
| 6 | ||
| 7 | import com.vladsch.flexmark.ast.Link; | |
| 1 | 8 | |
| 9 | /** | |
| 10 | * Represents the model for a hyperlinkSTR."[%s]\{}" |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.ui.models; | |
| 1 | 6 | |
| 7 | /** | |
| 8 | * Represents the model for an imageSTR."![%s]\{}" |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.ui.models; | |
| 6 | ||
| 7 | import static com.keenwrite.util.Strings.sanitize; | |
| 8 | ||
| 9 | /** | |
| 10 | * Represents the model for an object containing text, url, and title. | |
| 11 | */ | |
| 12 | class ObjectModel { | |
| 13 | private String mText; | |
| 14 | private String mUrl; | |
| 15 | private String mTitle; | |
| 16 | ||
| 17 | /** | |
| 18 | * Constructs a new object model in Markdown format by default with no | |
| 19 | * title (i.e., tooltip). | |
| 20 | * | |
| 21 | * @param text The hyperlink text displayed (e.g., displayed to the user). | |
| 22 | */ | |
| 23 | public ObjectModel( final String text ) { | |
| 24 | this( text, null, null ); | |
| 25 | } | |
| 26 | ||
| 27 | /** | |
| 28 | * Constructs a new object model in Markdown format by default. | |
| 29 | * | |
| 30 | * @param text The text displayed (e.g., to the user). | |
| 31 | * @param url The destination URL (e.g., when clicked). | |
| 32 | * @param title The text title (e.g., shown as a tooltip). | |
| 33 | */ | |
| 34 | public ObjectModel( | |
| 35 | final String text, final String url, final String title ) { | |
| 36 | setText( text ); | |
| 37 | setUrl( url ); | |
| 38 | setTitle( title ); | |
| 39 | } | |
| 40 | ||
| 41 | public void setText( final String text ) { | |
| 42 | mText = sanitize( text ); | |
| 43 | } | |
| 44 | ||
| 45 | public void setUrl( final String url ) { | |
| 46 | mUrl = sanitize( url ); | |
| 47 | } | |
| 48 | ||
| 49 | public void setTitle( final String title ) { | |
| 50 | mTitle = sanitize( title ); | |
| 51 | } | |
| 52 | ||
| 53 | /** | |
| 54 | * Answers whether text has been set for the model. | |
| 55 | * | |
| 56 | * @return true The text description is set. | |
| 57 | */ | |
| 58 | public boolean hasText() { | |
| 59 | return !getText().isEmpty(); | |
| 60 | } | |
| 61 | ||
| 62 | /** | |
| 63 | * Answers whether a title (tooltip) has been set for the model. | |
| 64 | * | |
| 65 | * @return true The title is set. | |
| 66 | */ | |
| 67 | public boolean hasTitle() { | |
| 68 | return !getTitle().isEmpty(); | |
| 69 | } | |
| 70 | ||
| 71 | public String getText() { | |
| 72 | return mText; | |
| 73 | } | |
| 74 | ||
| 75 | public String getUrl() { | |
| 76 | return mUrl; | |
| 77 | } | |
| 78 | ||
| 79 | public String getTitle() { | |
| 80 | return mTitle; | |
| 81 | } | |
| 82 | } | |
| 1 | 83 |
| 1 | package com.keenwrite.ui.outline; | |
| 1 | 2 | |
| 3 | import com.keenwrite.events.Bus; | |
| 4 | import com.keenwrite.events.; | |
| 5 | import com.keenwrite.events.ParseHeadingEvent; | |
| 6 | import javafx.Nodecontrol.TreeCell; | |
| 7 | i |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.ui.spelling; | |
| 1 | 3 | |
| 4 | import com.keenwrite.editors.TextEditor; | |
| 5 | import com.keenwrite.spelling.api.SpellCheckListener; | |
| 6 | import com.keenwrite.spelling.api.SpellChecker;; | |
| 7 | final var count = paragraphs == null ? 0 : paragraphscount |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.ui.tree; | |
| 3 | ||
| 4 | import com.keenwrite.ui.cells.AltTreeCell; | |
| 5 | import javafx.scene.control.TreeItem; | |
| 6 | import javafx.scene.control.TreeView; | |
| 7 | import javafx.util.StringConverter; | |
| 8 | ||
| 9 | /** | |
| 10 | * Responsible for allowing users to edit items in the tree as well as | |
| 11 | * drag and drop. The goal is to be a drop-in replacement for the regular | |
| 12 | * JavaFX {@link TreeView}, which does not offer editing and moving {@link | |
| 13 | * TreeItem} instances. | |
| 14 | * | |
| 15 | * @param <T> The type of data to edit. | |
| 16 | */ | |
| 17 | public class AltTreeView<T> extends TreeView<T> { | |
| 18 | public AltTreeView( | |
| 19 | final TreeItem<T> root, final StringConverter<T> converter ) { | |
| 20 | super( root ); | |
| 21 | ||
| 22 | assert root != null; | |
| 23 | assert converter != null; | |
| 24 | ||
| 25 | setEditable( true ); | |
| 26 | setCellFactory( _ -> new AltTreeCell<>( converter ) ); | |
| 27 | setShowRoot( false ); | |
| 28 | ||
| 29 | // When focus is lost while not editing, deselect all items. | |
| 30 | focusedProperty().addListener( ( _, o, _ ) -> { | |
| 31 | if( o && getEditingItem() == null ) { | |
| 32 | getSelectionModel().clearSelection(); | |
| 33 | } | |
| 34 | } ); | |
| 35 | } | |
| 36 | } | |
| 1 | 37 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.ui.tree; | |
| 3 | ||
| 4 | import javafx.util.StringConverter; | |
| 5 | ||
| 6 | import static com.keenwrite.util.Strings.sanitize; | |
| 7 | ||
| 8 | /** | |
| 9 | * Responsible for converting objects to and from string instances. The | |
| 10 | * tree items contain only strings, so this effectively is a string-to-string | |
| 11 | * converter, which allows the implementation to retain its generics. | |
| 12 | */ | |
| 13 | public class TreeItemConverter extends StringConverter<String> { | |
| 14 | ||
| 15 | @Override | |
| 16 | public String toString( final String object ) { | |
| 17 | return sanitize( object ); | |
| 18 | } | |
| 19 | ||
| 20 | @Override | |
| 21 | public String fromString( final String string ) { | |
| 22 | return sanitize( string ); | |
| 23 | } | |
| 24 | } | |
| 1 | 25 |
| 1 | /* | |
| 2 | * The Alphanum Algorithm is an improved sorting algorithm for strings | |
| 3 | * containing numbers. Rather than sort numbers in ASCII order like | |
| 4 | * a standard sort, this algorithm sorts numbers in numeric order. | |
| 5 | * | |
| 6 | * The Alphanum Algorithm is discussed at http://www.DaveKoelle.com | |
| 7 | * | |
| 8 | * Released under the MIT License - https://opensource.org/licenses/MIT | |
| 9 | * | |
| 10 | * Copyright 2007-2017 David Koelle | |
| 11 | * | |
| 12 | * Permission is hereby granted, free of charge, to any person obtaining | |
| 13 | * a copy of this software and associated documentation files (the "Software"), | |
| 14 | * to deal in the Software without restriction, including without limitation | |
| 15 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 16 | * and/or sell copies of the Software, and to permit persons to whom the | |
| 17 | * Software is furnished to do so, subject to the following conditions: | |
| 18 | * | |
| 19 | * The above copyright notice and this permission notice shall be included | |
| 20 | * in all copies or substantial portions of the Software. | |
| 21 | * | |
| 22 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
| 23 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
| 24 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
| 25 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, | |
| 26 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | |
| 27 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | |
| 28 | * USE OR OTHER DEALINGS IN THE SOFTWARE. | |
| 29 | */ | |
| 30 | package com.keenwrite.util; | |
| 31 | ||
| 32 | import java.io.Serializable; | |
| 33 | import java.util.Comparator; | |
| 34 | ||
| 35 | import static java.lang.Character.isDigit; | |
| 36 | ||
| 37 | /** | |
| 38 | * Responsible for sorting lists that may contain numeric values. Usage: | |
| 39 | * <pre> | |
| 40 | * Collections.sort(list, new AlphanumComparator()); | |
| 41 | * </pre> | |
| 42 | * <p> | |
| 43 | * Where "list" is the list to sort alphanumerically, not lexicographically. | |
| 44 | * </p> | |
| 45 | */ | |
| 46 | public final class AlphanumComparator<T> implements | |
| 47 | Comparator<T>, Serializable { | |
| 48 | ||
| 49 | /** | |
| 50 | * Returns a chunk of text that is continuous with respect to digits or | |
| 51 | * non-digits. | |
| 52 | * | |
| 53 | * @param s The string to compare. | |
| 54 | * @param length The string length, for improved efficiency. | |
| 55 | * @param marker The current index into a subset of the given string. | |
| 56 | * @return The substring {@code s} that is a continuous text chunk of the | |
| 57 | * same character type. | |
| 58 | */ | |
| 59 | private StringBuilder chunk( final String s, final int length, int marker ) { | |
| 60 | assert s != null; | |
| 61 | assert length >= 0; | |
| 62 | assert marker < length; | |
| 63 | ||
| 64 | // Prevent any possible memory re-allocations by using the length. | |
| 65 | final var chunk = new StringBuilder( length ); | |
| 66 | var c = s.charAt( marker ); | |
| 67 | final var chunkType = isDigit( c ); | |
| 68 | ||
| 69 | // While the character at the current position is the same type (numeric or | |
| 70 | // alphabetic), append the character to the current chunk. | |
| 71 | while( marker < length && | |
| 72 | isDigit( c = s.charAt( marker++ ) ) == chunkType ) { | |
| 73 | chunk.append( c ); | |
| 74 | } | |
| 75 | ||
| 76 | return chunk; | |
| 77 | } | |
| 78 | ||
| 79 | /** | |
| 80 | * Performs an alphanumeric comparison of two strings, sorting numerically | |
| 81 | * first when numbers are found within the string. If either argument is | |
| 82 | * {@code null}, this will return zero. | |
| 83 | * | |
| 84 | * @param o1 The object to compare against {@code s2}, converted to string. | |
| 85 | * @param o2 The object to compare against {@code s1}, converted to string. | |
| 86 | * @return a negative integer, zero, or a positive integer if the first | |
| 87 | * argument is less than, equal to, or greater than the second, respectively. | |
| 88 | */ | |
| 89 | @Override | |
| 90 | public int compare( final T o1, final T o2 ) { | |
| 91 | if( o1 == null || o2 == null ) { | |
| 92 | return 0; | |
| 93 | } | |
| 94 | ||
| 95 | final var s1 = o1.toString(); | |
| 96 | final var s2 = o2.toString(); | |
| 97 | final var s1Length = s1.length(); | |
| 98 | final var s2Length = s2.length(); | |
| 99 | ||
| 100 | var thisMarker = 0; | |
| 101 | var thatMarker = 0; | |
| 102 | ||
| 103 | while( thisMarker < s1Length && thatMarker < s2Length ) { | |
| 104 | final var thisChunk = chunk( s1, s1Length, thisMarker ); | |
| 105 | final var thisChunkLength = thisChunk.length(); | |
| 106 | thisMarker += thisChunkLength; | |
| 107 | final var thatChunk = chunk( s2, s2Length, thatMarker ); | |
| 108 | final var thatChunkLength = thatChunk.length(); | |
| 109 | thatMarker += thatChunkLength; | |
| 110 | ||
| 111 | // If both chunks contain numeric characters, sort them numerically | |
| 112 | int result; | |
| 113 | ||
| 114 | if( isDigit( thisChunk.charAt( 0 ) ) && | |
| 115 | isDigit( thatChunk.charAt( 0 ) ) ) { | |
| 116 | // If equal, the first different number counts | |
| 117 | if( (result = thisChunkLength - thatChunkLength) == 0 ) { | |
| 118 | for( var i = 0; i < thisChunkLength; i++ ) { | |
| 119 | result = thisChunk.charAt( i ) - thatChunk.charAt( i ); | |
| 120 | ||
| 121 | if( result != 0 ) { | |
| 122 | return result; | |
| 123 | } | |
| 124 | } | |
| 125 | } | |
| 126 | } | |
| 127 | else { | |
| 128 | result = thisChunk.compareTo( thatChunk ); | |
| 129 | } | |
| 130 | ||
| 131 | if( result != 0 ) { | |
| 132 | return result; | |
| 133 | } | |
| 134 | } | |
| 135 | ||
| 136 | return s1Length - s2Length; | |
| 137 | } | |
| 138 | } | |
| 1 | 139 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.util; | |
| 6 | ||
| 7 | import java.util.*; | |
| 8 | ||
| 9 | /** | |
| 10 | * Responsible for iterating over a list either forwards or backwards. When | |
| 11 | * the iterator reaches the last element in the list, the next element will | |
| 12 | * be the first. When the iterator reaches the first element in the list, | |
| 13 | * the previous element will be the last. | |
| 14 | * <p> | |
| 15 | * Due to the ability to move forwards and backwards through the list, rather | |
| 16 | * than force client classes to track the list index independently, this | |
| 17 | * iterator provides an accessor to the index. The index is zero-based. | |
| 18 | * </p> | |
| 19 | * | |
| 20 | * @param <T> The type of list to be cycled. | |
| 21 | */ | |
| 22 | public final class CyclicIterator<T> implements ListIterator<T> { | |
| 23 | private final List<T> mList; | |
| 24 | ||
| 25 | /** | |
| 26 | * Initialize to an invalid index so that the first calls to either | |
| 27 | * {@link #previous()} or {@link #next()} will return the starting or ending | |
| 28 | * element. | |
| 29 | */ | |
| 30 | private int mIndex = -1; | |
| 31 | ||
| 32 | /** | |
| 33 | * Creates an iterator that cycles indefinitely through the given list. | |
| 34 | * | |
| 35 | * @param list The list to cycle through indefinitely. | |
| 36 | */ | |
| 37 | public CyclicIterator( final Collection<T> list ) { | |
| 38 | mList = new ArrayList<>( list ); | |
| 39 | } | |
| 40 | ||
| 41 | /** | |
| 42 | * @return {@code true} if there is at least one element. | |
| 43 | */ | |
| 44 | @Override | |
| 45 | public boolean hasNext() { | |
| 46 | return !mList.isEmpty(); | |
| 47 | } | |
| 48 | ||
| 49 | /** | |
| 50 | * @return {@code true} if there is at least one element. | |
| 51 | */ | |
| 52 | @Override | |
| 53 | public boolean hasPrevious() { | |
| 54 | return !mList.isEmpty(); | |
| 55 | } | |
| 56 | ||
| 57 | @Override | |
| 58 | public int nextIndex() { | |
| 59 | return computeIndex( +1 ); | |
| 60 | } | |
| 61 | ||
| 62 | @Override | |
| 63 | public int previousIndex() { | |
| 64 | return computeIndex( -1 ); | |
| 65 | } | |
| 66 | ||
| 67 | @Override | |
| 68 | public void remove() { | |
| 69 | mList.remove( mIndex ); | |
| 70 | } | |
| 71 | ||
| 72 | @Override | |
| 73 | public void set( final T t ) { | |
| 74 | mList.set( mIndex, t ); | |
| 75 | } | |
| 76 | ||
| 77 | @Override | |
| 78 | public void add( final T t ) { | |
| 79 | mList.add( mIndex, t ); | |
| 80 | } | |
| 81 | ||
| 82 | /** | |
| 83 | * Returns the next item in the list, which will cycle to the first | |
| 84 | * item as necessary. | |
| 85 | * | |
| 86 | * @return The next item in the list, cycling to the start if needed. | |
| 87 | */ | |
| 88 | @Override | |
| 89 | public T next() { | |
| 90 | return cycle( +1 ); | |
| 91 | } | |
| 92 | ||
| 93 | /** | |
| 94 | * Returns the previous item in the list, which will cycle to the last | |
| 95 | * item as necessary. | |
| 96 | * | |
| 97 | * @return The previous item in the list, cycling to the end if needed. | |
| 98 | */ | |
| 99 | @Override | |
| 100 | public T previous() { | |
| 101 | return cycle( -1 ); | |
| 102 | } | |
| 103 | ||
| 104 | /** | |
| 105 | * Cycles to the next or previous element, depending on the direction value. | |
| 106 | * | |
| 107 | * @param direction Use -1 for previous, +1 for next. | |
| 108 | * @return The next or previous item in the list. | |
| 109 | */ | |
| 110 | private T cycle( final int direction ) { | |
| 111 | try { | |
| 112 | return mList.get( mIndex = computeIndex( direction ) ); | |
| 113 | } catch( final Exception ex ) { | |
| 114 | throw new NoSuchElementException( ex ); | |
| 115 | } | |
| 116 | } | |
| 117 | ||
| 118 | /** | |
| 119 | * Returns the index of the value retrieved from the most recent call to | |
| 120 | * either {@link #previous()} or {@link #next()}. | |
| 121 | * | |
| 122 | * @return The list item index or -1 if no calls have been made to retrieve | |
| 123 | * an item from the list. | |
| 124 | */ | |
| 125 | public int getIndex() { | |
| 126 | return mIndex; | |
| 127 | } | |
| 128 | ||
| 129 | private int computeIndex( final int direction ) { | |
| 130 | final var i = mIndex + direction; | |
| 131 | final var size = mList.size(); | |
| 132 | final var result = i < 0 | |
| 133 | ? size - 1 | |
| 134 | : size == 0 ? 0 : i % size; | |
| 135 | ||
| 136 | // Ensure the invariant holds. | |
| 137 | assert 0 <= result && result < size || size == 0; | |
| 138 | ||
| 139 | return result; | |
| 140 | } | |
| 141 | } | |
| 1 | 142 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.util; | |
| 3 | ||
| 4 | import java.security.MessageDigest; | |
| 5 | import java.security.NoSuchAlgorithmException; | |
| 6 | ||
| 7 | import static java.nio.charset.StandardCharsets.US_ASCII; | |
| 8 | import static java.nio.charset.StandardCharsets.UTF_8; | |
| 9 | ||
| 10 | /** | |
| 11 | * Responsible for converting various data types into other representations. | |
| 12 | */ | |
| 13 | public final class DataTypeConverter { | |
| 14 | private static final byte[] HEX = "0123456789ABCDEF".getBytes( US_ASCII ); | |
| 15 | ||
| 16 | /** | |
| 17 | * Returns a hexadecimal number that represents the bit sequences provided | |
| 18 | * in the given array of bytes. | |
| 19 | * | |
| 20 | * @param bytes The bytes to convert to a hexadecimal string. | |
| 21 | * @return An uppercase-encoded hexadecimal number. | |
| 22 | */ | |
| 23 | public static String toHex( final byte[] bytes ) { | |
| 24 | final var hexChars = new byte[ bytes.length * 2 ]; | |
| 25 | final var len = bytes.length; | |
| 26 | ||
| 27 | for( var i = 0; i < len; i++ ) { | |
| 28 | final var digit = bytes[ i ] & 0xFF; | |
| 29 | ||
| 30 | hexChars[ (i << 1) ] = HEX[ digit >>> 4 ]; | |
| 31 | hexChars[ (i << 1) + 1 ] = HEX[ digit & 0x0F ]; | |
| 32 | } | |
| 33 | ||
| 34 | return new String( hexChars, UTF_8 ); | |
| 35 | } | |
| 36 | ||
| 37 | /** | |
| 38 | * Hashes a string using the SHA-1 algorithm. | |
| 39 | * | |
| 40 | * @param s The string to has. | |
| 41 | * @return The hashed string. | |
| 42 | * @throws NoSuchAlgorithmException Could not find the SHA-1 algorithm. | |
| 43 | */ | |
| 44 | public static byte[] hash( final String s ) throws NoSuchAlgorithmException { | |
| 45 | final var digest = MessageDigest.getInstance( "SHA-1" ); | |
| 46 | return digest.digest( s.getBytes( UTF_8 ) ); | |
| 47 | } | |
| 48 | } | |
| 1 | 49 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.util; | |
| 3 | ||
| 4 | import static java.text.Normalizer.Form.NFD; | |
| 5 | import static java.text.Normalizer.normalize; | |
| 6 | ||
| 7 | /** | |
| 8 | * Responsible for modifying diacritics. | |
| 9 | */ | |
| 10 | public class Diacritics { | |
| 11 | private static final String UNCRITIC = "\\p{M}+"; | |
| 12 | ||
| 13 | /** | |
| 14 | * Returns the value of the string without diacritic marks. | |
| 15 | * | |
| 16 | * @param text The text to normalize. | |
| 17 | * @return A non-null, possibly empty string. | |
| 18 | */ | |
| 19 | public static String remove( final String text ) { | |
| 20 | return normalize( text, NFD ).replaceAll( UNCRITIC, "" ); | |
| 21 | } | |
| 22 | } | |
| 1 | 23 |
| 1 | /* Copyright 2024 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.util; | |
| 6 | ||
| 7 | import org.mozilla.universalchardet.UniversalDetector; | |
| 8 | ||
| 9 | import java.nio.charset.Charset; | |
| 10 | ||
| 11 | import static com.keenwrite.constants.Constants.DEFAULT_CHARSET; | |
| 12 | import static java.nio.charset.Charset.forName; | |
| 13 | import static java.util.Locale.ENGLISH; | |
| 14 | ||
| 15 | /** | |
| 16 | * Wraps the {@link UniversalDetector} with to provide enhanced abilities | |
| 17 | * and bug fixes (if needed). | |
| 18 | */ | |
| 19 | public class EncodingDetector { | |
| 20 | ||
| 21 | private final UniversalDetector mDetector; | |
| 22 | ||
| 23 | public EncodingDetector() { | |
| 24 | mDetector = new UniversalDetector( null ); | |
| 25 | } | |
| 26 | ||
| 27 | /** | |
| 28 | * Returns the character set for the constructed input. This will coerce | |
| 29 | * both US-ASCII and TIS620 to UTF-8. | |
| 30 | * | |
| 31 | * @param bytes The textual content having an as yet unknown encoding. | |
| 32 | * @return The character encoding for the given bytes. | |
| 33 | */ | |
| 34 | public Charset detect( final byte[] bytes ) { | |
| 35 | mDetector.handleData( bytes, 0, bytes.length ); | |
| 36 | mDetector.dataEnd(); | |
| 37 | ||
| 38 | final String detectedCharset = mDetector.getDetectedCharset(); | |
| 39 | ||
| 40 | // TODO: Revert when the issue has been fixed. | |
| 41 | // https://github.com/albfernandez/juniversalchardet/issues/35 | |
| 42 | return switch( detectedCharset ) { | |
| 43 | case null -> DEFAULT_CHARSET; | |
| 44 | case "US-ASCII", "TIS620" -> DEFAULT_CHARSET; | |
| 45 | default -> forName( detectedCharset.toUpperCase( ENGLISH ) ); | |
| 46 | }; | |
| 47 | } | |
| 48 | } | |
| 1 | 49 |
| 1 | /* | |
| 2 | * Licensed to the Apache Software Foundation (ASF) under one or more | |
| 3 | * contributor license agreements. See the NOTICE file distributed with | |
| 4 | * this work for additional information regarding copyright ownership. | |
| 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 | |
| 6 | * (the "License"); you may not use this file except in compliance with | |
| 7 | * the License. You may obtain a copy of the License at | |
| 8 | * | |
| 9 | * http://www.apache.org/licenses/LICENSE-2.0 | |
| 10 | * | |
| 11 | * Unless required by applicable law or agreed to in writing, software | |
| 12 | * distributed under the License is distributed on an "AS IS" BASIS, | |
| 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 14 | * See the License for the specific language governing permissions and | |
| 15 | * limitations under the License. | |
| 16 | */ | |
| 17 | package com.keenwrite.util; | |
| 18 | ||
| 19 | import java.util.function.BiConsumer; | |
| 20 | ||
| 21 | /** | |
| 22 | * A functional interface like {@link BiConsumer} that declares a {@link Throwable}. | |
| 23 | * | |
| 24 | * @param <T> Consumed type 1. | |
| 25 | * @param <U> Consumed type 2. | |
| 26 | * @param <E> The kind of thrown exception or error. | |
| 27 | */ | |
| 28 | @FunctionalInterface | |
| 29 | public interface FailableBiConsumer<T, U, E extends Throwable> { | |
| 30 | ||
| 31 | /** | |
| 32 | * Accepts the given arguments. | |
| 33 | * | |
| 34 | * @param t the first parameter for the consumable to accept | |
| 35 | * @param u the second parameter for the consumable to accept | |
| 36 | * @throws E Thrown when the consumer fails. | |
| 37 | */ | |
| 38 | void accept(T t, U u) throws E; | |
| 39 | } | |
| 1 | 40 |
| 1 | /* Copyright 2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.util; | |
| 3 | ||
| 4 | import java.io.IOException; | |
| 5 | import java.nio.file.Files; | |
| 6 | import java.nio.file.Path; | |
| 7 | import java.util.function.Consumer; | |
| 1 | 8 | |
| 9 | import static java.STR."glob:\{glob}" |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.util; | |
| 1 | 3 | |
| 4 | import java.awt.*; | |
| 5 | import java.awt.font.TextAttribute; | |
| 6 | import java.io.FileInputStream; | |
| 7 | import java.io.IOExLoads | |
| 8 | * preview can display text using non-system fonts |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.util; | |
| 3 | ||
| 4 | import java.util.LinkedList; | |
| 5 | import java.util.List; | |
| 6 | import java.util.function.BiConsumer; | |
| 7 | import java.util.function.Consumer; | |
| 8 | import java.util.functioLinkedassert consumer != null; | |
| 1 | 9 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.util; | |
| 3 | ||
| 4 | import java.io.File; | |
| 5 | import java.net.MalformedURLException; | |
| 6 | import java.net.URI; | |
| 7 | import java.net.URL; | |
| 8 | ||
| 9 | import static com.keenwrite.events.StatusEvent.clue; | |
| 10 | ||
| 11 | /** | |
| 12 | * Represents the type of data encoding scheme used for a universal resource | |
| 13 | * indicator. Prefer to use the {@code is*} methods to check equality because | |
| 14 | * there are cases where the protocol represents more than one possible type | |
| 15 | * (e.g., a Java Archive is a file, so comparing {@link #FILE} directly could | |
| 16 | * lead to incorrect results). | |
| 17 | */ | |
| 18 | public enum ProtocolScheme { | |
| 19 | /** | |
| 20 | * Denotes a local file. | |
| 21 | */ | |
| 22 | FILE( "file" ), | |
| 23 | /** | |
| 24 | * Denotes either HTTP or HTTPS. | |
| 25 | */ | |
| 26 | HTTP( "http" ), | |
| 27 | /** | |
| 28 | * Denotes the File Transfer Protocol. | |
| 29 | */ | |
| 30 | FTP( "ftp" ), | |
| 31 | /** | |
| 32 | * Denotes Java archive file. | |
| 33 | */ | |
| 34 | JAR( "jar" ), | |
| 35 | /** | |
| 36 | * Could not determine scheme (or is not supported by the application). | |
| 37 | */ | |
| 38 | UNKNOWN( "unknown" ); | |
| 39 | ||
| 40 | private final String mPrefix; | |
| 41 | ||
| 42 | ProtocolScheme( final String prefix ) { | |
| 43 | mPrefix = prefix; | |
| 44 | } | |
| 45 | ||
| 46 | /** | |
| 47 | * Returns the protocol for a given URI or file name. | |
| 48 | * | |
| 49 | * @param uri Determine the protocol for this URI or file name. | |
| 50 | * @return The protocol for the given resource. | |
| 51 | */ | |
| 52 | public static ProtocolScheme getProtocol( final String uri ) { | |
| 53 | try { | |
| 54 | return getProtocol( new URI( uri ) ); | |
| 55 | } catch( final Exception ex ) { | |
| 56 | // Using double-slashes is a shorthand to instruct the browser to | |
| 57 | // reference a resource using the parent URL's security model. This | |
| 58 | // is known as a protocol-relative URL. | |
| 59 | return uri.startsWith( "//" ) ? HTTP : valueFrom( new File( uri ) ); | |
| 60 | } | |
| 61 | } | |
| 62 | ||
| 63 | /** | |
| 64 | * Returns the protocol for a given URI or file name. | |
| 65 | * | |
| 66 | * @param uri Determine the protocol for this URI or file name. | |
| 67 | * @return The protocol for the given resource. | |
| 68 | */ | |
| 69 | public static ProtocolScheme getProtocol( final URI uri ) | |
| 70 | throws MalformedURLException { | |
| 71 | return uri.isAbsolute() | |
| 72 | ? valueFrom( uri ) | |
| 73 | : valueFrom( uri.toURL() ); | |
| 74 | } | |
| 75 | ||
| 76 | /** | |
| 77 | * Determines the protocol scheme for a given string. | |
| 78 | * | |
| 79 | * @param protocol A string representing data encoding protocol scheme. | |
| 80 | * @return {@link #UNKNOWN} if the protocol is unrecognized, otherwise a | |
| 81 | * valid value from this enumeration. | |
| 82 | */ | |
| 83 | public static ProtocolScheme valueFrom( final String protocol ) { | |
| 84 | final var sanitized = protocol == null ? "" : protocol.toUpperCase(); | |
| 85 | ||
| 86 | for( final var scheme : values() ) { | |
| 87 | // This will match HTTP/HTTPS as well as FILE*, which may be inaccurate. | |
| 88 | if( sanitized.startsWith( scheme.name() ) ) { | |
| 89 | return scheme; | |
| 90 | } | |
| 91 | } | |
| 92 | ||
| 93 | return UNKNOWN; | |
| 94 | } | |
| 95 | ||
| 96 | /** | |
| 97 | * Determines the protocol scheme for a given {@link File}. | |
| 98 | * | |
| 99 | * @param file A file having a URI that contains a protocol scheme. | |
| 100 | * @return {@link #UNKNOWN} if the protocol is unrecognized, otherwise a | |
| 101 | * valid value from this enumeration. | |
| 102 | */ | |
| 103 | public static ProtocolScheme valueFrom( final File file ) { | |
| 104 | return valueFrom( file.toURI() ); | |
| 105 | } | |
| 106 | ||
| 107 | /** | |
| 108 | * Determines the protocol scheme for a given {@link URI}. | |
| 109 | * | |
| 110 | * @param uri A URI that contains a protocol scheme. | |
| 111 | * @return {@link #UNKNOWN} if the protocol is unrecognized, otherwise a | |
| 112 | * valid value from this enumeration. | |
| 113 | */ | |
| 114 | public static ProtocolScheme valueFrom( final URI uri ) { | |
| 115 | try { | |
| 116 | return valueFrom( uri.toURL() ); | |
| 117 | } catch( final Exception ex ) { | |
| 118 | clue( ex ); | |
| 119 | return UNKNOWN; | |
| 120 | } | |
| 121 | } | |
| 122 | ||
| 123 | /** | |
| 124 | * Determines the protocol scheme for a given {@link URL}. | |
| 125 | * | |
| 126 | * @param url The {@link URL} containing a protocol scheme. | |
| 127 | * @return {@link #UNKNOWN} if the protocol is unrecognized, otherwise a | |
| 128 | * valid value from this enumeration. | |
| 129 | */ | |
| 130 | public static ProtocolScheme valueFrom( final URL url ) { | |
| 131 | return valueFrom( url.getProtocol() ); | |
| 132 | } | |
| 133 | ||
| 134 | /** | |
| 135 | * Answers whether the given {@link URL} points to a remote resource. | |
| 136 | * | |
| 137 | * @param url The {@link URL} containing a protocol scheme. | |
| 138 | * @return {@link true} if the protocol must be fetched via HTTP or FTP. | |
| 139 | */ | |
| 140 | @SuppressWarnings( "unused" ) | |
| 141 | public static boolean isRemote( final URL url ) { | |
| 142 | return valueFrom( url ).isRemote(); | |
| 143 | } | |
| 144 | ||
| 145 | /** | |
| 146 | * Answers {@code true} if the given protocol is for a local file, which | |
| 147 | * includes a JAR file. | |
| 148 | * | |
| 149 | * @return {@code false} the protocol is not a local file reference. | |
| 150 | */ | |
| 151 | public boolean isFile() { | |
| 152 | return this == FILE || this == JAR; | |
| 153 | } | |
| 154 | ||
| 155 | /** | |
| 156 | * Answers whether the given protocol is HTTP or HTTPS. | |
| 157 | * | |
| 158 | * @return {@code true} the protocol is either HTTP or HTTPS. | |
| 159 | */ | |
| 160 | public boolean isHttp() { | |
| 161 | return this == HTTP; | |
| 162 | } | |
| 163 | ||
| 164 | /** | |
| 165 | * Answers whether the given protocol is FTP. | |
| 166 | * | |
| 167 | * @return {@code true} the protocol is FTP. | |
| 168 | */ | |
| 169 | public boolean isFtp() { | |
| 170 | return this == FTP; | |
| 171 | } | |
| 172 | ||
| 173 | /** | |
| 174 | * Answers whether the given protocol represents a remote resource. | |
| 175 | * | |
| 176 | * @return {@code true} the protocol is HTTP or FTP. | |
| 177 | */ | |
| 178 | public boolean isRemote() { | |
| 179 | return isHttp() || isFtp(); | |
| 180 | } | |
| 181 | ||
| 182 | /** | |
| 183 | * Answers {@code true} if the given protocol is for a Java archive file. | |
| 184 | * | |
| 185 | * @return {@code false} the protocol is not a Java archive file. | |
| 186 | */ | |
| 187 | public boolean isJar() { | |
| 188 | return this == JAR; | |
| 189 | } | |
| 190 | ||
| 191 | /** | |
| 192 | * Prepends the protocol scheme to the given path, without a host name. | |
| 193 | * | |
| 194 | * @param path The path to decorate as a URI, including the scheme. | |
| 195 | * @return The | |
| 196 | */ | |
| 197 | public String decorate( final String path ) { | |
| 198 | return getPrefix() + "://" + path; | |
| 199 | } | |
| 200 | ||
| 201 | private String getPrefix() { | |
| 202 | return mPrefix; | |
| 203 | } | |
| 204 | } | |
| 1 | 205 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.util; | |
| 6 | ||
| 7 | import java.util.ArrayList; | |
| 8 | import java.util.List; | |
| 9 | import java.util.function.Predicate; | |
| 1 | 10 | |
| 11 | /** | |
| 12 | * Responsible for answering whether a given integer value fa |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.util; | |
| 1 | 3 | |
| 4 | import java.io.IOException; | |
| 5 | import java.net.URISyntaxException; | |
| 6 | import java.nio.file.FileSystem; | |
| 7 | import java.nio.file.Pat, regardless if they exist within | |
| 8 | * a Java Archive (.jar) file or on the native file system. | |
| 9 | * | |
| 10 | * @see FileWalker#walk(Path, String, Consumer)Walks the given directory hierarchy for files that match the given | |
| 11 | * globbing file name pattern. | |
| 12 | glob Only files matching the pattern will be consumed { | |
| 13 | FileWalker.walk( path, glob, c ); |
| 1 | /* | |
| 2 | * Licensed to the Apache Software Foundation (ASF) under one or more | |
| 3 | * contributor license agreements. See the NOTICE file distributed with | |
| 4 | * this work for additional information regarding copyright ownership. | |
| 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 | |
| 6 | * (the "License"); you may not use this file except in compliance with | |
| 7 | * the License. You may obtain a copy of the License at | |
| 8 | * | |
| 9 | * http://www.apache.org/licenses/LICENSE-2.0 | |
| 10 | * | |
| 11 | * Unless required by applicable law or agreed to in writing, software | |
| 12 | * distributed under the License is distributed on an "AS IS" BASIS, | |
| 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 14 | * See the License for the specific language governing permissions and | |
| 15 | * limitations under the License. | |
| 16 | */ | |
| 17 | package com.keenwrite.util; | |
| 18 | ||
| 19 | import java.lang.reflect.Array; | |
| 20 | import java.util.Arrays; | |
| 21 | import java.util.HashSet; | |
| 22 | import java.util.Set; | |
| 23 | ||
| 24 | import static java.lang.Character.isWhitespace; | |
| 25 | import static java.lang.String.format; | |
| 26 | ||
| 27 | /** | |
| 28 | * Java doesn't allow adding behaviour to its {@link String} class, so these | |
| 29 | * functions have no alternative home. They are duplicated here to eliminate | |
| 30 | * the dependency on an Apache library. Extracting the methods that only | |
| 31 | * the application uses may have some small performance gains, as well, | |
| 32 | * because numerous if clauses have been removed and other code simplified. | |
| 33 | */ | |
| 34 | public class Strings { | |
| 35 | /** | |
| 36 | * The empty String {@code ""}. | |
| 37 | */ | |
| 38 | private static final String EMPTY = ""; | |
| 39 | ||
| 40 | /** | |
| 41 | * Abbreviates a String using ellipses. This will turn | |
| 42 | * "Now is the time for all good men" into "Now is the time for..." | |
| 43 | * | |
| 44 | * @param str the String to check, may be {@code null}. | |
| 45 | * @param width maximum length of result String, must be at least 4. | |
| 46 | * @return abbreviated String, {@code null} if {@code null} String input. | |
| 47 | * @throws IllegalArgumentException if the width is too small. | |
| 48 | */ | |
| 49 | public static String abbreviate( final String str, final int width ) { | |
| 50 | return abbreviate( str, "...", 0, width ); | |
| 51 | } | |
| 52 | ||
| 53 | /** | |
| 54 | * Abbreviates a String using another given String as replacement marker. | |
| 55 | * This will turn"Now is the time for all good men" into "Now is the time | |
| 56 | * for..." if "..." was defined as the replacement marker. | |
| 57 | * | |
| 58 | * @param str the String to check, may be {@code null}. | |
| 59 | * @param abbrMarker the String used as replacement marker. | |
| 60 | * @param width maximum length of result String, must be at least | |
| 61 | * {@code abbrMarker.length + 1}. | |
| 62 | * @return abbreviated String, {@code null} if {@code null} String input. | |
| 63 | * @throws IllegalArgumentException if the width is too small. | |
| 64 | */ | |
| 65 | public static String abbreviate( | |
| 66 | final String str, | |
| 67 | final String abbrMarker, | |
| 68 | final int width ) { | |
| 69 | return abbreviate( str, abbrMarker, 0, width ); | |
| 70 | } | |
| 71 | ||
| 72 | /** | |
| 73 | * Abbreviates a String using a given replacement marker. This will turn | |
| 74 | * "Now is the time for all good men" into "...is the time for..." if "..." | |
| 75 | * was defined as the replacement marker. | |
| 76 | * | |
| 77 | * @param str the String to check, may be {@code null}. | |
| 78 | * @param abbrMarker the String used as replacement marker. | |
| 79 | * @param offset left edge of source String. | |
| 80 | * @param width maximum length of result String, must be at least 4. | |
| 81 | * @return abbreviated String, {@code null} if {@code null} String input. | |
| 82 | * @throws IllegalArgumentException if the width is too small. | |
| 83 | */ | |
| 84 | public static String abbreviate( | |
| 85 | final String str, | |
| 86 | final String abbrMarker, | |
| 87 | int offset, | |
| 88 | final int width ) { | |
| 89 | if( !isEmpty( str ) && EMPTY.equals( abbrMarker ) && width > 0 ) { | |
| 90 | return substring( str, width ); | |
| 91 | } | |
| 92 | ||
| 93 | if( isAnyEmpty( str, abbrMarker ) ) { | |
| 94 | return str; | |
| 95 | } | |
| 96 | ||
| 97 | final int abbrMarkerLen = abbrMarker.length(); | |
| 98 | final int minAbbrWidth = abbrMarkerLen + 1; | |
| 99 | final int minAbbrWidthOffset = abbrMarkerLen + abbrMarkerLen + 1; | |
| 100 | ||
| 101 | if( width < minAbbrWidth ) { | |
| 102 | final String msg = format( "Min abbreviation width: %d", minAbbrWidth ); | |
| 103 | throw new IllegalArgumentException( msg ); | |
| 104 | } | |
| 105 | ||
| 106 | final int strLen = str.length(); | |
| 107 | ||
| 108 | if( strLen <= width ) { | |
| 109 | return str; | |
| 110 | } | |
| 111 | ||
| 112 | if( offset > strLen ) { | |
| 113 | offset = strLen; | |
| 114 | } | |
| 115 | ||
| 116 | if( strLen - offset < width - abbrMarkerLen ) { | |
| 117 | offset = strLen - (width - abbrMarkerLen); | |
| 118 | } | |
| 119 | ||
| 120 | if( offset <= abbrMarkerLen + 1 ) { | |
| 121 | return str.substring( 0, width - abbrMarkerLen ) + abbrMarker; | |
| 122 | } | |
| 123 | ||
| 124 | if( width < minAbbrWidthOffset ) { | |
| 125 | final String msg = format( | |
| 126 | "Min abbreviation width with offset: %d", | |
| 127 | minAbbrWidthOffset | |
| 128 | ); | |
| 129 | throw new IllegalArgumentException( msg ); | |
| 130 | } | |
| 131 | ||
| 132 | if( offset + width - abbrMarkerLen < strLen ) { | |
| 133 | return abbrMarker + abbreviate( | |
| 134 | str.substring( offset ), | |
| 135 | abbrMarker, | |
| 136 | width - abbrMarkerLen | |
| 137 | ); | |
| 138 | } | |
| 139 | ||
| 140 | return abbrMarker + str.substring( strLen - (width - abbrMarkerLen) ); | |
| 141 | } | |
| 142 | ||
| 143 | /** | |
| 144 | * Strips whitespace characters from the end of a String. | |
| 145 | * | |
| 146 | * <p>A {@code null} input String returns {@code null}. | |
| 147 | * An empty string ("") input returns the empty string.</p> | |
| 148 | * | |
| 149 | * @param str the String to remove characters from, may be {@code null}. | |
| 150 | * @return the stripped String, {@code null} if {@code null} input. | |
| 151 | */ | |
| 152 | public static String trimEnd( final String str ) { | |
| 153 | int end = length( str ); | |
| 154 | ||
| 155 | if( end == 0 ) { | |
| 156 | return str; | |
| 157 | } | |
| 158 | ||
| 159 | while( end != 0 && isWhitespace( str.charAt( end - 1 ) ) ) { | |
| 160 | end--; | |
| 161 | } | |
| 162 | ||
| 163 | return str.substring( 0, end ); | |
| 164 | } | |
| 165 | ||
| 166 | /** | |
| 167 | * Strips whitespace characters from the start of a String. | |
| 168 | * | |
| 169 | * <p>A {@code null} input returns {@code null}. | |
| 170 | * An empty string ("") input returns the empty string.</p> | |
| 171 | * | |
| 172 | * @param str the String to remove characters from, may be {@code null}. | |
| 173 | * @return the stripped String, {@code null} if {@code null} input. | |
| 174 | */ | |
| 175 | public static String trimStart( final String str ) { | |
| 176 | final int strLen = length( str ); | |
| 177 | ||
| 178 | if( strLen == 0 ) { | |
| 179 | return str; | |
| 180 | } | |
| 181 | ||
| 182 | int start = 0; | |
| 183 | ||
| 184 | while( start != strLen && isWhitespace( str.charAt( start ) ) ) { | |
| 185 | start++; | |
| 186 | } | |
| 187 | ||
| 188 | return str.substring( start ); | |
| 189 | } | |
| 190 | ||
| 191 | /** | |
| 192 | * Replaces all occurrences of Strings within another String. | |
| 193 | * | |
| 194 | * @param text the haystack, no-op if {@code null}. | |
| 195 | * @param searchList the needles, no-op if {@code null}. | |
| 196 | * @param replacementList the new needles, no-op if {@code null}. | |
| 197 | * @return the text with any replacements processed, {@code null} if | |
| 198 | * {@code null} String input. | |
| 199 | * @throws IllegalArgumentException if the lengths of the arrays are not | |
| 200 | * the same ({@code null} is ok, and/or | |
| 201 | * size 0). | |
| 202 | */ | |
| 203 | public static String replaceEach( final String text, | |
| 204 | final String[] searchList, | |
| 205 | final String[] replacementList ) { | |
| 206 | return replaceEach( text, searchList, replacementList, 0 ); | |
| 207 | } | |
| 208 | ||
| 209 | /** | |
| 210 | * Replace all occurrences of Strings within another String. | |
| 211 | * | |
| 212 | * @param text the haystack, no-op if {@code null}. | |
| 213 | * @param searchList the needles, no-op if {@code null}. | |
| 214 | * @param replacementList the new needles, no-op if {@code null}. | |
| 215 | * @param timeToLive if less than 0 then there is a circular reference | |
| 216 | * and endless loop | |
| 217 | * @return the text with any replacements processed, {@code null} if | |
| 218 | * {@code null} String input. | |
| 219 | * @throws IllegalStateException if the search is repeating and there is | |
| 220 | * an endless loop due to outputs of one | |
| 221 | * being inputs to another | |
| 222 | * @throws IllegalArgumentException if the lengths of the arrays are not | |
| 223 | * the same ({@code null} is ok, and/or | |
| 224 | * size 0) | |
| 225 | */ | |
| 226 | private static String replaceEach( | |
| 227 | final String text, | |
| 228 | final String[] searchList, | |
| 229 | final String[] replacementList, | |
| 230 | final int timeToLive | |
| 231 | ) { | |
| 232 | // If in a recursive call, this shouldn't be less than zero. | |
| 233 | if( timeToLive < 0 ) { | |
| 234 | final Set<String> searchSet = | |
| 235 | new HashSet<>( Arrays.asList( searchList ) ); | |
| 236 | final Set<String> replacementSet = new HashSet<>( Arrays.asList( | |
| 237 | replacementList ) ); | |
| 238 | searchSet.retainAll( replacementSet ); | |
| 239 | if( !searchSet.isEmpty() ) { | |
| 240 | throw new IllegalStateException( | |
| 241 | "Aborting to protect against StackOverflowError - " + | |
| 242 | "output of one loop is the input of another" ); | |
| 243 | } | |
| 244 | } | |
| 245 | ||
| 246 | if( isEmpty( text ) || | |
| 247 | isEmpty( searchList ) || | |
| 248 | isEmpty( replacementList ) || | |
| 249 | isNotEmpty( searchList ) && | |
| 250 | timeToLive == -1 ) { | |
| 251 | return text; | |
| 252 | } | |
| 253 | ||
| 254 | final int searchLength = searchList.length; | |
| 255 | final int replacementLength = replacementList.length; | |
| 256 | ||
| 257 | // make sure lengths are ok, these need to be equal | |
| 258 | if( searchLength != replacementLength ) { | |
| 259 | final String msg = format( | |
| 260 | "Search and Replace array lengths don't match: %d vs %d", | |
| 261 | searchLength, | |
| 262 | replacementLength | |
| 263 | ); | |
| 264 | throw new IllegalArgumentException( msg ); | |
| 265 | } | |
| 266 | ||
| 267 | // keep track of which still have matches | |
| 268 | final boolean[] noMoreMatchesForReplIndex = new boolean[ searchLength ]; | |
| 269 | ||
| 270 | // index on index that the match was found | |
| 271 | int textIndex = -1; | |
| 272 | int replaceIndex = -1; | |
| 273 | int tempIndex; | |
| 274 | ||
| 275 | // index of replace array that will replace the search string found | |
| 276 | // NOTE: logic duplicated below START | |
| 277 | for( int i = 0; i < searchLength; i++ ) { | |
| 278 | if( noMoreMatchesForReplIndex[ i ] || isEmpty( searchList[ i ] ) || replacementList[ i ] == null ) { | |
| 279 | continue; | |
| 280 | } | |
| 281 | tempIndex = text.indexOf( searchList[ i ] ); | |
| 282 | ||
| 283 | // see if we need to keep searching for this | |
| 284 | if( tempIndex == -1 ) { | |
| 285 | noMoreMatchesForReplIndex[ i ] = true; | |
| 286 | } | |
| 287 | else if( textIndex == -1 || tempIndex < textIndex ) { | |
| 288 | textIndex = tempIndex; | |
| 289 | replaceIndex = i; | |
| 290 | } | |
| 291 | } | |
| 292 | // NOTE: logic mostly below END | |
| 293 | ||
| 294 | // no search strings found, we are done | |
| 295 | if( textIndex == -1 ) { | |
| 296 | return text; | |
| 297 | } | |
| 298 | ||
| 299 | int start = 0; | |
| 300 | ||
| 301 | // Guess the result buffer size, to prevent doubling capacity. | |
| 302 | final StringBuilder buf = createStringBuilder( | |
| 303 | text, searchList, replacementList | |
| 304 | ); | |
| 305 | ||
| 306 | while( textIndex != -1 ) { | |
| 307 | for( int i = start; i < textIndex; i++ ) { | |
| 308 | buf.append( text.charAt( i ) ); | |
| 309 | } | |
| 310 | ||
| 311 | buf.append( replacementList[ replaceIndex ] ); | |
| 312 | ||
| 313 | start = textIndex + searchList[ replaceIndex ].length(); | |
| 314 | ||
| 315 | textIndex = -1; | |
| 316 | replaceIndex = -1; | |
| 317 | ||
| 318 | // find the next earliest match | |
| 319 | // NOTE: logic mostly duplicated above START | |
| 320 | for( int i = 0; i < searchLength; i++ ) { | |
| 321 | if( noMoreMatchesForReplIndex[ i ] || isEmpty( searchList[ i ] ) || replacementList[ i ] == null ) { | |
| 322 | continue; | |
| 323 | } | |
| 324 | tempIndex = text.indexOf( searchList[ i ], start ); | |
| 325 | ||
| 326 | // see if we need to keep searching for this | |
| 327 | if( tempIndex == -1 ) { | |
| 328 | noMoreMatchesForReplIndex[ i ] = true; | |
| 329 | } | |
| 330 | else if( textIndex == -1 || tempIndex < textIndex ) { | |
| 331 | textIndex = tempIndex; | |
| 332 | replaceIndex = i; | |
| 333 | } | |
| 334 | } | |
| 335 | ||
| 336 | // NOTE: logic duplicated above END | |
| 337 | } | |
| 338 | ||
| 339 | final int textLength = text.length(); | |
| 340 | for( int i = start; i < textLength; i++ ) { | |
| 341 | buf.append( text.charAt( i ) ); | |
| 342 | } | |
| 343 | ||
| 344 | return replaceEach( | |
| 345 | buf.toString(), | |
| 346 | searchList, | |
| 347 | replacementList, | |
| 348 | timeToLive - 1 | |
| 349 | ); | |
| 350 | } | |
| 351 | ||
| 352 | private static StringBuilder createStringBuilder( | |
| 353 | final String text, | |
| 354 | final String[] searchList, | |
| 355 | final String[] replacementList ) { | |
| 356 | int increase = 0; | |
| 357 | ||
| 358 | // count the replacement text elements that are larger than their | |
| 359 | // corresponding text being replaced | |
| 360 | for( int i = 0; i < searchList.length; i++ ) { | |
| 361 | if( searchList[ i ] == null || replacementList[ i ] == null ) { | |
| 362 | continue; | |
| 363 | } | |
| 364 | final int greater = | |
| 365 | replacementList[ i ].length() - searchList[ i ].length(); | |
| 366 | if( greater > 0 ) { | |
| 367 | increase += 3 * greater; // assume 3 matches | |
| 368 | } | |
| 369 | } | |
| 370 | ||
| 371 | // have upper-bound at 20% increase, then let Java take over | |
| 372 | increase = Math.min( increase, text.length() / 5 ); | |
| 373 | ||
| 374 | return new StringBuilder( text.length() + increase ); | |
| 375 | } | |
| 376 | ||
| 377 | /** | |
| 378 | * Gets a {@link CharSequence} length or {@code 0} if the | |
| 379 | * {@link CharSequence} is {@code null}. | |
| 380 | * | |
| 381 | * @param cs a {@link CharSequence} or {@code null}. | |
| 382 | * @return {@link CharSequence} length or {@code 0} if the | |
| 383 | * {@link CharSequence} is {@code null}. | |
| 384 | */ | |
| 385 | private static int length( final CharSequence cs ) { | |
| 386 | return cs == null ? 0 : cs.length(); | |
| 387 | } | |
| 388 | ||
| 389 | /** | |
| 390 | * Checks if a {@link CharSequence} is empty ("") or {@code null}. | |
| 391 | * | |
| 392 | * @param cs the {@link CharSequence} to check, may be {@code null}. | |
| 393 | * @return {@code true} if the {@link CharSequence} is empty or {@code null}. | |
| 394 | */ | |
| 395 | public static boolean isEmpty( final CharSequence cs ) { | |
| 396 | return cs == null || cs.isEmpty(); | |
| 397 | } | |
| 398 | ||
| 399 | private static boolean isEmpty( final Object[] array ) { | |
| 400 | return array == null || Array.getLength( array ) == 0; | |
| 401 | } | |
| 402 | ||
| 403 | private static boolean isNotEmpty( final Object[] array ) { | |
| 404 | return array != null && Array.getLength( array ) > 0; | |
| 405 | } | |
| 406 | ||
| 407 | private static boolean isAnyEmpty( final CharSequence... css ) { | |
| 408 | if( isNotEmpty( css ) ) { | |
| 409 | for( final CharSequence cs : css ) { | |
| 410 | if( isEmpty( cs ) ) { | |
| 411 | return true; | |
| 412 | } | |
| 413 | } | |
| 414 | } | |
| 415 | ||
| 416 | return false; | |
| 417 | } | |
| 418 | ||
| 419 | /** | |
| 420 | * Gets a substring from the specified String avoiding exceptions. | |
| 421 | * | |
| 422 | * <p>A negative start position can be used to start/end {@code n} | |
| 423 | * characters from the end of the String.</p> | |
| 424 | * | |
| 425 | * <p>The returned substring starts with the character in the {@code start} | |
| 426 | * position and ends before the {@code end} position. All position counting | |
| 427 | * is zero-based -- i.e., to start at the beginning of the string use | |
| 428 | * {@code start = 0}. Negative start and end positions can be used to | |
| 429 | * specify offsets relative to the end of the String.</p> | |
| 430 | * | |
| 431 | * <p>If {@code start} is not strictly to the left of {@code end}, "" | |
| 432 | * is returned.</p> | |
| 433 | * | |
| 434 | * @param str the String to get the substring from, may be {@code null}. | |
| 435 | * @param end the position to end at (exclusive), negative means | |
| 436 | * count back from the end of the String by this many characters | |
| 437 | * @return substring from start position to end position, {@code null} if | |
| 438 | * {@code null} String input | |
| 439 | */ | |
| 440 | private static String substring( final String str, int end ) { | |
| 441 | if( str == null ) { | |
| 442 | return null; | |
| 443 | } | |
| 444 | ||
| 445 | final int len = str.length(); | |
| 446 | ||
| 447 | if( end < 0 ) { | |
| 448 | end = len + end; | |
| 449 | } | |
| 450 | ||
| 451 | if( end > len ) { | |
| 452 | end = len; | |
| 453 | } | |
| 454 | ||
| 455 | final int start = 0; | |
| 456 | ||
| 457 | if( start > end ) { | |
| 458 | return EMPTY; | |
| 459 | } | |
| 460 | ||
| 461 | return str.substring( start, end ); | |
| 462 | } | |
| 463 | ||
| 464 | public static boolean validate( final String s ) { | |
| 465 | assert s != null; | |
| 466 | assert !s.isBlank(); | |
| 467 | ||
| 468 | return true; | |
| 469 | } | |
| 470 | ||
| 471 | public static String sanitize( final String s ) { | |
| 472 | return s == null ? "" : s; | |
| 473 | } | |
| 474 | } | |
| 1 | 475 |
| 1 | /* | |
| 2 | * Licensed to the Apache Software Foundation (ASF) under one or more | |
| 3 | * contributor license agreements. See the NOTICE file distributed with | |
| 4 | * this work for additional information regarding copyright ownership. | |
| 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 | |
| 6 | * (the "License"); you may not use this file except in compliance with | |
| 7 | * the License. You may obtain a copy of the License at | |
| 8 | * | |
| 9 | * http://www.apache.org/licenses/LICENSE-2.0 | |
| 10 | * | |
| 11 | * Unless required by applicable law or agreed to in writing, software | |
| 12 | * distributed under the License is distributed on an "AS IS" BASIS, | |
| 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 14 | * See the License for the specific language governing permissions and | |
| 15 | * limitations under the License. | |
| 16 | */ | |
| 17 | package com.keenwrite.util; | |
| 18 | ||
| 19 | import java.util.Properties; | |
| 20 | ||
| 21 | import static com.keenwrite.util.Strings.isEmpty; | |
| 22 | ||
| 23 | /** | |
| 24 | * Helpers for {@code java.lang.System}. | |
| 25 | */ | |
| 26 | public class SystemUtils { | |
| 27 | ||
| 28 | // System property constants | |
| 29 | // ----------------------------------------------------------------------- | |
| 30 | // These MUST be declared first. Other constants depend on this. | |
| 31 | ||
| 32 | /** | |
| 33 | * The System property name {@value}. | |
| 34 | */ | |
| 35 | public static final String PROPERTY_OS_NAME = "os.name"; | |
| 36 | ||
| 37 | /** | |
| 38 | * Gets the current value from the system properties map. | |
| 39 | * <p> | |
| 40 | * Returns {@code null} if the property cannot be read due to a | |
| 41 | * {@link SecurityException}. | |
| 42 | * </p> | |
| 43 | * | |
| 44 | * @return the current value from the system properties map. | |
| 45 | */ | |
| 46 | @SuppressWarnings( "ConstantValue" ) | |
| 47 | private static String getOsName() { | |
| 48 | assert PROPERTY_OS_NAME != null; | |
| 49 | assert !PROPERTY_OS_NAME.isBlank(); | |
| 50 | ||
| 51 | try { | |
| 52 | final String value = System.getProperty( PROPERTY_OS_NAME ); | |
| 53 | ||
| 54 | return isEmpty( value ) ? "" : value; | |
| 55 | } catch( final SecurityException ignore ) {} | |
| 56 | ||
| 57 | return ""; | |
| 58 | } | |
| 59 | ||
| 60 | /** | |
| 61 | * The Operating System name, derived from Java's system properties. | |
| 62 | * | |
| 63 | * <p> | |
| 64 | * Defaults to empty if the runtime does not have security access to | |
| 65 | * read this property or the property does not exist. | |
| 66 | * </p> | |
| 67 | * <p> | |
| 68 | * This value is initialized when the class is loaded. If | |
| 69 | * {@link System#setProperty(String, String)} or | |
| 70 | * {@link System#setProperties(Properties)} is called after this | |
| 71 | * class is loaded, the value will be out of sync with that System property. | |
| 72 | * </p> | |
| 73 | */ | |
| 74 | public static final String OS_NAME = getOsName(); | |
| 75 | ||
| 76 | /** | |
| 77 | * Is {@code true} if this is AIX. | |
| 78 | * | |
| 79 | * <p> | |
| 80 | * The field will return {@code false} if {@code OS_NAME} is {@code null}. | |
| 81 | * </p> | |
| 82 | */ | |
| 83 | public static final boolean IS_OS_AIX = osNameMatches( "AIX" ); | |
| 84 | ||
| 85 | /** | |
| 86 | * Is {@code true} if this is HP-UX. | |
| 87 | * | |
| 88 | * <p> | |
| 89 | * The field will return {@code false} if {@code OS_NAME} is {@code null}. | |
| 90 | * </p> | |
| 91 | */ | |
| 92 | public static final boolean IS_OS_HP_UX = osNameMatches( "HP-UX" ); | |
| 93 | ||
| 94 | /** | |
| 95 | * Is {@code true} if this is Irix. | |
| 96 | * | |
| 97 | * <p> | |
| 98 | * The field will return {@code false} if {@code OS_NAME} is {@code null}. | |
| 99 | * </p> | |
| 100 | */ | |
| 101 | public static final boolean IS_OS_IRIX = osNameMatches( "Irix" ); | |
| 102 | ||
| 103 | /** | |
| 104 | * Is {@code true} if this is Linux. | |
| 105 | * | |
| 106 | * <p> | |
| 107 | * The field will return {@code false} if {@code OS_NAME} is {@code null}. | |
| 108 | * </p> | |
| 109 | */ | |
| 110 | public static final boolean IS_OS_LINUX = | |
| 111 | osNameMatches( "Linux" ) || | |
| 112 | osNameMatches( "LINUX" ); | |
| 113 | ||
| 114 | /** | |
| 115 | * Is {@code true} if this is Mac. | |
| 116 | * | |
| 117 | * <p> | |
| 118 | * The field will return {@code false} if {@code OS_NAME} is {@code null}. | |
| 119 | * </p> | |
| 120 | */ | |
| 121 | public static final boolean IS_OS_MAC = osNameMatches( "Mac" ); | |
| 122 | ||
| 123 | /** | |
| 124 | * Is {@code true} if this is Mac. | |
| 125 | * | |
| 126 | * <p> | |
| 127 | * The field will return {@code false} if {@code OS_NAME} is {@code null}. | |
| 128 | * </p> | |
| 129 | */ | |
| 130 | public static final boolean IS_OS_MAC_OSX = osNameMatches( "Mac OS X" ); | |
| 131 | ||
| 132 | /** | |
| 133 | * Is {@code true} if this is FreeBSD. | |
| 134 | * | |
| 135 | * <p> | |
| 136 | * The field will return {@code false} if {@code OS_NAME} is {@code null}. | |
| 137 | * </p> | |
| 138 | */ | |
| 139 | public static final boolean IS_OS_FREE_BSD = osNameMatches( "FreeBSD" ); | |
| 140 | ||
| 141 | /** | |
| 142 | * Is {@code true} if this is OpenBSD. | |
| 143 | * | |
| 144 | * <p> | |
| 145 | * The field will return {@code false} if {@code OS_NAME} is {@code null}. | |
| 146 | * </p> | |
| 147 | */ | |
| 148 | public static final boolean IS_OS_OPEN_BSD = osNameMatches( "OpenBSD" ); | |
| 149 | ||
| 150 | /** | |
| 151 | * Is {@code true} if this is NetBSD. | |
| 152 | * | |
| 153 | * <p> | |
| 154 | * The field will return {@code false} if {@code OS_NAME} is {@code null}. | |
| 155 | * </p> | |
| 156 | */ | |
| 157 | public static final boolean IS_OS_NET_BSD = osNameMatches( "NetBSD" ); | |
| 158 | ||
| 159 | /** | |
| 160 | * Is {@code true} if this is Solaris. | |
| 161 | * | |
| 162 | * <p> | |
| 163 | * The field will return {@code false} if {@code OS_NAME} is {@code null}. | |
| 164 | * </p> | |
| 165 | */ | |
| 166 | public static final boolean IS_OS_SOLARIS = osNameMatches( "Solaris" ); | |
| 167 | ||
| 168 | /** | |
| 169 | * Is {@code true} if this is SunOS. | |
| 170 | * | |
| 171 | * <p> | |
| 172 | * The field will return {@code false} if {@code OS_NAME} is {@code null}. | |
| 173 | * </p> | |
| 174 | */ | |
| 175 | public static final boolean IS_OS_SUN_OS = osNameMatches( "SunOS" ); | |
| 176 | ||
| 177 | /** | |
| 178 | * Is {@code true} if this is a UNIX like system, as in any of AIX, HP-UX, | |
| 179 | * Irix, Linux, MacOSX, Solaris or SUN OS. | |
| 180 | * | |
| 181 | * <p> | |
| 182 | * The field will return {@code false} if {@code OS_NAME} is {@code null}. | |
| 183 | * </p> | |
| 184 | */ | |
| 185 | public static final boolean IS_OS_UNIX = | |
| 186 | IS_OS_AIX || | |
| 187 | IS_OS_HP_UX || | |
| 188 | IS_OS_IRIX || | |
| 189 | IS_OS_LINUX || | |
| 190 | IS_OS_MAC_OSX || | |
| 191 | IS_OS_SOLARIS || | |
| 192 | IS_OS_SUN_OS || | |
| 193 | IS_OS_FREE_BSD || | |
| 194 | IS_OS_OPEN_BSD || | |
| 195 | IS_OS_NET_BSD; | |
| 196 | ||
| 197 | /** | |
| 198 | * The prefix String for all Windows OS. | |
| 199 | */ | |
| 200 | private static final String OS_NAME_WINDOWS_PREFIX = "Windows"; | |
| 201 | ||
| 202 | /** | |
| 203 | * Is {@code true} if this is Windows. | |
| 204 | * | |
| 205 | * <p> | |
| 206 | * The field will return {@code false} if {@code OS_NAME} is {@code null}. | |
| 207 | * </p> | |
| 208 | */ | |
| 209 | public static final boolean IS_OS_WINDOWS = | |
| 210 | osNameMatches( OS_NAME_WINDOWS_PREFIX ); | |
| 211 | ||
| 212 | /** | |
| 213 | * Decides if the operating system matches. | |
| 214 | * <p> | |
| 215 | * This method is package private instead of private to support unit test | |
| 216 | * invocation. | |
| 217 | * </p> | |
| 218 | * | |
| 219 | * @param prefix the prefix for the expected OS name | |
| 220 | * @return true if matches, or false if not or can't determine | |
| 221 | */ | |
| 222 | private static boolean osNameMatches( final String prefix ) { | |
| 223 | return OS_NAME.startsWith( prefix ); | |
| 224 | } | |
| 225 | } | |
| 1 | 226 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.util; | |
| 3 | ||
| 4 | import java.time.Duration; | |
| 5 | ||
| 6 | /** | |
| 7 | * Responsible for time-related functionality. | |
| 8 | */ | |
| 9 | public final class Time {duration An elapsed timeString toElapsedTime( final Duration duration ) { | |
| 10 | final var elapsed = duration.toMillis();} | |
| 1 | 11 |
| 1 | module keenwrite.main { | |
| 2 | requires java.desktop; | |
| 3 | requires java.prefs; | |
| 4 | requires java.scripting; | |
| 5 | requires java.xml; | |
| 6 | requires javafx.graphics; | |
| 7 | requires javafx.controls; | |
| 8 | requires javafx.swing; | |
| 9 | ||
| 10 | requires annotations; | |
| 1 | 11 | |
| 12 | requires echosvg.anim; | |
| 13 | requires echosvg.bridge; | |
| 14 | requires echosvg.css; | |
| 15 | requires echosvg.gvt; | |
| 16 | requires echosvgechosvg |
| 1 | ||
| 1 | com.keenwrite.service.impl.DefaultSettings |
| 1 | ||
| 1 | com.keenwrite.service.events.impl.DefaultNotifier |
| 1 | application.title=KeenWrite | |
| 1 | 2 |
| 1 | app.properties | |
| 1 | 2 |
| 1 | ||
| 1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> | |
| 2 | <svg | |
| 3 | xmlns:dc="http://purl.org/dc/elements/1.1/" | |
| 4 | xmlns:cc="http://creativecommons.org/ns#" | |
| 5 | xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | |
| 6 | xmlns:svg="http://www.w3.org/2000/svg" | |
| 7 | 971.53119" | |
| 8 | height="498.39355" | |
| 9 | viewBox="0 0 971.53119 498.3935app-title | |
| 10 | inkscape:export-filename="/home/jarvisd/dev/java/scrivenvar/docs/images/app-title.png" | |
| 11 | inkscape:export-xdpi="24.66" | |
| 12 | inkscape:export-ydpi="24.66 /455.5775" | |
| 13 | inkscape:cy="347.59625 | |
| 14 | fit-margin-top="0" | |
| 15 | fit-margin-left="0" | |
| 16 | fit-margin-right="0" | |
| 17 | fit-margin-bottom="033 | |
| 18 | transform="translate(-394.35834,-171.20491)"opacity:1opacity:1opacity:1fill:#000000transform="translate(-394.35834,-171.20491)" />" | |
| 19 | x="311.66693" | |
| 20 | y="402.2062766693" | |
| 21 | y="402.20627 |
| 1 | /* Copyright 2020 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | ||
| 3 | .markdown { | |
| 4 | -fx-font-family: 'Noto Sans'; | |
| 5 | -fx-font-size: 11pt; | |
| 6 | -fx-padding: .25em; | |
| 7 | } | |
| 8 | ||
| 9 | /* Editor background color */ | |
| 10 | .styled-text-area { | |
| 11 | -fx-background-color: -fx-control-inner-background; | |
| 12 | } | |
| 13 | ||
| 14 | /* Text foreground colour */ | |
| 15 | .styled-text-area .text { | |
| 16 | -fx-fill: -fx-text-foreground; | |
| 17 | } | |
| 1 | 18 | |
| 19 | /* Subtly highlight the current paragraph. */ | |
| 20 | .markdown .paragraph-box:has-caret { | |
| 21 | -fx-b-fx-text-background-fx-text-selection 255, 131, 67, .7 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | .markdown { | |
| 2 | -fx-font-family: 'Noto Sans CJK JP'; | |
| 3 | } | |
| 1 | 4 |
| 1 | .markdown { | |
| 2 | -fx-font-family: 'Noto Sans CJK KR'; | |
| 3 | } | |
| 1 | 4 |
| 1 | .markdown { | |
| 2 | -fx-font-family: 'Noto Sans CJK SC'; | |
| 3 | } | |
| 1 | 4 |
| 1 | .markdown { | |
| 2 | -fx-font-family: 'Noto Sans CJK SC'; | |
| 3 | } | |
| 1 | 4 |
| 1 | .markdown { | |
| 2 | -fx-font-family: 'Noto Sans CJK HK'; | |
| 3 | } | |
| 1 | 4 |
| 1 | .markdown { | |
| 2 | -fx-font-family: 'Noto Sans CJK TC'; | |
| 3 | } | |
| 1 | 4 |
| 1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> | |
| 2 | <svg | |
| 3 | xmlns:dc="http://purl.org/dc/elements/1.1/" | |
| 4 | xmlns:cc="http://creativecommons.org/ns#" | |
| 5 | xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | |
| 6 | xmlns:svg="http://www.w3.org/2000/svg" | |
| 7 | ||
| 8 | sodipodi:docname="icon.svg" | |
| 9 | id="svg52" | |
| 10 | xml:space="preserve" | |
| 11 | viewBox="0 0 512 512" | |
| 12 | height="512" | |
| 13 | width="512" | |
| 14 | version="1.1 | |
| 15 | inkscape:cy="369.17559" | |
| 16 | inkscape:cx="343.24925objecttolerance="10bordercolor="#666666id="rect933" | |
| 17 | height="175.55823" | |
| 18 | width="470.12033" | |
| 19 | y="132.06313" | |
| 20 | x="114.92139x1="0.15235768" | |
| 21 | y1="-0.0449115712="-0.049471263"> | |
| 22 | <stop | |
| 23 | offset="0%id="stop9" /> | |
| 24 | <stop | |
| 25 | offset="100%id="stop11transform="translate(-384.01706,-164.40168)"id="path14 /><path | |
| 26 | id="path22opacity:1" /><path | |
| 27 | id="path26opacity:1" /><path | |
| 28 | id="path30" /><path | |
| 29 | id="path34" /><path | |
| 30 | id="path38" /><path | |
| 31 | id="path42opacity:1" /></g> | |
| 32 | ||
| 33 | <text | |
| 34 | style="fill:#000000id="text931" | |
| 35 | xml:space="preserve" /></svg> | |
| 1 | 36 |
| 1 | # ######################################################################## | |
| 2 | # Main Application Window | |
| 3 | # ######################################################################## | |
| 4 | ||
| 5 | # suppress inspection "UnusedProperty" for whole file | |
| 1 | 6 | |
| 7 | # ##################### |
| 1 | body,h1,h2,h3,h4,h5,h6,ol,p,ul{margin:0;padding:0}img{max-width:100%;height:auto}table{table-collapse:collapse;table-spacing:0;border-spacing:0} | |
| 1 | 2 | |
| 3 | /* Do not use points (pt): FlyingSaucer on Debian fails to render. */ | |
| 4 | body { | |
| 5 | color: #454545; | |
| 6 | background-c (" attr(data-type) " reference) |
| 1 | body { | |
| 2 | font-family: 'Noto Serif CJK JP'; | |
| 3 | } | |
| 4 | ||
| 5 | pre, code, tt { | |
| 6 | font-family: 'Noto Sans Mono CJK JP'; | |
| 7 | } | |
| 1 | 8 |
| 1 | body { | |
| 2 | font-family: 'Noto Serif CJK KR'; | |
| 3 | } | |
| 4 | ||
| 5 | pre, code, tt { | |
| 6 | font-family: 'Noto Sans Mono CJK KR'; | |
| 7 | } | |
| 1 | 8 |
| 1 | body { | |
| 2 | font-family: 'Noto Serif CJK SC'; | |
| 3 | } | |
| 4 | ||
| 5 | pre, code, tt { | |
| 6 | font-family: 'Noto Sans Mono CJK SC'; | |
| 7 | } | |
| 1 | 8 |
| 1 | body { | |
| 2 | font-family: 'Noto Serif CJK SC'; | |
| 3 | } | |
| 4 | ||
| 5 | pre, code, tt { | |
| 6 | font-family: 'Noto Sans Mono CJK SC'; | |
| 7 | } | |
| 1 | 8 |
| 1 | body { | |
| 2 | font-family: 'Noto Serif CJK SC'; | |
| 3 | } | |
| 4 | ||
| 5 | pre, code, tt { | |
| 6 | font-family: 'Noto Sans Mono CJK HK'; | |
| 7 | } | |
| 1 | 8 |
| 1 | body { | |
| 2 | font-family: 'Noto Serif CJK TC'; | |
| 3 | } | |
| 4 | ||
| 5 | pre, code, tt { | |
| 6 | font-family: 'Noto Sans Mono CJK TC'; | |
| 7 | } | |
| 1 | 8 |
| 1 | # suppress inspection "UnusedProperty" for whole file | |
| 2 | ||
| 3 | # ######################################################################## | |
| 4 | # Application | |
| 5 | # ######################################################################## | |
| 6 | ||
| 7 | application.title=keenwrite | |
| 8 | application.package=com/${application.title} | |
| 9 | application.messages= com.${application.title}.messages | |
| 10 | ||
| 11 | # Suppress multiple file modified notifications for one logical modification. | |
| 12 | # Given in milliseconds. | |
| 13 | application.watchdog.timeout=50 | |
| 14 | ||
| 15 | # ######################################################################## | |
| 16 | # Preferences | |
| 17 | # ######################################################################## | |
| 18 | ||
| 19 | preferences.root=com.${application.title} | |
| 20 | preferences.root.state=state | |
| 21 | preferences.root.options=options | |
| 22 | preferences.root.definition.source=definition.source | |
| 23 | ||
| 24 | # ######################################################################## | |
| 25 | # File and Path References | |
| 26 | # ######################################################################## | |
| 27 | ||
| 28 | file.stylesheet.application.dir=${application.package}/skins | |
| 29 | file.stylesheet.application.base=${file.stylesheet.application.dir}/scene.css | |
| 30 | file.stylesheet.application.skin=${file.stylesheet.application.dir}/{0}.css | |
| 31 | file.stylesheet.markdown=${application.package}/editor/markdown.css | |
| 32 | # {0} language code, {1} script code, {2} country code | |
| 33 | file.stylesheet.markdown.locale=${application.package}/editor/markdown_{0}-{1}-{2}.css | |
| 34 | file.stylesheet.xml=${application.package}/xml.css | |
| 35 | ||
| 36 | # Preview styles are loaded statically through a class's classloader. | |
| 37 | file.stylesheet.preview=webview.css | |
| 38 | # {0} language code, {1} script code, {2} country code | |
| 39 | file.stylesheet.preview.locale=webview_{0}-{1}-{2}.css | |
| 40 | ||
| 41 | file.logo.16=${application.package}/logo16.png | |
| 42 | file.logo.32=${application.package}/logo32.png | |
| 43 | file.logo.128=${application.package}/logo128.png | |
| 44 | file.logo.256=${application.package}/logo256.png | |
| 45 | file.logo.512=${application.package}/logo512.png | |
| 46 | ||
| 47 | # Default file name when a new file is created. | |
| 48 | # This ensures that the file type can always be | |
| 49 | # discerned so that the correct type of variable | |
| 50 | # reference can be inserted. | |
| 51 | file.default.document.prefix=untitled | |
| 52 | file.default.document.suffix=md | |
| 53 | file.default.document=${file.default.document.prefix}.${file.default.document.suffix} | |
| 54 | file.default.definition=variables.yaml | |
| 55 | ||
| 56 | # Default file name to be replaced by the most | |
| 57 | # recently exported file name. | |
| 58 | file.default.pdf=untitled.pdf | |
| 59 | ||
| 60 | # ######################################################################## | |
| 61 | # File name Extensions | |
| 62 | # ######################################################################## | |
| 63 | ||
| 64 | # Comma-separated list of definition file name extensions. | |
| 65 | definition.file.ext.json=*.json | |
| 66 | definition.file.ext.toml=*.toml | |
| 67 | definition.file.ext.yaml=*.yml,*.yaml | |
| 68 | definition.file.ext.properties=*.properties,*.props | |
| 69 | ||
| 70 | # Comma-separated list of file name extensions. | |
| 71 | file.ext.rmarkdown=*.Rmd | |
| 72 | file.ext.rxml=*.Rxml | |
| 73 | file.ext.source=*.md,*.markdown,*.mkdown,*.mdown,*.mkdn,*.mkd,*.mdwn,*.mdtxt,*.mdtext,*.text,*.txt,${file.ext.rmarkdown},${file.ext.rxml} | |
| 74 | file.ext.definition=${definition.file.ext.yaml} | |
| 75 | file.ext.xml=*.xml,${file.ext.rxml} | |
| 76 | file.ext.all=*.* | |
| 77 | ||
| 78 | # File name extension search order for images. | |
| 79 | file.ext.image.order=svg pdf png jpg tiff | |
| 80 | ||
| 81 | # ######################################################################## | |
| 82 | # Variable Name Editor | |
| 83 | # ######################################################################## | |
| 84 | ||
| 85 | # Maximum number of characters for a variable name. A variable is defined | |
| 86 | # as one or more non-whitespace characters up to this maximum length. | |
| 87 | editor.variable.maxLength=256 | |
| 88 | ||
| 89 | # ######################################################################## | |
| 90 | # Dialog Preferences | |
| 91 | # ######################################################################## | |
| 92 | ||
| 93 | dialog.alert.button.order.mac=L_HE+U+FBIX_NCYOA_R | |
| 94 | dialog.alert.button.order.linux=L_HE+UNYACBXIO_R | |
| 95 | dialog.alert.button.order.windows=L_E+U+FBXI_YNOCAH_R | |
| 96 | ||
| 97 | # Ensures a consistent button order for alert dialogs across platforms (because | |
| 98 | # the default button order on Linux defies all logic). | |
| 99 | dialog.alert.button.order=${dialog.alert.button.order.windows} | |
| 1 | 100 |
| 1 | .root { | |
| 2 | -fx-base: rgb( 43, 43, 43 ); | |
| 3 | -fx-background: -fx-base;: -fx-base; | |
| 4 | 187, 187, 187 ); | |
| 5 | -fx-mid-text-color: derive( -fx-base, 100%derive( -fx-base, 25% ); | |
| 6 | -fx-text-foreground: -fx-light-text-color; | |
| 7 | -fx-text-background7.5% ); | |
| 8 | -fx-text-selection45% ); | |
| 9 | ||
| 10 | /* Make controls ( buttons, thumb, etc. ) slightly lighter */ | |
| 11 | -fx-color: derive( -fx-base20% ); | |
| 12 | } | |
| 1 | 13 | |
| 14 | .caret { | |
| 15 | -fx-stroke: -fx-accentfx-light-text-color; | |
| 16 | -fx-fill:hover { | |
| 17 | -fx-effect: dropshadow( three-pass-box, rgba( 0, 0, 0, 0.2 ), 4, 0, 0, 0 ) -fx-light-text-color |
| 1 | /* https://stackoverflow.com/a/58441758/59087 | |
| 2 | */ | |
| 3 | .root { | |
| 4 | -fx-accent: #1e74c6; | |
| 5 | -fx-focus-color: -fx-accent; | |
| 6 | -fx-base: #373e43; | |
| 7 | -fx-control-inner-background: derive( -fx-base, 35% ); | |
| 8 | -fx-control-inner-background-alt: -fx-control-inner-background; | |
| 9 | ||
| 10 | -fx-light-text-color: derive( -fx-base, 150% ); | |
| 11 | -fx-mid-text-color: derive( -fx-base, 100% ); | |
| 12 | -fx-dark-text-color: derive( -fx-base, 25% ); | |
| 13 | -fx-text-foreground: -fx-light-text-color; | |
| 14 | -fx-text-background: derive( -fx-control-inner-background, 7.5% ); | |
| 15 | -fx-text-selection: derive( -fx-control-inner-background, 45% ); | |
| 16 | } | |
| 17 | ||
| 18 | .glyph-icon { | |
| 19 | -fx-text-fill: -fx-light-text-color; | |
| 20 | -fx-fill: -fx-light-text-color; | |
| 21 | } | |
| 22 | ||
| 23 | .glyph-icon:hover { | |
| 24 | -fx-effect: dropshadow( three-pass-box, rgba( 0, 0, 0, 0.2 ), 4, 0, 0, 0 ); | |
| 25 | } | |
| 26 | ||
| 27 | .label { | |
| 28 | -fx-text-fill: -fx-light-text-color; | |
| 29 | } | |
| 30 | ||
| 31 | .text-field { | |
| 32 | -fx-prompt-text-fill: gray; | |
| 33 | } | |
| 34 | ||
| 35 | .button { | |
| 36 | -fx-focus-traversable: false; | |
| 37 | } | |
| 38 | ||
| 39 | .button:hover { | |
| 40 | -fx-text-fill: white; | |
| 41 | } | |
| 42 | ||
| 43 | .separator *.line { | |
| 44 | -fx-background-color: #3C3C3C; | |
| 45 | -fx-border-style: solid; | |
| 46 | -fx-border-width: 1px; | |
| 47 | } | |
| 48 | ||
| 49 | .scroll-bar { | |
| 50 | -fx-background-color: derive( -fx-base, 45% ); | |
| 51 | } | |
| 52 | ||
| 53 | .button:default { | |
| 54 | -fx-base: -fx-accent; | |
| 55 | } | |
| 56 | ||
| 57 | .table-view { | |
| 58 | -fx-selection-bar-non-focused: derive( -fx-base, 50% ); | |
| 59 | } | |
| 60 | ||
| 61 | .table-view .column-header .label { | |
| 62 | -fx-alignment: CENTER_LEFT; | |
| 63 | -fx-font-weight: none; | |
| 64 | } | |
| 65 | ||
| 66 | .list-cell:even, | |
| 67 | .list-cell:odd, | |
| 68 | .table-row-cell:even, | |
| 69 | .table-row-cell:odd { | |
| 70 | -fx-control-inner-background: derive( -fx-base, 15% ); | |
| 71 | } | |
| 72 | ||
| 73 | .list-cell:empty, | |
| 74 | .table-row-cell:empty { | |
| 75 | -fx-background-color: transparent; | |
| 76 | } | |
| 77 | ||
| 78 | .list-cell, | |
| 79 | .table-row-cell { | |
| 80 | -fx-border-color: transparent; | |
| 81 | -fx-table-cell-border-color: transparent; | |
| 82 | } | |
| 83 | ||
| 84 | /* Avoid clipping text descenders in statistics table row. */ | |
| 85 | .table-row-cell { | |
| 86 | -fx-cell-size: 30px; | |
| 87 | } | |
| 1 | 88 |
| 1 | /* https://github.com/joffrey-bion/javafx-themes/blob/master/css/modena_dark.css | |
| 2 | */ | |
| 3 | .root { | |
| 4 | -fx-base: rgb( 50, 50, 50 ); | |
| 5 | -fx-background: -fx-base; | |
| 1 | 6 | |
| 7 | /* Make controls ( buttons, thumb, etc. ) slightly lighter */ | |
| 8 | -fx-color: derive( -fx-base |
| 1 | .root { | |
| 2 | -fx-text-foreground: -fx-dark-text-color; | |
| 3 | -fx-text-background: derive( -fx-accent, 124% ); | |
| 4 | -fx-text-selection: #a6d2ff; | |
| 5 | } | |
| 1 | 6 |
| 1 | /* | |
| 2 | * Theme contributed by mery6299 | |
| 3 | * | |
| 4 | * https://github.com/mery6299 | |
| 5 | */ | |
| 6 | .root { | |
| 7 | -fx-accent: #75715E; | |
| 8 | -fx-focus-color: -fx-accent; | |
| 9 | -fx-base: #262626; | |
| 10 | -fx-control-inner-background: -fx-base; | |
| 11 | -fx-control-inner-background-alt: -fx-control-inner-backgroundtheme-text-selection: #78dce8; | |
| 12 | -theme-search-selection: #ffd8662theme-text-selection, -50% ); | |
| 13 | } | |
| 14 | ||
| 15 | /* Caret colour */ | |
| 16 | .styled-text-area .caret { | |
| 17 | -fx-stroke: white; | |
| 18 | } | |
| 19 | ||
| 20 | /* Spelling errors */ | |
| 21 | .markdown .spelling { | |
| 22 | -rtfx-underline-color: #fc9867; | |
| 23 | } | |
| 24 | ||
| 25 | /* Search result */ | |
| 26 | .markdown .search { | |
| 27 | -rtfx-background-color: derive( -theme-search-selection, -2derive( -fx-accent, -25% ) | |
| 28 | /* Toolbar */ | |
| 29 | .tool-bar .button:hoveaccent, -25% ); | |
| 30 | -fx-color: -fx-hover-base; | |
| 31 | } | |
| 32 | ||
| 33 | /* Tabs */ | |
| 34 | .tab-pane *.tab-header-background { | |
| 35 | -fx-background-color: -fx-base; | |
| 36 | } | |
| 37 | ||
| 38 | .tab:selected { | |
| 39 | -fx-background-color: derive( #A9DC76, -30% ); | |
| 40 | } | |
| 41 | ||
| 1 | 42 |
| 1 | .tool-bar { | |
| 2 | -fx-spacing: 0; | |
| 3 | } | |
| 4 | ||
| 5 | .tool-bar .button { | |
| 6 | -fx-background-color: transparent; | |
| 7 | } | |
| 8 | ||
| 9 | .tool-bar .button:hover { | |
| 10 | -fx-background-color: -fx-shadow-highlight-color, -fx-outer-border, -fx-inner-border, -fx-body-color; | |
| 11 | -fx-color: -fx-hover-base; | |
| 12 | } | |
| 13 | ||
| 14 | .tool-bar .button:armed { | |
| 15 | -fx-color: -fx-pressed-base; | |
| 16 | } | |
| 17 | ||
| 18 | /* Definition editor drag and drop target. | |
| 19 | */ | |
| 20 | .drop-target { | |
| 21 | -fx-border-color: #eea82f; | |
| 22 | -fx-border-width: 0 0 2 0; | |
| 23 | -fx-padding: 3 3 1 3 | |
| 24 | } | |
| 1 | 25 |
| 1 | /* https://toedter.com/2011/10/26/java-fx-2-0-css-styling/ | |
| 2 | */ | |
| 3 | .root { | |
| 4 | -fx-base: rgb( 50, 50, 50 ); | |
| 5 | -fx-background: -fx-base; | |
| 6 | -fx-control-inner-background: -fx-base; | |
| 1 | 7 | |
| 8 | : derive( -fx-base, 150% ); | |
| 9 | -fx-mid-text-color: derive( -fx- |
| 1 | /* https://ethanschoonover.com/solarized | |
| 2 | */ | |
| 3 | .root { | |
| 4 | /* Solarized: base03 */ | |
| 5 | -fx-base: rgb( 0, 43, 54 ); | |
| 6 | -fx-background: -fx-base; | |
| 7 | ||
| 8 | /* Brighten controls */ | |
| 9 | -fx-40% ); | |
| 1 | 10 | |
| 11 | -fx-control-inner-background: -fx-base; | |
| 12 | , 5 |
| 1 | /* https://github.com/Col-E/Recaf/blob/master/src/main/resources/style/ui-dark.css | |
| 2 | */ | |
| 3 | .root { | |
| 4 | -fx-base: rgb( 45, 45, 46 ); | |
| 5 | -fx-background: -fx-base; | |
| 6 | ||
| 7 | /* Brighten controls */ | |
| 8 | -fx-color: derive( -fx-base, -40% ); | |
| 1 | 9 | |
| 10 | /* Control background */ | |
| 11 | /* Text colors */ | |
| 12 | /* Accent colors */ | |
| 13 | -fx-accent: rgb( 51, 51, 52 ); | |
| 14 | -item { | |
| 15 | -fx-border-insets: -1; | |
| 16 | { | |
| 17 | -fx-min-width: 80px; | |
| 18 | -fx-border-insets: -1; | |
| 19 | -fx-opacity: 1.0; | |
| 20 | -fx-padding: 2 2 1 2; | |
| 21 | -fx-border-insets: 0; | |
| 22 | 1 1; | |
| 23 | -fx-padding: 2; | |
| 24 | -fx-border-insets: 0; | |
| 25 | 6, 56, 59 ); | |
| 26 | -fx-padding: -1; | |
| 27 | -fx-padding: -1; | |
| 28 | -fx-border-insets: 0; | |
| 29 | 1 0 1; | |
| 30 | -fx-padding: 2; | |
| 31 | -fx-padding: 0; | |
| 32 | 1 0 0; | |
| 33 | hyperlink { | |
| 34 |
| 1 | ||
| 1 | <svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M.238 64h83.524V0H.238zm16.16-4.91H6.41V52h9.988zm30.688 0h-9.988V52h9.988zM67.602 4.363h9.988v7.274h-9.988zm0 47.453h9.988v7.094h-9.988zM52.168 4.363h9.805v7.09h-9.985v-7.09zm0 47.453h9.805v7.094h-9.985zM36.914 4.363h9.988v7.09h-9.988zM35.464 22l13.071 7.453c2.363 1.457 2.363 3.637 0 5.094L35.465 42c-2.363 1.453-4.36.184-4.36-2.547v-15.09c0-2.547 1.997-3.816 4.36-2.363zM21.485 4.363h9.805v7.09h-9.805zm0 47.453h9.805v7.094h-9.805zM6.41 4.363h9.988v7.274H6.41zm0 0" fill="#f60"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M.238 64h83.524V0H.238zm16.16-4.91H6.41V52h9.988zm30.688 0h-9.988V52h9.988zM67.602 4.363h9.988v7.274h-9.988zm0 47.453h9.988v7.094h-9.988zM52.168 4.363h9.805v7.09h-9.985v-7.09zm0 47.453h9.805v7.094h-9.985zM36.914 4.363h9.988v7.09h-9.988zM35.464 22l13.071 7.453c2.363 1.457 2.363 3.637 0 5.094L35.465 42c-2.363 1.453-4.36.184-4.36-2.547v-15.09c0-2.547 1.997-3.816 4.36-2.363zM21.485 4.363h9.805v7.09h-9.805zm0 47.453h9.805v7.094h-9.805zM6.41 4.363h9.988v7.274H6.41zm0 0" fill="#f60"/></svg> |
| 1 | ||
| 1 | <svg height="63" width="54" xmlns="http://www.w3.org/2000/svg"><path d="M53.344 18.172H44.02V8.965zM28.309 8.965v33.437h25.199V20.434H41.727V8.964zm3.93-8.723H4.417v6.461h10.965l-6.875 5.332v5.652l10.148-7.753V6.867H54V4.281zM18.655 14.297 8.508 22.05v5.652l10.148-7.754zM8.344 37.559l10.148-7.754v-5.657L8.344 31.902zm10.312 2.261v-5.656L8.508 41.918v2.91h-4.09v6.461h6.219v4.523H7.035c-.652-1.132-1.797-1.937-3.273-1.937C1.637 53.875 0 55.488 0 57.59c0 2.097 1.637 3.715 3.762 3.715 1.476 0 2.62-.809 3.273-1.938h3.602v3.39h5.562v-3.39h3.602c.652 1.13 1.8 1.938 3.273 1.938 2.125 0 3.762-1.618 3.762-3.715 0-2.102-1.637-3.715-3.762-3.715-1.472 0-2.62.805-3.273 1.938h-3.602v-4.524h15.875l21.762-3.879v-2.582H11.78zm0 0" fill="#90c"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M56.633 44.984V63.27c0 .363-.367.73-.735.73H1.102c-.368 0-.735-.367-.735-.73V61.62c0-.363.367-.73.735-.73h2.39l28.5-28.344L2.391 3.109c-.184-.183-.184-.367-.184-.55V.73c0-.363.367-.73.734-.73h52.957c.368 0 .735.367.735.73v18.106c0 .363-.367.73-.735.73h-2.023c-.367 0-.734-.367-.734-.73 0-7.684-4.598-14.082-12.688-14.082H19.121l24.09 24.137c.367.367.367.73 0 1.097L19.676 53.395h20.777c5.516 0 10.297-3.473 12.133-8.594.184-.367.367-.551.738-.551h2.758c.367 0 .55.367.55.734zm0 0" fill="#999"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="67" xmlns="http://www.w3.org/2000/svg"><path d="M66.824 40.465c-.176 1.59-2.097 2.824-5.945 3.707-3.852.879-8.75 1.41-14.52 1.41h-4.898v9.172c1.574.176 3.324.176 4.898.176 5.77 0 10.668-.528 14.52-1.586 3.848-1.059 5.945-2.293 6.121-3.707-.176-.352-.176-9.172-.176-9.172zm-20.64-6.7c-1.75 0-3.325 0-4.899-.18v9.352h4.899c5.773 0 10.671-.53 14.52-1.59s5.944-2.292 5.944-3.702v-8.997c-.171 1.586-2.097 2.825-6.12 3.704-3.673 1.058-8.571 1.59-14.344 1.414zm0-11.468c-1.75 0-3.325 0-4.899-.176v9.352c1.574.175 3.324.175 4.899.175 5.773 0 10.671-.53 14.695-1.59C64.727 29 66.824 27.767 67 26.356V17.36c-.176 1.59-2.098 2.825-6.121 3.704-4.024.707-8.922 1.234-14.695 1.234zm0-13.05c-1.75 0-3.325 0-4.899.175v10.406c1.574.176 3.324.176 4.899.176 5.773 0 10.671-.527 14.695-1.586 3.848-1.059 5.945-2.293 6.121-3.703-.176-1.59-2.098-2.824-6.121-3.883-4.024-1.055-8.922-1.41-14.695-1.586zM18.02 23.886c-.176.527-.528 2.293-1.227 5.293l-1.223 5.113h5.07l-1.222-5.113c-.7-3-1.227-4.766-1.227-5.293zM0 7.129v49.918l37.785 6.527V.426zm23.09 37.219-1.399-5.645-6.996-.176-1.398 5.29-4.375-.352 6.648-23.813 5.07-.351 7.348 25.222zm0 0" fill="#a03537"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="67" xmlns="http://www.w3.org/2000/svg"><path d="M66.824 40.465c-.176 1.59-2.097 2.824-5.945 3.707-3.852.879-8.75 1.41-14.52 1.41h-4.898v9.172c1.574.176 3.324.176 4.898.176 5.77 0 10.668-.528 14.52-1.586 3.848-1.059 5.945-2.293 6.121-3.707-.176-.352-.176-9.172-.176-9.172zm-20.64-6.7c-1.75 0-3.325 0-4.899-.18v9.352h4.899c5.773 0 10.671-.53 14.52-1.59s5.944-2.292 5.944-3.702v-8.997c-.171 1.586-2.097 2.825-6.12 3.704-3.673 1.058-8.571 1.59-14.344 1.414zm0-11.468c-1.75 0-3.325 0-4.899-.176v9.352c1.574.175 3.324.175 4.899.175 5.773 0 10.671-.53 14.695-1.59C64.727 29 66.824 27.767 67 26.356V17.36c-.176 1.59-2.098 2.825-6.121 3.704-4.024.707-8.922 1.234-14.695 1.234zm0-13.05c-1.75 0-3.325 0-4.899.175v10.406c1.574.176 3.324.176 4.899.176 5.773 0 10.671-.527 14.695-1.586 3.848-1.059 5.945-2.293 6.121-3.703-.176-1.59-2.098-2.824-6.121-3.883-4.024-1.055-8.922-1.41-14.695-1.586zM18.02 23.886c-.176.527-.528 2.293-1.227 5.293l-1.223 5.113h5.07l-1.222-5.113c-.7-3-1.227-4.766-1.227-5.293zM0 7.129v49.918l37.785 6.527V.426zm23.09 37.219-1.399-5.645-6.996-.176-1.398 5.29-4.375-.352 6.648-23.813 5.07-.351 7.348 25.222zm0 0" fill="#999"/></svg> |
| 1 | ||
| 1 | <svg height="63" width="54" xmlns="http://www.w3.org/2000/svg"><path d="M53.344 18.172H44.02V8.965zM28.309 8.965v33.437h25.199V20.434H41.727V8.964zm3.93-8.723H4.417v6.461h10.965l-6.875 5.332v5.652l10.148-7.753V6.867H54V4.281zM18.655 14.297 8.508 22.05v5.652l10.148-7.754zM8.344 37.559l10.148-7.754v-5.657L8.344 31.902zm10.312 2.261v-5.656L8.508 41.918v2.91h-4.09v6.461h6.219v4.523H7.035c-.652-1.132-1.797-1.937-3.273-1.937C1.637 53.875 0 55.488 0 57.59c0 2.097 1.637 3.715 3.762 3.715 1.476 0 2.62-.809 3.273-1.938h3.602v3.39h5.562v-3.39h3.602c.652 1.13 1.8 1.938 3.273 1.938 2.125 0 3.762-1.618 3.762-3.715 0-2.102-1.637-3.715-3.762-3.715-1.472 0-2.62.805-3.273 1.938h-3.602v-4.524h15.875l21.762-3.879v-2.582H11.78zm0 0" fill="#90c"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="67" xmlns="http://www.w3.org/2000/svg"><path d="M66.824 40.465c-.176 1.59-2.097 2.824-5.945 3.707-3.852.879-8.75 1.41-14.52 1.41h-4.898v9.172c1.574.176 3.324.176 4.898.176 5.77 0 10.668-.528 14.52-1.586 3.848-1.059 5.945-2.293 6.121-3.707-.176-.352-.176-9.172-.176-9.172zm-20.64-6.7c-1.75 0-3.325 0-4.899-.18v9.352h4.899c5.773 0 10.671-.53 14.52-1.59s5.944-2.292 5.944-3.702v-8.997c-.171 1.586-2.097 2.825-6.12 3.704-3.673 1.058-8.571 1.59-14.344 1.414zm0-11.468c-1.75 0-3.325 0-4.899-.176v9.352c1.574.175 3.324.175 4.899.175 5.773 0 10.671-.53 14.695-1.59C64.727 29 66.824 27.767 67 26.356V17.36c-.176 1.59-2.098 2.825-6.121 3.704-4.024.707-8.922 1.234-14.695 1.234zm0-13.05c-1.75 0-3.325 0-4.899.175v10.406c1.574.176 3.324.176 4.899.176 5.773 0 10.671-.527 14.695-1.586 3.848-1.059 5.945-2.293 6.121-3.703-.176-1.59-2.098-2.824-6.121-3.883-4.024-1.055-8.922-1.41-14.695-1.586zM18.02 23.886c-.176.527-.528 2.293-1.227 5.293l-1.223 5.113h5.07l-1.222-5.113c-.7-3-1.227-4.766-1.227-5.293zM0 7.129v49.918l37.785 6.527V.426zm23.09 37.219-1.399-5.645-6.996-.176-1.398 5.29-4.375-.352 6.648-23.813 5.07-.351 7.348 25.222zm0 0" fill="#999"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="66" xmlns="http://www.w3.org/2000/svg"><path d="M40.266 62.762 34.922 45.55h-19.98l-5.34 17.21h-7.32L21.468 5.59h7.32l19.39 57.172zM26.813 19.438c-.594-2.176-1.387-5.145-1.583-7.32h-.199c-.394 1.98-.988 4.945-1.781 7.32L16.523 41H33.54zm33.039-9.891c-2.375 0-4.356-1.781-4.356-4.156s1.98-4.153 4.356-4.153c2.37 0 4.351 1.778 4.351 4.153 0 2.375-1.98 4.156-4.351 4.156zm-3.563 53.215V18.05h7.32v44.71zm0 0" fill="#fea500" stroke="#fea500" stroke-miterlimit="10" stroke-width="2.47295"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="66" xmlns="http://www.w3.org/2000/svg"><path d="M40.266 62.762 34.922 45.55h-19.98l-5.34 17.21h-7.32L21.468 5.59h7.32l19.39 57.172zM26.813 19.438c-.594-2.176-1.387-5.145-1.583-7.32h-.199c-.394 1.98-.988 4.945-1.781 7.32L16.523 41H33.54zm33.039-9.891c-2.375 0-4.356-1.781-4.356-4.156s1.98-4.153 4.356-4.153c2.37 0 4.351 1.778 4.351 4.153 0 2.375-1.98 4.156-4.351 4.156zm-3.563 53.215V18.05h7.32v44.71zm0 0" fill="#fea500" stroke="#fea500" stroke-miterlimit="10" stroke-width="2.47295"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="53" xmlns="http://www.w3.org/2000/svg"><path d="M49.023.375H3.977C1.703.375 0 2.07 0 4.328 0 6.59 1.703 8.281 3.977 8.281h.187v3.953c0 8.286 5.11 15.625 12.684 18.637.379.188.757.563.757.942v.375c0 .378-.378.753-.757.94C9.086 36.142 3.977 43.48 4.164 51.767v3.953h-.187C1.703 55.719 0 57.41 0 59.672c0 2.258 1.703 3.953 3.977 3.953h45.046c2.274 0 3.977-1.695 3.977-3.953 0-2.262-1.703-3.953-3.977-3.953h-.187v-3.953c0-8.286-5.11-15.625-12.684-18.637-.379-.188-.757-.563-.757-.941v-.376c0-.378.378-.753.757-.94 7.762-3.013 12.871-10.352 12.684-18.638V8.281h.187C51.297 8.281 53 6.59 53 4.328 53 2.07 51.297.375 49.023.375zm-5.488 11.86c0 6.023-3.785 11.484-9.465 13.742-2.46.941-4.164 3.199-4.164 5.836v.375c0 2.636 1.703 4.894 4.164 5.835 5.68 2.258 9.465 7.72 9.465 13.743v3.953H9.465v-3.953c0-6.024 3.785-11.485 9.465-13.743 2.46-.941 4.164-3.199 4.164-5.836v-.374c0-2.637-1.703-4.895-4.164-5.836-5.68-2.258-9.465-7.72-9.465-13.743V8.281h34.07zm-28.77 6.777c-.378-.567-.19-1.317.38-1.696.187-.187.375-.187.753-.187H37.29c.566 0 1.137.566 1.137 1.129 0 .187 0 .566-.192.754-1.324 1.883-3.027 3.199-5.109 3.953-2.27.754-3.977 2.445-5.11 4.515-.378.754-1.328 1.133-2.081.567-.192-.188-.57-.375-.57-.567-1.134-2.07-2.84-3.761-5.11-4.515-2.274-.942-4.164-2.258-5.488-3.953zM29.907 42.73a6.64 6.64 0 0 0 4.164 1.504c2.84 0 5.301 1.883 5.868 4.707v.188c.19.566.19 1.129.19 1.883s-.565 1.316-1.323 1.316H14.008c-.758 0-1.324-.562-1.324-1.316 0-.567.187-1.317.187-1.883v-.188c.758-2.636 3.219-4.52 6.059-4.52a6.64 6.64 0 0 0 4.164-1.503c.758-.754 1.511-1.508 1.89-2.45.38-.562.95-.937 1.703-.75.57.188.95.376 1.137.75.57.755 1.137 1.509 2.082 2.262zm0 0" fill="#8ed200"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="54" xmlns="http://www.w3.org/2000/svg"><path d="M10.867 48.152c0 1.551 1.04 2.582 2.602 2.582h2.773v9.305c0 2.066 1.91 3.961 3.992 3.961s3.989-1.895 3.989-3.96v-9.306h5.379v9.305c0 2.066 1.91 3.961 3.992 3.961s3.988-1.895 3.988-3.96v-9.306h2.602c1.562 0 2.605-1.03 2.605-2.757V21.449H10.867zM4.097 21.45C2.017 21.45.11 23.344.11 25.41v18.606c0 2.066 1.907 3.96 3.989 3.96s3.992-1.894 3.992-3.96V25.41c0-2.066-1.735-3.96-3.992-3.96zm45.805 0c-2.082 0-3.992 1.895-3.992 3.961v18.606c0 2.066 1.91 3.96 3.992 3.96s3.989-1.894 3.989-3.96V25.41c0-2.066-1.907-3.96-3.989-3.96zM36.367 5.945l3.473-3.449c.52-.516.52-1.375 0-1.894a1.373 1.373 0 0 0-1.91 0L33.94 4.566c-1.91-1.379-4.34-1.894-6.941-1.894-2.777 0-5.031.515-7.285 1.55L15.898.259c-.523-.344-1.562-.344-2.082 0-.347.515-.347 1.55 0 2.066l3.47 3.446c-3.817 2.93-6.419 7.41-6.419 12.75h32.266c0-5.168-2.602-9.82-6.766-12.575zm-14.746 7.407h-2.773v-2.586h2.773zm13.531 0H32.38v-2.586h2.773zm0 0" fill="#a4ca39"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M62.887 38.266c-2.684-.84-4.532-3.36-4.532-6.215 0-2.852 1.848-5.371 4.532-6.211.84-.336 1.343-1.172 1.008-2.012-.84-3.023-1.848-5.707-3.524-8.394-.504-.84-1.344-1.008-2.184-.672-1.007.504-2.015.84-3.19.84-3.692 0-6.548-3.024-6.548-6.547 0-1.176.336-2.184.84-3.188.504-.84.168-1.68-.672-2.183a40.47 40.47 0 0 0-8.39-3.528c-.84-.168-1.68.168-2.016 1.008C37.37 3.852 34.855 5.7 32 5.7s-5.371-1.847-6.21-4.535C25.452.324 24.612-.18 23.772.156c-3.02.84-5.707 1.848-8.39 3.528-.84.503-1.008 1.343-.672 2.183.504 1.004.84 2.012.84 3.188 0 3.691-3.024 6.547-6.547 6.547-1.176 0-2.184-.336-3.191-.84-.84-.504-1.68-.168-2.184.672a40.699 40.699 0 0 0-3.524 8.394c-.167.84.168 1.676 1.008 2.012 2.684.84 4.532 3.36 4.532 6.21 0 2.856-1.848 5.376-4.532 6.216-.84.332-1.343 1.172-1.008 2.011.84 3.024 1.848 5.707 3.524 8.395.504.84 1.344 1.008 2.184.672 1.007-.504 2.015-.84 3.19-.84 3.692 0 6.548 3.02 6.548 6.547 0 1.176-.336 2.183-.84 3.187-.504.84-.168 1.68.672 2.184a40.47 40.47 0 0 0 8.39 3.527h.336c.672 0 1.344-.504 1.512-1.176.84-2.687 3.356-4.535 6.211-4.535s5.371 1.848 6.211 4.535c.336.84 1.176 1.344 2.016 1.008 3.02-.84 5.707-1.847 8.39-3.527.84-.504 1.008-1.344.672-2.184-.504-1.004-.84-2.011-.84-3.187 0-3.692 3.024-6.547 6.547-6.547 1.176 0 2.184.336 3.192.84.84.504 1.68.168 2.183-.672a40.698 40.698 0 0 0 3.524-8.395c.503-.672 0-1.511-.84-1.843zm-30.719 3.691c-5.371 0-9.902-4.363-9.902-9.906 0-5.371 4.363-9.903 9.902-9.903 5.371 0 9.902 4.364 9.902 9.903 0 5.375-4.53 9.906-9.902 9.906zm0 0"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="68" xmlns="http://www.w3.org/2000/svg"><g fill="#999"><path d="M51.6 33H28.3c-3.2 0-5.9 2.601-5.9 5.9v26.3h-5.9c0 3.2 2.599 5.9 5.9 5.9h23.4c3.2 0 5.9-2.601 5.9-5.9V41.7h5.9v-2.9a5.98 5.98 0 0 0-6-5.8zm-2.9 31.6c0 1.9-1.5 3.4-3.4 3.4H23.9c1.399-1 1.399-2.9 1.399-2.9V38.9c0-1.6 1.3-2.9 2.902-2.9 1.598 0 2.899 1.3 2.899 2.9v2.901h17.6zM34.1 38.9V36h17.6c2.7 0 2.9 1.7 2.9 2.9zm0 0" stroke="#999" stroke-miterlimit="10" stroke-width=".75" transform="matrix(1.62485 0 0 1.6469 -26.2 -53.722)"/><path d="M28.719 46.082c-.489-.332-.973-.824-1.461-1.32-.488-.492-.813-1.153-1.137-1.645-.812-1.316-1.625-2.637-1.953-4.117-.484-1.648-.813-3.293-.813-4.941 0-1.813.329-3.293 1.141-4.61.484-.988 1.297-1.976 2.438-2.472a5.777 5.777 0 0 1 3.246-.989c.328 0 .812 0 1.3.164.325.164.653.164 1.137.496.653.164.977.329 1.14.493.325.164.65.164.973.164.165 0 .489 0 .653-.164.16 0 .484-.164.972-.328s.813-.329 1.137-.329c.488-.168.813-.168 1.137-.332.488 0 .812-.164 1.3 0 .813 0 1.466.164 2.278.496 1.137.493 2.11 1.153 2.762 2.305-.324.164-.489.328-.813.66-.488.492-.976 1.153-1.465 1.645-.484.824-.812 1.812-.648 2.965 0 1.316.324 2.304.977 3.293.484.66.972 1.32 1.785 1.812l.976.496c-.164.492-.324.82-.488 1.317-.324.988-.813 1.812-1.461 2.632-.488.66-.812 1.32-1.14 1.649l-1.297 1.316a3.095 3.095 0 0 1-1.625.496c-.329 0-.813 0-1.141-.164-.324-.164-.649-.164-.973-.332-.324-.164-.648-.328-.976-.328-.485-.164-.813-.164-1.297-.164-.488 0-.977 0-1.301.164-.324.164-.652.164-.977.328-.488.168-.812.332-.972.332-.328.164-.813.164-1.14.164-1.298-.66-1.786-.824-2.274-1.152zm7.636-21.246c-.812.328-1.46.492-2.273.492-.164-.656 0-1.48.324-2.305.324-.656.649-1.316 1.137-1.976a5.093 5.093 0 0 1 1.789-1.48c.813-.329 1.461-.66 2.11-.66.163.823 0 1.484-.325 2.304-.324.66-.648 1.484-1.137 1.977-.324.824-.812 1.32-1.625 1.648zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M21.344 36.297c-1.871 1.527-3.739 2.887-5.61 4.246L4.52 49.211c-.512.34-.852.508-1.36.168A15.884 15.884 0 0 0 .781 48.19c-.511-.171-.68-.511-.68-1.02V17.267c0-.34.34-.852.508-1.02.852d5006e"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="80" xmlns="http://www.w3.org/2000/svg"><g fill="#bababa"><path d="M0 61.766V2.234C0 1.004 1 0 2.223 0h53.332c.668 0 1.222.223 1.668.781l22.222 24.922c.332.445.555.89.555 1.45v34.613C80 62.996 79 64 77.777 64H2.223A2.234 2.234 0 0 1 0 61.766zm75.555-33.72-21-23.577H4.445V59.53h71.11zm0 0"/><path d="M53.332 29.055V4.469c0-1.227 1-2.235 2.223-2.235a2.236 2.236 0 0 1 2.222 2.235V26.82h17.778a2.234 2.234 0 0 1 0 4.47h-20a2.236 2.236 0 0 1-2.223-2.235zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M21.344 36.297c-1.871 1.527-3.739 2.887-5.61 4.246L4.52 49.211c-.512.34-.852.508-1.36.168A15.884 15.884 0 0 0 .781 48.19c-.511-.171-.68-.511-.68-1.02V17.267c0-.34.34-.852.508-1.02.852d5006e"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M.238 64h83.524V0H.238zm16.16-4.91H6.41V52h9.988zm30.688 0h-9.988V52h9.988zM67.602 4.363h9.988v7.274h-9.988zm0 47.453h9.988v7.094h-9.988zM52.168 4.363h9.805v7.09h-9.985v-7.09zm0 47.453h9.805v7.094h-9.985zM36.914 4.363h9.988v7.09h-9.988zM35.464 22l13.071 7.453c2.363 1.457 2.363 3.637 0 5.094L35.465 42c-2.363 1.453-4.36.184-4.36-2.547v-15.09c0-2.547 1.997-3.816 4.36-2.363zM21.485 4.363h9.805v7.09h-9.805zm0 47.453h9.805v7.094h-9.805zM6.41 4.363h9.988v7.274H6.41zm0 0" fill="#f60"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="69" xmlns="http://www.w3.org/2000/svg"><path d="M13.875 13.874h10.9v2.701h-10.9zm0 5.4h10.9v2.701h-10.9zm0 5.5h10.9v2.702h-10.9zm19-24.399H11.177c-3 0-5.402 2.4-5.402 5.4v24.4h-5.4c0 3 2.402 5.4 5.4 5.4h21.7c3 0 5.402-2.4 5.402-5.4v-21.7h5.4v-2.7c0-3-2.402-5.4-5.4-5.4zm-2.7 29.3c0 1.801-1.4 3.2-3.2 3.2h-19.9c1.3-.9 1.3-2.7 1.3-2.7v-24.4c0-1.5 1.2-2.7 2.7-2.7 1.501 0 2.7 1.2 2.7 2.7v2.7h16.3zm-13.6-23.9v-2.7h16.3c2.501 0 2.7 1.6 2.7 2.7zm0 0" fill="#999" stroke="#999" stroke-miterlimit="10" stroke-width=".75" transform="matrix(1.7717 0 0 1.78025 .262 0)"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M21.344 36.297c-1.871 1.527-3.739 2.887-5.61 4.246L4.52 49.211c-.512.34-.852.508-1.36.168A15.884 15.884 0 0 0 .781 48.19c-.511-.171-.68-.511-.68-1.02V17.267c0-.34.34-.852.508-1.02.852d5006e"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="83" height="63"><path style="stroke:none;fill-rule:nonzero;fill:#999;fill-opacity:1" d="M.125 0h69.586v8.184H.125zm13.164 18.273h69.586v8.18H13.289zM.125 36.543h69.586v8.184H.125zm13.164 18.273h69.586V63H13.289zm0 0"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M21.344 36.297c-1.871 1.527-3.739 2.887-5.61 4.246L4.52 49.211c-.512.34-.852.508-1.36.168A15.884 15.884 0 0 0 .781 48.19c-.511-.171-.68-.511-.68-1.02V17.267c0-.34.34-.852.508-1.02.852d5006e"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M21.344 36.297c-1.871 1.527-3.739 2.887-5.61 4.246L4.52 49.211c-.512.34-.852.508-1.36.168A15.884 15.884 0 0 0 .781 48.19c-.511-.171-.68-.511-.68-1.02V17.267c0-.34.34-.852.508-1.02.852-.512 1.7-.851 2.72-1.36.51-.171.85 0 1.19.169 3.06 2.379 6.118 4.757 9.348 7.136 2.547 1.872 5.098 3.91 7.645 5.778l.511-.508C31.367 18.453 40.543 9.449 49.891.44c.507-.507.847-.507 1.527-.34 3.91 1.532 7.816 3.231 11.727 4.758.34.172.507.512.68.852.167.168 0 .508 0 .68v51.316c0 1.188 0 1.188-1.192 1.7-3.738 1.527-7.477 2.886-11.215 4.417-.68.34-1.02.168-1.527-.34-9.348-8.496-18.524-17.504-27.868-26.34-.171-.34-.34-.507-.68-.847zm26.676 8.156V19.984L31.707 32.22zM13.867 32.22c-2.719-2.38-5.437-4.758-8.16-7.309v14.613c2.723-2.378 5.441-4.757 8.16-7.304zm0 0" fill="#c33"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M21.344 36.297c-1.871 1.527-3.739 2.887-5.61 4.246L4.52 49.211c-.512.34-.852.508-1.36.168A15.884 15.884 0 0 0 .781 48.19c-.511-.171-.68-.511-.68-1.02V17.267c0-.34.34-.852.508-1.02.852d5006e"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="68" xmlns="http://www.w3.org/2000/svg"><path d="M34 0c-7.133 0-13.672 1.98-18.625 5.547S7.051 14.266 7.051 20.21v8.719C3.09 31.902.316 38.242.316 45.574.316 55.68 5.664 64 12.203 64c1.586 0 3.371-.594 4.953-1.586V28.73c-.988-.593-2.18-1.187-3.367-1.386V20.21c0-3.566 1.785-6.738 5.352-9.113C22.707 8.52 28.055 6.738 34 6.738s11.098 1.782 14.86 4.36c3.566 2.574 5.35 5.746 5.35 9.113v6.934c-1.187.398-2.378.793-3.366 1.386v33.29c1.582.992 3.367 1.585 4.953 1.585 6.34 0 11.887-8.324 11.887-18.43 0-6.933-2.774-13.273-6.735-16.246v-8.52c0-5.944-3.37-11.292-8.324-14.663C47.672 2.18 41.133 0 34 0zm0 29.723-7.332 14.465-4.555-5.946-1.586 2.38v11.093l1.586-1.98 5.746 7.331L34 44.582l6.14 12.484 5.747-7.332 1.586 1.98V40.622l-1.586-2.379-4.356 6.14zm0 0" fill="#1493f6"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M.238 64h83.524V0H.238zm16.16-4.91H6.41V52h9.988zm30.688 0h-9.988V52h9.988zM67.602 4.363h9.988v7.274h-9.988zm0 47.453h9.988v7.094h-9.988zM52.168 4.363h9.805v7.09h-9.985v-7.09zm0 47.453h9.805v7.094h-9.985zM36.914 4.363h9.988v7.09h-9.988zM35.464 22l13.071 7.453c2.363 1.457 2.363 3.637 0 5.094L35.465 42c-2.363 1.453-4.36.184-4.36-2.547v-15.09c0-2.547 1.997-3.816 4.36-2.363zM21.485 4.363h9.805v7.09h-9.805zm0 47.453h9.805v7.094h-9.805zM6.41 4.363h9.988v7.274H6.41zm0 0" fill="#f60"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M21.344 36.297c-1.871 1.527-3.739 2.887-5.61 4.246L4.52 49.211c-.512.34-.852.508-1.36.168A15.884 15.884 0 0 0 .781 48.19c-.511-.171-.68-.511-.68-1.02V17.267c0-.34.34-.852.508-1.02.852d5006e"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="52" xmlns="http://www.w3.org/2000/svg"><path d="M34.625 63.98c14.355-12.652 1.95-28.816-1.773-30.574.53 1.934.355 5.27-1.594 7.203-.887-4.918-4.785-11.07-10.278-13.18.883 7.032-3.19 11.95-4.964 14.41-1.418 2.286-9.922 14.06-1.418 22.141-20.38-6.328-15.239-26.535-9.391-35.496C11.41 19.172 18.676 11.617 17.078.02c9.926 3.515 16.66 13.882 18.434 21.789 3.367-3.164 3.898-8.786 3.011-11.95 6.914 2.813 28.536 41.47-3.898 54.121zm0 0" fill="#ff9800"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><g fill="#bababa"><path d="M0 0v36.57h13.715V13.715H36.57V0zm0 0"/><path d="M18.285 18.285V64H64V18.285zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="69" xmlns="http://www.w3.org/2000/svg"><path d="M13.875 13.874h10.9v2.701h-10.9zm0 5.4h10.9v2.701h-10.9zm0 5.5h10.9v2.702h-10.9zm19-24.399H11.177c-3 0-5.402 2.4-5.402 5.4v24.4h-5.4c0 3 2.402 5.4 5.4 5.4h21.7c3 0 5.402-2.4 5.402-5.4v-21.7h5.4v-2.7c0-3-2.402-5.4-5.4-5.4zm-2.7 29.3c0 1.801-1.4 3.2-3.2 3.2h-19.9c1.3-.9 1.3-2.7 1.3-2.7v-24.4c0-1.5 1.2-2.7 2.7-2.7 1.501 0 2.7 1.2 2.7 2.7v2.7h16.3zm-13.6-23.9v-2.7h16.3c2.501 0 2.7 1.6 2.7 2.7zm0 0" fill="#999" stroke="#999" stroke-miterlimit="10" stroke-width=".75" transform="matrix(1.7717 0 0 1.78025 .262 0)"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><g fill="#999"><path d="M64 0H0v64h64zM12.8 12.633H6.399V6.23h6.403zm44.802 0h-38.57V6.23h38.57zm0 44.797H6.23V19.2h51.372zm0 0"/><path d="m16.336 24.59-4.547 4.547 7.41 7.41-7.41 7.242 4.547 4.547 11.957-11.79zm10.613 21.558h12.797v6.399H26.95zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="69" xmlns="http://www.w3.org/2000/svg"><path d="M17.8.5c-2.9 0-5.4 2.801-5.4 6.2 0 3.4 2.4 6.2 5.4 6.2 2.9 0 5.399-2.8 5.399-6.2C23.199 3.302 20.8.5 17.8.5zm0 10.1c-1.6 0-3-1.7-3-3.9 0-2.1 1.3-3.9 3-3.9s3 1.7 3 3.9-1.3 3.9-3 3.9zM7 11.8V1.7C7 1 6.5.5 5.8.5S4.6 1 4.6 1.7v10.1c0 .7.5 1.2 1.2 1.2S7 12.4 7 11.8zm-1.1 6.9C3 18.7.5 21.5.5 24.9s2.4 6.2 5.4 6.2 5.401-2.8 5.401-6.2c-.102-3.3-2.5-6.2-5.4-6.2zm0 10.2c-1.6 0-3-1.699-3-3.9 0-2.1 1.3-3.9 3-3.9s3 1.7 3 3.9c-.1 2.1-1.4 3.9-3 3.9zM19 30V19.9c0-.7-.5-1.2-1.2-1.2s-1.2.5-1.2 1.2V30c0 .7.5 1.2 1.2 1.2S19 30.7 19 30zM31.3 12.7V2.6c0-.7-.499-1.2-1.2-1.2-.7 0-1.1.5-1.1 1.2v10.099c0 .701.5 1.2 1.2 1.2s1.1-.6 1.1-1.2zm-1.2 6.9c-2.9 0-5.401 2.8-5.401 6.2 0 3.4 2.4 6.202 5.4 6.202 2.901 0 5.402-2.802 5.402-6.202S33.1 19.6 30.1 19.6zm0 10.102c-1.6 0-3-1.7-3-3.902 0-2.099 1.3-3.9 3-3.9s3 1.7 3 3.9c0 2.202-1.3 3.902-3 3.902zm0 0" fill="#999" stroke="#999" stroke-miterlimit="10" transform="matrix(1.91667 0 0 1.9394 0 .485)"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="80" xmlns="http://www.w3.org/2000/svg"><g fill="#bababa"><path d="M0 61.766V2.234C0 1.004 1 0 2.223 0h53.332c.668 0 1.222.223 1.668.781l22.222 24.922c.332.445.555.89.555 1.45v34.613C80 62.996 79 64 77.777 64H2.223A2.234 2.234 0 0 1 0 61.766zm75.555-33.72-21-23.577H4.445V59.53h71.11zm0 0"/><path d="M53.332 29.055V4.469c0-1.227 1-2.235 2.223-2.235a2.236 2.236 0 0 1 2.222 2.235V26.82h17.778a2.234 2.234 0 0 1 0 4.47h-20a2.236 2.236 0 0 1-2.223-2.235zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="82" xmlns="http://www.w3.org/2000/svg"><g fill="#3c3"><path d="M0 .094v63.812h82V.094zM77.34 4.8v27.86L57.773 17.6 36.34 39.247l-15.094-8.469L4.844 43.953V4.801zm0 0"/><path d="M22.55 17.223c0 3.222-2.585 5.836-5.777 5.836-3.191 0-5.777-2.614-5.777-5.836s2.586-5.836 5.777-5.836c3.192 0 5.778 2.613 5.778 5.836zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="72" xmlns="http://www.w3.org/2000/svg"><filter id="a" height="100%" width="100%" x="0%" y="0%"><feColorMatrix in="SourceGraphic" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/></filter><mask id="c"><g filter="url(#a)"><path d="M0 0h72v64H0z" fill-opacity=".65"/></g></mask><clipPath id="b"><path d="M0 0h72v64H0z"/></clipPath><g clip-path="url(#b)" mask="url(#c)"><path d="M25.281.082h4.356l.168.168c1.34.34 2.843.508 4.183 1.18 4.524 1.855 7.203 5.39 8.875 9.937 0 .168.168.508.336.676 1.004.336 2.008.504 3.016.84l.164-.168c2.68-5.39 7.035-8.422 12.894-9.43 1.508-.34 3.016-.172 4.524.336-.168.168-.168.336-.336.336-2.012 2.191-3.516 4.547-3.852 7.41-.168 1.012-.336 1.852-.504 2.863-.5 2.528-1.34 5.055-3.347 6.907C53.246 23.497 50.062 24 46.883 24c-.168 0-.504-.168-.504-.504-.332-.508-.5-1.012-.668-1.687-2.176.507-2.848 1.011-3.016 2.863.672 0 1.34.172 2.012.172 5.691.672 11.387 1.515 16.91 2.691 2.68.676 5.192 1.348 7.703 2.528 1.34.675 2.012 1.683 2.344 3.199 0 .34.168.675.336.843v2.02c-.168.168-.168.508-.336.676-.332 1.011-.836 1.851-1.672 2.527-1.008.84-2.18 1.176-3.52 1.348.337 1.683-.667 2.691-1.84 3.367-.835.504-1.675.84-2.51 1.012-1.34.168-2.513 0-3.852 0-1.004 1.851-2.68 2.187-4.52 2.355-1.844.168-3.52-.336-5.023-1.347-.672.843-1.34 1.347-2.512 1.347-2.012.336-3.684-.168-5.36-.84l-.167-.168.167.168c1.172 2.188 2.344 4.211 3.348 6.399.336.676.336 1.683.336 2.36 0 1.515-.836 2.523-2.008 2.862-.168 1.18-.84 2.188-1.676 2.864-1.171.84-2.511 1.007-4.02 1.007-.167 0-.667-.167-.667 0-.672 1.012-1.844 1.348-2.848 1.856h-1.507c-1.004-.168-1.84-1.18-3.016-.34-.164.172-.5.172-.668.172-1.172 0-3.348-.676-3.852-2.36s-1.34-3.538-2.007-5.222l-.168.168c-1.508 3.035-4.856 4.21-8.04 2.695a14.392 14.392 0 0 1-4.351-3.367C1.67 46.402-1.508 35.621.668 23.496 2.676 12.043 11.551 3.286 22.77.926 23.44.422 24.445.25 25.28.082zm13.73 19.035c1.676.168 3.52.168 5.192-.676 1.508-.671 3.184-.671 4.688-.504 1.007.168 2.18.504 3.183.672-.504-.504-1.004-1.011-1.676-1.347-2.68-2.02-5.691-3.367-9.207-3.703-.336 0-.84 0-.84.168-1.003 1.515-1.671 3.03-1.671 4.882-.168 1.18.164 2.36.668 3.371 1.843-.843 3.851-1.687 5.691-2.527v-.508c-1.004.172-1.84.508-2.844.676-1.172.168-2.343.336-3.183-.504zM56.427 7.664c-2.176 2.356-3.684 5.05-5.024 7.746l3.684 3.2c1.176-1.516 1.508-3.2 2.012-4.883.668-3.032.836-6.235 3.18-8.59-4.352-.168-10.715 4.379-12.055 8.422l2.175 1.175c.168-.168.168-.504.336-.671.668-1.18 1.34-2.36 2.176-3.368 1.004-1.18 2.012-2.36 3.516-3.03zm-7.867 24.59c1.34.168 2.68.336 4.015.336l12.395 1.347c.668 0 1.172.168 1.84.168-.336-1.011-.836-1.851-1.676-2.19-.836-.337-1.84-.505-2.676-.84-3.684-.677-7.203-1.516-10.887-2.192-3.515-.504-7.199-.84-10.715-1.348-.167 0-.503 0-.671.172l-2.008 2.02c-3.684 2.695-7.703 3.367-12.055 3.367a25.933 25.933 0 0 0 3.348-1.18c3.515-1.344 6.531-3.2 8.707-6.23.336-.504.336-.84.168-1.348a12.356 12.356 0 0 1-1.508-5.895c0-2.527.836-4.714 2.68-6.566.336-.34.336-.676.168-1.012-1.172-2.695-2.848-4.715-5.36-6.234-3.015-1.852-6.363-2.02-9.543-1.516-7.535 1.18-13.23 5.055-17.25 11.285-3.683 5.895-4.855 12.297-4.015 19.204.332 2.187.836 4.21 1.84 6.062.167.504.335 1.012.671 1.516 4.52 8.254 11.551 12.968 20.93 13.64 5.527.34 10.383-2.695 12.055-7.914.336-1.18.84-2.36.168-3.539 1.172 1.012 2.68 1.516 4.355 1.688 1.672.168 3.012-.34 3.684-1.688.168 0 .332.172.5.172 1.34.672 2.68.84 4.187.672 1.844-.168 2.68-1.012 2.848-2.695.836.168 1.84.336 2.68.168 2.675 0 3.851-1.516 3.347-3.704 1.004 0 2.176 0 3.18-.167 1.008-.172 2.012-.676 2.68-1.856l-10.047-2.02-10.047-2.023c-.332.34 2.012.34 2.012.34zm-1.676-13.645c.336 1.012.504 1.852.668 2.696.168.504.336.504.84.504 1.672-.168 3.18-.504 4.52-1.176.167-.172.335-.172.839-.508l-4.02-1.008-.503.84h-.168v-1.012zm0 0" fill="#543828"/><path d="M5.02 40c-1.004-1.852-1.504-4.043-1.84-6.063-1.004-6.906.168-13.304 4.02-19.203 4.015-6.398 9.878-10.273 17.245-11.28 3.348-.509 6.532-.34 9.543 1.515 2.512 1.515 4.188 3.535 5.36 6.23.168.336.168.676-.168 1.012-1.672 1.851-2.512 4.043-2.68 6.566 0 2.024.504 4.043 1.508 5.895.336.508.168.844-.168 1.348-2.176 3.03-5.192 5.054-8.707 6.234-1.004.336-2.176.672-3.348 1.176 4.352 0 8.54-.672 12.055-3.368-.836 1.348-1.34 2.696-2.344 3.875-4.351 5.727-10.047 8.254-17.414 6.231-.668-.168-1.34-.336-2.008.336l-1.008.508c-3.18.84-6.695.504-10.046-1.012zm22.605-29.813c-3.516 0-6.195 2.696-6.195 6.403 0 3.367 2.847 6.23 6.363 6.23s6.195-2.863 6.195-6.398c0-3.54-2.843-6.402-6.363-6.235zm0 0" fill="#e95927"/><path d="M5.02 40c3.351 1.516 6.867 1.684 10.382.676.336-.172.836-.172 1.004-.508.672-.504 1.34-.504 2.012-.336 7.367 2.02 13.059-.504 17.414-6.23.836-1.18 1.508-2.528 2.344-3.875l2.008-2.02c.168-.172.504-.172.671-.172 3.516.508 7.2.844 10.715 1.348 3.684.676 7.203 1.347 10.887 2.191-.168 0-.336.168-.336.168-4.523.336-9.043.672-13.394 1.012h-2.348l10.047 2.02c-.164.335-.164 1.011-.332 1.18-.504.503-1.172 1.01-1.844 1.179-.836.168-1.676 0-2.512 0 .168.84 0 1.683-.668 2.355-.504.34-1.007.844-1.675 1.012-1.508.676-3.016.676-4.52-.168-.336 1.516-1.676 2.02-2.848 2.188-1.34.171-2.511 0-3.683-.84l-.168.168 1.004 2.359c.672 1.176.168 2.355-.168 3.535-1.672 5.223-6.528 8.422-12.055 7.918-9.379-.676-16.41-5.39-20.93-13.644-.672-.504-.84-1.012-1.007-1.516zm0 0" fill="#fbcd00"/><path d="M51.402 36.8c.84 0 1.844.169 2.512 0 .672-.167 1.34-.675 1.844-1.179.336-.168.336-.844.336-1.18l10.047 2.024c-.672 1.008-1.508 1.683-2.68 1.851-1.004.168-2.176.168-3.184.168.504 2.192-.668 3.707-3.347 3.707-.836 0-1.844-.171-2.68-.171-.168 1.687-1.004 2.527-2.848 2.695-1.504.168-2.843 0-4.183-.672 0-.336-.168-.336-.336-.336-.668 1.348-2.008 1.852-3.684 1.684s-3.015-.676-4.355-1.684l-1.004-2.36.168-.167c1.172.84 2.344 1.18 3.683.84 1.34-.168 2.512-.672 2.848-2.188 1.508.844 3.012.844 4.52.168.504-.168 1.171-.672 1.675-1.012.668-.504.836-1.347.668-2.187zm0 0" fill="#3daf00"/><path d="M56.426 7.664c-1.504.672-2.676 1.852-3.684 3.2-.836 1.011-1.504 2.187-2.176 3.366-.168.168-.168.336-.336.676l-2.175-1.18c1.34-4.21 7.703-8.59 12.054-8.421-2.343 2.527-2.343 5.726-3.18 8.59-.335 1.683-.835 3.367-2.007 4.882l-3.684-3.199c1.504-2.863 3.18-5.558 5.188-7.914.336-.172 0 0 0 0zm0 0" fill="#25a7f0"/><path d="M38.68 18.777c0-1.851.5-3.535 1.672-4.882.168-.168.671-.168.84-.168 3.515.168 6.359 1.683 9.206 3.703.504.34 1.172.843 1.676 1.347-1.004-.168-2.176-.504-3.183-.672-1.672-.335-3.18-.167-4.688.504-1.672.676-3.348.676-5.191.676zm0 0" fill="#cbcbca"/><path d="M48.559 32.254c4.52-.34 9.039-.676 13.394-1.012.168 0 .336 0 .336-.168.836.336 1.84.504 2.68.84 1.004.34 1.34 1.18 1.672 2.191-.668 0-1.34-.167-1.84-.167l-12.227-1.18zm0 0" fill="#3eae00"/><path d="m46.883 18.61 2.176.335v1.012h.168l.503-1.012 4.02 1.012c-.336.168-.504.336-.84.504-1.508.676-3.012 1.012-4.52 1.18-.335 0-.671 0-.84-.504-.163-.676-.5-1.516-.667-2.528zm0 0" fill="#25a5ec"/><path d="m38.68 18.777.164.34c1.008.84 2.18.84 3.183.672 1.004-.168 1.84-.504 2.848-.672v.504l-5.695 2.527c-.168-1.011-.5-2.191-.5-3.37zm0 0" fill="#c9c8c7"/><path d="M27.625 10.188c3.52 0 6.363 2.695 6.363 6.234 0 3.535-2.843 6.398-6.195 6.398-3.348 0-6.363-2.863-6.363-6.23 0-3.707 2.68-6.403 6.195-6.403zm3.684 6.234c0-2.192-1.672-3.875-3.684-3.875-2.008 0-3.684 1.683-3.852 3.875 0 2.02 1.676 3.871 3.688 3.871 2.344-.168 3.848-1.684 3.848-3.871zm0 0" fill="#fbcb00"/><path d="M56.426 7.664c.168.168 0 0 0 0zm0 0" fill="#543828"/><path d="M31.309 16.422c0 2.187-1.672 3.703-3.848 3.703-2.18 0-3.852-1.684-3.688-3.871 0-2.024 1.676-3.875 3.852-3.875 2.18.168 3.684 1.851 3.684 4.043zm-3.684-.168a8.37 8.37 0 0 0 1.844-.676c.668-.336.668-1.18 0-1.683-.836-.676-2.68-.676-3.516 0-.672.503-.672 1.347 0 1.683.5.336 1.004.504 1.672.676zm0 0" fill="#553928"/><path d="M27.625 16.254c-.668-.172-1.172-.34-1.672-.676-.672-.336-.672-1.18 0-1.683.836-.676 2.68-.676 3.516 0 .668.503.668 1.347 0 1.683a8.37 8.37 0 0 1-1.844.676zm0 0" fill="#fff"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="82" xmlns="http://www.w3.org/2000/svg"><g fill="#3c3"><path d="M0 .094v63.812h82V.094zM77.34 4.8v27.86L57.773 17.6 36.34 39.247l-15.094-8.469L4.844 43.953V4.801zm0 0"/><path d="M22.55 17.223c0 3.222-2.585 5.836-5.777 5.836-3.191 0-5.777-2.614-5.777-5.836s2.586-5.836 5.777-5.836c3.192 0 5.778 2.613 5.778 5.836zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg height="63" width="54" xmlns="http://www.w3.org/2000/svg"><path d="M53.344 18.172H44.02V8.965zM28.309 8.965v33.437h25.199V20.434H41.727V8.964zm3.93-8.723H4.417v6.461h10.965l-6.875 5.332v5.652l10.148-7.753V6.867H54V4.281zM18.655 14.297 8.508 22.05v5.652l10.148-7.754zM8.344 37.559l10.148-7.754v-5.657L8.344 31.902zm10.312 2.261v-5.656L8.508 41.918v2.91h-4.09v6.461h6.219v4.523H7.035c-.652-1.132-1.797-1.937-3.273-1.937C1.637 53.875 0 55.488 0 57.59c0 2.097 1.637 3.715 3.762 3.715 1.476 0 2.62-.809 3.273-1.938h3.602v3.39h5.562v-3.39h3.602c.652 1.13 1.8 1.938 3.273 1.938 2.125 0 3.762-1.618 3.762-3.715 0-2.102-1.637-3.715-3.762-3.715-1.472 0-2.62.805-3.273 1.938h-3.602v-4.524h15.875l21.762-3.879v-2.582H11.78zm0 0" fill="#90c"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="52" xmlns="http://www.w3.org/2000/svg"><path d="M47.734 32c8.914 12.195 3.325 28-11.785 31.46C28.695 52.927 40.33 43.59 47.734 32zM8.45 60.3l.453.302a18.118 18.118 0 0 0 9.215 3.011c-2.867-5.87-2.265-12.945 1.363-18.367l10.575-15.355c5.742-8.578 3.476-20.32-5.137-26.043l-.605-.45A18.106 18.106 0 0 0 15.098.387c2.87 6.02 2.265 12.945-1.36 18.367L3.16 34.109c-5.742 8.73-3.472 20.473 5.29 26.192zm27.047-17.76s3.02-4.067 4.531-6.474l4.383-6.476c5.438-7.977-4.082-14.3-5.289-14.45 1.207 2.407 0 7.376-1.512 9.786l-4.382 6.472c-2.414 3.762-1.508 8.73 2.27 11.141zm0 0" fill="#bababa"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="83" height="63"><path style="stroke:none;fill-rule:nonzero;fill:#999;fill-opacity:1" d="M.125 0h69.586v8.184H.125zm13.164 18.273h69.586v8.18H13.289zM.125 36.543h69.586v8.184H.125zm13.164 18.273h69.586V63H13.289zm0 0"/></svg> |
| 1 | ||
| 1 | <svg height="63" width="54" xmlns="http://www.w3.org/2000/svg"><path d="M53.344 18.172H44.02V8.965zM28.309 8.965v33.437h25.199V20.434H41.727V8.964zm3.93-8.723H4.417v6.461h10.965l-6.875 5.332v5.652l10.148-7.753V6.867H54V4.281zM18.655 14.297 8.508 22.05v5.652l10.148-7.754zM8.344 37.559l10.148-7.754v-5.657L8.344 31.902zm10.312 2.261v-5.656L8.508 41.918v2.91h-4.09v6.461h6.219v4.523H7.035c-.652-1.132-1.797-1.937-3.273-1.937C1.637 53.875 0 55.488 0 57.59c0 2.097 1.637 3.715 3.762 3.715 1.476 0 2.62-.809 3.273-1.938h3.602v3.39h5.562v-3.39h3.602c.652 1.13 1.8 1.938 3.273 1.938 2.125 0 3.762-1.618 3.762-3.715 0-2.102-1.637-3.715-3.762-3.715-1.472 0-2.62.805-3.273 1.938h-3.602v-4.524h15.875l21.762-3.879v-2.582H11.78zm0 0" fill="#4d1b9b"/></svg> |
| 1 | ||
| 1 | <svg height="63" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M33.325 19.55c-.498-.2-1.1 0-1.299.5-1.1 2.5-2.901 4.7-5.1 6.4l-6.7-13.601c1-.8 1.6-1.999 1.6-3.4 0-2.099-1.501-3.899-3.501-4.3v-3.4a1 1 0 0 0-2 0v3.4c-2 .401-3.5 2.201-3.5 4.3 0 1.401.6 2.6 1.601 3.4l-6.7 13.602c-2.201-1.7-4-3.801-5.1-6.401-.201-.5-.8-.7-1.301-.5-.499.199-.7.8-.499 1.3 1.299 3 3.4 5.4 6 7.3l-4 8c-.2.5 0 1.1.4 1.3.098 0 .3.1.4.1.3 0 .7-.2.9-.5l3.8-7.8c2.7 1.5 5.6 2.2 8.7 2.2 3.1 0 6-.8 8.699-2.2l3.8 7.8c.1.3.501.5.9.5.1 0 .3 0 .4-.1.5-.2.7-.8.4-1.3l-3.9-8c2.6-1.8 4.701-4.4 6-7.3.6-.5.401-1.101 0-1.3zM17.326 6.95c1.4 0 2.5 1.1 2.5 2.499 0 1.401-1.1 2.502-2.5 2.502s-2.5-1.1-2.5-2.502c0-1.4 1.199-2.5 2.5-2.5zm0 22.6c-2.8 0-5.4-.7-7.801-2l6.8-13.7c.3.1.701.1 1.1.1.402 0 .701 0 1.1-.1l6.8 13.7c-2.5 1.3-5.199 2-7.999 2zm0 0" fill="#369" stroke="#369" stroke-miterlimit="10" stroke-width="1.5" transform="matrix(1.6544 0 0 1.63607 0 .154)"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="67" xmlns="http://www.w3.org/2000/svg"><path d="M5.102 59.219v-10.11h11.605v10.11zm14.066 0v-10.11h12.836v10.11zM5.102 46.805V35.457h11.605v11.348zm14.066 0V35.457h12.836v11.348zM5.102 33.152V23.047h11.605v10.105zM34.645 59.22v-10.11H47.48v10.11zM19.168 33.152V23.047h12.836v10.105zm30.95 26.067v-10.11h11.605v10.11zM34.644 46.805V35.457H47.48v11.348zm-14.07-30.496c0 .53-.528 1.062-1.231 1.062h-2.637c-.703 0-1.23-.531-1.23-1.062V6.203c0-.535.527-1.066 1.23-1.066h2.461c.703 0 1.23.531 1.23 1.066V16.31zm29.542 30.496V35.457h11.606v11.348zM34.645 33.152V23.047H47.48v10.105zm15.472 0V23.047h11.606v10.105zm1.406-16.843c0 .53-.527 1.062-1.23 1.062h-2.637c-.703 0-1.23-.531-1.23-1.062V6.203c0-.535.527-1.066 1.23-1.066h2.637c.703 0 1.23.531 1.23 1.066zM67 14.004c0-2.484-2.285-4.434-5.102-4.434h-5.097V6.203c0-3.016-2.813-5.676-6.508-5.676h-2.637c-3.515 0-6.508 2.48-6.508 5.676V9.57H25.676V6.203c0-3.016-2.817-5.676-6.508-5.676h-2.637c-3.52 0-6.508 2.48-6.508 5.676V9.57H5.102C2.285 9.57 0 11.7 0 14.004v45.035c0 2.484 2.285 4.434 5.102 4.434h56.62c2.817 0 5.102-2.13 5.102-4.434V14.004zm0 0" fill="#111"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="67" xmlns="http://www.w3.org/2000/svg"><path d="M43.195 53.328v-24l13.93-2.308C55.008 15.11 44.605 6.043 32.09 6.043c-14.106 0-25.563 11.555-25.563 25.773 0 14.223 11.457 25.778 25.563 25.778 1.41 0 2.644-.18 4.055-.356 1.058-1.777 2.82-3.023 5.113-3.734.703-.176 1.41-.176 1.937-.176zM36.848 8.176l-2.82 12.09h-2.645l-1.938-12.09c2.82-1.422 7.403 0 7.403 0zM32.09 41.418c-5.29 0-9.52-4.266-9.52-9.602 0-5.332 4.23-9.597 9.52-9.597 5.289 0 9.52 4.265 9.52 9.597 0 5.336-4.231 9.602-9.52 9.602zm0-16.887c-4.055 0-7.227 3.2-7.227 7.285 0 4.09 3.172 7.29 7.227 7.29s7.226-3.2 7.226-7.29c0-4.086-3.171-7.285-7.226-7.285zm0 12.442c-2.82 0-5.113-2.309-5.113-5.157 0-2.843 2.293-5.152 5.113-5.152 2.82 0 5.113 2.309 5.113 5.152.176 2.848-2.293 5.157-5.113 5.157zm3.347 24.707c.18.71.356 1.246.708 1.957-1.41.175-2.645.355-4.055.355C14.637 63.992.355 49.594.355 31.996S14.637 0 32.09 0c15.512 0 28.558 11.375 31.203 26.129l-2.996.535C57.828 13.332 46.19 3.024 32.09 3.024 16.398 3.023 3.53 15.995 3.53 31.815c0 15.82 12.867 28.797 28.559 28.797 1.058 0 2.117 0 3.172-.175 0 .355 0 .886.175 1.242zm31.208-33.95v27.73c0 2.31-1.766 4.087-4.41 4.798-2.82.71-5.641-.531-6.344-2.664-.532-2.313 1.41-4.621 4.23-5.332 1.234-.356 2.645-.18 3.703.175V35.73l-14.808 2.665V59.19c0 1.957-1.766 3.91-4.235 4.621-2.82.711-5.816-.71-6.168-2.664-.531-2.312 1.41-4.62 4.23-5.332 1.235-.355 2.645-.18 3.704.176V31.105zm0 0" fill="#039"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="52" xmlns="http://www.w3.org/2000/svg"><path d="M48.793 26.879h-4.629V18.05C44.164 7.988 35.973.043 26 .043S7.836 8.164 7.836 18.051v8.828H3.207A3.181 3.181 0 0 0 0 30.059V60.78c0 1.762 1.426 3.176 3.207 3.176h45.586c1.781 0 3.207-1.414 3.207-3.176V29.883c0-1.59-1.426-3.004-3.207-3.004zM29.918 52.305c.355 1.058-.535 1.941-1.602 1.941h-4.808c-1.07 0-1.781-1.059-1.606-1.941l1.426-5.649c-1.781-.883-3.027-2.648-3.027-4.945 0-3 2.492-5.473 5.52-5.473 3.027 0 5.523 2.473 5.523 5.473 0 2.117-1.246 4.062-3.028 4.945zm5.164-25.426H16.918V18.05c0-4.942 4.098-9.004 9.082-9.004s9.082 4.062 9.082 9.004zm0 0" fill="#696"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M41.266 22.992c0-3.945-2.403-7.035-5.664-8.406V3.262C35.602 1.372 34.23 0 32.344 0s-3.262 1.371-3.262 3.262v11.324c-3.43 1.2-5.66 4.46-5.66 8.406 0 3.945 2.402 7.035 5.66 8.406 0 .172-.172.516-.172.688V60.57c0 1.887 1.375 3.258 3.262 3.258s3.258-1.371 3.258-3.258V31.914c0-.344 0-.516-.168-.687 3.601-1.028 6.004-4.29 6.004-8.235zm-9.094 2.574c-1.371 0-2.402-1.03-2.402-2.402 0-1.375 1.03-2.402 2.402-2.402s2.402 1.027 2.402 2.402c.172 1.2-1.031 2.402-2.402 2.402zM58.254 3.602c0-1.887-1.375-3.258-3.262-3.258s-3.262 1.37-3.262 3.258v26.597c-3.43 1.2-5.66 4.461-5.66 8.406 0 3.946 2.403 7.036 5.66 8.407 0 .172-.171.515-.171.687v13.04c0 1.89 1.375 3.261 3.261 3.261 1.887 0 3.262-1.371 3.262-3.262V47.7c0-.344 0-.515-.172-.687 3.43-1.2 5.66-4.461 5.66-8.407 0-3.945-2.402-7.035-5.66-8.406V3.602zm-3.262 37.406c-1.37 0-2.402-1.028-2.402-2.403 0-1.37 1.031-2.402 2.402-2.402 1.371 0 2.403 1.031 2.403 2.402 0 1.375-1.032 2.403-2.403 2.403zm-48.73 19.39c0 1.887 1.375 3.258 3.261 3.258 1.887 0 3.258-1.37 3.258-3.258V47.355c0-.343 0-.511-.172-.683 3.434-1.203 5.664-4.461 5.664-8.41 0-3.946-2.402-7.035-5.664-8.407V3.602c0-1.887-1.37-3.258-3.257-3.258S6.09 1.714 6.09 3.602v26.597C2.66 31.4.43 34.66.43 38.605c0 3.946 2.402 7.036 5.66 8.407 0 .172-.172.515-.172.687v13.04c0-.34.344-.34.344-.34zm3.261-24.367c1.372 0 2.403 1.032 2.403 2.403 0 1.375-1.031 2.402-2.403 2.402-1.375 0-2.402-1.027-2.402-2.402 0-1.371 1.027-2.403 2.402-2.403zm0 0" fill="#999"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M11.427 34.125c-7.399 0-10.8-7.1-10.8-14.9-.099-7.7 3.3-14.9 10.8-14.9 2.3 0 4.2.6 5.7 1.6l-1 2.4c-1.1-.7-2.6-1.2-4.2-1.2-5.2 0-7.3 6-7.3 12.1 0 6 2.1 12 7.2 12 1.6 0 3.2-.5 4.2-1.2l1 2.5c-1.5 1-3.3 1.6-5.6 1.6zm14.901-20.8v20.3h-3.701v-20.3h-2.599v-2.3h2.599v-3.2c0-4.3 2.4-7.2 6.9-7.2h.8v2.4h-.3c-2 0-3.699 1-3.699 4.6v3.3h3.899v2.4zm0 0" fill="#679eb2" stroke="#679eb2" stroke-miterlimit="10" stroke-width="1.25" transform="matrix(1.84155 0 0 1.8314 0 .18)"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M11.427 34.125c-7.399 0-10.8-7.1-10.8-14.9-.099-7.7 3.3-14.9 10.8-14.9 2.3 0 4.2.6 5.7 1.6l-1 2.4c-1.1-.7-2.6-1.2-4.2-1.2-5.2 0-7.3 6-7.3 12.1 0 6 2.1 12 7.2 12 1.6 0 3.2-.5 4.2-1.2l1 2.5c-1.5 1-3.3 1.6-5.6 1.6zm14.901-20.8v20.3h-3.701v-20.3h-2.599v-2.3h2.599v-3.2c0-4.3 2.4-7.2 6.9-7.2h.8v2.4h-.3c-2 0-3.699 1-3.699 4.6v3.3h3.899v2.4zm0 0" fill="#679eb2" stroke="#679eb2" stroke-miterlimit="10" stroke-width="1.25" transform="matrix(1.84155 0 0 1.8314 0 .18)"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="73" xmlns="http://www.w3.org/2000/svg"><path d="M.184 46.813 26.828 64V51.383h45.625v-9.145H26.828V29.805zm45.988-34.196H.547v9.145h45.625v12.617l26.644-17.191L46.172 0zm0 0" fill="#666"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="59" xmlns="http://www.w3.org/2000/svg"><path d="M59 0H13.41C6.613 0 0 2.668 0 10.668V64h48.273V10.668H6.613c0-3.914 2.684-5.336 5.367-5.336h41.477v53.336l5.363-5.336V0zm0 0" fill="#c93"/><path d="M21.992 40.18c0-5.512 6.434-6.403 6.434-10.493 0-1.777-1.61-3.199-3.754-3.199-2.324.18-4.11 1.778-4.11 1.778L17.88 24.89s2.683-2.848 7.332-2.848c4.289 0 8.402 2.668 8.402 7.289 0 6.402-6.797 7.113-6.797 11.203v1.422h-4.824zm0 5.152h4.824v4.445h-4.824zm0 0" fill="#fff"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="48" xmlns="http://www.w3.org/2000/svg"><g fill="#f60" stroke="#f60" stroke-miterlimit="10" stroke-width=".5"><path d="M44.2 75.3c7.2-3.701 3.9-7.3 1.5-6.799-.6.099-.801.2-.801.2s.2-.3.601-.5C50.1 66.6 53.6 73 44 75.5zM37.8 64.8c1.801 2.1-.5 4-.5 4s4.7-2.4 2.5-5.5c-2-2.8-3.6-4.2 4.8-9.101 0 .101-13.1 3.401-6.8 10.6" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/><path d="M39.8 46.499s3.999 4-3.8 10.102c-6.2 4.898-1.4 7.7 0 10.899-3.601-3.3-6.3-6.2-4.5-8.8 2.7-4 9.9-5.9 8.3-12.201M31 76.8s-1.5.9 1 1.1c3 .299 4.6.299 7.9-.3 0 0 .9.599 2.1 1-7.4 3.3-16.901-.1-11-1.8m-.9-4.2s-1.6 1.199.9 1.5c3.2.3 5.8.4 10.2-.5 0 0 .6.6 1.599 1-9.1 2.6-19.199.2-12.698-2" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/><path d="M47.7 79.9s1.1.9-1.2 1.599c-4.3 1.302-18 1.702-21.8.101-1.4-.6 1.2-1.4 2-1.6.8-.2 1.3-.1 1.3-.1-1.5-1.1-9.8 2.1-4.2 3 15.3 2.4 27.9-1.199 23.9-3M31.7 68.3s-7 1.702-2.499 2.301c1.9.301 5.699.2 9.2-.101 2.9-.2 5.799-.8 5.799-.8s-1 .4-1.8.901c-7.1 1.9-20.7.999-16.8-.9 3.4-1.6 6.1-1.401 6.1-1.401" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/><path d="M32.399 85.4c6.901.4 17.502-.2 17.7-3.5 0 0-.499 1.2-5.699 2.2-5.899 1.1-13.101 1-17.5.3.1 0 1 .7 5.499 1" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><g fill="#999"><path d="M64 0H0v64h64zM12.8 12.633H6.399V6.23h6.403zm44.802 0h-38.57V6.23h38.57zm0 44.797H6.23V19.2h51.372zm0 0"/><path d="m16.336 24.59-4.547 4.547 7.41 7.41-7.41 7.242 4.547 4.547 11.957-11.79zm10.613 21.558h12.797v6.399H26.95zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="79" xmlns="http://www.w3.org/2000/svg"><path d="M30.86 9.86c7.523-.567 9.59-5.458 18.43-6.212 4.323-.375 6.956.567 7.331 2.07.188 1.317-1.879 2.446-4.512 2.634-3.574.378-5.078-.938-5.453-2.258-2.633.187-3.008 1.32-3.008 2.258.188 1.507 3.57 3.011 9.024 2.449 6.207-.567 8.277-3.012 7.898-5.457-.562-3.2-5.453-5.836-14.101-5.082-11.098.941-11.098 6.02-18.43 6.773-3.008.188-4.89-.375-5.078-1.691-.188-1.13 1.316-1.883 3.008-1.883 1.695-.188 3.574.187 4.703.562.754-.375.941-.75.754-1.128-.192-1.13-2.633-1.692-5.457-1.317-5.64.567-5.64 3.012-5.453 4.14.754 2.634 4.89 4.516 10.343 4.141zM68.28 22.468c-6.957 1.691-15.797 2.633-26.328 2.633-10.906 0-19.742-1.13-26.512-2.633-6.207-1.696-9.402-3.39-10.718-5.082.562 3.953 1.691 7.902 3.007 11.668-1.503.941-3.007 2.257-4.324 3.761C.961 35.828-.168 39.402.02 42.98c.187 3.575 1.882 6.399 4.703 8.657 2.82 2.258 6.015 2.824 9.402 2.258 1.316-.188 2.82-.942 4.137-1.317-2.82 0-5.266-.941-7.711-2.824-2.633-1.883-4.512-4.703-4.89-7.902-.563-3.012 0-6.024 1.694-8.47.375-.566.75-.94 1.125-1.316.942 2.446 2.07 4.704 3.387 6.961 2.633 3.953 5.266 7.528 7.899 11.293 1.129 2.258 1.879 4.516 2.445 6.586 1.691 2.446 4.137 4.14 7.332 5.082 3.762 1.317 7.71 1.88 11.848 1.88h.375c3.949 0 8.273-.563 12.222-1.88a14.826 14.826 0 0 0 7.149-5.082h.187a27.312 27.312 0 0 1 2.258-6.586c2.629-3.765 5.262-7.34 7.895-11.293 3.574-6.398 6.02-13.738 7.335-21.64-1.128 2.07-4.515 3.761-10.53 5.082zm-52.84-5.457c6.957 1.691 15.793 2.633 26.325 2.633 10.906 0 19.558-.942 26.328-2.633C75.426 15.316 79 13.059 79 10.8c0-1.696-1.691-3.012-4.512-4.14.563.374 1.125 1.128 1.125 1.882 0 2.258-3.383 3.95-9.965 5.457-6.207 1.316-14.101 2.258-23.695 2.258-9.21 0-17.488-.942-23.504-2.258-6.394-1.695-9.777-3.387-9.777-5.457 0-.941.375-1.695 1.691-2.637-3.949 1.696-6.207 2.824-6.207 4.895.188 2.258 3.762 4.515 11.285 6.21zm0 0" fill="#28334c"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M54.633 9.367C42.145-3.12 21.855-3.12 9.367 9.367s-12.488 32.778 0 45.266 32.778 12.488 45.266 0 12.488-32.778 0-45.266zM12.176 44.801c-5.934-9.211-4.84-21.543 3.12-29.504s20.294-9.055 29.505-3.121zm7.023 7.023L51.824 19.2c5.934 9.211 4.84 21.543-3.12 29.504s-20.294 9.055-29.505 3.121zm0 0" fill="#bababa"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><g fill="#999"><path d="M64 0H0v64h64zM12.8 12.633H6.399V6.23h6.403zm44.802 0h-38.57V6.23h38.57zm0 44.797H6.23V19.2h51.372zm0 0"/><path d="m16.336 24.59-4.547 4.547 7.41 7.41-7.41 7.242 4.547 4.547 11.957-11.79zm10.613 21.558h12.797v6.399H26.95zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="68" xmlns="http://www.w3.org/2000/svg"><g fill="#bababa"><path d="M59.906 48.902H0m60.715 7.387V19.035H68v44.8H1.617v-44.8h7.29V56.29zM16.675.164h36.106L34.648 18.543C28.82 12.637 22.668 6.398 16.676.164zm0 0"/><path d="M23.8 33.805v-7.383h7.286v7.383zm22.02 0h-7.285v-7.383h7.285zm-29.468 7.55h7.285v7.383h-7.285zm29.628 7.383v-7.383h7.286v7.383zm-7.609-7.383v7.383h-7.285v-7.383zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M41.266 22.992c0-3.945-2.403-7.035-5.664-8.406V3.262C35.602 1.372 34.23 0 32.344 0s-3.262 1.371-3.262 3.262v11.324c-3.43 1.2-5.66 4.46-5.66 8.406 0 3.945 2.402 7.035 5.66 8.406 0 .172-.172.516-.172.688V60.57c0 1.887 1.375 3.258 3.262 3.258s3.258-1.371 3.258-3.258V31.914c0-.344 0-.516-.168-.687 3.601-1.028 6.004-4.29 6.004-8.235zm-9.094 2.574c-1.371 0-2.402-1.03-2.402-2.402 0-1.375 1.03-2.402 2.402-2.402s2.402 1.027 2.402 2.402c.172 1.2-1.031 2.402-2.402 2.402zM58.254 3.602c0-1.887-1.375-3.258-3.262-3.258s-3.262 1.37-3.262 3.258v26.597c-3.43 1.2-5.66 4.461-5.66 8.406 0 3.946 2.403 7.036 5.66 8.407 0 .172-.171.515-.171.687v13.04c0 1.89 1.375 3.261 3.261 3.261 1.887 0 3.262-1.371 3.262-3.262V47.7c0-.344 0-.515-.172-.687 3.43-1.2 5.66-4.461 5.66-8.407 0-3.945-2.402-7.035-5.66-8.406V3.602zm-3.262 37.406c-1.37 0-2.402-1.028-2.402-2.403 0-1.37 1.031-2.402 2.402-2.402 1.371 0 2.403 1.031 2.403 2.402 0 1.375-1.032 2.403-2.403 2.403zm-48.73 19.39c0 1.887 1.375 3.258 3.261 3.258 1.887 0 3.258-1.37 3.258-3.258V47.355c0-.343 0-.511-.172-.683 3.434-1.203 5.664-4.461 5.664-8.41 0-3.946-2.402-7.035-5.664-8.407V3.602c0-1.887-1.37-3.258-3.257-3.258S6.09 1.714 6.09 3.602v26.597C2.66 31.4.43 34.66.43 38.605c0 3.946 2.402 7.036 5.66 8.407 0 .172-.172.515-.172.687v13.04c0-.34.344-.34.344-.34zm3.261-24.367c1.372 0 2.403 1.032 2.403 2.403 0 1.375-1.031 2.402-2.403 2.402-1.375 0-2.402-1.027-2.402-2.402 0-1.371 1.027-2.403 2.402-2.403zm0 0" fill="#999"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M41.266 22.992c0-3.945-2.403-7.035-5.664-8.406V3.262C35.602 1.372 34.23 0 32.344 0s-3.262 1.371-3.262 3.262v11.324c-3.43 1.2-5.66 4.46-5.66 8.406 0 3.945 2.402 7.035 5.66 8.406 0 .172-.172.516-.172.688V60.57c0 1.887 1.375 3.258 3.262 3.258s3.258-1.371 3.258-3.258V31.914c0-.344 0-.516-.168-.687 3.601-1.028 6.004-4.29 6.004-8.235zm-9.094 2.574c-1.371 0-2.402-1.03-2.402-2.402 0-1.375 1.03-2.402 2.402-2.402s2.402 1.027 2.402 2.402c.172 1.2-1.031 2.402-2.402 2.402zM58.254 3.602c0-1.887-1.375-3.258-3.262-3.258s-3.262 1.37-3.262 3.258v26.597c-3.43 1.2-5.66 4.461-5.66 8.406 0 3.946 2.403 7.036 5.66 8.407 0 .172-.171.515-.171.687v13.04c0 1.89 1.375 3.261 3.261 3.261 1.887 0 3.262-1.371 3.262-3.262V47.7c0-.344 0-.515-.172-.687 3.43-1.2 5.66-4.461 5.66-8.407 0-3.945-2.402-7.035-5.66-8.406V3.602zm-3.262 37.406c-1.37 0-2.402-1.028-2.402-2.403 0-1.37 1.031-2.402 2.402-2.402 1.371 0 2.403 1.031 2.403 2.402 0 1.375-1.032 2.403-2.403 2.403zm-48.73 19.39c0 1.887 1.375 3.258 3.261 3.258 1.887 0 3.258-1.37 3.258-3.258V47.355c0-.343 0-.511-.172-.683 3.434-1.203 5.664-4.461 5.664-8.41 0-3.946-2.402-7.035-5.664-8.407V3.602c0-1.887-1.37-3.258-3.257-3.258S6.09 1.714 6.09 3.602v26.597C2.66 31.4.43 34.66.43 38.605c0 3.946 2.402 7.036 5.66 8.407 0 .172-.172.515-.172.687v13.04c0-.34.344-.34.344-.34zm3.261-24.367c1.372 0 2.403 1.032 2.403 2.403 0 1.375-1.031 2.402-2.403 2.402-1.375 0-2.402-1.027-2.402-2.402 0-1.371 1.027-2.403 2.402-2.403zm0 0" fill="#999"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="83" height="43"><path style="stroke:none;fill-rule:nonzero;fill:#999;fill-opacity:1" d="M21.02 0c9.93 0 14.718 5.578 14.718 5.578l-4.433 9.715s-3.903-3.957-9.399-3.957c-6.738 0-9.93 4.676-9.93 10.074 0 5.395 3.368 10.434 9.93 10.434 6.207 0 9.754-4.856 9.754-4.856l5.32 9.356S31.836 43 21.195 43C8.605 43 .273 34.004.273 21.59.093 9.355 8.605 0 21.02 0zm19.152 18.531h7.094v-8.093h5.851v8.093h7.094v6.117h-7.094v8.098h-5.851v-8.098h-7.094zm22.523 0h7.094v-8.093h5.852v8.093h7.093v6.117h-7.093v8.098h-6.032v-8.098h-7.093zm0 0"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="69" xmlns="http://www.w3.org/2000/svg"><path d="M11.9 28C4.5 28 1 21.501 1 14.5 1 7.5 4.4 1 11.9 1c2.3 0 4.2.6 5.6 1.4l-1 2.1c-1-.6-2.7-1.1-4.2-1.1-5.2 0-7.2 5.5-7.2 11 0 5.4 2.101 10.9 7.2 10.9 1.6 0 3.1-.5 4.2-1.1l1 2.3c-1.4 1.1-3.2 1.5-5.6 1.5zM29.1 28c-1.302 0-2.702-.2-3.5-.501v8.4H22V8.2c1.9-1 4.4-1.4 7-1.4 6.5 0 10 4 10 10.3C39 23.9 35.1 28 29.1 28zM28.8 8.8c-1.1 0-2.4.199-3.2.601v16.1c.7.198 1.601.4 2.799.4 4.601 0 7.002-3.102 7.002-8.6-.102-5.201-1.9-8.5-6.601-8.5zm0 0" fill="#63b763" stroke="#63b763" stroke-miterlimit="10" stroke-width="2" transform="matrix(1.725 0 0 1.72973 0 .086)"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="82" xmlns="http://www.w3.org/2000/svg"><g fill="#3c3"><path d="M0 .094v63.812h82V.094zM77.34 4.8v27.86L57.773 17.6 36.34 39.247l-15.094-8.469L4.844 43.953V4.801zm0 0"/><path d="M22.55 17.223c0 3.222-2.585 5.836-5.777 5.836-3.191 0-5.777-2.614-5.777-5.836s2.586-5.836 5.777-5.836c3.192 0 5.778 2.613 5.778 5.836zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="52" xmlns="http://www.w3.org/2000/svg"><path d="M48.793 26.879h-4.629V18.05C44.164 7.988 35.973.043 26 .043S7.836 8.164 7.836 18.051v8.828H3.207A3.181 3.181 0 0 0 0 30.059V60.78c0 1.762 1.426 3.176 3.207 3.176h45.586c1.781 0 3.207-1.414 3.207-3.176V29.883c0-1.59-1.426-3.004-3.207-3.004zM29.918 52.305c.355 1.058-.535 1.941-1.602 1.941h-4.808c-1.07 0-1.781-1.059-1.606-1.941l1.426-5.649c-1.781-.883-3.027-2.648-3.027-4.945 0-3 2.492-5.473 5.52-5.473 3.027 0 5.523 2.473 5.523 5.473 0 2.117-1.246 4.062-3.028 4.945zm5.164-25.426H16.918V18.05c0-4.942 4.098-9.004 9.082-9.004s9.082 4.062 9.082 9.004zm0 0" fill="#696"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="52" xmlns="http://www.w3.org/2000/svg"><path d="M48.793 26.879h-4.629V18.05C44.164 7.988 35.973.043 26 .043S7.836 8.164 7.836 18.051v8.828H3.207A3.181 3.181 0 0 0 0 30.059V60.78c0 1.762 1.426 3.176 3.207 3.176h45.586c1.781 0 3.207-1.414 3.207-3.176V29.883c0-1.59-1.426-3.004-3.207-3.004zM29.918 52.305c.355 1.058-.535 1.941-1.602 1.941h-4.808c-1.07 0-1.781-1.059-1.606-1.941l1.426-5.649c-1.781-.883-3.027-2.648-3.027-4.945 0-3 2.492-5.473 5.52-5.473 3.027 0 5.523 2.473 5.523 5.473 0 2.117-1.246 4.062-3.028 4.945zm5.164-25.426H16.918V18.05c0-4.942 4.098-9.004 9.082-9.004s9.082 4.062 9.082 9.004zm0 0" fill="#a03537"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M21.344 36.297c-1.871 1.527-3.739 2.887-5.61 4.246L4.52 49.211c-.512.34-.852.508-1.36.168A15.884 15.884 0 0 0 .781 48.19c-.511-.171-.68-.511-.68-1.02V17.267c0-.34.34-.852.508-1.02.852d5006e"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="69" xmlns="http://www.w3.org/2000/svg"><path d="M13.875 13.874h10.9v2.701h-10.9zm0 5.4h10.9v2.701h-10.9zm0 5.5h10.9v2.702h-10.9zm19-24.399H11.177c-3 0-5.402 2.4-5.402 5.4v24.4h-5.4c0 3 2.402 5.4 5.4 5.4h21.7c3 0 5.402-2.4 5.402-5.4v-21.7h5.4v-2.7c0-3-2.402-5.4-5.4-5.4zm-2.7 29.3c0 1.801-1.4 3.2-3.2 3.2h-19.9c1.3-.9 1.3-2.7 1.3-2.7v-24.4c0-1.5 1.2-2.7 2.7-2.7 1.501 0 2.7 1.2 2.7 2.7v2.7h16.3zm-13.6-23.9v-2.7h16.3c2.501 0 2.7 1.6 2.7 2.7zm0 0" fill="#999" stroke="#999" stroke-miterlimit="10" stroke-width=".75" transform="matrix(1.7717 0 0 1.78025 .262 0)"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="83" height="63"><path style="stroke:none;fill-rule:nonzero;fill:#999;fill-opacity:1" d="M.125 0h69.586v8.184H.125zm13.164 18.273h69.586v8.18H13.289zM.125 36.543h69.586v8.184H.125zm13.164 18.273h69.586V63H13.289zm0 0"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="75" xmlns="http://www.w3.org/2000/svg"><path d="M.5 19v-4.1c.9-.1 1.6-.2 2-.4.4-.2.8-.6 1.2-1.001.4-.5.5-1.1.7-1.9.1-.6.2-1.499.2-2.799 0-2.201.1-3.7.4-4.6.2-.8.6-1.6 1.2-2 .5-.5 1.4-.9 2.5-1.2.7-.2 1.9-.4 3.5-.4h.9v3.9c-1.3 0-2.2.1-2.6.3-.4.2-.6.4-.9.6-.2.3-.3.7-.3 1.501 0 .8-.1 2-.2 4.099-.101 1.2-.2 2-.4 2.801-.301.6-.6 1.2-1 1.8-.4.4-1 .9-1.8 1.399.7.4 1.3.8 1.8 1.3s.8 1.2 1.1 1.899c.3.702.4 1.802.4 3.001.1 1.9.1 3.1.1 3.599 0 .702.1 1.202.3 1.602.2.4.5.5.9.6.4.2 1.2.3 2.6.3v4.098h-1c-1.6 0-2.9-.1-3.701-.4-.9-.3-1.6-.6-2.2-1.2-.6-.6-.999-1.2-1.2-1.999-.198-.8-.299-2.1-.299-4 0-2-.1-3.5-.3-4.1-.3-.9-.7-1.601-1.201-2-.698-.5-1.5-.7-2.7-.7zm39.1 0c-.9.1-1.6.2-2 .4s-.8.6-1.2 1.001c-.4.5-.5 1.1-.7 1.9-.099.6-.2 1.499-.2 2.799 0 2.201-.1 3.7-.4 4.6-.2.9-.6 1.6-1.2 2-.5.5-1.4.9-2.5 1.2-.7.2-1.9.4-3.5.4h-.999v-4.1c1.298 0 2.1-.1 2.599-.3s.7-.4.899-.6c.2-.3.301-.7.301-1.501 0-.6.1-2 .2-3.999.099-1.2.3-2.1.5-2.8.3-.7.6-1.3 1.1-1.9.4-.5 1-.9 1.7-1.3-.901-.6-1.6-1.1-2-1.6-.5-.7-1-1.801-1.201-2.8-.199-.8-.299-2.6-.299-5.2 0-.8-.1-1.4-.301-1.8-.199-.3-.4-.5-.799-.6-.2-.3-1-.3-2.5-.3v-4h.999c1.602 0 2.9.1 3.7.4.902.3 1.6.6 2.2 1.2.6.6 1.002 1.2 1.2 2 .201.8.402 2.1.402 4 0 2 .098 3.4.299 4.1.299.9.7 1.601 1.2 1.9.5.4 1.401.6 2.5.6.1.1 0 4.3 0 4.3zm0 0" fill="#72a536" stroke="#72a536" stroke-miterlimit="10" transform="matrix(1.86825 0 0 1.87558 0 .209)"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="84" height="52"><path style="fill:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke:#1f7244;stroke-opacity:1;stroke-miterlimit:10" d="M0 1.5h8.5m3.3 0h8.5m3.4 0h8.5m3.3 0H44M0 7.4h8.5m3.3 0h8.5m3.4 0h8.5m3.3 0H44M0 13.3h8.5m3.3 0h8.5m3.4 0h8.5m3.3 0H44M0 19.2h8.5m3.3 0h8.5m3.4 0h8.5m3.3 0H44M0 25.1h8.5m3.3 0h8.5m3.4 0h8.5m3.3 0H44" transform="matrix(1.9091 0 0 1.92593 0 .385)"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><g fill="#eab41b"><path d="M28.023 32c0 1.04.344 2.074 1.211 2.766 1.555 1.558 4.149 1.558 5.707 0 .692-.692 1.211-1.727 1.211-2.766s-.347-2.074-1.21-2.766c-.692-.695-1.731-1.21-2.77-1.21-1.035 0-2.074.343-2.766 1.21-1.039.692-1.383 1.727-1.383 2.766zm0 0"/><path d="M9.34 9.34c-12.453 12.453-12.453 32.691 0 45.32 12.453 12.453 32.691 12.453 45.32 0 12.453-12.453 12.453-32.691 0-45.32-12.453-12.453-32.867-12.453-45.32 0zm47.394 36.152c-1.21 2.074-2.765 4.153-4.496 5.88-1.73 1.73-3.804 3.288-5.883 4.5l-7.437-14.184s.691-.176 2.078-1.56c1.383-1.382 1.727-2.073 1.727-2.073zM37.707 26.293c1.559 1.555 2.422 3.633 2.422 5.707s-.863 4.152-2.422 5.707a7.933 7.933 0 0 1-11.242 0c-1.559-1.555-2.422-3.633-2.422-5.707s.691-4.152 2.422-5.707c2.941-3.113 8.129-3.113 11.242 0zm-10.895-5.535s-1.558.863-2.769 2.246c-1.211 1.387-1.211 1.558-1.73 2.25l-14.184-7.61c1.21-2.078 2.77-4.152 4.5-5.882 1.902-1.73 3.805-3.285 5.879-4.496zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="55" xmlns="http://www.w3.org/2000/svg"><path d="M54.652 53.883 41.801 64 27.289 46.172l-9.3 11.351L.347 0l53.07 29.219-13.277 6.836zm0 0" fill="#8ed200"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="m10.98 2.23 12.672 10.356c-.355-3.75-1.96-7.856-4.46-10.356-1.786-1.785-3.391-2.5-5-2.14-1.426.18-2.5 1.07-3.212 2.14zM2.23 19.191c2.68 2.676 6.786 4.106 10.536 4.461L2.41 10.98c-1.25.891-2.14 1.786-2.32 3.211-.36 1.61.355 3.215 2.14 5zm51.06 22.672L41.862 53.29c1.43 1.43 3.75 2.676 6.07 3.035.715.18 1.25.18 1.965.18 1.07 0 2.141-.18 3.036-.715l7.675 7.676c.356.355.891.535 1.426.535s1.07-.18 1.43-.535c.715-.715.715-2.145 0-2.856l-7.676-7.675c1.606-3.575 0-8.57-2.5-11.07zM4.91 7.766l34.274 42.488 11.07-11.07L7.766 4.91c-.715-.715-1.965-.535-2.68.176-.89.715-.89 1.789-.176 2.68zm0 0" fill="#0091ea"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="69" xmlns="http://www.w3.org/2000/svg"><path d="M17.8.5c-2.9 0-5.4 2.801-5.4 6.2 0 3.4 2.4 6.2 5.4 6.2 2.9 0 5.399-2.8 5.399-6.2C23.199 3.302 20.8.5 17.8.5zm0 10.1c-1.6 0-3-1.7-3-3.9 0-2.1 1.3-3.9 3-3.9s3 1.7 3 3.9-1.3 3.9-3 3.9zM7 11.8V1.7C7 1 6.5.5 5.8.5S4.6 1 4.6 1.7v10.1c0 .7.5 1.2 1.2 1.2S7 12.4 7 11.8zm-1.1 6.9C3 18.7.5 21.5.5 24.9s2.4 6.2 5.4 6.2 5.401-2.8 5.401-6.2c-.102-3.3-2.5-6.2-5.4-6.2zm0 10.2c-1.6 0-3-1.699-3-3.9 0-2.1 1.3-3.9 3-3.9s3 1.7 3 3.9c-.1 2.1-1.4 3.9-3 3.9zM19 30V19.9c0-.7-.5-1.2-1.2-1.2s-1.2.5-1.2 1.2V30c0 .7.5 1.2 1.2 1.2S19 30.7 19 30zM31.3 12.7V2.6c0-.7-.499-1.2-1.2-1.2-.7 0-1.1.5-1.1 1.2v10.099c0 .701.5 1.2 1.2 1.2s1.1-.6 1.1-1.2zm-1.2 6.9c-2.9 0-5.401 2.8-5.401 6.2 0 3.4 2.4 6.202 5.4 6.202 2.901 0 5.402-2.802 5.402-6.202S33.1 19.6 30.1 19.6zm0 10.102c-1.6 0-3-1.7-3-3.902 0-2.099 1.3-3.9 3-3.9s3 1.7 3 3.9c0 2.202-1.3 3.902-3 3.902zm0 0" fill="#999" stroke="#999" stroke-miterlimit="10" transform="matrix(1.91667 0 0 1.9394 0 .485)"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="69" xmlns="http://www.w3.org/2000/svg"><path d="M17.8.5c-2.9 0-5.4 2.801-5.4 6.2 0 3.4 2.4 6.2 5.4 6.2 2.9 0 5.399-2.8 5.399-6.2C23.199 3.302 20.8.5 17.8.5zm0 10.1c-1.6 0-3-1.7-3-3.9 0-2.1 1.3-3.9 3-3.9s3 1.7 3 3.9-1.3 3.9-3 3.9zM7 11.8V1.7C7 1 6.5.5 5.8.5S4.6 1 4.6 1.7v10.1c0 .7.5 1.2 1.2 1.2S7 12.4 7 11.8zm-1.1 6.9C3 18.7.5 21.5.5 24.9s2.4 6.2 5.4 6.2 5.401-2.8 5.401-6.2c-.102-3.3-2.5-6.2-5.4-6.2zm0 10.2c-1.6 0-3-1.699-3-3.9 0-2.1 1.3-3.9 3-3.9s3 1.7 3 3.9c-.1 2.1-1.4 3.9-3 3.9zM19 30V19.9c0-.7-.5-1.2-1.2-1.2s-1.2.5-1.2 1.2V30c0 .7.5 1.2 1.2 1.2S19 30.7 19 30zM31.3 12.7V2.6c0-.7-.499-1.2-1.2-1.2-.7 0-1.1.5-1.1 1.2v10.099c0 .701.5 1.2 1.2 1.2s1.1-.6 1.1-1.2zm-1.2 6.9c-2.9 0-5.401 2.8-5.401 6.2 0 3.4 2.4 6.202 5.4 6.202 2.901 0 5.402-2.802 5.402-6.202S33.1 19.6 30.1 19.6zm0 10.102c-1.6 0-3-1.7-3-3.902 0-2.099 1.3-3.9 3-3.9s3 1.7 3 3.9c0 2.202-1.3 3.902-3 3.902zm0 0" fill="#999" stroke="#999" stroke-miterlimit="10" transform="matrix(1.91667 0 0 1.9394 0 .485)"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="51" xmlns="http://www.w3.org/2000/svg"><path d="M23.023 63.957c-8.199-.34-15.543-2.875-19.468-6.77-1.196-1.011-2.39-2.535-2.903-3.55L.31 52.96v-7.617c0-7.614 0-7.614.171-6.934.34 1.692 1.368 3.383 2.903 4.735 1.023.847 3.074 2.37 4.781 3.214 2.906 1.524 6.66 2.54 10.59 3.047 2.39.34 3.246.34 6.66.34 3.418 0 4.27 0 6.66-.34 3.93-.508 7.516-1.691 10.59-3.047 1.707-.843 3.758-2.199 4.781-3.214 1.368-1.352 2.563-3.043 2.903-4.735.172-.508.172-.508.172 6.934v7.445l-.34.68c-1.196 2.367-3.246 4.398-5.98 6.09-5.294 3.046-13.321 4.738-21.177 4.398zm0-18.95c-7.171-.339-13.832-2.37-18.101-5.413-1.027-.68-2.39-2.032-2.906-2.707-.512-.68-1.024-1.524-1.364-2.371L.31 33.84v-7.445c0-7.446 0-7.446.171-6.938.34 1.184.852 2.54 1.88 3.555.511.675 1.367 1.523 1.878 1.86.168.171.684.339 1.024.679 3.414 2.367 8.199 4.058 13.664 4.906 2.39.336 3.242.336 6.66.336 3.414 0 4.27 0 6.66-.336 3.93-.508 7.516-1.691 10.59-3.047 1.707-.847 3.758-2.2 4.781-3.215 1.367-1.351 2.39-3.047 2.903-4.738.171-.508.171-.508.171 6.938v7.445l-.511 1.015c-.856 1.524-1.368 2.368-2.39 3.383-1.028 1.016-2.052 1.864-3.419 2.54-5.465 3.046-13.492 4.738-21.348 4.23zm-.511-18.78c-4.782-.34-8.54-1.184-12.125-2.54-4.27-1.69-7.344-3.89-8.883-6.597a5.594 5.594 0 0 1-.852-2.031C.48 14.383.31 12.69.48 11.676 1.504 6.262 8.848 1.859 18.754.34 21.144 0 22 0 25.414 0c3.418 0 4.27 0 6.66.34 3.93.508 7.516 1.691 10.59 3.043 4.441 2.199 7.172 5.078 7.684 8.12.172.849.172 2.708-.168 3.388-.512 1.691-1.196 2.707-2.563 4.058-3.586 3.723-9.906 6.094-17.762 6.938-1.023.34-6.32.34-7.343.34zm0 0" fill="#999"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="51" xmlns="http://www.w3.org/2000/svg"><path d="M23.023 63.957c-8.199-.34-15.543-2.875-19.468-6.77-1.196-1.011-2.39-2.535-2.903-3.55L.31 52.96v-7.617c0-7.614 0-7.614.171-6.934.34 1.692 1.368 3.383 2.903 4.735 1.023.847 3.074 2.37 4.781 3.214 2.906 1.524 6.66 2.54 10.59 3.047 2.39.34 3.246.34 6.66.34 3.418 0 4.27 0 6.66-.34 3.93-.508 7.516-1.691 10.59-3.047 1.707-.843 3.758-2.199 4.781-3.214 1.368-1.352 2.563-3.043 2.903-4.735.172-.508.172-.508.172 6.934v7.445l-.34.68c-1.196 2.367-3.246 4.398-5.98 6.09-5.294 3.046-13.321 4.738-21.177 4.398zm0-18.95c-7.171-.339-13.832-2.37-18.101-5.413-1.027-.68-2.39-2.032-2.906-2.707-.512-.68-1.024-1.524-1.364-2.371L.31 33.84v-7.445c0-7.446 0-7.446.171-6.938.34 1.184.852 2.54 1.88 3.555.511.675 1.367 1.523 1.878 1.86.168.171.684.339 1.024.679 3.414 2.367 8.199 4.058 13.664 4.906 2.39.336 3.242.336 6.66.336 3.414 0 4.27 0 6.66-.336 3.93-.508 7.516-1.691 10.59-3.047 1.707-.847 3.758-2.2 4.781-3.215 1.367-1.351 2.39-3.047 2.903-4.738.171-.508.171-.508.171 6.938v7.445l-.511 1.015c-.856 1.524-1.368 2.368-2.39 3.383-1.028 1.016-2.052 1.864-3.419 2.54-5.465 3.046-13.492 4.738-21.348 4.23zm-.511-18.78c-4.782-.34-8.54-1.184-12.125-2.54-4.27-1.69-7.344-3.89-8.883-6.597a5.594 5.594 0 0 1-.852-2.031C.48 14.383.31 12.69.48 11.676 1.504 6.262 8.848 1.859 18.754.34 21.144 0 22 0 25.414 0c3.418 0 4.27 0 6.66.34 3.93.508 7.516 1.691 10.59 3.043 4.441 2.199 7.172 5.078 7.684 8.12.172.849.172 2.708-.168 3.388-.512 1.691-1.196 2.707-2.563 4.058-3.586 3.723-9.906 6.094-17.762 6.938-1.023.34-6.32.34-7.343.34zm0 0" fill="#a03537"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="74" xmlns="http://www.w3.org/2000/svg"><path d="m49.332 34.941-12.25-5.714L61.75 17.633 74 23.348l-12.25 5.879zM61.75 6.207 49.5.492 37.25 6.207l24.5 11.594L74 12.086zm-37.082 17.14-12.25-5.714-12.25 5.715L24.836 34.94l12.246-5.714zm0-11.429 12.25-5.711L24.668.492 0 12.086 12.25 17.8zM61.75 32.59l-11.074 5.039-1.344.672-1.34-.672-11.074-5.04-11.078 5.04-1.34.672-1.344-.672-11.074-5.04v17.977L36.75 63.508l25-12.942zm0 0" fill="#4d1b9b"/></svg> |
| 1 | ||
| 1 | <svg height="63" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M33.325 19.55c-.498-.2-1.1 0-1.299.5-1.1 2.5-2.901 4.7-5.1 6.4l-6.7-13.601c1-.8 1.6-1.999 1.6-3.4 0-2.099-1.501-3.899-3.501-4.3v-3.4a1 1 0 0 0-2 0v3.4c-2 .401-3.5 2.201-3.5 4.3 0 1.401.6 2.6 1.601 3.4l-6.7 13.602c-2.201-1.7-4-3.801-5.1-6.401-.201-.5-.8-.7-1.301-.5-.499.199-.7.8-.499 1.3 1.299 3 3.4 5.4 6 7.3l-4 8c-.2.5 0 1.1.4 1.3.098 0 .3.1.4.1.3 0 .7-.2.9-.5l3.8-7.8c2.7 1.5 5.6 2.2 8.7 2.2 3.1 0 6-.8 8.699-2.2l3.8 7.8c.1.3.501.5.9.5.1 0 .3 0 .4-.1.5-.2.7-.8.4-1.3l-3.9-8c2.6-1.8 4.701-4.4 6-7.3.6-.5.401-1.101 0-1.3zM17.326 6.95c1.4 0 2.5 1.1 2.5 2.499 0 1.401-1.1 2.502-2.5 2.502s-2.5-1.1-2.5-2.502c0-1.4 1.199-2.5 2.5-2.5zm0 22.6c-2.8 0-5.4-.7-7.801-2l6.8-13.7c.3.1.701.1 1.1.1.402 0 .701 0 1.1-.1l6.8 13.7c-2.5 1.3-5.199 2-7.999 2zm0 0" fill="#369" stroke="#369" stroke-miterlimit="10" stroke-width="1.5" transform="matrix(1.6544 0 0 1.63607 0 .154)"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="83" height="54"><path style="fill-rule:nonzero;fill:#999;fill-opacity:1;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#999;stroke-opacity:1;stroke-miterlimit:10" d="M11.242 25.867c-.5 0-1.1-.2-1.498-.6l-8.4-8.401c-.802-.799-.802-2.099 0-3l8.4-8.398c.8-.8 2.098-.8 2.999 0 .8.8.8 2.098 0 2.999l-6.9 6.9 6.9 6.9c.8.801.8 2.1 0 3-.401.4-1 .6-1.5.6zm25.1 0c-.499 0-1.099-.2-1.5-.6-.8-.8-.8-2.099 0-3.002l6.9-6.898-6.9-6.9c-.8-.8-.8-2.101 0-3 .8-.8 2.1-.8 3.001 0l8.398 8.4c.802.8.802 2.1 0 3l-8.398 8.4c-.4.4-1.001.6-1.5.6zm-16.7 4.1c-.199 0-.398 0-.698-.1-1.102-.401-1.702-1.5-1.301-2.6l8.398-25.1c.4-1.1 1.5-1.699 2.6-1.301 1.102.4 1.702 1.5 1.301 2.601l-8.398 25.1c-.202.899-1.102 1.4-1.901 1.4zm0 0" transform="matrix(1.74425 0 0 1.75713 0 .013)"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="84" height="60"><path style="stroke:none;fill-rule:nonzero;fill:#bababa;fill-opacity:1" d="M72.277.21c-4.906 0-3.586 4.978-4.53 7.083-.376.77-.946 2.297-1.509 3.64l.375-.765c-.375.762-.566.953-1.32 1.527 0 0-3.398 2.11-6.422 3.832C55.285 9.211 48.863 5.57 41.875 5.57c-6.984 0-13.594 3.828-16.992 9.957-3.207-1.914-6.61-3.832-6.61-3.832-.753-.574-1.128-.765-1.32-1.527l.375.762c-.566-1.34-1.129-2.68-1.508-3.637C15.066 5 16.383.211 11.29.211c-4.915 0-3.97 6.7-5.477 9.379-.946 1.726-3.778 3.445-5.098 5.363-.192.188-.192.379-.192.574-.566.957-.753 2.297.192 3.637 2.453 4.211 6.039.766 8.305.383.945-.192 2.27-.192 3.777-.574l-.945.191c.757-.191 1.136 0 2.078.574 0 0 3.59 2.106 8.308 4.785v1.149c0 3.64.946 7.469 3.024 10.527a656.505 656.505 0 0 0-11.895 7.278c-.758.574-1.137.765-1.89.574h.753-3.585c-2.27 0-5.102-2.68-7.93.957-2.649 3.637 2.828 5.36 3.965 7.469 1.133 2.105-.38 7.843 4.34 7.27 4.535-.571 3.777-4.403 4.91-6.505.566-.765 1.136-1.918 1.699-3.062l-.375.765c.375-.578.754-.765 1.508-1.343 0 0 5.289-2.868 11.332-6.508v8.804c1.699.766 3.398 1.153 5.097 1.532v-4.785l2.454.574v4.785c1.699.387 3.402.578 5.101.578v-4.789h2.266v4.598c1.695 0 3.398-.196 5.097-.578v-4.786l2.453-.574v4.977c1.7-.38 3.399-.766 5.098-1.532v-8.804a396.942 396.942 0 0 1 11.332 6.508c.754.578 1.133.765 1.512 1.343.566.762.941 1.72 1.32 2.297.946 1.914.375 5.934 4.91 6.504 4.536.578 3.211-5.164 4.344-7.27 1.133-2.109 6.61-3.64 3.965-7.468-2.645-3.637-5.664-1.149-7.93-.957h-3.59.754c-.754 0-.941 0-1.886-.574 0 0-5.477-3.446-11.899-7.278 2.078-3.25 3.024-6.695 3.024-10.527v-1.149c4.722-2.68 8.308-4.785 8.308-4.785.754-.574 1.32-.574 2.078-.574l-.57-.191c1.516.191 2.836.382 3.781.574 2.266.383 5.852 3.828 8.309-.383 2.453-4.21-3.59-6.89-5.098-9.574-.945-1.719-.758-5.164-2.078-7.27 0-.195-.191-.386-.191-.386C74.735.785 73.793.402 72.277.21zM34.324 23.376c.567 0 .758 0 1.32.191 2.645.766 3.403 3.254 2.645 6.125-.754 2.684-3.586 4.403-6.23 3.637-2.645-.766-3.59-3.445-2.645-6.121.57-2.3 2.645-3.832 4.91-3.832zm14.73 0c2.266 0 4.532 1.531 5.098 3.637.754 2.68 0 5.172-2.644 6.129-2.645.761-5.477-.77-6.23-3.641-.755-2.68 0-5.168 2.644-6.125a1.19 1.19 0 0 0 1.133 0zm-7.363 12.824c.754 0 3.961 4.215 3.586 4.79-.379.574-6.797.574-7.175 0-.38-.575 3.02-4.79 3.59-4.79zm0 0"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="67" xmlns="http://www.w3.org/2000/svg"><path d="M67 .445 36.203 4.63v24.55H67zM30.797 5.172 0 9.355V29.18h30.797zM.18 34.82v19.825l30.797 4.183V35zm36.023 0v24.551L67 63.555V34.82zm0 0" fill="#666"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M57.602 41.688c2.488 0 4.62 1.066 6.218 2.492L58.488 5.422C58.133 2.222 55.29.09 52.266.09H11.734c-3.199 0-5.867 2.133-6.402 5.332L0 44.18c1.777-1.426 3.91-2.493 6.398-2.493zm0 3.023H6.398A6.372 6.372 0 0 0 0 51.109v6.403a6.372 6.372 0 0 0 6.398 6.398h51.204A6.372 6.372 0 0 0 64 57.512v-6.403a6.372 6.372 0 0 0-6.398-6.398zM52.09 56.977h-3.91a1.97 1.97 0 0 1-1.957-1.954c0-1.066.886-1.957 1.957-1.957h3.91c1.066 0 1.953.891 1.953 1.957a1.97 1.97 0 0 1-1.953 1.954zm5.156 0a1.972 1.972 0 0 1-1.957-1.954c0-1.066.89-1.957 1.957-1.957s1.953.891 1.953 1.957c.18 1.067-.71 1.954-1.953 1.954zm0 0" fill="#4d1b9b"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="82" xmlns="http://www.w3.org/2000/svg"><g fill="#3c3"><path d="M0 .094v63.812h82V.094zM77.34 4.8v27.86L57.773 17.6 36.34 39.247l-15.094-8.469L4.844 43.953V4.801zm0 0"/><path d="M22.55 17.223c0 3.222-2.585 5.836-5.777 5.836-3.191 0-5.777-2.614-5.777-5.836s2.586-5.836 5.777-5.836c3.192 0 5.778 2.613 5.778 5.836zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="84" height="60"><path style="stroke:none;fill-rule:nonzero;fill:#1a75ce;fill-opacity:1" d="m12.762 33.262-8.39-26.09c-.349-1.059-.524-1.41-.7-1.41-.176-.176-.352-.176-.527-.352l-2.97-.883L0 .824h15.734l.348 3.703-2.973.883v.352c0 .351.176 1.058.528 1.761L16.78 17.57 22.38.824 26.57.648l5.07 16.747 3.497-10.051c.175-.703.527-1.41.527-1.762V5.41l-2.621-.707-.176-3.879h12.235l.351 3.703-3.32 1.059c-.176 0-.352.176-.528.176 0 .176-.347.351-.523 1.234l-9.266 25.91-4.37.356-4.716-16.043-5.597 15.687zm0 0"/><path style="fill-rule:nonzero;fill:#1a75ce;fill-opacity:1;stroke-width:.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#1a75ce;stroke-opacity:1;stroke-miterlimit:10" d="M42.4 48.6H60v2.8H42.4zm0 7.401H60V58.8H42.4zm0 7.7H60V66.5H42.4zm-29.4 7.8h47v2.798H13zm0 7.598h47v2.8H13zm0 0" transform="matrix(1.74818 0 0 1.76287 -21.328 -85.027)"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="84" height="60"><path style="stroke:none;fill-rule:nonzero;fill:#1a75ce;fill-opacity:1" d="m12.762 33.262-8.39-26.09c-.349-1.059-.524-1.41-.7-1.41-.176-.176-.352-.176-.527-.352l-2.97-.883L0 .824h15.734l.348 3.703-2.973.883v.352c0 .351.176 1.058.528 1.761L16.78 17.57 22.38.824 26.57.648l5.07 16.747 3.497-10.051c.175-.703.527-1.41.527-1.762V5.41l-2.621-.707-.176-3.879h12.235l.351 3.703-3.32 1.059c-.176 0-.352.176-.528.176 0 .176-.347.351-.523 1.234l-9.266 25.91-4.37.356-4.716-16.043-5.597 15.687zm0 0"/><path style="fill-rule:nonzero;fill:#1a75ce;fill-opacity:1;stroke-width:.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#1a75ce;stroke-opacity:1;stroke-miterlimit:10" d="M42.4 48.6H60v2.8H42.4zm0 7.401H60V58.8H42.4zm0 7.7H60V66.5H42.4zm-29.4 7.8h47v2.798H13zm0 7.598h47v2.8H13zm0 0" transform="matrix(1.74818 0 0 1.76287 -21.328 -85.027)"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="84" height="60"><path style="stroke:none;fill-rule:nonzero;fill:#1a75ce;fill-opacity:1" d="m12.762 33.262-8.39-26.09c-.349-1.059-.524-1.41-.7-1.41-.176-.176-.352-.176-.527-.352l-2.97-.883L0 .824h15.734l.348 3.703-2.973.883v.352c0 .351.176 1.058.528 1.761L16.78 17.57 22.38.824 26.57.648l5.07 16.747 3.497-10.051c.175-.703.527-1.41.527-1.762V5.41l-2.621-.707-.176-3.879h12.235l.351 3.703-3.32 1.059c-.176 0-.352.176-.528.176 0 .176-.347.351-.523 1.234l-9.266 25.91-4.37.356-4.716-16.043-5.597 15.687zm0 0"/><path style="fill-rule:nonzero;fill:#1a75ce;fill-opacity:1;stroke-width:.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#1a75ce;stroke-opacity:1;stroke-miterlimit:10" d="M42.4 48.6H60v2.8H42.4zm0 7.401H60V58.8H42.4zm0 7.7H60V66.5H42.4zm-29.4 7.8h47v2.798H13zm0 7.598h47v2.8H13zm0 0" transform="matrix(1.74818 0 0 1.76287 -21.328 -85.027)"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="84" height="60"><path style="stroke:none;fill-rule:nonzero;fill:#1a75ce;fill-opacity:1" d="m12.762 33.262-8.39-26.09c-.349-1.059-.524-1.41-.7-1.41-.176-.176-.352-.176-.527-.352l-2.97-.883L0 .824h15.734l.348 3.703-2.973.883v.352c0 .351.176 1.058.528 1.761L16.78 17.57 22.38.824 26.57.648l5.07 16.747 3.497-10.051c.175-.703.527-1.41.527-1.762V5.41l-2.621-.707-.176-3.879h12.235l.351 3.703-3.32 1.059c-.176 0-.352.176-.528.176 0 .176-.347.351-.523 1.234l-9.266 25.91-4.37.356-4.716-16.043-5.597 15.687zm0 0"/><path style="fill-rule:nonzero;fill:#1a75ce;fill-opacity:1;stroke-width:.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#1a75ce;stroke-opacity:1;stroke-miterlimit:10" d="M42.4 48.6H60v2.8H42.4zm0 7.401H60V58.8H42.4zm0 7.7H60V66.5H42.4zm-29.4 7.8h47v2.798H13zm0 7.598h47v2.8H13zm0 0" transform="matrix(1.74818 0 0 1.76287 -21.328 -85.027)"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="84" height="60"><path style="stroke:none;fill-rule:nonzero;fill:#1a75ce;fill-opacity:1" d="m12.762 33.262-8.39-26.09c-.349-1.059-.524-1.41-.7-1.41-.176-.176-.352-.176-.527-.352l-2.97-.883L0 .824h15.734l.348 3.703-2.973.883v.352c0 .351.176 1.058.528 1.761L16.78 17.57 22.38.824 26.57.648l5.07 16.747 3.497-10.051c.175-.703.527-1.41.527-1.762V5.41l-2.621-.707-.176-3.879h12.235l.351 3.703-3.32 1.059c-.176 0-.352.176-.528.176 0 .176-.347.351-.523 1.234l-9.266 25.91-4.37.356-4.716-16.043-5.597 15.687zm0 0"/><path style="fill-rule:nonzero;fill:#1a75ce;fill-opacity:1;stroke-width:.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#1a75ce;stroke-opacity:1;stroke-miterlimit:10" d="M42.4 48.6H60v2.8H42.4zm0 7.401H60V58.8H42.4zm0 7.7H60V66.5H42.4zm-29.4 7.8h47v2.798H13zm0 7.598h47v2.8H13zm0 0" transform="matrix(1.74818 0 0 1.76287 -21.328 -85.027)"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="84" height="60"><path style="stroke:none;fill-rule:nonzero;fill:#1a75ce;fill-opacity:1" d="m12.762 33.262-8.39-26.09c-.349-1.059-.524-1.41-.7-1.41-.176-.176-.352-.176-.527-.352l-2.97-.883L0 .824h15.734l.348 3.703-2.973.883v.352c0 .351.176 1.058.528 1.761L16.78 17.57 22.38.824 26.57.648l5.07 16.747 3.497-10.051c.175-.703.527-1.41.527-1.762V5.41l-2.621-.707-.176-3.879h12.235l.351 3.703-3.32 1.059c-.176 0-.352.176-.528.176 0 .176-.347.351-.523 1.234l-9.266 25.91-4.37.356-4.716-16.043-5.597 15.687zm0 0"/><path style="fill-rule:nonzero;fill:#1a75ce;fill-opacity:1;stroke-width:.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#1a75ce;stroke-opacity:1;stroke-miterlimit:10" d="M42.4 48.6H60v2.8H42.4zm0 7.401H60V58.8H42.4zm0 7.7H60V66.5H42.4zm-29.4 7.8h47v2.798H13zm0 7.598h47v2.8H13zm0 0" transform="matrix(1.74818 0 0 1.76287 -21.328 -85.027)"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="84" height="60"><path style="stroke:none;fill-rule:nonzero;fill:#1a75ce;fill-opacity:1" d="m12.762 33.262-8.39-26.09c-.349-1.059-.524-1.41-.7-1.41-.176-.176-.352-.176-.527-.352l-2.97-.883L0 .824h15.734l.348 3.703-2.973.883v.352c0 .351.176 1.058.528 1.761L16.78 17.57 22.38.824 26.57.648l5.07 16.747 3.497-10.051c.175-.703.527-1.41.527-1.762V5.41l-2.621-.707-.176-3.879h12.235l.351 3.703-3.32 1.059c-.176 0-.352.176-.528.176 0 .176-.347.351-.523 1.234l-9.266 25.91-4.37.356-4.716-16.043-5.597 15.687zm0 0"/><path style="fill-rule:nonzero;fill:#1a75ce;fill-opacity:1;stroke-width:.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#1a75ce;stroke-opacity:1;stroke-miterlimit:10" d="M42.4 48.6H60v2.8H42.4zm0 7.401H60V58.8H42.4zm0 7.7H60V66.5H42.4zm-29.4 7.8h47v2.798H13zm0 7.598h47v2.8H13zm0 0" transform="matrix(1.74818 0 0 1.76287 -21.328 -85.027)"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="72" xmlns="http://www.w3.org/2000/svg"><filter id="a" height="100%" width="100%" x="0%" y="0%"><feColorMatrix in="SourceGraphic" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/></filter><mask id="c"><g filter="url(#a)"><path d="M0 0h72v64H0z" fill-opacity=".6"/></g></mask><clipPath id="b"><path d="M0 0h72v64H0z"/></clipPath><mask id="e"><g filter="url(#a)"><path d="M0 0h72v64H0z" fill-opacity=".6"/></g></mask><clipPath id="d"><path d="M0 0h72v64H0z"/></clipPath><g clip-path="url(#b)" mask="url(#c)"><path d="M67.418 37.824C70.199 40.454 72 44.391 72 48.656c0 8.207-6.71 14.934-14.89 14.934-8.184 0-14.891-6.727-14.891-14.934 0-.492 0-1.148.164-1.64.816-7.387 7.199-13.293 14.89-13.293 3.926-.164 7.528 1.64 10.145 4.101zm0 0" fill="#ef806f"/></g><g clip-path="url(#d)" mask="url(#e)"><path d="M68.563 32.082c0 1.148-.165 2.297-.325 3.61-3.11-2.626-7.039-4.102-11.129-4.102-8.672 0-16.035 6.562-17.02 15.262H11.782C5.238 46.852 0 41.602 0 35.035c0-5.086 3.273-9.515 7.691-11.16v-.656c0-6.07 4.91-10.992 10.965-10.992 1.961 0 3.762.492 5.399 1.312C25.69 6.152 32.398.41 40.418.41c9.328 0 16.855 7.547 16.855 16.902v.329c6.543 1.476 11.29 7.386 11.29 14.441zm0 0" fill="#1ea6c6"/></g><path d="m64.965 48.82-7.528 7.715-7.69-7.715h4.581V38.152h6.055V48.82zm0 0" fill="#fff"/></svg> |
| 1 | ||
| 1 | <svg height="63" width="49" xmlns="http://www.w3.org/2000/svg"><path d="M24.842 21.014c2.2-.7 4.4.7 4.202 2.8-.2 2.4-3.302 3.601-5.1 4.2l.1-.099-.1-.101c1.3-1 3.898-2.199 3.7-4.6-.1-1.2-1.001-2.098-2.702-2v-.2zm-16.099.401.1-.101c-1 0-1.901.4-2.701.7-.798.3-1.8.401-2.198 1.3.399.7 1.4.7 2.398.802 3.4.5 8.302.398 11.701 0 1.799-.201 3.4-.401 4.2-1.201l-.1-.101.1-.1c-3.4.402-7.8 1-11.9.8-1.301-.099-3-.099-3.7-.8.4-.7 1.4-.9 2.1-1.299zm19.9 14.099v-.1c-5.1 2.5-13.201 2.8-20.5 2.201l.1.1-.1.2c2.999.5 6.9.7 10.7.398 3.7-.198 8.199-.698 9.9-2.698zm-14.4-15.398h.1c-.8-1.802-2.3-2.602-2.499-4.7-.2-1.902.7-3.102 1.598-4 1.101-1.201 2.702-2.201 3.901-3.5 1.6-1.803 3.4-4.5 1.9-7.102l-.101.101-.299-.101c.4 2.5-.6 4.101-1.901 5.4-.999 1.201-2.6 2.201-4 3.3-1.6 1.3-3.7 2.901-3.1 5.3.502 2.302 2.8 3.9 4.102 5.4zm8-11.602-.1-.099c-2.7 1-6.701 2.6-7.1 5.698-.1 1.503.399 2.602.9 3.401.4.602 1.1 1 1.3 1.901.2.8 0 1.6-.2 2.2h.1l.1.1c1.099-.8 2.2-1.901 1.899-3.401-.198-1.5-1.9-2.5-2.1-3.899-.1-.802.1-1.5.401-1.9 1.1-1.701 3.5-2.902 4.8-4zm-13.8 17.401-.101-.101c-.5.301-1.5.4-1.4 1.2.1.8 1.5 1 2.2 1.2 3.7.8 9.2.3 11.902-.599l-.1-.101.1-.099c-.301-.101-.7-.7-1.3-.7-.502-.1-1.6.299-2.602.4-1.6.199-3.299.3-4.799.199-1.101-.1-4.5-.1-3.9-1.399zm.9 4.099.1-.1c-.6.201-1.3.4-1.3 1.1 0 .601 1.2 1 1.9 1.3 3.299 1 8.5.4 10.9-.699-.2-.302-.6-.4-.9-.601-.4-.1-.7-.3-1.1-.5-2.001.5-5.1.7-7.5.4-.7-.1-1.701-.1-1.9-.799zm17.699 3.2-.1-.099c-.098 1-1.3 1.1-2.1 1.3-.898.2-1.9.398-2.998.5-4.902.599-11.5.898-16.302 0-.898-.102-2.2-.401-2.499-1.102.4-.698 1.5-.8 2.399-1.198l-.098-.101.098-.1c-1.2.1-2.1.4-2.998.701-.7.3-1.701.698-1.902 1.5.6.8 1.801.8 2.8 1 6.6 1 15.7 1.198 21.402-.7.998-.401 3.098-1 2.1-1.901zm-3.7-5.099c.2 0 .4-.101.702-.2m.898-6.8c-.198 0-.399.1-.7.1m-2.2 1.7c.1 0 .2-.101.401-.101m-12.5-1.6c-.4.1-.8.1-1.3.201m-2.2 15.898c.499.2 1.099.2 1.7.401m20.5-2.2c.1-.1.2-.2.3-.399M19.043.814c0-.099-.098-.3-.098-.399m-4.702 19.7c.1.1.301.4.402.5m2.298 1.199c.1-.1.2-.198.3-.399m5.7-13.2c-.3.099-.499.2-.7.398m-1.198 18.802h.198m-12.6-1.8c0 .1-.2.1-.2.199m.9 4.2.101-.1m-2.8 2.701c-.4 0-.7.1-1 .1m21.399.5c0-.1-.1-.1-.1-.1h-.098" fill="#666" stroke="#666" stroke-miterlimit="10" transform="matrix(1.63519 0 0 1.61722 .336 0)"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="72" xmlns="http://www.w3.org/2000/svg"><path d="M67.566 0H4.56C2.125 0 .339 1.953.339 4.234V48.04c0 2.445 1.946 4.234 4.22 4.234h62.843c2.438 0 4.223-1.953 4.223-4.234V4.4C71.949 1.952 70.004 0 67.566 0zm0 0" fill="#ced2d8"/><path d="M4.559 10.586h63.007v37.453H4.56zm0 0" fill="#f2f2f2"/><path d="M17.55 5.7a1.462 1.462 0 1 1-2.921 0 1.462 1.462 0 1 1 2.922 0zm0 0" fill="#54b845"/><path d="M12.516 5.7c0 .808-.653 1.464-1.461 1.464a1.465 1.465 0 0 1 0-2.93c.808 0 1.46.657 1.46 1.465zm0 0" fill="#fbd303"/><path d="M7.809 5.7c0 .808-.657 1.464-1.461 1.464-.809 0-1.461-.656-1.461-1.465 0-.808.652-1.465 1.46-1.465.805 0 1.462.657 1.462 1.465zm0 0" fill="#f0582f"/><path d="m57.5 38.594-4.223-1.137c-.324-1.793-1.136-3.422-1.949-4.887l2.11-3.582c.324-.328.164-.976-.16-1.304L50.19 24.59c-.324-.324-.812-.324-1.3-.164l-3.57 2.117c-1.462-.813-3.087-1.625-4.872-1.953l-1.136-4.07c-.165-.489-.489-.817-.977-.817h-4.223c-.484 0-.808.328-.972.817l-1.301 4.07c-1.785.328-3.41 1.14-4.871 1.953l-3.735-1.953c-.324-.324-.972-.164-1.297.164l-3.085 3.094c-.325.324-.325.812-.164 1.3l2.113 3.586c-.813 1.465-1.625 3.094-1.95 4.883l-4.062.977c-.484.164-.809.488-.809.98v4.23c0 .493.325.817.81.981l4.222 1.137c.324 1.793 1.136 3.422 1.949 4.887l-2.11 3.746c-.324.324-.164.976.16 1.304l3.087 3.094c.324.324.812.324 1.3.16l3.57-2.117c1.462.816 3.087 1.629 4.872 1.957l1.137 4.234c.164.489.488.813.976.813h4.223c.484 0 .812-.324.972-.813l1.137-4.234c1.785-.328 3.41-1.14 4.871-1.957l3.574 2.117c.325.328.973.164 1.297-.16l3.086-3.094c.325-.328.325-.816.164-1.304l-2.113-3.582c.813-1.465 1.625-3.094 1.95-4.887l4.058-.977c.488-.164.812-.488.812-.976v-4.399c.164-.488 0-.812-.484-1.14zM36.062 49.832c-4.382 0-7.957-3.582-7.957-7.98 0-4.395 3.575-7.98 7.957-7.98 4.387 0 7.958 3.585 7.958 7.98 0 4.398-3.57 7.98-7.958 7.98zm0 0" fill="#6eb1e1"/></svg> |
| 1 | ||
| 1 | <svg height="63" width="62" xmlns="http://www.w3.org/2000/svg"><g fill="#999"><path d="m11.426 26.762 27.386-4.489-1.007-4.32-27.387 4.488zm4.203 18.453 1.008 4.652 11.086-2.16v-4.652zm-1.516-6.985 13.61-2.492v-3.656c0-.332 0-.664.168-.996l-14.786 2.656zm13.61 16.625L13.945 57.68l-9.07-40.89 35.617-5.653 2.856 12.468c.672 0 1.343 0 1.847-.168L39.82 0 .34 5.652 12.434 60.34l15.457-3.156v-.168zm18.312-7.148c-8.566 0-15.625-2.824-15.625-6.148v6.148c0 3.492 7.059 6.152 15.625 6.152 8.57 0 15.625-2.828 15.625-6.152v-6.148c0 3.324-7.055 6.148-15.625 6.148zm0 9.14c-8.566 0-15.625-2.824-15.625-6.148v6.149C30.41 60.34 37.47 63 46.035 63c8.57 0 15.625-2.824 15.625-6.152v-6.149c0 3.492-7.055 6.149-15.625 6.149zm0-30.917c-8.566 0-15.625 2.828-15.625 6.152v6.316c0 3.493 7.059 6.149 15.625 6.149 8.57 0 15.625-2.824 15.625-6.149v-6.152c0-3.488-7.055-6.316-15.625-6.316zm0 0"/><path d="M46.035 36.902c-8.566 0-14.11-2.824-14.11-4.656 0-1.828 5.544-4.652 14.11-4.652 8.57 0 14.113 2.824 14.113 4.652 0 1.832-5.543 4.656-14.113 4.656zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="76" xmlns="http://www.w3.org/2000/svg"><path d="m14.974 16.374-11-5.5v-.1l11-5.398V1.574L.374 9.375v3l14.6 7.7zm7.502-3.2L23.174.376h-4.798l.698 12.8zm-1.701 8.002c1.6 0 2.701-1.401 2.701-3.102 0-1.898-1.102-3.1-2.701-3.1s-2.701 1.3-2.701 3.1c-.1 1.7 1 3.102 2.701 3.102zm5.8-19.602v3.802l11.2 5.399v.1l-11.2 5.5v3.7l14.6-7.7v-3.1zm-24 23.401h36.5v2.5h-36.5zm0 7.1h36.5v2.5h-36.5zm0 0" fill="#999" stroke="#999" stroke-miterlimit="10" stroke-width=".75" transform="matrix(1.81211 0 0 1.83119 .353 0)"/></svg> |
| 1 | ||
| 1 | <svg height="63" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M33.325 19.55c-.498-.2-1.1 0-1.299.5-1.1 2.5-2.901 4.7-5.1 6.4l-6.7-13.601c1-.8 1.6-1.999 1.6-3.4 0-2.099-1.501-3.899-3.501-4.3v-3.4a1 1 0 0 0-2 0v3.4c-2 .401-3.5 2.201-3.5 4.3 0 1.401.6 2.6 1.601 3.4l-6.7 13.602c-2.201-1.7-4-3.801-5.1-6.401-.201-.5-.8-.7-1.301-.5-.499.199-.7.8-.499 1.3 1.299 3 3.4 5.4 6 7.3l-4 8c-.2.5 0 1.1.4 1.3.098 0 .3.1.4.1.3 0 .7-.2.9-.5l3.8-7.8c2.7 1.5 5.6 2.2 8.7 2.2 3.1 0 6-.8 8.699-2.2l3.8 7.8c.1.3.501.5.9.5.1 0 .3 0 .4-.1.5-.2.7-.8.4-1.3l-3.9-8c2.6-1.8 4.701-4.4 6-7.3.6-.5.401-1.101 0-1.3zM17.326 6.95c1.4 0 2.5 1.1 2.5 2.499 0 1.401-1.1 2.502-2.5 2.502s-2.5-1.1-2.5-2.502c0-1.4 1.199-2.5 2.5-2.5zm0 22.6c-2.8 0-5.4-.7-7.801-2l6.8-13.7c.3.1.701.1 1.1.1.402 0 .701 0 1.1-.1l6.8 13.7c-2.5 1.3-5.199 2-7.999 2zm0 0" fill="#369" stroke="#369" stroke-miterlimit="10" stroke-width="1.5" transform="matrix(1.6544 0 0 1.63607 0 .154)"/></svg> |
| 1 | ||
| 1 | <svg height="63" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M33.325 19.55c-.498-.2-1.1 0-1.299.5-1.1 2.5-2.901 4.7-5.1 6.4l-6.7-13.601c1-.8 1.6-1.999 1.6-3.4 0-2.099-1.501-3.899-3.501-4.3v-3.4a1 1 0 0 0-2 0v3.4c-2 .401-3.5 2.201-3.5 4.3 0 1.401.6 2.6 1.601 3.4l-6.7 13.602c-2.201-1.7-4-3.801-5.1-6.401-.201-.5-.8-.7-1.301-.5-.499.199-.7.8-.499 1.3 1.299 3 3.4 5.4 6 7.3l-4 8c-.2.5 0 1.1.4 1.3.098 0 .3.1.4.1.3 0 .7-.2.9-.5l3.8-7.8c2.7 1.5 5.6 2.2 8.7 2.2 3.1 0 6-.8 8.699-2.2l3.8 7.8c.1.3.501.5.9.5.1 0 .3 0 .4-.1.5-.2.7-.8.4-1.3l-3.9-8c2.6-1.8 4.701-4.4 6-7.3.6-.5.401-1.101 0-1.3zM17.326 6.95c1.4 0 2.5 1.1 2.5 2.499 0 1.401-1.1 2.502-2.5 2.502s-2.5-1.1-2.5-2.502c0-1.4 1.199-2.5 2.5-2.5zm0 22.6c-2.8 0-5.4-.7-7.801-2l6.8-13.7c.3.1.701.1 1.1.1.402 0 .701 0 1.1-.1l6.8 13.7c-2.5 1.3-5.199 2-7.999 2zm0 0" fill="#369" stroke="#369" stroke-miterlimit="10" stroke-width="1.5" transform="matrix(1.6544 0 0 1.63607 0 .154)"/></svg> |
| 1 | ||
| 1 | <svg height="63" width="45" xmlns="http://www.w3.org/2000/svg"><path d="M22.686 26.4h.8c0 2.401-.4 4.2-1.2 5.3-.801 1.1-1.8 1.7-3 1.7-1.001 0-1.9-.4-2.8-1.1-.9-.699-1.701-2.7-2.4-5.9l-2-8.9-6.902 15.599h-4.4l9.901-21.2c-.5-2.698-1.2-4.799-1.899-6.098-.701-1.3-1.7-2.002-2.7-2.002-.902 0-1.601.301-2.3 1-.6.7-1 1.701-1.1 3.1h-.8c0-2.299.5-4.1 1.4-5.4.899-1.3 1.898-2 3.2-2 .8 0 1.599.302 2.3 1.002.7.699 1.4 1.799 1.9 3.499.599 1.7 1.4 5.1 2.6 10.3l1.599 7.3c.701 3 1.4 5 2.1 6.1.7 1 1.6 1.5 2.6 1.5 1.9-.1 2.901-1.3 3.101-3.8zm0 0" fill="#999" stroke="#999" stroke-miterlimit="10" transform="matrix(1.87615 0 0 1.85407 0 .073)"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M68.633.102H16.39v7.226H5.738v2.274H0v2.062h5.738v2.684h10.653V26.94H5.738v2.477H0v2.066h5.738v2.27h10.653v13.625H5.738v2.48H0v2.063h5.738v2.273h10.653v9.703h52.242v-9.703h9.629v-2.48H84v-2.063h-5.738v-2.476h-9.63v-13.63h9.63v-2.062H84v-2.066h-5.738v-2.684h-9.63V14.141h9.63v-2.684H84V9.395h-5.738V7.12h-9.63zm-10.04 17.136c-2.253 0-4.097-1.86-4.097-4.129S56.34 8.98 58.594 8.98s4.097 1.86 4.097 4.13c0 2.476-1.843 4.128-4.097 4.128zm0 0" fill="#999"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="84" height="60"><path style="fill-rule:nonzero;fill:#7e57c2;fill-opacity:1;stroke-width:.75;stroke-linecap:butt;stroke-linejoin:miter;stroke:#7e57c2;stroke-opacity:1;stroke-miterlimit:10" d="M6.274 25.574h28.3l-9.698-9.3-4.501 3.802-4.5-3.802zm34.1-25.2v28.002H.376V.374zM26.976 14.576l10.7 10.298v-19.3zm-24.2 10.298 10.7-10.298-10.7-9.002zm1.4-21.7 15.9 13.4 15.9-13.4zm0 0" transform="matrix(2.06135 0 0 2.08166 0 .076)"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="52" xmlns="http://www.w3.org/2000/svg"><path d="M48.793 26.879h-4.629V18.05C44.164 7.988 35.973.043 26 .043S7.836 8.164 7.836 18.051v8.828H3.207A3.181 3.181 0 0 0 0 30.059V60.78c0 1.762 1.426 3.176 3.207 3.176h45.586c1.781 0 3.207-1.414 3.207-3.176V29.883c0-1.59-1.426-3.004-3.207-3.004zM29.918 52.305c.355 1.058-.535 1.941-1.602 1.941h-4.808c-1.07 0-1.781-1.059-1.606-1.941l1.426-5.649c-1.781-.883-3.027-2.648-3.027-4.945 0-3 2.492-5.473 5.52-5.473 3.027 0 5.523 2.473 5.523 5.473 0 2.117-1.246 4.062-3.028 4.945zm5.164-25.426H16.918V18.05c0-4.942 4.098-9.004 9.082-9.004s9.082 4.062 9.082 9.004zm0 0" fill="#696"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="84" height="48"><path style="stroke:none;fill-rule:nonzero;fill:#7291a1;fill-opacity:1" d="M28.621 33.172h-16.32l-2.012 4.45c-.55 1.483-.918 2.593-.918 3.706 0 1.297.547 2.223 1.649 2.781.55.371 2.203.555 4.582.743v1.293H.203v-1.293c1.652-.188 2.934-.93 4.035-2.04 1.098-1.113 2.383-3.34 3.848-6.859L24.586 0h.73L42 36.879c1.648 3.52 2.934 5.746 3.852 6.672.73.742 1.832 1.113 3.296 1.113v1.297h-22.18v-1.297h.919c1.832 0 3.113-.184 3.847-.742.551-.371.735-.926.735-1.48 0-.372 0-.743-.184-1.301 0-.184-.367-1.11-1.101-2.407zm-1.101-2.406-6.786-15.57-7.148 15.57zm0 0"/><path style="stroke:none;fill-rule:nonzero;fill:#36454d;fill-opacity:1" d="m83.797 16.309-6.602 22.054-.734 2.778c0 .375-.184.558-.184.742 0 .187.184.558.371.742.184.188.368.371.547.371.551 0 1.102-.371 2.016-1.113.371-.367 1.102-1.297 2.387-2.965l1.097.559c-1.648 2.964-3.3 5.003-5.132 6.3-1.833 1.297-3.852 2.04-5.864 2.04-1.285 0-2.203-.372-2.933-.93-.735-.742-1.102-1.485-1.102-2.407 0-.93.367-2.41 1.102-4.82l.73-2.781c-2.562 4.45-5.133 7.601-7.516 9.453C60.516 47.442 59.05 48 57.582 48c-2.016 0-3.668-.926-4.582-2.594-.918-1.668-1.465-3.523-1.465-5.746 0-3.152.914-6.672 2.934-10.75 2.011-4.074 4.582-7.226 7.695-9.82 2.566-2.04 5.133-2.965 7.332-2.965 1.285 0 2.203.367 3.121 1.11.73.742 1.281 2.038 1.649 3.89l1.28-4.074zM72.98 22.797c0-1.856-.367-3.152-.918-3.895-.367-.554-.914-.742-1.648-.742-.734 0-1.469.375-2.2.93-1.464 1.297-3.116 4.074-4.948 8.336-1.832 4.265-2.57 7.785-2.57 10.937 0 1.11.183 2.035.554 2.594.363.559.914.742 1.281.742 1.098 0 2.016-.558 3.117-1.668 1.465-1.668 2.934-3.707 4.032-5.93 2.199-4.449 3.3-8.156 3.3-11.304zm0 0"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M16.223 21.805.09 55.844l3.012 3.015 20.035-20.035c-.711-1.594-.532-3.543.886-4.96 1.774-1.774 4.43-1.774 6.204 0 1.773 1.769 1.773 4.429 0 6.202-1.243 1.243-3.368 1.594-4.965.887L5.23 60.984 8.242 64l34.04-16.133L49.73 27.48 36.61 14.36zm46.625-4.075L46.184 1.062c-1.418-1.417-3.547-1.417-4.965 0L37.32 4.966c-1.422 1.418-1.422 3.543 0 4.965l16.664 16.664c1.418 1.418 3.543 1.418 4.965 0l3.899-3.903c1.418-1.418 1.418-3.543 0-4.96zm0 0" fill="#fea500"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="70" xmlns="http://www.w3.org/2000/svg"><path d="M69.723 24.898c-.336-.851-1.012-1.535-1.688-2.222-.168.687-.336 1.37-.844 2.054L46.098 57.723c-.844 1.199-2.532 1.539-3.88 1.199l-33.75-9.574c-2.023-.512-4.386-1.711-4.554-4.106 0-.851 0-1.195.504-1.535.508-.344 1.016-.344 1.52-.172l31.726 8.89c4.555 1.368 5.902.34 9.277-4.788l19.239-30.09a5.83 5.83 0 0 0 .675-4.957c-.507-1.54-1.855-2.735-3.543-3.246L35.47 1.48c-.676-.171-1.352-.171-2.024-.171v-.172c-4.218-2.563-5.906 2.222-8.101 4.101-.844.684-1.856 1.2-2.196 1.883-.336.684-.168 1.367-.336 1.879-.843 1.883-3.207 4.957-4.386 5.813-.676.515-1.688.683-2.196 1.539-.335.511-.335 1.539-.503 2.222-.676 1.711-2.872 4.617-4.387 5.985-.508.511-1.352.855-1.688 1.539-.34.511-.172 1.539-.675 2.05-1.012 1.711-3.04 4.446-4.559 5.985-.844.855-1.856 1.195-2.191 2.05-.168.34 0 1.028-.168 1.54-.34.855-.676 1.539-.844 2.222C.37 41.141-.137 42.852.03 44.56c.34 4.105 3.375 8.207 7.09 9.234l33.746 9.574c3.207.852 7.09-.683 8.778-3.422l19.402-30.258c1.016-1.367 1.183-3.25.676-4.789zm-38.98-10.941 1.35-2.05c.337-.512 1.18-.856 1.856-.684l22.274 6.324c.675.172.843.855.507 1.371l-1.351 2.05c-.336.512-1.18.856-1.856.684L31.25 15.328c-.676-.172-.844-.687-.508-1.371zm-5.567 8.55 1.347-2.054c.34-.512 1.184-.851 1.86-.683l22.273 6.328c.676.172.844.855.504 1.367l-1.347 2.05c-.34.512-1.184.856-1.856.684L25.68 23.875c-.672-.172-1.012-.855-.504-1.367zm0 0" fill="#963"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M54.633 9.367C42.145-3.12 21.855-3.12 9.367 9.367s-12.488 32.778 0 45.266 32.778 12.488 45.266 0 12.488-32.778 0-45.266zM12.176 44.801c-5.934-9.211-4.84-21.543 3.12-29.504s20.294-9.055 29.505-3.121zm7.023 7.023L51.824 19.2c5.934 9.211 4.84 21.543-3.12 29.504s-20.294 9.055-29.505 3.121zm0 0" fill="#bababa"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M62.887 38.266c-2.684-.84-4.532-3.36-4.532-6.215 0-2.852 1.848-5.371 4.532-6.211.84-.336 1.343-1.172 1.008-2.012-.84-3.023-1.848-5.707-3.524-8.394-.504-.84-1.344-1.008-2.184-.672-1.007.504-2.015.84-3.19.84-3.692 0-6.548-3.024-6.548-6.547 0-1.176.336-2.184.84-3.188.504-.84.168-1.68-.672-2.183a40.47 40.47 0 0 0-8.39-3.528c-.84-.168-1.68.168-2.016 1.008C37.37 3.852 34.855 5.7 32 5.7s-5.371-1.847-6.21-4.535C25.452.324 24.612-.18 23.772.156c-3.02.84-5.707 1.848-8.39 3.528-.84.503-1.008 1.343-.672 2.183.504 1.004.84 2.012.84 3.188 0 3.691-3.024 6.547-6.547 6.547-1.176 0-2.184-.336-3.191-.84-.84-.504-1.68-.168-2.184.672a40.699 40.699 0 0 0-3.524 8.394c-.167.84.168 1.676 1.008 2.012 2.684.84 4.532 3.36 4.532 6.21 0 2.856-1.848 5.376-4.532 6.216-.84.332-1.343 1.172-1.008 2.011.84 3.024 1.848 5.707 3.524 8.395.504.84 1.344 1.008 2.184.672 1.007-.504 2.015-.84 3.19-.84 3.692 0 6.548 3.02 6.548 6.547 0 1.176-.336 2.183-.84 3.187-.504.84-.168 1.68.672 2.184a40.47 40.47 0 0 0 8.39 3.527h.336c.672 0 1.344-.504 1.512-1.176.84-2.687 3.356-4.535 6.211-4.535s5.371 1.848 6.211 4.535c.336.84 1.176 1.344 2.016 1.008 3.02-.84 5.707-1.847 8.39-3.527.84-.504 1.008-1.344.672-2.184-.504-1.004-.84-2.011-.84-3.187 0-3.692 3.024-6.547 6.547-6.547 1.176 0 2.184.336 3.192.84.84.504 1.68.168 2.183-.672a40.698 40.698 0 0 0 3.524-8.395c.503-.672 0-1.511-.84-1.843zm-30.719 3.691c-5.371 0-9.902-4.363-9.902-9.906 0-5.371 4.363-9.903 9.902-9.903 5.371 0 9.902 4.364 9.902 9.903 0 5.375-4.53 9.906-9.902 9.906zm0 0"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="52" xmlns="http://www.w3.org/2000/svg"><path d="M46.168 13.516c1.793-.711 3.766-.891 5.738-.891V.008c-8.605-.18-16.851 3.554-22.23 10.308-2.153 2.844-4.125 5.864-5.559 9.243l-4.12 10.128c-1.079 3.024-2.333 6.223-3.767 9.067a31.916 31.916 0 0 1-3.945 6.754c-1.254 1.777-3.047 3.199-5.02 4.09-2.152 1.066-4.66 1.597-7.171 1.597v12.797c8.605.18 16.851-3.554 22.23-10.308 1.613-2.309 3.227-4.797 4.485-7.286l3.406-8h14.879v-12.62h-9.86c.715-1.954 1.793-3.731 3.047-5.508.895-1.602 2.153-2.844 3.407-3.91 1.613-1.422 3.046-2.313 4.48-2.844zm0 0" fill="#d10407"/></svg> |
| 1 | ||
| 1 | <svg height="63" width="60" xmlns="http://www.w3.org/2000/svg"><path d="M21.516 22.047V3.832c0-1.91 1.574-3.297 3.324-3.297h20.816l10.672 10.582v10.754c0 .348-.351.695-.703.695h-3.672c-.351 0-.7-.347-.7-.695v-7.285H44.43c-1.399 0-2.446-1.04-2.446-2.43v-6.59H26.59v16.305c0 .348-.352.695-.7.695h-3.675c-.348.172-.7-.171-.7-.52zm0 39.203V28.984c0-.695.523-1.214 1.226-1.214h36.035c.7 0 1.223.52 1.223 1.214v27.063c0 3.469-2.973 6.418-6.473 6.418H22.914c-.875 0-1.398-.52-1.398-1.215zm25.363-24.98c0 1.562 1.226 2.601 2.625 2.601 1.398 0 2.625-1.215 2.625-2.601 0-1.56-1.227-2.602-2.625-2.602-1.399-.172-2.625 1.043-2.625 2.602zm0 8.847c0 1.563 1.226 2.602 2.625 2.602 1.574 0 2.625-1.215 2.625-2.602 0-1.387-1.227-2.601-2.625-2.773-1.399 0-2.625 1.21-2.625 2.773zM37.96 36.27c0 1.386 1.223 2.601 2.621 2.601 1.402 0 2.625-1.215 2.625-2.601s-1.223-2.602-2.625-2.602c-1.398-.172-2.621 1.043-2.621 2.602zm0 8.847c0 1.387 1.223 2.602 2.621 2.602 1.574 0 2.625-1.215 2.625-2.602 0-1.562-1.223-2.601-2.625-2.773-1.398 0-2.621 1.21-2.621 2.773zm0 8.848c0 1.387 1.223 2.601 2.621 2.601 1.574 0 2.625-1.214 2.625-2.601s-1.223-2.602-2.625-2.602c-1.398 0-2.621 1.215-2.621 2.602zM29.039 36.27c0 1.562 1.223 2.601 2.621 2.601 1.403 0 2.625-1.215 2.625-2.601 0-1.56-1.222-2.602-2.625-2.602-1.574-.172-2.62 1.043-2.62 2.602zm0 8.847c0 1.563 1.223 2.602 2.621 2.602 1.574 0 2.625-1.215 2.625-2.602 0-1.562-1.222-2.601-2.625-2.773-1.398 0-2.62 1.21-2.62 2.773zm0 8.848c0 1.387 1.223 2.601 2.621 2.601 1.574 0 2.625-1.214 2.625-2.601s-1.222-2.602-2.625-2.602c-1.574 0-2.62 1.215-2.62 2.602zm-22.566 8.5h8.57c.7 0 1.227-.52 1.227-1.215V20.832c0-.695-.528-1.215-1.227-1.215h-6.82C3.672 19.617 0 23.262 0 27.77v28.449c0 3.297 2.8 6.246 6.473 6.246zm0 0" fill="#fea500"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="70" xmlns="http://www.w3.org/2000/svg"><path d="M69.723 24.898c-.336-.851-1.012-1.535-1.688-2.222-.168.687-.336 1.37-.844 2.054L46.098 57.723c-.844 1.199-2.532 1.539-3.88 1.199l-33.75-9.574c-2.023-.512-4.386-1.711-4.554-4.106 0-.851 0-1.195.504-1.535.508-.344 1.016-.344 1.52-.172l31.726 8.89c4.555 1.368 5.902.34 9.277-4.788l19.239-30.09a5.83 5.83 0 0 0 .675-4.957c-.507-1.54-1.855-2.735-3.543-3.246L35.47 1.48c-.676-.171-1.352-.171-2.024-.171v-.172c-4.218-2.563-5.906 2.222-8.101 4.101-.844.684-1.856 1.2-2.196 1.883-.336.684-.168 1.367-.336 1.879-.843 1.883-3.207 4.957-4.386 5.813-.676.515-1.688.683-2.196 1.539-.335.511-.335 1.539-.503 2.222-.676 1.711-2.872 4.617-4.387 5.985-.508.511-1.352.855-1.688 1.539-.34.511-.172 1.539-.675 2.05-1.012 1.711-3.04 4.446-4.559 5.985-.844.855-1.856 1.195-2.191 2.05-.168.34 0 1.028-.168 1.54-.34.855-.676 1.539-.844 2.222C.37 41.141-.137 42.852.03 44.56c.34 4.105 3.375 8.207 7.09 9.234l33.746 9.574c3.207.852 7.09-.683 8.778-3.422l19.402-30.258c1.016-1.367 1.183-3.25.676-4.789zm-38.98-10.941 1.35-2.05c.337-.512 1.18-.856 1.856-.684l22.274 6.324c.675.172.843.855.507 1.371l-1.351 2.05c-.336.512-1.18.856-1.856.684L31.25 15.328c-.676-.172-.844-.687-.508-1.371zm-5.567 8.55 1.347-2.054c.34-.512 1.184-.851 1.86-.683l22.273 6.328c.676.172.844.855.504 1.367l-1.347 2.05c-.34.512-1.184.856-1.856.684L25.68 23.875c-.672-.172-1.012-.855-.504-1.367zm0 0" fill="#963"/></svg> |
| 1 | ||
| 1 | <svg height="63" width="49" xmlns="http://www.w3.org/2000/svg"><path d="M4.524 3.224v10.102h8.5v2.598h-8.5v13.7h-3.9V.626h13.301v2.598zm14.402 26.3V.826h3.7v28.7zm0 0" fill="#d10407" stroke="#d10407" stroke-miterlimit="10" stroke-width="1.25" transform="matrix(2.10753 0 0 2.07742 0 .079)"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="52" xmlns="http://www.w3.org/2000/svg"><path d="M46.168 13.516c1.793-.711 3.766-.891 5.738-.891V.008c-8.605-.18-16.851 3.554-22.23 10.308-2.153 2.844-4.125 5.864-5.559 9.243l-4.12 10.128c-1.079 3.024-2.333 6.223-3.767 9.067a31.916 31.916 0 0 1-3.945 6.754c-1.254 1.777-3.047 3.199-5.02 4.09-2.152 1.066-4.66 1.597-7.171 1.597v12.797c8.605.18 16.851-3.554 22.23-10.308 1.613-2.309 3.227-4.797 4.485-7.286l3.406-8h14.879v-12.62h-9.86c.715-1.954 1.793-3.731 3.047-5.508.895-1.602 2.153-2.844 3.407-3.91 1.613-1.422 3.046-2.313 4.48-2.844zm0 0" fill="#d10407"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="84" height="48"><path style="stroke:none;fill-rule:nonzero;fill:#7291a1;fill-opacity:1" d="M28.621 33.172h-16.32l-2.012 4.45c-.55 1.483-.918 2.593-.918 3.706 0 1.297.547 2.223 1.649 2.781.55.371 2.203.555 4.582.743v1.293H.203v-1.293c1.652-.188 2.934-.93 4.035-2.04 1.098-1.113 2.383-3.34 3.848-6.859L24.586 0h.73L42 36.879c1.648 3.52 2.934 5.746 3.852 6.672.73.742 1.832 1.113 3.296 1.113v1.297h-22.18v-1.297h.919c1.832 0 3.113-.184 3.847-.742.551-.371.735-.926.735-1.48 0-.372 0-.743-.184-1.301 0-.184-.367-1.11-1.101-2.407zm-1.101-2.406-6.786-15.57-7.148 15.57zm0 0"/><path style="stroke:none;fill-rule:nonzero;fill:#36454d;fill-opacity:1" d="m83.797 16.309-6.602 22.054-.734 2.778c0 .375-.184.558-.184.742 0 .187.184.558.371.742.184.188.368.371.547.371.551 0 1.102-.371 2.016-1.113.371-.367 1.102-1.297 2.387-2.965l1.097.559c-1.648 2.964-3.3 5.003-5.132 6.3-1.833 1.297-3.852 2.04-5.864 2.04-1.285 0-2.203-.372-2.933-.93-.735-.742-1.102-1.485-1.102-2.407 0-.93.367-2.41 1.102-4.82l.73-2.781c-2.562 4.45-5.133 7.601-7.516 9.453C60.516 47.442 59.05 48 57.582 48c-2.016 0-3.668-.926-4.582-2.594-.918-1.668-1.465-3.523-1.465-5.746 0-3.152.914-6.672 2.934-10.75 2.011-4.074 4.582-7.226 7.695-9.82 2.566-2.04 5.133-2.965 7.332-2.965 1.285 0 2.203.367 3.121 1.11.73.742 1.281 2.038 1.649 3.89l1.28-4.074zM72.98 22.797c0-1.856-.367-3.152-.918-3.895-.367-.554-.914-.742-1.648-.742-.734 0-1.469.375-2.2.93-1.464 1.297-3.116 4.074-4.948 8.336-1.832 4.265-2.57 7.785-2.57 10.937 0 1.11.183 2.035.554 2.594.363.559.914.742 1.281.742 1.098 0 2.016-.558 3.117-1.668 1.465-1.668 2.934-3.707 4.032-5.93 2.199-4.449 3.3-8.156 3.3-11.304zm0 0"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M81.227 64H2.773a2.514 2.514 0 0 1-2.535-2.54V21.333h83.524v40.129A2.514 2.514 0 0 1 81.227 64zm0 0" fill="#efce4a"/><path d="M33.008 10.059v-7.52A2.514 2.514 0 0 0 30.468 0H2.774A2.514 2.514 0 0 0 .238 2.54v18.792h83.524v-8.734a2.514 2.514 0 0 0-2.535-2.54zm0 0" fill="#ebba16"/><path d="m53.059 42.668-10.754-9.754v6.5H30.94v6.504h11.364v6.5zm0 0" fill="#039"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M81.227 64H2.773a2.514 2.514 0 0 1-2.535-2.54V21.333h83.524v40.129A2.514 2.514 0 0 1 81.227 64zm0 0" fill="#efce4a"/><path d="M33.008 10.059v-7.52A2.514 2.514 0 0 0 30.468 0H2.774A2.514 2.514 0 0 0 .238 2.54v18.792h83.524v-8.734a2.514 2.514 0 0 0-2.535-2.54zm0 0" fill="#ebba16"/><path d="m42 31.594-9.738 10.77h6.492v11.374h6.492V42.363h6.492zm0 0" fill="#039"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M81.227 64H2.773a2.514 2.514 0 0 1-2.535-2.54V21.333h83.524v40.129A2.514 2.514 0 0 1 81.227 64zm0 0" fill="#efce4a"/><path d="M33.008 10.059v-7.52A2.514 2.514 0 0 0 30.468 0H2.774A2.514 2.514 0 0 0 .238 2.54v18.792h83.524v-8.734a2.514 2.514 0 0 0-2.535-2.54zm0 0" fill="#ebba16"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="84" height="48"><path style="stroke:none;fill-rule:nonzero;fill:#7291a1;fill-opacity:1" d="M28.621 33.172h-16.32l-2.012 4.45c-.55 1.483-.918 2.593-.918 3.706 0 1.297.547 2.223 1.649 2.781.55.371 2.203.555 4.582.743v1.293H.203v-1.293c1.652-.188 2.934-.93 4.035-2.04 1.098-1.113 2.383-3.34 3.848-6.859L24.586 0h.73L42 36.879c1.648 3.52 2.934 5.746 3.852 6.672.73.742 1.832 1.113 3.296 1.113v1.297h-22.18v-1.297h.919c1.832 0 3.113-.184 3.847-.742.551-.371.735-.926.735-1.48 0-.372 0-.743-.184-1.301 0-.184-.367-1.11-1.101-2.407zm-1.101-2.406-6.786-15.57-7.148 15.57zm0 0"/><path style="stroke:none;fill-rule:nonzero;fill:#36454d;fill-opacity:1" d="m83.797 16.309-6.602 22.054-.734 2.778c0 .375-.184.558-.184.742 0 .187.184.558.371.742.184.188.368.371.547.371.551 0 1.102-.371 2.016-1.113.371-.367 1.102-1.297 2.387-2.965l1.097.559c-1.648 2.964-3.3 5.003-5.132 6.3-1.833 1.297-3.852 2.04-5.864 2.04-1.285 0-2.203-.372-2.933-.93-.735-.742-1.102-1.485-1.102-2.407 0-.93.367-2.41 1.102-4.82l.73-2.781c-2.562 4.45-5.133 7.601-7.516 9.453C60.516 47.442 59.05 48 57.582 48c-2.016 0-3.668-.926-4.582-2.594-.918-1.668-1.465-3.523-1.465-5.746 0-3.152.914-6.672 2.934-10.75 2.011-4.074 4.582-7.226 7.695-9.82 2.566-2.04 5.133-2.965 7.332-2.965 1.285 0 2.203.367 3.121 1.11.73.742 1.281 2.038 1.649 3.89l1.28-4.074zM72.98 22.797c0-1.856-.367-3.152-.918-3.895-.367-.554-.914-.742-1.648-.742-.734 0-1.469.375-2.2.93-1.464 1.297-3.116 4.074-4.948 8.336-1.832 4.265-2.57 7.785-2.57 10.937 0 1.11.183 2.035.554 2.594.363.559.914.742 1.281.742 1.098 0 2.016-.558 3.117-1.668 1.465-1.668 2.934-3.707 4.032-5.93 2.199-4.449 3.3-8.156 3.3-11.304zm0 0"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="69" xmlns="http://www.w3.org/2000/svg"><path d="M43.8 55.613H11.036c-3.586 0-6.488-2.906-6.488-6.5s2.902-6.504 6.488-6.504h12.797c5.8 0 10.582-4.793 10.582-10.609s-4.781-10.61-10.582-10.61h-6.996c.172.684.172 1.368.172 2.055 0 .684 0 1.368-.172 2.051h6.996c3.586 0 6.484 2.91 6.484 6.504s-2.898 6.504-6.484 6.504H11.035C5.23 38.504.453 43.293.453 49.114c0 5.816 4.777 10.609 10.582 10.609H43.97c-.168-.684-.168-1.371-.168-2.055zm10.067-4.277c-3.414 0-6.312 2.738-6.312 6.332S50.285 64 53.867 64c3.586 0 6.317-2.738 6.317-6.332s-2.73-6.332-6.317-6.332zM19.567 0H6.765C5.742 0 4.719.855 4.719 2.055v15.398C2.16 18.31.453 20.707.453 23.445c0 3.422 2.73 6.332 6.313 6.332 3.586 0 6.316-2.738 6.316-6.332 0-2.738-1.707-5.136-4.266-5.992v-4.789h10.75c1.024 0 2.047-.855 2.047-2.055V2.055C21.441 1.027 20.59 0 19.566 0zm34.3 4.277c-8.191 0-14.847 6.676-14.847 14.887 0 4.45 1.878 8.559 5.292 11.297l7.68 15.23c.68 1.54 2.899 1.54 3.582 0l7.68-15.23c3.414-2.91 5.289-7.016 5.289-11.297.172-8.21-6.484-14.887-14.676-14.887zm0 21.22c-3.414 0-6.312-2.74-6.312-6.333s2.73-6.328 6.312-6.328c3.586 0 6.317 2.734 6.317 6.328s-2.73 6.332-6.317 6.332zm0 0" fill="#999"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M61.988 2.012v59.976L46.996 17.004zM2.012 61.988h59.976L17.004 46.996zm14.992-14.992 44.984 14.992L32 32zM32 32l29.988 29.988-14.992-44.984zM2.012 46.996v14.992l14.992-14.992zM32 32H17.004v14.996zm14.996-14.996H32V32zM61.988 2.012H46.996v14.992zM17.004 32 2.012 46.996h14.992zM32 17.004 17.004 32H32zM46.996 2.012 32 17.004h14.996zm0 0" fill="#666" stroke="#fff" stroke-width="1.66605"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="82" xmlns="http://www.w3.org/2000/svg"><g fill="#3c3"><path d="M0 .094v63.812h82V.094zM77.34 4.8v27.86L57.773 17.6 36.34 39.247l-15.094-8.469L4.844 43.953V4.801zm0 0"/><path d="M22.55 17.223c0 3.222-2.585 5.836-5.777 5.836-3.191 0-5.777-2.614-5.777-5.836s2.586-5.836 5.777-5.836c3.192 0 5.778 2.613 5.778 5.836zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M62.773 29.176 34.824 1.226c-1.636-1.636-4.164-1.636-5.797 0L23.23 7.024l7.282 7.286c1.636-.594 3.718-.149 5.054 1.191 1.34 1.336 1.786 3.418 1.192 5.055l7.137 7.133a4.905 4.905 0 0 1 5.054 1.19 4.942 4.942 0 0 1-6.988 6.99c-1.488-1.49-1.785-3.571-1.043-5.356l-6.54-6.54v17.395l1.337.89a4.935 4.935 0 0 1 0 6.99 4.937 4.937 0 0 1-6.985 0c-1.933-1.934-2.082-5.056-.148-6.99.445-.444.89-.89 1.484-1.038V23.527c-.445-.297-1.039-.597-1.484-1.043-1.488-1.484-1.785-3.566-1.043-5.351l-7.137-7.285-19.175 19.18c-1.637 1.632-1.637 4.16 0 5.796l27.949 27.95c1.636 1.636 4.164 1.636 5.797 0l27.8-27.801c1.637-1.633 1.637-4.313 0-5.797zm0 0" fill="#bababa"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M54.633 9.367C42.145-3.12 21.855-3.12 9.367 9.367s-12.488 32.778 0 45.266 32.778 12.488 45.266 0 12.488-32.778 0-45.266zM12.176 44.801c-5.934-9.211-4.84-21.543 3.12-29.504s20.294-9.055 29.505-3.121zm7.023 7.023L51.824 19.2c5.934 9.211 4.84 21.543-3.12 29.504s-20.294 9.055-29.505 3.121zm0 0" fill="#bababa"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="84" height="42"><path style="stroke:none;fill-rule:nonzero;fill:#2dbcaf;fill-opacity:1" d="M41.156 11.465c-3.449.906-5.804 1.633-9.254 2.539-.906.184-.906.184-1.632-.36-.907-.91-1.27-1.636-2.54-2-3.449-1.812-6.714-1.085-9.98.91-3.809 2.54-5.625 6.169-5.625 10.344 0 4.172 3.086 8.165 7.441 8.528 3.809.363 6.711-.906 9.254-3.63.36-.726.907-1.273 1.633-1.995H19.746c-1.09 0-1.27-.727-1.09-1.633.727-1.816 1.996-4.535 2.723-6.168.183-.184.363-.91 1.27-.91h20.14c0 1.633 0 2.902-.18 4.535-.726 3.996-1.996 7.621-4.535 10.887-3.992 5.265-9.074 8.347-15.61 9.258-5.44.722-10.339-.184-14.694-3.63C3.777 35.056 1.422 30.88.695 25.98c-.73-6.168 1.086-11.246 4.715-15.968C9.223 4.754 14.484 1.668 20.832.578c5.266-.906 10.164-.18 14.7 2.723 2.902 1.996 4.898 4.535 6.35 7.62 0 0 0 .18-.726.544zm0 0"/><path style="stroke:none;fill-rule:nonzero;fill:#2dbcaf;fill-opacity:1" d="M59.117 41.766c-4.898 0-9.433-1.633-13.242-4.715-3.086-2.723-5.262-6.352-5.809-10.707-.906-6.352.727-11.793 4.54-16.692 3.988-5.265 8.89-8.168 15.421-9.254 5.625-.91 10.887-.363 15.606 2.723 4.351 2.902 7.074 7.074 7.62 12.156.907 7.438-1.089 13.61-6.35 18.688-3.63 3.629-8.165 6.168-13.063 7.078-1.633.363-3.266.723-4.723.723zm13.25-22.133c0-.727 0-1.274-.183-1.817-.907-5.445-6.168-8.527-11.25-7.257-5.262 1.086-8.348 4.351-9.797 9.433-.907 4.356 1.09 8.528 4.898 10.344 2.903 1.27 6.172 1.09 9.07-.184 4.54-2.175 6.899-5.804 7.262-10.52zm0 0"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M31.816 6.078c5.094 5.094 6.547 12.184 4.73 18.547l26.907 26.91.547 12-15.09-1.273v-7.637h-7.637v-7.637h-7.457L24 37.172c-6.363 1.816-13.637.363-18.547-4.73-7.27-7.27-7.27-19.27 0-26.544a18.494 18.494 0 0 1 26.363.18zM18 11.172c-2.184-2.184-5.453-2.184-7.637 0-2.18 2.18-2.18 5.453 0 7.637 2.184 2.18 5.453 2.18 7.637 0 2.184-2.184 2.184-5.637 0-7.637zm0 0" fill="#696"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="65" xmlns="http://www.w3.org/2000/svg"><path d="M21.61 63.91c-.176 0-.352 0-.528-.176C8.434 58.934 0 46.488 0 32.977 0 14.844 14.582.09 32.5.09S65 14.844 65 32.977c0 13.511-8.434 25.957-21.082 30.757a1.12 1.12 0 0 1-1.055 0c-.351-.18-.527-.355-.699-.71l-7.027-18.669c-.352-.71.175-1.601.875-1.777 3.867-1.422 6.324-5.156 6.324-9.422 0-5.511-4.39-9.957-9.836-9.957s-9.836 4.446-9.836 9.957c0 4.09 2.633 7.82 6.324 9.422.7.356 1.051 1.067.875 1.777l-7.027 18.668c-.172.356-.348.711-.7.711 0 .176-.175.176-.527.176zm0 0" fill="#af7931"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="81" xmlns="http://www.w3.org/2000/svg"><path d="M78.398 6.79C75.508 1.55 70.492 0 66.828 0c-4.437 0-8.101 2.328-7.328 4.074.191.387.965 2.133 1.543 2.906.77 1.165 2.121.196 2.508 0 1.347-.773 2.89-.968 4.433-.773 1.543.191 3.664 1.164 5.207 3.879 3.278 6.398-6.941 19.781-19.863 10.473-13.113-9.118-25.652-6.207-31.437-4.27-5.786 1.941-8.293 3.688-5.977 7.953 3.086 5.82 2.121 4.074 5.012 8.922 4.629 7.758 15.043-3.492 15.043-3.492-7.711 11.441-14.27 8.726-16.778 4.656-2.312-3.492-4.05-7.758-4.05-7.758C-4.336 33.55.87 64 .87 64h9.64C13.02 52.75 21.7 53.14 23.243 64h7.328c6.559-21.914 22.95 0 22.95 0h9.644c-2.7-14.934 5.398-19.586 10.414-28.316 5.399-8.922 10.223-19.586 4.82-28.895zM53.52 35.683c-5.012-1.746-3.278-6.786-3.278-6.786s4.434 1.356 10.414 3.489c-.191 1.36-3.277 4.46-7.136 3.297zm0 0" fill="#02303a"/></svg> |
| 1 | ||
| 1 | <svg height="63" width="54" xmlns="http://www.w3.org/2000/svg"><path d="M53.344 18.172H44.02V8.965zM28.309 8.965v33.437h25.199V20.434H41.727V8.964zm3.93-8.723H4.417v6.461h10.965l-6.875 5.332v5.652l10.148-7.753V6.867H54V4.281zM18.655 14.297 8.508 22.05v5.652l10.148-7.754zM8.344 37.559l10.148-7.754v-5.657L8.344 31.902zm10.312 2.261v-5.656L8.508 41.918v2.91h-4.09v6.461h6.219v4.523H7.035c-.652-1.132-1.797-1.937-3.273-1.937C1.637 53.875 0 55.488 0 57.59c0 2.097 1.637 3.715 3.762 3.715 1.476 0 2.62-.809 3.273-1.938h3.602v3.39h5.562v-3.39h3.602c.652 1.13 1.8 1.938 3.273 1.938 2.125 0 3.762-1.618 3.762-3.715 0-2.102-1.637-3.715-3.762-3.715-1.472 0-2.62.805-3.273 1.938h-3.602v-4.524h15.875l21.762-3.879v-2.582H11.78zm0 0" fill="#90c"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><g fill="#999" stroke="#999" stroke-miterlimit="10" stroke-width=".25"><path d="M63.773.227H.227v63.546h63.546zM60.324 60.14H4.04V12.574h56.285zm0 0" stroke-width=".4539"/><path d="M9.305 18.203h45.39v6.352H9.305zm7.445 10.348h27.777v2.543H16.75zm3.992 7.808h27.781v2.723h-27.78zm-3.992 8.168h27.777v2.723H16.75zm3.992 8.352h27.781v2.723h-27.78zm0 0" stroke-width=".4539"/></g></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="83" height="51"><path style="stroke:none;fill-rule:nonzero;fill:#c19770;fill-opacity:1" d="M30.605 30.332c2.782-.18 5.735.879 7.993 2.824 1.039.883 2.086 2.121 2.777 3.535 1.39-2.296 3.477-4.242 6.082-5.3a15.304 15.304 0 0 1 9.73 0 20.188 20.188 0 0 1 7.293 4.77 62.33 62.33 0 0 0 5.04 4.593c.867.883 1.91 1.41 2.953 1.766 1.562.53 3.297 0 4.343-1.06.868-1.058.868-2.827-.175-4.062-.696-.53-1.563-.53-2.258.176 0 0 0 .176-.176.176-.348.707-.348 1.59.176 2.121-.867-.531-1.563-1.59-1.738-2.828-.172-1.414.87-2.648 2.085-3.004 2.43-.883 5.387-.176 6.774 1.945 1.219 2.118 1.738 4.59 1.39 6.887-.347 2.3-1.566 4.242-3.472 5.656-2.606 1.766-5.734 2.649-9.035 2.297-2.953-.176-6.078-.707-8.688-1.945-4.687-1.941-9.031-4.414-13.722-6.008-1.563-.351-3.473-.879-5.04-1.059h-3.82c-1.562.18-3.125.532-4.515 1.06-4.864 1.593-9.207 4.241-13.899 6.187-3.996 1.59-8.336 2.296-12.504 1.414-2.433-.356-4.691-1.594-6.258-3.535a7.888 7.888 0 0 1-1.906-5.829c-.176-2.12.344-4.066 1.563-5.656 1.214-1.59 3.129-2.297 5.035-2.121 1.215 0 2.262.531 3.129 1.59.52.887.695 1.77.347 2.828-.347.883-.87 1.59-1.566 1.945.352-.53.523-1.414.172-2.12-.516-.708-1.559-.884-2.254-.356-.176 0-.176.18-.348.18-.87.882-.87 2.296-.347 3.355.695 1.059 1.738 1.766 2.949 1.945 1.742 0 3.48-.886 4.691-2.125 2.606-2.648 5.387-4.945 8.34-7.242 2.781-1.941 5.906-2.828 8.86-3zm0-30.215c2.782-.176 5.735.887 7.993 2.828 1.039.883 2.086 2.118 2.777 3.532 1.39-2.297 3.477-4.239 6.082-5.297a15.25 15.25 0 0 1 9.73 0 20.22 20.22 0 0 1 7.293 4.77 62.33 62.33 0 0 0 5.04 4.593c.867.883 1.91 1.414 2.953 1.766 1.562.53 3.297 0 4.343-1.059.868-1.063.868-2.828-.175-4.066-.696-.528-1.563-.528-2.258.18 0 0 0 .175-.176.175-.348.707-.348 1.59.176 2.121-.867-.531-1.563-1.59-1.738-2.828-.172-1.414.87-2.652 2.085-3.004 2.43-.883 5.387-.176 6.778 1.942 1.215 2.12 1.734 4.597 1.387 6.894-.348 2.297-1.563 4.238-3.473 5.652-2.606 1.77-5.734 2.649-9.035 2.297-2.953-.175-6.078-.707-8.684-1.941-4.691-1.945-9.035-4.418-13.723-6.008-1.562-.355-3.476-.887-5.039-1.062h-3.82c-1.566.175-3.129.53-4.52 1.062-4.863 1.59-9.206 4.238-13.898 6.18-3.992 1.593-8.336 2.297-12.504 1.414-2.433-.352-4.691-1.586-6.258-3.531a7.913 7.913 0 0 1-1.906-5.832C-.14 8.773.38 6.832 1.598 5.242c1.214-1.59 3.129-2.297 5.035-2.12 1.215 0 2.262.53 3.129 1.589.52.887.695 1.766.347 2.828-.347.883-.87 1.59-1.566 1.941.352-.527.523-1.41.172-2.117-.516-.707-1.559-.886-2.254-.351-.176 0-.176.172-.348.172-.87.882-.87 2.296-.347 3.359.695 1.059 1.738 1.766 2.949 1.941 1.742 0 3.48-.882 4.691-2.117 2.606-2.648 5.387-4.949 8.34-7.246 2.781-1.941 5.91-2.824 8.86-3.004zm0 0"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="83" height="51"><path style="stroke:none;fill-rule:nonzero;fill:#c19770;fill-opacity:1" d="M30.605 30.332c2.782-.18 5.735.879 7.993 2.824 1.039.883 2.086 2.121 2.777 3.535 1.39-2.296 3.477-4.242 6.082-5.3a15.304 15.304 0 0 1 9.73 0 20.188 20.188 0 0 1 7.293 4.77 62.33 62.33 0 0 0 5.04 4.593c.867.883 1.91 1.41 2.953 1.766 1.562.53 3.297 0 4.343-1.06.868-1.058.868-2.827-.175-4.062-.696-.53-1.563-.53-2.258.176 0 0 0 .176-.176.176-.348.707-.348 1.59.176 2.121-.867-.531-1.563-1.59-1.738-2.828-.172-1.414.87-2.648 2.085-3.004 2.43-.883 5.387-.176 6.774 1.945 1.219 2.118 1.738 4.59 1.39 6.887-.347 2.3-1.566 4.242-3.472 5.656-2.606 1.766-5.734 2.649-9.035 2.297-2.953-.176-6.078-.707-8.688-1.945-4.687-1.941-9.031-4.414-13.722-6.008-1.563-.351-3.473-.879-5.04-1.059h-3.82c-1.562.18-3.125.532-4.515 1.06-4.864 1.593-9.207 4.241-13.899 6.187-3.996 1.59-8.336 2.296-12.504 1.414-2.433-.356-4.691-1.594-6.258-3.535a7.888 7.888 0 0 1-1.906-5.829c-.176-2.12.344-4.066 1.563-5.656 1.214-1.59 3.129-2.297 5.035-2.121 1.215 0 2.262.531 3.129 1.59.52.887.695 1.77.347 2.828-.347.883-.87 1.59-1.566 1.945.352-.53.523-1.414.172-2.12-.516-.708-1.559-.884-2.254-.356-.176 0-.176.18-.348.18-.87.882-.87 2.296-.347 3.355.695 1.059 1.738 1.766 2.949 1.945 1.742 0 3.48-.886 4.691-2.125 2.606-2.648 5.387-4.945 8.34-7.242 2.781-1.766 5.906-2.828 8.86-3zm0-30.215c2.782-.176 5.735.887 7.993 2.828 1.039.883 2.086 2.118 2.777 3.532 1.39-2.297 3.477-4.239 6.082-5.297a15.25 15.25 0 0 1 9.73 0 20.22 20.22 0 0 1 7.293 4.77 62.33 62.33 0 0 0 5.04 4.593c.867.883 1.91 1.414 2.953 1.766 1.562.53 3.297 0 4.343-1.059.868-1.063.868-2.828-.175-4.066-.696-.528-1.563-.528-2.258.18 0 0 0 .175-.176.175-.348.707-.348 1.59.176 2.121-.867-.531-1.563-1.59-1.738-2.828-.172-1.414.87-2.652 2.085-3.004 2.43-.883 5.387-.176 6.778 1.942 1.215 2.12 1.734 4.597 1.387 6.894-.348 2.297-1.563 4.238-3.473 5.652-2.606 1.77-5.734 2.649-9.035 2.297-2.953-.175-6.078-.707-8.684-1.941-4.691-1.945-9.035-4.418-13.723-6.008-1.562-.355-3.476-.887-5.039-1.062h-3.82c-1.566.175-3.129.53-4.52 1.062-4.863 1.59-9.206 4.238-13.898 6.18-3.992 1.593-8.336 2.297-12.504 1.414-2.433-.352-4.691-1.586-6.258-3.531a7.913 7.913 0 0 1-1.906-5.832C-.14 8.773.38 6.832 1.598 5.242c1.214-1.59 3.129-2.297 5.035-2.12 1.215 0 2.262.53 3.129 1.589.52.887.695 1.766.347 2.828-.347.883-.87 1.59-1.566 1.941.352-.527.523-1.41.172-2.117-.516-.707-1.559-.886-2.254-.351-.176 0-.176.172-.348.172-.87.882-.87 2.296-.347 3.359.695 1.059 1.738 1.766 2.949 1.941 1.742 0 3.48-.882 4.691-2.117 2.606-2.648 5.387-4.949 8.34-7.246 2.781-1.766 5.91-2.824 8.86-3.004zm0 0"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="82" xmlns="http://www.w3.org/2000/svg"><g fill="#3c3"><path d="M0 .094v63.812h82V.094zM77.34 4.8v27.86L57.773 17.6 36.34 39.247l-15.094-8.469L4.844 43.953V4.801zm0 0"/><path d="M22.55 17.223c0 3.222-2.585 5.836-5.777 5.836-3.191 0-5.777-2.614-5.777-5.836s2.586-5.836 5.777-5.836c3.192 0 5.778 2.613 5.778 5.836zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="59" xmlns="http://www.w3.org/2000/svg"><path d="M59 0H13.41C6.613 0 0 2.668 0 10.668V64h48.273V10.668H6.613c0-3.914 2.684-5.336 5.367-5.336h41.477v53.336l5.363-5.336V0zm0 0" fill="#c93"/><path d="M21.992 40.18c0-5.512 6.434-6.403 6.434-10.493 0-1.777-1.61-3.199-3.754-3.199-2.324.18-4.11 1.778-4.11 1.778L17.88 24.89s2.683-2.848 7.332-2.848c4.289 0 8.402 2.668 8.402 7.289 0 6.402-6.797 7.113-6.797 11.203v1.422h-4.824zm0 5.152h4.824v4.445h-4.824zm0 0" fill="#fff"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="83" height="59"><path style="stroke:none;fill-rule:nonzero;fill:#8f4e8b;fill-opacity:1" d="m.469 59 19.367-29.5L.469 0h14.379l19.367 29.5L14.848 59zm0 0"/><path style="stroke:none;fill-rule:nonzero;fill:#8f4e8b;fill-opacity:1" d="m19.836 59 19.363-29.5L19.836 0h14.379l38.73 59h-14.57L46.293 40.633 34.215 59zm46.59-17.191-6.328-9.965H82.53v9.965zm-9.59-14.653-6.516-9.965h32.211v9.965zm0 0"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="83" height="59"><path style="stroke:none;fill-rule:nonzero;fill:#8f4e8b;fill-opacity:1" d="m.469 59 19.367-29.5L.469 0h14.379l19.367 29.5L14.848 59zm0 0"/><path style="stroke:none;fill-rule:nonzero;fill:#8f4e8b;fill-opacity:1" d="m19.836 59 19.363-29.5L19.836 0h14.379l38.73 59h-14.57L46.293 40.633 34.215 59zm46.59-17.191-6.328-9.965H82.53v9.965zm-9.59-14.653-6.516-9.965h32.211v9.965zm0 0"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="83" height="55"><path style="fill-rule:nonzero;fill:#d75b26;fill-opacity:1;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#d75b26;stroke-opacity:1;stroke-miterlimit:10" d="M11.241 25.867c-.498 0-1.1-.2-1.5-.6l-8.398-8.4c-.8-.799-.8-2.1 0-3.001l8.398-8.4c.8-.798 2.101-.798 3.002 0 .8.801.8 2.1 0 3.001l-7 6.9 6.9 6.9c.8.8.8 2.098 0 3-.4.4-.9.6-1.402.6zm25 0c-.5 0-1.099-.2-1.499-.6-.8-.8-.8-2.1 0-3l6.901-6.9-6.9-6.9c-.8-.8-.8-2.1 0-3 .8-.8 2.1-.8 2.998 0l8.4 8.399c.801.8.801 2.102 0 3l-8.4 8.3c-.4.5-.898.7-1.5.7zm-16.698 4.1c-.2 0-.402 0-.7-.1-1.1-.399-1.7-1.5-1.3-2.599l8.399-25.1c.402-1.101 1.5-1.702 2.6-1.302 1.1.4 1.7 1.502 1.3 2.6l-8.4 25.101c-.198.901-1 1.4-1.899 1.4zm0 0" transform="matrix(1.74792 0 0 1.75607 0 .53)"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="83" height="55"><path style="fill-rule:nonzero;fill:#d75b26;fill-opacity:1;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#d75b26;stroke-opacity:1;stroke-miterlimit:10" d="M11.241 25.867c-.498 0-1.1-.2-1.5-.6l-8.398-8.4c-.8-.799-.8-2.1 0-3.001l8.398-8.4c.8-.798 2.101-.798 3.002 0 .8.801.8 2.1 0 3.001l-7 6.9 6.9 6.9c.8.8.8 2.098 0 3-.4.4-.9.6-1.402.6zm25 0c-.5 0-1.099-.2-1.499-.6-.8-.8-.8-2.1 0-3l6.901-6.9-6.9-6.9c-.8-.8-.8-2.1 0-3 .8-.8 2.1-.8 2.998 0l8.4 8.399c.801.8.801 2.102 0 3l-8.4 8.3c-.4.5-.898.7-1.5.7zm-16.698 4.1c-.2 0-.402 0-.7-.1-1.1-.399-1.7-1.5-1.3-2.599l8.399-25.1c.402-1.101 1.5-1.702 2.6-1.302 1.1.4 1.7 1.502 1.3 2.6l-8.4 25.101c-.198.901-1 1.4-1.899 1.4zm0 0" transform="matrix(1.74792 0 0 1.75607 0 .53)"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="70" xmlns="http://www.w3.org/2000/svg"><path d="M69.723 24.898c-.336-.851-1.012-1.535-1.688-2.222-.168.687-.336 1.37-.844 2.054L46.098 57.723c-.844 1.199-2.532 1.539-3.88 1.199l-33.75-9.574c-2.023-.512-4.386-1.711-4.554-4.106 0-.851 0-1.195.504-1.535.508-.344 1.016-.344 1.52-.172l31.726 8.89c4.555 1.368 5.902.34 9.277-4.788l19.239-30.09a5.83 5.83 0 0 0 .675-4.957c-.507-1.54-1.855-2.735-3.543-3.246L35.47 1.48c-.676-.171-1.352-.171-2.024-.171v-.172c-4.218-2.563-5.906 2.222-8.101 4.101-.844.684-1.856 1.2-2.196 1.883-.336.684-.168 1.367-.336 1.879-.843 1.883-3.207 4.957-4.386 5.813-.676.515-1.688.683-2.196 1.539-.335.511-.335 1.539-.503 2.222-.676 1.711-2.872 4.617-4.387 5.985-.508.511-1.352.855-1.688 1.539-.34.511-.172 1.539-.675 2.05-1.012 1.711-3.04 4.446-4.559 5.985-.844.855-1.856 1.195-2.191 2.05-.168.34 0 1.028-.168 1.54-.34.855-.676 1.539-.844 2.222C.37 41.141-.137 42.852.03 44.56c.34 4.105 3.375 8.207 7.09 9.234l33.746 9.574c3.207.852 7.09-.683 8.778-3.422l19.402-30.258c1.016-1.367 1.183-3.25.676-4.789zm-38.98-10.941 1.35-2.05c.337-.512 1.18-.856 1.856-.684l22.274 6.324c.675.172.843.855.507 1.371l-1.351 2.05c-.336.512-1.18.856-1.856.684L31.25 15.328c-.676-.172-.844-.687-.508-1.371zm-5.567 8.55 1.347-2.054c.34-.512 1.184-.851 1.86-.683l22.273 6.328c.676.172.844.855.504 1.367l-1.347 2.05c-.34.512-1.184.856-1.856.684L25.68 23.875c-.672-.172-1.012-.855-.504-1.367zm0 0" fill="#963"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="67" xmlns="http://www.w3.org/2000/svg"><path d="M33.383.531c.176-.707.527-.707.699 0l7.176 22.582c.176.707.875 1.235 1.574 1.235h23.45c.698 0 .698.351.175.707L47.383 38.816c-.524.528-.7 1.235-.524 1.942l7.172 22.582c.176.707 0 .883-.523.351L34.434 49.754c-.524-.352-1.399-.352-1.926 0L13.438 63.69c-.528.356-.876.176-.528-.351l7.176-22.582c.176-.707 0-1.414-.527-1.942L.489 24.88c-.528-.356-.352-.707.175-.707H24.11c.7 0 1.399-.531 1.575-1.235zm0 0" fill="#8ed200"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="67" xmlns="http://www.w3.org/2000/svg"><path d="M33.383.531c.176-.707.527-.707.699 0l7.176 22.582c.176.707.875 1.235 1.574 1.235h23.45c.698 0 .698.351.175.707L47.383 38.816c-.524.528-.7 1.235-.524 1.942l7.172 22.582c.176.707 0 .883-.523.351L34.434 49.754c-.524-.352-1.399-.352-1.926 0L13.438 63.69c-.528.356-.876.176-.528-.351l7.176-22.582c.176-.707 0-1.414-.527-1.942L.489 24.88c-.528-.356-.352-.707.175-.707H24.11c.7 0 1.399-.531 1.575-1.235zm0 0" fill="#8ed200"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="67" xmlns="http://www.w3.org/2000/svg"><path d="M5.102 59.219v-10.11h11.605v10.11zm14.066 0v-10.11h12.836v10.11zM5.102 46.805V35.457h11.605v11.348zm14.066 0V35.457h12.836v11.348zM5.102 33.152V23.047h11.605v10.105zM34.645 59.22v-10.11H47.48v10.11zM19.168 33.152V23.047h12.836v10.105zm30.95 26.067v-10.11h11.605v10.11zM34.644 46.805V35.457H47.48v11.348zm-14.07-30.496c0 .53-.528 1.062-1.231 1.062h-2.637c-.703 0-1.23-.531-1.23-1.062V6.203c0-.535.527-1.066 1.23-1.066h2.461c.703 0 1.23.531 1.23 1.066V16.31zm29.542 30.496V35.457h11.606v11.348zM34.645 33.152V23.047H47.48v10.105zm15.472 0V23.047h11.606v10.105zm1.406-16.843c0 .53-.527 1.062-1.23 1.062h-2.637c-.703 0-1.23-.531-1.23-1.062V6.203c0-.535.527-1.066 1.23-1.066h2.637c.703 0 1.23.531 1.23 1.066zM67 14.004c0-2.484-2.285-4.434-5.102-4.434h-5.097V6.203c0-3.016-2.813-5.676-6.508-5.676h-2.637c-3.515 0-6.508 2.48-6.508 5.676V9.57H25.676V6.203c0-3.016-2.817-5.676-6.508-5.676h-2.637c-3.52 0-6.508 2.48-6.508 5.676V9.57H5.102C2.285 9.57 0 11.7 0 14.004v45.035c0 2.484 2.285 4.434 5.102 4.434h56.62c2.817 0 5.102-2.13 5.102-4.434V14.004zm0 0" fill="#111"/></svg> |
| 1 | ||
| 1 | <svg height="63" width="48" xmlns="http://www.w3.org/2000/svg"><path d="M47.66 38.852c0 3.89-2.894 17.074-2.894 17.074-.68 3.21-3.575 6.594-7.317 6.594H19.75c-2.555 0-4.938-1.524-5.957-3.891 0 0-8.68-15.887-12.082-21.637-2.383-4.054-2.383-4.054.68-5.746a2.905 2.905 0 0 1 1.703-.508c1.191 0 2.039.676 2.89 1.692l5.278 6.086 1.531 2.027V3.863c0-1.86 1.703-3.383 3.742-3.383 1.875 0 3.406 1.524 3.406 3.383l.68 23.664h1.531l.34-4.054c0-1.86 1.531-3.383 3.406-3.383 1.872 0 3.403 1.523 3.403 3.383l.34 4.898h1.53l.34-3.21c0-1.86 1.532-3.38 3.407-3.38 1.871 0 3.402 1.52 3.402 3.38l.34 3.21v.848h1.192l.34-1.692c0-1.859 1.53-3.379 3.406-3.379 1.87 0 3.402 1.52 3.402 3.38-.34 0-.34 7.437-.34 11.324zm0 0" fill="#999"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M28.023 32c0 1.04.344 2.074 1.211 2.766 1.555 1.558 4.149 1.558 5.707 0 .692-.692 1.211-1.727 1.211-2.766s-.347-2.074-1.21-2.766c-.692-.695-1.731-1.21-2.77-1.21-1.035 0-2.074.343-2.766 1.21-1.039.692-1.383 1.727-1.383 2.766zm0 0" fill="#bababa"/><path d="M9.34 9.34c-12.453 12.453-12.453 32.691 0 45.32 12.453 12.453 32.691 12.453 45.32 0 12.453-12.453 12.453-32.691 0-45.32-12.453-12.453-32.867-12.453-45.32 0zm47.394 36.152c-1.21 2.074-2.765 4.153-4.496 5.88-1.73 1.73-3.804 3.288-5.883 4.5l-7.437-14.184s.691-.176 2.078-1.56c1.383-1.382 1.727-2.073 1.727-2.073zM37.707 26.293c1.559 1.555 2.422 3.633 2.422 5.707s-.863 4.152-2.422 5.707a7.933 7.933 0 0 1-11.242 0c-1.559-1.555-2.422-3.633-2.422-5.707s.691-4.152 2.422-5.707c2.941-3.113 8.129-3.113 11.242 0zm-10.895-5.535s-1.558.863-2.769 2.246c-1.211 1.387-1.211 1.558-1.73 2.25l-14.184-7.61c1.21-2.078 2.77-4.152 4.5-5.882 1.902-1.73 3.805-3.285 5.879-4.496zm0 0" fill="#999"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M64 32C64 14.43 49.57 0 32 0S0 14.43 0 32s14.43 32 32 32c17.57-.629 32-14.43 32-32zm0 0" fill="#3c3"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><g fill="#eab41b"><path d="M28.023 32c0 1.04.344 2.074 1.211 2.766 1.555 1.558 4.149 1.558 5.707 0 .692-.692 1.211-1.727 1.211-2.766s-.347-2.074-1.21-2.766c-.692-.695-1.731-1.21-2.77-1.21-1.035 0-2.074.343-2.766 1.21-1.039.692-1.383 1.727-1.383 2.766zm0 0"/><path d="M9.34 9.34c-12.453 12.453-12.453 32.691 0 45.32 12.453 12.453 32.691 12.453 45.32 0 12.453-12.453 12.453-32.691 0-45.32-12.453-12.453-32.867-12.453-45.32 0zm47.394 36.152c-1.21 2.074-2.765 4.153-4.496 5.88-1.73 1.73-3.804 3.288-5.883 4.5l-7.437-14.184s.691-.176 2.078-1.56c1.383-1.382 1.727-2.073 1.727-2.073zM37.707 26.293c1.559 1.555 2.422 3.633 2.422 5.707s-.863 4.152-2.422 5.707a7.933 7.933 0 0 1-11.242 0c-1.559-1.555-2.422-3.633-2.422-5.707s.691-4.152 2.422-5.707c2.941-3.113 8.129-3.113 11.242 0zm-10.895-5.535s-1.558.863-2.769 2.246c-1.211 1.387-1.211 1.558-1.73 2.25l-14.184-7.61c1.21-2.078 2.77-4.152 4.5-5.882 1.902-1.73 3.805-3.285 5.879-4.496zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="48" xmlns="http://www.w3.org/2000/svg"><g fill="#999" stroke="#999" stroke-miterlimit="10" stroke-width=".5"><path d="M44.2 75.3c7.2-3.701 3.9-7.3 1.5-6.799-.6.099-.801.2-.801.2s.2-.3.601-.5C50.1 66.6 53.6 73 44 75.5zm-6.4-10.5c1.801 2.1-.5 4-.5 4s4.7-2.4 2.5-5.5c-2-2.8-3.6-4.2 4.8-9.101 0 .101-13.1 3.401-6.8 10.6" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/><path d="M39.8 46.499s3.999 4-3.8 10.102c-6.2 4.898-1.4 7.7 0 10.899-3.601-3.3-6.3-6.2-4.5-8.8 2.7-4 9.9-5.9 8.3-12.201M31 76.8s-1.5.9 1 1.1c3 .299 4.6.299 7.9-.3 0 0 .9.599 2.1 1-7.4 3.3-16.901-.1-11-1.8m-.9-4.2s-1.6 1.199.9 1.5c3.2.3 5.8.4 10.2-.5 0 0 .6.6 1.599 1-9.1 2.6-19.199.2-12.698-2" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/><path d="M47.7 79.9s1.1.9-1.2 1.599c-4.3 1.302-18 1.702-21.8.101-1.4-.6 1.2-1.4 2-1.6.8-.2 1.3-.1 1.3-.1-1.5-1.1-9.8 2.1-4.2 3 15.3 2.4 27.9-1.199 23.9-3M31.7 68.3s-7 1.702-2.499 2.301c1.9.301 5.699.2 9.2-.101 2.9-.2 5.799-.8 5.799-.8s-1 .4-1.8.901c-7.1 1.9-20.7.999-16.8-.9 3.4-1.6 6.1-1.401 6.1-1.401" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/><path d="M32.399 85.4c6.901.4 17.502-.2 17.7-3.5 0 0-.499 1.2-5.699 2.2-5.899 1.1-13.101 1-17.5.3.1 0 1 .7 5.499 1" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="71" xmlns="http://www.w3.org/2000/svg"><path d="m12.225 17.126-7.7 7.598c-.9 1.001-1.4 2.201-1.4 3.501 0 1.2.5 2.5 1.4 3.4l.1.1c.9.9 2.2 1.4 3.4 1.4 1.3 0 2.5-.5 3.5-1.4l8.6-8.6 9.3-9.3c.4-.4.6-1 .6-1.5s-.2-1.101-.6-1.5-1-.6-1.5-.6-1.1.2-1.5.6l-13.4 13.3c-.6.6-1.5.6-2.2 0-.6-.6-.6-1.6 0-2.2l13.3-13.299c1-1 2.3-1.502 3.7-1.502 1.3 0 2.7.501 3.7 1.502 1 .998 1.5 2.299 1.5 3.698 0 1.3-.5 2.7-1.5 3.701l-9.3 9.3-8.6 8.6c-1.5 1.5-3.6 2.3-5.6 2.3-2 0-4-.7-5.499-2.2l-.1-.1c-1.5-1.5-2.3-3.501-2.3-5.6 0-2.001.8-4.1 2.3-5.6l8.6-8.599 10.899-11c2-2.001 4.6-3.002 7.3-3.002s5.3 1 7.3 3.002c1.999 1.999 2.999 4.6 2.999 7.3 0 2.6-1 5.3-3 7.299l-14.9 14.9c-.6.599-1.599.599-2.199 0-.6-.6-.6-1.6 0-2.201l14.9-14.898c1.4-1.4 2.1-3.301 2.1-5.1s-.7-3.701-2.1-5.101-3.3-2.1-5.2-2.1c-1.9 0-3.7.7-5.1 2.1zm0 0" fill="#999" stroke="#999" stroke-miterlimit="10" stroke-width=".25" transform="matrix(1.7579 0 0 1.76066 .65 0)"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="58" xmlns="http://www.w3.org/2000/svg"><path d="M.624 29.625V.725h3.9v28899-4-9.8901zm0 0 stroke-width="1.25" transform="matrix(2.09009 0 0 2.08311 0 .076)"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M41.266 22.992c0-3.945-2.403-7.035-5.664-8.406V3.262C35.602 1.372 34.23 0 32.344 0s-3.262 1.371-3.262 3.262v11.324c-3.43 1.2-5.66 4.46-5.66 8.406 0 3.945 2.402 7.035 5.66 8.406 0 .172-.172.516-.172.688V60.57c0 1.887 1.375 3.258 3.262 3.258s3.258-1.371 3.258-3.258V31.914c0-.344 0-.516-.168-.687 3.601-1.028 6.004-4.29 6.004-8.235zm-9.094 2.574c-1.371 0-2.402-1.03-2.402-2.402 0-1.375 1.03-2.402 2.402-2.402s2.402 1.027 2.402 2.402c.172 1.2-1.031 2.402-2.402 2.402zM58.254 3.602c0-1.887-1.375-3.258-3.262-3.258s-3.262 1.37-3.262 3.258v26.597c-3.43 1.2-5.66 4.461-5.66 8.406 0 3.946 2.403 7.036 5.66 8.407 0 .172-.171.515-.171.687v13.04c0 1.89 1.375 3.261 3.261 3.261 1.887 0 3.262-1.371 3.262-3.262V47.7c0-.344 0-.515-.172-.687 3.43-1.2 5.66-4.461 5.66-8.407 0-3.945-2.402-7.035-5.66-8.406V3.602zm-3.262 37.406c-1.37 0-2.402-1.028-2.402-2.403 0-1.37 1.031-2.402 2.402-2.402 1.371 0 2.403 1.031 2.403 2.402 0 1.375-1.032 2.403-2.403 2.403zm-48.73 19.39c0 1.887 1.375 3.258 3.261 3.258 1.887 0 3.258-1.37 3.258-3.258V47.355c0-.343 0-.511-.172-.683 3.434-1.203 5.664-4.461 5.664-8.41 0-3.946-2.402-7.035-5.664-8.407V3.602c0-1.887-1.37-3.258-3.257-3.258S6.09 1.714 6.09 3.602v26.597C2.66 31.4.43 34.66.43 38.605c0 3.946 2.402 7.036 5.66 8.407 0 .172-.172.515-.172.687v13.04c0-.34.344-.34.344-.34zm3.261-24.367c1.372 0 2.403 1.032 2.403 2.403 0 1.375-1.031 2.402-2.403 2.402-1.375 0-2.402-1.027-2.402-2.402 0-1.371 1.027-2.403 2.402-2.403zm0 0" fill="#999"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><g fill="#999"><path d="M35.2 13.332c-1.067 0-1.954.355-2.665 1.066-.715.711-1.07 1.602-1.07 2.668s.355 1.957 1.07 2.668c.711.711 1.598 1.067 2.664 1.067 1.067 0 1.957-.356 2.668-1.067.711-.71 1.067-1.601 1.067-2.668s-.356-1.957-1.067-2.668c-.535-.71-1.422-1.066-2.668-1.066zm1.777 12.09-.176.355h.176zm-.176.355c-3.555.535-6.934.711-10.489 1.246l-.355 1.598h.887c.535 0 1.066.18 1.422.535s.535.711.535 1.067c0 .53-.18.886-.535 2.132l-3.73 12.622C24.18 46.043 24 46.754 24 47.465c0 1.07.355 1.781 1.066 2.492.711.711 2.844.887 3.91.887 3.024 0 8-1.598 10.669-6.223l-2.133-1.242c-1.067 1.777-3.024 3.02-4.09 3.555-1.067.53-1.602.355-1.777.355-.18 0-.356 0-.536-.18-.175-.175-.175-.355-.175-.53 0-.356.175-1.067.53-2.134zm0 0"/><path d="M32 1.777C15.29 1.777 1.777 15.29 1.777 32S15.29 62.223 32 62.223 62.223 48.71 62.223 32 48.71 1.777 32 1.777zm0 3.38c14.934 0 26.844 12.09 26.844 26.843 0 14.934-12.09 26.844-26.844 26.844S5.156 46.754 5.156 32C5.156 17.066 17.066 5.156 32 5.156zm0 0" stroke="#999" stroke-miterlimit="10" stroke-width="3.55556"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M41.266 22.992c0-3.945-2.403-7.035-5.664-8.406V3.262C35.602 1.372 34.23 0 32.344 0s-3.262 1.371-3.262 3.262v11.324c-3.43 1.2-5.66 4.46-5.66 8.406 0 3.945 2.402 7.035 5.66 8.406 0 .172-.172.516-.172.688V60.57c0 1.887 1.375 3.258 3.262 3.258s3.258-1.371 3.258-3.258V31.914c0-.344 0-.516-.168-.687 3.601-1.028 6.004-4.29 6.004-8.235zm-9.094 2.574c-1.371 0-2.402-1.03-2.402-2.402 0-1.375 1.03-2.402 2.402-2.402s2.402 1.027 2.402 2.402c.172 1.2-1.031 2.402-2.402 2.402zM58.254 3.602c0-1.887-1.375-3.258-3.262-3.258s-3.262 1.37-3.262 3.258v26.597c-3.43 1.2-5.66 4.461-5.66 8.406 0 3.946 2.403 7.036 5.66 8.407 0 .172-.171.515-.171.687v13.04c0 1.89 1.375 3.261 3.261 3.261 1.887 0 3.262-1.371 3.262-3.262V47.7c0-.344 0-.515-.172-.687 3.43-1.2 5.66-4.461 5.66-8.407 0-3.945-2.402-7.035-5.66-8.406V3.602zm-3.262 37.406c-1.37 0-2.402-1.028-2.402-2.403 0-1.37 1.031-2.402 2.402-2.402 1.371 0 2.403 1.031 2.403 2.402 0 1.375-1.032 2.403-2.403 2.403zm-48.73 19.39c0 1.887 1.375 3.258 3.261 3.258 1.887 0 3.258-1.37 3.258-3.258V47.355c0-.343 0-.511-.172-.683 3.434-1.203 5.664-4.461 5.664-8.41 0-3.946-2.402-7.035-5.664-8.407V3.602c0-1.887-1.37-3.258-3.257-3.258S6.09 1.714 6.09 3.602v26.597C2.66 31.4.43 34.66.43 38.605c0 3.946 2.402 7.036 5.66 8.407 0 .172-.172.515-.172.687v13.04c0-.34.344-.34.344-.34zm3.261-24.367c1.372 0 2.403 1.032 2.403 2.403 0 1.375-1.031 2.402-2.403 2.402-1.375 0-2.402-1.027-2.402-2.402 0-1.371 1.027-2.403 2.402-2.403zm0 0" fill="#999"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M47.914 26.813V9.688L31.828 0 15.914 9.512v17.3L0 35.462v19.2L16.434 64 32 55.004 47.566 64 64 54.66V35.633zm-2.941 0-11.59 6.398V20.066l11.59-6.746zM31.828 3.633l11.414 6.918-11.414 6.746-11.07-6.918zM4.844 36.324l12.8-6.746 11.243 6.399-12.453 7.265zm12.972 9.512 12.625-7.262v13.492l-12.625 7.438zm17.47-9.86 11.245-6.398 12.797 6.918-11.762 6.746zm25.6 16.782-11.761 6.746V45.836l11.762-6.742zm0 0" fill="#938886"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><g fill="#eab41b"><path d="M28.023 32c0 1.04.344 2.074 1.211 2.766 1.555 1.558 4.149 1.558 5.707 0 .692-.692 1.211-1.727 1.211-2.766s-.347-2.074-1.21-2.766c-.692-.695-1.731-1.21-2.77-1.21-1.035 0-2.074.343-2.766 1.21-1.039.692-1.383 1.727-1.383 2.766zm0 0"/><path d="M9.34 9.34c-12.453 12.453-12.453 32.691 0 45.32 12.453 12.453 32.691 12.453 45.32 0 12.453-12.453 12.453-32.691 0-45.32-12.453-12.453-32.867-12.453-45.32 0zm47.394 36.152c-1.21 2.074-2.765 4.153-4.496 5.88-1.73 1.73-3.804 3.288-5.883 4.5l-7.437-14.184s.691-.176 2.078-1.56c1.383-1.382 1.727-2.073 1.727-2.073zM37.707 26.293c1.559 1.555 2.422 3.633 2.422 5.707s-.863 4.152-2.422 5.707a7.933 7.933 0 0 1-11.242 0c-1.559-1.555-2.422-3.633-2.422-5.707s.691-4.152 2.422-5.707c2.941-3.113 8.129-3.113 11.242 0zm-10.895-5.535s-1.558.863-2.769 2.246c-1.211 1.387-1.211 1.558-1.73 2.25l-14.184-7.61c1.21-2.078 2.77-4.152 4.5-5.882 1.902-1.73 3.805-3.285 5.879-4.496zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="67" xmlns="http://www.w3.org/2000/svg"><path d="M39.06.14s-7.599 3.599-13.7 4.4c-6.1.798-17.9 1.6-20.2 1-2.3-.601-4-1.201-4-1.201l.501 1.6-1.5 1.3.3.5h.6l1.9.201.3.799 1.1.1.501 1.8s2.2.2 2.9.2c.698 0 1.999-.101 1.999-.101v.7l.501.101v.801l-1.1.9h.3v.298s-2.4.201-3.302 0c-1-.098-1.098-.098-1.098-.098l-.101.098v.402h.2l.101 1.798 4.899-.198-.499 6.6v.798l-4.101-.198v-1.7h.9l.1-.701.801-.2.099-.2-3.2-.7-2.4.7.4.3h.4v.6h.8v1.6l-.899.2.2.4.2.1v1.301h.6v5.9l-.901.1.101 1.7.6.098-.101 4h2.5l-.499-3.8 3.798-.1-.299 2.1-.4 1.502h3.801v-3.702l2.599-.198-.099 2.398-.1 1.401h2.198l-.099-3.8h.301l.299-1.9h-.4l-.1-.8-.2-2.2.1-2.5h.501v-1.5h-.602l.101-1.8.701-.1v-.601l.4-.098.4-.301-2.5-.5-2.5.6.2.4h.6l.098.7h.701v1.6l-3-.1.1-1.7.101-1.5v-2l.1-2.099 5.999-.301 7.1-.4.101 1.299-.301 3.202-.099 2.999h-2.6v-2.1h.999v-.6l.4-.1v-.101h.4l.2-.299-3-.7-2.9.6.2.399h.3v.2h.4v.701h.9v1.9h-.9v.4h.3v1.6h.6l-.099 6.4-.802.2v.3h.301v1.6h.501l-.2 2.3-.2 1.9 3.1.101-.101-1.7-.2-1.401v-1.2h2.601l-.101 1.9v2l1.5.1 2-.1.6-.2-.4-1.1-.1-1.7-.2-1.2 2.5-.1-.1 1.5v2.3l1 .1h1.001l.499-.2-.3-2.2-.1-1.6h.4v-1.5h.1v-.299h-.5l-.099-1.1V24.74h.4v-1.6h.2v-.301h-.6V21.04l.898-.1-.098-.601h.4v-.1l.498-.3-2.7-.6-2.5.6.2.3h.402v.1h.4v.7h.898l.102 1.7H28.06l-.4-2.6-.299-1.4-.2-2.501.1-1.399 6.3-.5v-2.1l.298-.1v-.301l-.2-.098s-3.5.5-4.6.6c-.298 0-.298 0-.498.098v-.4l-1.3-.7v-.799h.5v-1.1s2.7-.2 3.7-.399c.999-.2 2.398-.502 2.398-.502l.701-1.798 1.3-.402.1-.299 3-.801.3-.299-1.1-2.499.1-.6.6-.301.4-1.299zM24.662 9.638v.901h.699v.9l-1.3.901-.1.299h.501v.2l-4.2.2v-.6l.2-.3v-.6l.099-.299v-.402l.2-.698zm-8.502.801-.098.6.298.4v.7l.301.5-.1.5.2.301-4.199.199v-.1l.499-.099v-.2l-1.099-.601-.1-.9h.5v-1.001zm6.101 14.1 2.5.2-.099 3.4.299 2.8-2.7-.1zm-16.9.1 4 .2-.3 2.3v2l.3 1.1-4 .2zm25.9 0v5.8l-2.6.2-.1-3.1-.3-2.8zm-19.5.1h3v5.4h-2.799l-.1-1.7v-1.7zm0 0" fill="#b41717" stroke="#b41717" stroke-miterlimit="10" stroke-width=".25" transform="matrix(1.7 0 0 1.71166 0 .105)"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="48" xmlns="http://www.w3.org/2000/svg"><g stroke-miterlimit="10" stroke-width=".5"><path d="M44.2 75.3c7.2-3.701 3.9-7.3 1.5-6.799-.6.099-.801.2-.801.2s.2-.3.601-.5C50.1 66.6 53.6 73 44 75.5zm0 0" fill="#265db4" stroke="#265db4" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/><path d="M37.8 64.8c1.801 2.1-.5 4-.5 4s4.7-2.4 2.5-5.5c-2-2.8-3.6-4.2 4.8-9.101 0 .101-13.1 3.401-6.8 10.6" fill="#c00" stroke="#c00" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/><path d="M39.8 46.499s3.999 4-3.8 10.102c-6.2 4.898-1.4 7.7 0 10.899-3.601-3.3-6.3-6.2-4.5-8.8 2.7-4 9.9-5.9 8.3-12.201" fill="#c00" stroke="#c00" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/><g fill="#265db4" stroke="#265db4"><path d="M31 76.8s-1.5.9 1 1.1c3 .299 4.6.299 7.9-.3 0 0 .9.599 2.1 1-7.4 3.3-16.901-.1-11-1.8m-.9-4.2s-1.6 1.199.9 1.5c3.2.3 5.8.4 10.2-.5 0 0 .6.6 1.599 1-9.1 2.6-19.199.2-12.698-2" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/><path d="M47.7 79.9s1.1.9-1.2 1.599c-4.3 1.302-18 1.702-21.8.101-1.4-.6 1.2-1.4 2-1.6.8-.2 1.3-.1 1.3-.1-1.5-1.1-9.8 2.1-4.2 3 15.3 2.4 27.9-1.199 23.9-3M31.7 68.3s-7 1.702-2.499 2.301c1.9.301 5.699.2 9.2-.101 2.9-.2 5.799-.8 5.799-.8s-1 .4-1.8.901c-7.1 1.9-20.7.999-16.8-.9 3.4-1.6 6.1-1.401 6.1-1.401" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/><path d="M32.399 85.4c6.901.4 17.502-.2 17.7-3.5 0 0-.499 1.2-5.699 2.2-5.899 1.1-13.101 1-17.5.3.1 0 1 .7 5.499 1" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/></g></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="48" xmlns="http://www.w3.org/2000/svg"><g stroke-miterlimit="10" stroke-width=".5"><path d="M44.2 75.3c7.2-3.701 3.9-7.3 1.5-6.799-.6.099-.801.2-.801.2s.2-.3.601-.5C50.1 66.6 53.6 73 44 75.5zm0 0" fill="#265db4" stroke="#265db4" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/><path d="M37.8 64.8c1.801 2.1-.5 4-.5 4s4.7-2.4 2.5-5.5c-2-2.8-3.6-4.2 4.8-9.101 0 .101-13.1 3.401-6.8 10.6" fill="#c00" stroke="#c00" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/><path d="M39.8 46.499s3.999 4-3.8 10.102c-6.2 4.898-1.4 7.7 0 10.899-3.601-3.3-6.3-6.2-4.5-8.8 2.7-4 9.9-5.9 8.3-12.201" fill="#c00" stroke="#c00" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/><g fill="#265db4" stroke="#265db4"><path d="M31 76.8s-1.5.9 1 1.1c3 .299 4.6.299 7.9-.3 0 0 .9.599 2.1 1-7.4 3.3-16.901-.1-11-1.8m-.9-4.2s-1.6 1.199.9 1.5c3.2.3 5.8.4 10.2-.5 0 0 .6.6 1.599 1-9.1 2.6-19.199.2-12.698-2" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/><path d="M47.7 79.9s1.1.9-1.2 1.599c-4.3 1.302-18 1.702-21.8.101-1.4-.6 1.2-1.4 2-1.6.8-.2 1.3-.1 1.3-.1-1.5-1.1-9.8 2.1-4.2 3 15.3 2.4 27.9-1.199 23.9-3M31.7 68.3s-7 1.702-2.499 2.301c1.9.301 5.699.2 9.2-.101 2.9-.2 5.799-.8 5.799-.8s-1 .4-1.8.901c-7.1 1.9-20.7.999-16.8-.9 3.4-1.6 6.1-1.401 6.1-1.401" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/><path d="M32.399 85.4c6.901.4 17.502-.2 17.7-3.5 0 0-.499 1.2-5.699 2.2-5.899 1.1-13.101 1-17.5.3.1 0 1 .7 5.499 1" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/></g></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="82" xmlns="http://www.w3.org/2000/svg"><g fill="#3c3"><path d="M0 .094v63.812h82V.094zM77.34 4.8v27.86L57.773 17.6 36.34 39.247l-15.094-8.469L4.844 43.953V4.801zm0 0"/><path d="M22.55 17.223c0 3.222-2.585 5.836-5.777 5.836-3.191 0-5.777-2.614-5.777-5.836s2.586-5.836 5.777-5.836c3.192 0 5.778 2.613 5.778 5.836zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="75" xmlns="http://www.w3.org/2000/svg"><path d="M.5 19v-4.1c.9-.1 1.6-.2 2-.4.4-.2.8-.6 1.2-1.001.4-.5.5-1.1.7-1.9.1-.6.2-1.499.2-2.799 0-2.201.1-3.7.4-4.6.2-.8.6-1.6 1.2-2 .5-.5 1.4-.9 2.5-1.2.7-.2 1.9-.4 3.5-.4h.9v3.9c-1.3 0-2.2.1-2.6.3-.4.2-.6.4-.9.6-.2.3-.3.7-.3 1.501 0 .8-.1 2-.2 4.099-.101 1.2-.2 2-.4 2.801-.301.6-.6 1.2-1 1.8-.4.4-1 .9-1.8 1.399.7.4 1.3.8 1.8 1.3s.8 1.2 1.1 1.899c.3.702.4 1.802.4 3.001.1 1.9.1 3.1.1 3.599 0 .702.1 1.202.3 1.602.2.4.5.5.9.6.4.2 1.2.3 2.6.3v4.098h-1c-1.6 0-2.9-.1-3.701-.4-.9-.3-1.6-.6-2.2-1.2-.6-.6-.999-1.2-1.2-1.999-.198-.8-.299-2.1-.299-4 0-2-.1-3.5-.3-4.1-.3-.9-.7-1.601-1.201-2-.698-.5-1.5-.7-2.7-.7zm39.1 0c-.9.1-1.6.2-2 .4s-.8.6-1.2 1.001c-.4.5-.5 1.1-.7 1.9-.099.6-.2 1.499-.2 2.799 0 2.201-.1 3.7-.4 4.6-.2.9-.6 1.6-1.2 2-.5.5-1.4.9-2.5 1.2-.7.2-1.9.4-3.5.4h-.999v-4.1c1.298 0 2.1-.1 2.599-.3s.7-.4.899-.6c.2-.3.301-.7.301-1.501 0-.6.1-2 .2-3.999.099-1.2.3-2.1.5-2.8.3-.7.6-1.3 1.1-1.9.4-.5 1-.9 1.7-1.3-.901-.6-1.6-1.1-2-1.6-.5-.7-1-1.801-1.201-2.8-.199-.8-.299-2.6-.299-5.2 0-.8-.1-1.4-.301-1.8-.199-.3-.4-.5-.799-.6-.2-.3-1-.3-2.5-.3v-4h.999c1.602 0 2.9.1 3.7.4.902.3 1.6.6 2.2 1.2.6.6 1.002 1.2 1.2 2 .201.8.402 2.1.402 4 0 2 .098 3.4.299 4.1.299.9.7 1.601 1.2 1.9.5.4 1.401.6 2.5.6.1.1 0 4.3 0 4.3zm0 0" fill="#307ac6" stroke="#307ac6" stroke-miterlimit="10" transform="matrix(1.86825 0 0 1.87558 0 .209)"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="77" xmlns="http://www.w3.org/2000/svg"><g fill="#999" stroke="#999" stroke-miterlimit="10" stroke-width=".5"><path d="M16.4 67.5v-4.1c.901-.1 1.6-.2 2-.4.4-.2.8-.6 1.2-1 .4-.5.5-1.1.7-1.9.1-.6.2-1.5.2-2.8 0-2.2.1-3.7.4-4.6.2-.8.599-1.6 1.2-2 .5-.5 1.4-.9 2.5-1.2.7-.2 1.9-.4 3.5-.4h.9V53c-1.3 0-2.2.1-2.6.3-.4.2-.6.4-.9.6-.2.3-.3.7-.3 1.5 0 .801-.1 2-.2 4.1-.1 1.2-.2 2-.4 2.8-.3.6-.6 1.2-1 1.8-.4.4-1 .9-1.8 1.401.7.4 1.301.8 1.8 1.299.5.499.801 1.2 1.1 1.9.3.7.4 1.8.4 3 .1 1.9.1 3.1.1 3.6 0 .7.1 1.2.3 1.6.199.4.5.5.9.6.4.2 1.2.3 2.6.3v4.1h-1c-1.6 0-2.9-.1-3.7-.4-.9-.3-1.6-.6-2.2-1.199-.601-.601-1-1.2-1.2-2.002-.2-.799-.3-2.1-.3-4 0-2-.1-3.5-.3-4.1-.3-.898-.7-1.6-1.2-1.999-.7-.5-1.5-.7-2.7-.7zm39.1 0c-.9.1-1.6.2-2 .4-.401.2-.8.6-1.2 1-.4.5-.499 1.1-.7 1.9-.1.6-.2 1.5-.2 2.8 0 2.2-.1 3.7-.4 4.6-.2.9-.6 1.6-1.2 2-.5.5-1.4.9-2.501 1.2-.698.2-1.9.4-3.5.4h-1v-4.1c1.3 0 2.101-.1 2.6-.3.501-.2.7-.4.902-.6.2-.3.3-.7.3-1.5 0-.601.098-2 .199-4 .1-1.2.3-2.099.499-2.8.302-.7.602-1.3 1.1-1.9.401-.5 1.001-.9 1.701-1.3-.9-.6-1.6-1.1-2-1.6-.5-.7-1-1.8-1.2-2.8-.2-.8-.3-2.6-.3-5.2 0-.8-.1-1.401-.3-1.8-.2-.3-.4-.5-.8-.6-.2-.3-1-.3-2.5-.3v-4h1c1.6 0 2.9.1 3.7.4.9.3 1.6.6 2.2 1.199.6.601 1 1.2 1.2 2.002.2.799.4 2.1.4 4 0 2 .1 3.4.301 4.1.3.898.698 1.6 1.2 1.9.499.399 1.398.598 2.499.598.1.1 0 4.302 0 4.302zm0 0" transform="matrix(1.90195 0 0 1.91617 -29.917 -93.413)"/><path d="M44.1 67.1c-.7-.3-1.2-.9-1.2-1.599 0-.701.5-1.4 1.2-1.6.299-.1.4-.3.299-.502-.3-.799-.499-1.598-.998-2.2-.1-.3-.4-.3-.602-.2-.2.1-.499.3-.799.3-1 0-1.7-.799-1.7-1.7 0-.3.1-.599.3-.799.1-.3 0-.4-.2-.6-.7-.4-1.499-.7-2.2-1-.3-.1-.4.1-.5.3-.3.7-.9 1.2-1.6 1.2s-1.4-.5-1.6-1.2c-.101-.3-.3-.4-.5-.3-.8.3-1.6.5-2.2 1-.301.1-.301.4-.2.6.2.3.3.5.3.8 0 1-.8 1.7-1.699 1.7-.302 0-.602-.1-.801-.3-.3-.1-.4 0-.6.2-.4.7-.7 1.5-1 2.2-.1.3.1.4.3.5.7.3 1.2.9 1.2 1.601 0 .7-.5 1.398-1.2 1.598-.3.1-.4.302-.3.502.3.799.5 1.6 1 2.2.1.299.4.299.6.2.3-.2.5-.3.801-.3.998 0 1.699.799 1.699 1.7 0 .3-.1.599-.3.799-.101.3 0 .4.2.6.7.4 1.5.7 2.2 1 .2 0 .399-.1.399-.3.302-.7.902-1.2 1.602-1.2.698 0 1.399.5 1.6 1.2.098.3.3.4.499.3.801-.3 1.6-.5 2.2-1 .3-.1.3-.4.2-.6-.1-.3-.301-.5-.301-.8 0-1 .801-1.7 1.7-1.7.3 0 .6.1.802.3.3.1.4 0 .6-.2.4-.701.7-1.5 1-2.2.199-.1.098-.4-.202-.5zm-8.3 1c-1.5 0-2.699-1.2-2.699-2.701 0-1.498 1.2-2.699 2.699-2.699 1.499 0 2.7 1.2 2.7 2.699.1 1.5-1.201 2.701-2.7 2.701zm0 0" transform="matrix(1.90195 0 0 1.91617 -29.917 -93.413)"/></g></svg> |
| 1 | ||
| 1 | <svg height="63" width="49" xmlns="http://www.w3.org/2000/svg"><path d="M24.842 21.014c2.2-.7 4.4.7 4.202 2.8-.2 2.4-3.302 3.601-5.1 4.2l.1-.099-.1-.101c1.3-1 3.898-2.199 3.7-4.6-.1-1.2-1.001-2.098-2.702-2v-.2zm-16.099.401.1-.101c-1 0-1.901.4-2.701.7-.798.3-1.8.401-2.198 1.3.399.7 1.4.7 2.398.802 3.4.5 8.302.398 11.701 0 1.799-.201 3.4-.401 4.2-1.201l-.1-.101.1-.1c-3.4.402-7.8 1-11.9.8-1.301-.099-3-.099-3.7-.8.4-.7 1.4-.9 2.1-1.299zm19.9 14.099v-.1c-5.1 2.5-13.201 2.8-20.5 2.201l.1.1-.1.2c2.999.5 6.9.7 10.7.398 3.7-.198 8.199-.698 9.9-2.698zm-14.4-15.398h.1c-.8-1.802-2.3-2.602-2.499-4.7-.2-1.902.7-3.102 1.598-4 1.101-1.201 2.702-2.201 3.901-3.5 1.6-1.803 3.4-4.5 1.9-7.102l-.101.101-.299-.101c.4 2.5-.6 4.101-1.901 5.4-.999 1.201-2.6 2.201-4 3.3-1.6 1.3-3.7 2.901-3.1 5.3.502 2.302 2.8 3.9 4.102 5.4zm8-11.602-.1-.099c-2.7 1-6.701 2.6-7.1 5.698-.1 1.503.399 2.602.9 3.401.4.602 1.1 1 1.3 1.901.2.8 0 1.6-.2 2.2h.1l.1.1c1.099-.8 2.2-1.901 1.899-3.401-.198-1.5-1.9-2.5-2.1-3.899-.1-.802.1-1.5.401-1.9 1.1-1.701 3.5-2.902 4.8-4zm-13.8 17.401-.101-.101c-.5.301-1.5.4-1.4 1.2.1.8 1.5 1 2.2 1.2 3.7.8 9.2.3 11.902-.599l-.1-.101.1-.099c-.301-.101-.7-.7-1.3-.7-.502-.1-1.6.299-2.602.4-1.6.199-3.299.3-4.799.199-1.101-.1-4.5-.1-3.9-1.399zm.9 4.099.1-.1c-.6.201-1.3.4-1.3 1.1 0 .601 1.2 1 1.9 1.3 3.299 1 8.5.4 10.9-.699-.2-.302-.6-.4-.9-.601-.4-.1-.7-.3-1.1-.5-2.001.5-5.1.7-7.5.4-.7-.1-1.701-.1-1.9-.799zm17.699 3.2-.1-.099c-.098 1-1.3 1.1-2.1 1.3-.898.2-1.9.398-2.998.5-4.902.599-11.5.898-16.302 0-.898-.102-2.2-.401-2.499-1.102.4-.698 1.5-.8 2.399-1.198l-.098-.101.098-.1c-1.2.1-2.1.4-2.998.701-.7.3-1.701.698-1.902 1.5.6.8 1.801.8 2.8 1 6.6 1 15.7 1.198 21.402-.7.998-.401 3.098-1 2.1-1.901zm-3.7-5.099c.2 0 .4-.101.702-.2m.898-6.8c-.198 0-.399.1-.7.1m-2.2 1.7c.1 0 .2-.101.401-.101m-12.5-1.6c-.4.1-.8.1-1.3.201m-2.2 15.898c.499.2 1.099.2 1.7.401m20.5-2.2c.1-.1.2-.2.3-.399M19.043.814c0-.099-.098-.3-.098-.399m-4.702 19.7c.1.1.301.4.402.5m2.298 1.199c.1-.1.2-.198.3-.399m5.7-13.2c-.3.099-.499.2-.7.398m-1.198 18.802h.198m-12.6-1.8c0 .1-.2.1-.2.199m.9 4.2.101-.1m-2.8 2.701c-.4 0-.7.1-1 .1m21.399.5c0-.1-.1-.1-.1-.1h-.098" fill="#666" stroke="#666" stroke-miterlimit="10" transform="matrix(1.63519 0 0 1.61722 .336 0)"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="72" xmlns="http://www.w3.org/2000/svg"><g fill="#72bed3" stroke="#72bed3" stroke-miterlimit="10" stroke-width=".75"><path d="M56.4 65.6c0-2.7-3.4-5.3-8.5-6.9 1.2-5.3.7-9.5-1.7-10.9-.6-.3-1.2-.4-1.9-.4v1.9c.4 0 .7.1.9.201 1.1.7 1.7 3.098 1.2 6.299-.1.8-.2 1.6-.4 2.4-1.7-.401-3.4-.7-5.3-.9-1.099-1.6-2.3-2.9-3.4-4.2 2.8-2.5 5.3-3.9 7-3.9V47.3c-2.3 0-5.3 1.7-8.301 4.5-3.098-2.8-6.098-4.4-8.3-4.4V49.3c1.802 0 4.201 1.3 7 3.9-1.198 1.2-2.3 2.6-3.4 4.2-1.9.2-3.698.399-5.3.9-.098-.9-.298-1.7-.4-2.4-.4-3.1.102-5.7 1.201-6.301.2-.098.6-.198.9-.198v-1.902c-.7 0-1.3.1-1.9.402-2.3 1.3-2.8 5.498-1.7 10.899-5.3 1.6-8.7 4.199-8.7 6.9 0 2.7 3.4 5.3 8.5 6.9-1.2 5.301-.7 9.5 1.7 10.9.6.3 1.2.401 1.9.401 2.3 0 5.3-1.7 8.301-4.5 3.098 2.8 6.098 4.4 8.3 4.4.698 0 1.299-.1 1.9-.401C48.3 82.1 48.8 77.9 47.7 72.5c5.4-1.7 8.7-4.2 8.7-6.9zm-10.8-5.601c-.3 1.1-.7 2.202-1.1 3.3-.3-.699-.701-1.299-1.099-1.998-.4-.7-.8-1.302-1.2-2.002 1.2.2 2.3.401 3.399.7zM41.8 68.9c-.7 1.099-1.3 2.2-1.999 3.098-1.2.1-2.401.2-3.7.2s-2.501-.1-3.8-.1c-.7-.998-1.3-1.999-2.002-3.1-.7-1.099-1.198-2.2-1.799-3.299.6-1.1 1.1-2.2 1.799-3.3.702-1.1 1.302-2.2 2.001-3.101 1.2-.098 2.5-.098 3.8-.098s2.5.098 3.8.098c.7 1 1.3 2.002 1.999 3.1.701 1.101 1.2 2.2 1.801 3.301-.7 1.001-1.3 2.1-1.9 3.2zm2.7-1.101c.4 1.1.9 2.2 1.199 3.3-1.1.2-2.298.4-3.4.7.4-.7.8-1.301 1.2-2 .3-.6.601-1.3 1.001-2zM36 76.7C35.2 75.9 34.4 74.9 33.7 74c.798 0 1.5.1 2.298.1.8 0 1.6 0 2.3-.1-.7.999-1.5 1.9-2.3 2.7zm-6.2-4.9c-1.2-.1-2.3-.4-3.399-.7.3-1.1.7-2.199 1.1-3.3.301.7.699 1.3 1.1 2 .4.699.8 1.3 1.2 2zM36 54.5c.8.8 1.6 1.799 2.3 2.7-.798 0-1.5-.1-2.3-.1-.798 0-1.599 0-2.298.1.7-1 1.5-1.9 2.298-2.7zm-6.2 4.9c-.4.7-.8 1.301-1.2 2-.4.7-.7 1.3-1.1 2-.4-1.101-.899-2.2-1.2-3.3 1.2-.4 2.3-.6 3.5-.7zm-7.5 10.4c-3-1.2-4.9-2.9-4.9-4.2 0-1.3 1.9-3 4.9-4.2.701-.3 1.502-.601 2.3-.9.4 1.701 1.102 3.3 1.9 5.1a46.22 46.22 0 0 0-1.9 5c-.798-.199-1.599-.4-2.3-.8zm4.4 11.899c-1.1-.7-1.7-3.098-1.198-6.299.099-.8.2-1.6.4-2.4 1.7.401 3.4.7 5.3.9 1.1 1.6 2.3 2.9 3.4 4.2-2.8 2.5-5.3 3.9-7 3.9-.2-.1-.6-.1-.902-.301zM46.5 75.4c.4 3.1-.099 5.7-1.198 6.299-.2.1-.6.2-.902.2-1.799 0-4.2-1.299-7-3.9 1.201-1.199 2.3-2.599 3.4-4.2 1.9-.2 3.701-.398 5.3-.9.2.8.301 1.701.4 2.501zm3.2-5.6c-.7.3-1.5.601-2.298.9-.4-1.701-1.102-3.3-1.9-5.1a46.22 46.22 0 0 0 1.9-5c.798.199 1.599.6 2.298.899C52.7 62.7 54.6 64.4 54.6 65.7c-.102 1.2-2.002 2.9-4.902 4.1zm0 0" transform="matrix(1.69822 0 0 1.71352 -24.966 -80.407)"/><path d="M39.801 65.6a3.8 3.8 0 1 1-7.601 0 3.8 3.8 0 0 1 7.601 0zm0 0" transform="matrix(1.69822 0 0 1.71352 -24.966 -80.407)"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M31.816 6.078c5.094 5.094 6.547 12.184 4.73 18.547l26.907 26.91.547 12-15.09-1.273v-7.637h-7.637v-7.637h-7.457L24 37.172c-6.363 1.816-13.637.363-18.547-4.73-7.27-7.27-7.27-19.27 0-26.544a18.494 18.494 0 0 1 26.363.18zM18 11.172c-2.184-2.184-5.453-2.184-7.637 0-2.18 2.18-2.18 5.453 0 7.637 2.184 2.18 5.453 2.18 7.637 0 2.184-2.184 2.184-5.637 0-7.637zm0 0" fill="#696"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="70" xmlns="http://www.w3.org/2000/svg"><path d="M69.723 24.898c-.336-.851-1.012-1.535-1.688-2.222-.168.687-.336 1.37-.844 2.054L46.098 57.723c-.844 1.199-2.532 1.539-3.88 1.199l-33.75-9.574c-2.023-.512-4.386-1.711-4.554-4.106 0-.851 0-1.195.504-1.535.508-.344 1.016-.344 1.52-.172l31.726 8.89c4.555 1.368 5.902.34 9.277-4.788l19.239-30.09a5.83 5.83 0 0 0 .675-4.957c-.507-1.54-1.855-2.735-3.543-3.246L35.47 1.48c-.676-.171-1.352-.171-2.024-.171v-.172c-4.218-2.563-5.906 2.222-8.101 4.101-.844.684-1.856 1.2-2.196 1.883-.336.684-.168 1.367-.336 1.879-.843 1.883-3.207 4.957-4.386 5.813-.676.515-1.688.683-2.196 1.539-.335.511-.335 1.539-.503 2.222-.676 1.711-2.872 4.617-4.387 5.985-.508.511-1.352.855-1.688 1.539-.34.511-.172 1.539-.675 2.05-1.012 1.711-3.04 4.446-4.559 5.985-.844.855-1.856 1.195-2.191 2.05-.168.34 0 1.028-.168 1.54-.34.855-.676 1.539-.844 2.222C.37 41.141-.137 42.852.03 44.56c.34 4.105 3.375 8.207 7.09 9.234l33.746 9.574c3.207.852 7.09-.683 8.778-3.422l19.402-30.258c1.016-1.367 1.183-3.25.676-4.789zm-38.98-10.941 1.35-2.05c.337-.512 1.18-.856 1.856-.684l22.274 6.324c.675.172.843.855.507 1.371l-1.351 2.05c-.336.512-1.18.856-1.856.684L31.25 15.328c-.676-.172-.844-.687-.508-1.371zm-5.567 8.55 1.347-2.054c.34-.512 1.184-.851 1.86-.683l22.273 6.328c.676.172.844.855.504 1.367l-1.347 2.05c-.34.512-1.184.856-1.856.684L25.68 23.875c-.672-.172-1.012-.855-.504-1.367zm0 0" fill="#963"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="74" xmlns="http://www.w3.org/2000/svg"><g fill="#1f385e"><path d="M73.734 51.555c0-2.844-2.289-5.157-5.109-5.157H5.375c-2.82 0-5.11 2.313-5.11 5.157v7.289c0 2.843 2.29 5.156 5.11 5.156h63.25c2.82 0 5.11-2.313 5.11-5.156zm-27.308 6.757a2.985 2.985 0 0 1-2.996-3.023 2.985 2.985 0 0 1 2.996-3.023 2.985 2.985 0 0 1 2.996 3.023c0 1.777-1.234 3.023-2.996 3.023zm8.984 0a2.984 2.984 0 0 1-2.992-3.023c0-1.777 1.23-3.023 2.992-3.023a2.985 2.985 0 0 1 2.996 3.023 2.985 2.985 0 0 1-2.996 3.023zm8.813 0a2.985 2.985 0 0 1-2.996-3.023c0-1.777 1.234-3.023 2.996-3.023a2.981 2.981 0 0 1 2.992 3.023 2.981 2.981 0 0 1-2.992 3.023zM5.375 43.38h63.25c1.41 0 2.82.355 3.879 1.066l-6.168-12.98c-1.762-3.73-4.582-5.153-7.398-5.153h-6.876L42.2 36.623c-.707.71-1.586 1.245-2.469 1.6-.878.356-1.937.532-2.82.532-1.055 0-1.937-.176-2.816-.531h-.352c-.707-.356-1.41-.891-2.117-1.422l-9.867-10.668h-6.871c-2.817 0-5.461 1.601-7.399 5.156L1.32 44.266c1.235-.532 2.47-.887 4.055-.887zm0 0"/><path d="M51.71 21.332c.352-.355.532-.71.884-1.242.176-.535.351-.89.351-1.602 0-.531-.175-1.066-.351-1.422-.176-.53-.532-.886-.883-1.246a5.273 5.273 0 0 0-1.23-.886c-.356-.18-.883-.356-1.41-.356-.532 0-1.06.176-1.41.356-.528.175-.884.53-1.235.886l-5.637 5.692V3.734c0-.535-.176-1.066-.352-1.421-.18-.536-.53-.891-.882-1.247-.352-.355-.703-.71-1.235-.886C37.97 0 37.441 0 36.91 0c-.527 0-1.055 0-1.406.18-.531.175-.883.53-1.234.886-.352.356-.708.711-.883 1.246-.176.532-.352.887-.352 1.422v17.953L27.398 16c-.351-.355-.707-.71-1.234-.89-.352-.176-.879-.356-1.41-.356-.527 0-1.055.18-1.41.355-.352.18-.88.536-1.23.891-.356.355-.708.71-.884 1.246-.175.531-.351.887-.351 1.422 0 .531.176 1.066.351 1.598.176.535.528.89.883 1.246L34.27 33.957c.351.355.703.711 1.234.887.351.18.879.355 1.406.355.531 0 1.059-.176 1.41-.355.532-.176.883-.532 1.235-.887zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="69" xmlns="http://www.w3.org/2000/svg"><path d="M13.875 13.874h10.9v2.701h-10.9zm0 5.4h10.9v2.701h-10.9zm0 5.5h10.9v2.702h-10.9zm19-24.399H11.177c-3 0-5.402 2.4-5.402 5.4v24.4h-5.4c0 3 2.402 5.4 5.4 5.4h21.7c3 0 5.402-2.4 5.402-5.4v-21.7h5.4v-2.7c0-3-2.402-5.4-5.4-5.4zm-2.7 29.3c0 1.801-1.4 3.2-3.2 3.2h-19.9c1.3-.9 1.3-2.7 1.3-2.7v-24.4c0-1.5 1.2-2.7 2.7-2.7 1.501 0 2.7 1.2 2.7 2.7v2.7h16.3zm-13.6-23.9v-2.7h16.3c2.501 0 2.7 1.6 2.7 2.7zm0 0" fill="#999" stroke="#999" stroke-miterlimit="10" stroke-width=".75" transform="matrix(1.7717 0 0 1.78025 .262 0)"/></svg> |
| 1 | ||
| 1 | <svg height="63" width="60" xmlns="http://www.w3.org/2000/svg"><path d="M.125 47.379V28.586c0-1.125.379-1.879 1.523-2.441 14.29-7.707 28.579-15.598 42.868-23.493 2.097-.937 4.004-2.254 6.48-2.254 4 .188 7.43 2.442 8.57 6.204 1.145 3.757 0 8.078-3.238 10.144-3.617 2.258-7.621 4.324-11.43 6.578C30.61 31.031 16.32 38.922 1.84 46.816c-.574.188-.953.375-1.715.563zm0 0" fill="#e88e3d"/><path d="M22.797 40.426c.57-.375.953-.563 1.144-.938 4.762-2.633 9.524-5.074 13.907-7.52.953-.562 1.715-.562 2.668.188 5.336 4.887 10.859 9.399 16.004 14.285 3.046 2.63 3.812 6.012 2.667 9.582-.953 3.57-3.62 5.641-7.43 6.204-2.476.375-4.952-.375-6.859-1.88-7.242-6.577-14.48-13.156-22.101-19.921.191.375.191.187 0 0zM.125 22.008c0-4.695-.383-9.207.191-13.528C.886 3.406 5.84.398 11.367.96c4.57.567 8.383 5.263 8 9.774 0 .563-.379 1.13-.953 1.317-5.906 3.195-11.812 6.578-17.91 9.77.191.187 0 0-.379.187zm19.242 20.297c0 4.324.192 8.082 0 12.027-.379 4.7-4.762 8.27-9.336 8.27-4.57 0-8.953-3.383-9.715-7.891-.191-1.316 0-2.258 1.332-3.008 5.336-3.008 10.86-5.828 16.196-8.832.379 0 .761-.187 1.523-.566zm0 0" fill="#5171a5"/></svg> |
| 1 | ||
| 1 | <svg height="63" width="60" xmlns="http://www.w3.org/2000/svg"><path d="M.125 47.379V28.586c0-1.125.379-1.879 1.523-2.441 14.29-7.707 28.579-15.598 42.868-23.493 2.097-.937 4.004-2.254 6.48-2.254 4 .188 7.43 2.442 8.57 6.204 1.145 3.757 0 8.078-3.238 10.144-3.617 2.258-7.621 4.324-11.43 6.578C30.61 31.031 16.32 38.922 1.84 46.816c-.574.188-.953.375-1.715.563zm0 0" fill="#e88e3d"/><path d="M22.797 40.426c.57-.375.953-.563 1.144-.938 4.762-2.633 9.524-5.074 13.907-7.52.953-.562 1.715-.562 2.668.188 5.336 4.887 10.859 9.399 16.004 14.285 3.046 2.63 3.812 6.012 2.667 9.582-.953 3.57-3.62 5.641-7.43 6.204-2.476.375-4.952-.375-6.859-1.88-7.242-6.577-14.48-13.156-22.101-19.921.191.375.191.187 0 0zM.125 22.008c0-4.695-.383-9.207.191-13.528C.886 3.406 5.84.398 11.367.96c4.57.567 8.383 5.263 8 9.774 0 .563-.379 1.13-.953 1.317-5.906 3.195-11.812 6.578-17.91 9.77.191.187 0 0-.379.187zm19.242 20.297c0 4.324.192 8.082 0 12.027-.379 4.7-4.762 8.27-9.336 8.27-4.57 0-8.953-3.383-9.715-7.891-.191-1.316 0-2.258 1.332-3.008 5.336-3.008 10.86-5.828 16.196-8.832.379 0 .761-.187 1.523-.566zm0 0" fill="#5171a5"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="54" xmlns="http://www.w3.org/2000/svg"><path d="M32.707 50.086c-4.18-4.148-9.402.348-13.93 4.324-5.742 5.184-9.746 8.125-13.402 4.668-2.613-2.594-2.438-5.707 0-8.992l2.438 2.25a1.847 1.847 0 0 0 2.261 0L37.406 27.27 26.09 16.03.848 43.344c-.524.691-.524 1.558 0 2.25l2.437 2.418c-4.527 5.36-2.96 10.547 0 13.484 5.918 5.879 12.535.172 17.758-4.496 4.7-4.148 7.66-6.395 9.574-4.492.695.52 1.738.52 2.262-.172.348-.691.348-1.559-.172-2.25zm-8.008-19.188c-.699.692-1.57.692-2.265 0-.696-.691-.696-1.554 0-2.246l2.265-2.246c.696-.691 1.567-.691 2.262 0 .695.692.695 1.555 0 2.246zm14.797-5.875c.348.344.695.516 1.043.516 2.262 0 4.7-.516 6.617-1.727L29.57 6.352c-1.218 2.074-1.738 4.324-1.738 6.57 0 .344.172.863.52 1.035zm10.27-21.261c-5.047-5.016-13.23-5.016-18.278 0L49.766 21.91a12.77 12.77 0 0 0 0-18.148zm0 0" fill="#039"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="75" xmlns="http://www.w3.org/2000/svg"><path d="M.5 19v-4.1c.9-.1 1.6-.2 2-.4.4-.2.8-.6 1.2-1.001.4-.5.5-1.1.7-1.9.1-.6.2-1.499.2-2.799 0-2.201.1-3.7.4-4.6.2-.8.6-1.6 1.2-2 .5-.5 1.4-.9 2.5-1.2.7-.2 1.9-.4 3.5-.4h.9v3.9c-1.3 0-2.2.1-2.6.3-.4.2-.6.4-.9.6-.2.3-.3.7-.3 1.501 0 .8-.1 2-.2 4.099-.101 1.2-.2 2-.4 2.801-.301.6-.6 1.2-1 1.8-.4.4-1 .9-1.8 1.399.7.4 1.3.8 1.8 1.3s.8 1.2 1.1 1.899c.3.702.4 1.802.4 3.001.1 1.9.1 3.1.1 3.599 0 .702.1 1.202.3 1.602.2.4.5.5.9.6.4.2 1.2.3 2.6.3v4.098h-1c-1.6 0-2.9-.1-3.701-.4-.9-.3-1.6-.6-2.2-1.2-.6-.6-.999-1.2-1.2-1.999-.198-.8-.299-2.1-.299-4 0-2-.1-3.5-.3-4.1-.3-.9-.7-1.601-1.201-2-.698-.5-1.5-.7-2.7-.7zm39.1 0c-.9.1-1.6.2-2 .4s-.8.6-1.2 1.001c-.4.5-.5 1.1-.7 1.9-.099.6-.2 1.499-.2 2.799 0 2.201-.1 3.7-.4 4.6-.2.9-.6 1.6-1.2 2-.5.5-1.4.9-2.5 1.2-.7.2-1.9.4-3.5.4h-.999v-4.1c1.298 0 2.1-.1 2.599-.3s.7-.4.899-.6c.2-.3.301-.7.301-1.501 0-.6.1-2 .2-3.999.099-1.2.3-2.1.5-2.8.3-.7.6-1.3 1.1-1.9.4-.5 1-.9 1.7-1.3-.901-.6-1.6-1.1-2-1.6-.5-.7-1-1.801-1.201-2.8-.199-.8-.299-2.6-.299-5.2 0-.8-.1-1.4-.301-1.8-.199-.3-.4-.5-.799-.6-.2-.3-1-.3-2.5-.3v-4h.999c1.602 0 2.9.1 3.7.4.902.3 1.6.6 2.2 1.2.6.6 1.002 1.2 1.2 2 .201.8.402 2.1.402 4 0 2 .098 3.4.299 4.1.299.9.7 1.601 1.2 1.9.5.4 1.401.6 2.5.6.1.1 0 4.3 0 4.3zm0 0" fill="#7058c6" stroke="#7058c6" stroke-miterlimit="10" transform="matrix(1.86825 0 0 1.87558 0 .209)"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="80" xmlns="http://www.w3.org/2000/svg"><path d="M38.027 37.414c-5.011-4.812-9.425-9.223-12.03-19.25H43.64v-7.219H26.195V1.121h-7.617v10.024H.93v7.421h18.047s-.2 1.403-.399 2.606C15.968 30.996 13.164 37.215.93 43.23l2.61 7.418c11.429-6.015 17.444-13.835 20.05-22.257 2.605 6.418 6.816 11.629 11.629 16.441zM61.29 13.352H51.262L33.617 62.879h7.617l5.016-14.836H66.3l5.013 14.836h7.62zm-12.434 27.27 7.622-19.65 7.617 19.852zm0 0" fill="#c93" stroke="#c93" stroke-miterlimit="10" stroke-width="1.5039150000000001"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M21.344 36.297c-1.871 1.527-3.739 2.887-5.61 4.246L4.52 49.211c-.512.34-.852.508-1.36.168A15.884 15.884 0 0 0 .781 48.19c-.511-.171-.68-.511-.68-1.02V17.267c0-.34.34-.852.508-1.02.852-.512 1.7-.851 2.72-1.36.51-.171.85 0 1.19.169 3.06 2.379 6.118 4.757 9.348 7.136 2.547 1.872 5.098 3.91 7.645 5.778l.511-.508C31.367 18.453 40.543 9.449 49.891.44c.507-.507.847-.507 1.527-.34 3.91 1.532 7.816 3.231 11.727 4.758.34.172.507.512.68.852.167.168 0 .508 0 .68v51.316c0 1.188 0 1.188-1.192 1.7-3.738 1.527-7.477 2.886-11.215 4.417-.68.34-1.02.168-1.527-.34-9.348-8.496-18.524-17.504-27.868-26.34-.171-.34-.34-.507-.68-.847zm26.676 8.156V19.984L31.707 32.22zM13.867 32.22c-2.719-2.38-5.437-4.758-8.16-7.309v14.613c2.723-2.378 5.441-4.757 8.16-7.304zm0 0" fill="#999"/></svg> |
| 1 | ||
| 1 | <svg height="63" width="45" xmlns="http://www.w3.org/2000/svg"><path d="M22.686 26.4h.8c0 2.401-.4 4.2-1.2 5.3-.801 1.1-1.8 1.7-3 1.7-1.001 0-1.9-.4-2.8-1.1-.9-.699-1.701-2.7-2.4-5.9l-2-8.9-6.902 15.599h-4.4l9.901-21.2c-.5-2.698-1.2-4.799-1.899-6.098-.701-1.3-1.7-2.002-2.7-2.002-.902 0-1.601.301-2.3 1-.6.7-1 1.701-1.1 3.1h-.8c0-2.299.5-4.1 1.4-5.4.899-1.3 1.898-2 3.2-2 .8 0 1.599.302 2.3 1.002.7.699 1.4 1.799 1.9 3.499.599 1.7 1.4 5.1 2.6 10.3l1.599 7.3c.701 3 1.4 5 2.1 6.1.7 1 1.6 1.5 2.6 1.5 1.9-.1 2.901-1.3 3.101-3.8zm0 0" fill="#066" stroke="#066" stroke-miterlimit="10" transform="matrix(1.87615 0 0 1.85407 0 .073)"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="70" xmlns="http://www.w3.org/2000/svg"><path d="M69.723 24.898c-.336-.851-1.012-1.535-1.688-2.222-.168.687-.336 1.37-.844 2.054L46.098 57.723c-.844 1.199-2.532 1.539-3.88 1.199l-33.75-9.574c-2.023-.512-4.386-1.711-4.554-4.106 0-.851 0-1.195.504-1.535.508-.344 1.016-.344 1.52-.172l31.726 8.89c4.555 1.368 5.902.34 9.277-4.788l19.239-30.09a5.83 5.83 0 0 0 .675-4.957c-.507-1.54-1.855-2.735-3.543-3.246L35.47 1.48c-.676-.171-1.352-.171-2.024-.171v-.172c-4.218-2.563-5.906 2.222-8.101 4.101-.844.684-1.856 1.2-2.196 1.883-.336.684-.168 1.367-.336 1.879-.843 1.883-3.207 4.957-4.386 5.813-.676.515-1.688.683-2.196 1.539-.335.511-.335 1.539-.503 2.222-.676 1.711-2.872 4.617-4.387 5.985-.508.511-1.352.855-1.688 1.539-.34.511-.172 1.539-.675 2.05-1.012 1.711-3.04 4.446-4.559 5.985-.844.855-1.856 1.195-2.191 2.05-.168.34 0 1.028-.168 1.54-.34.855-.676 1.539-.844 2.222C.37 41.141-.137 42.852.03 44.56c.34 4.105 3.375 8.207 7.09 9.234l33.746 9.574c3.207.852 7.09-.683 8.778-3.422l19.402-30.258c1.016-1.367 1.183-3.25.676-4.789zm-38.98-10.941 1.35-2.05c.337-.512 1.18-.856 1.856-.684l22.274 6.324c.675.172.843.855.507 1.371l-1.351 2.05c-.336.512-1.18.856-1.856.684L31.25 15.328c-.676-.172-.844-.687-.508-1.371zm-5.567 8.55 1.347-2.054c.34-.512 1.184-.851 1.86-.683l22.273 6.328c.676.172.844.855.504 1.367l-1.347 2.05c-.34.512-1.184.856-1.856.684L25.68 23.875c-.672-.172-1.012-.855-.504-1.367zm0 0" fill="#963"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><g fill="#bababa"><path d="M34.84 4.973 23.66 16.156a19.478 19.478 0 0 1 10.266 0c.55.184.914.364 1.281.364l5.684-5.68c3.3-3.3 8.8-3.3 12.097 0 3.301 3.297 3.301 8.797 0 12.098L41.074 34.852c-1.101 1.101-2.383 1.836-3.851 2.199-2.746.734-6.047 0-8.246-2.2-1.47-1.464-2.383-3.48-2.383-5.316-.735.367-1.285.735-1.836 1.102l-5.317 5.316c.735 1.832 2.02 3.484 3.485 4.95 2.199 2.199 4.765 3.667 7.699 4.398 4.398 1.101 9.164.55 13.016-1.832 1.28-.735 2.382-1.649 3.3-2.567L59.04 28.805c6.598-6.602 6.598-17.418 0-24.016a17.443 17.443 0 0 0-24.2.184zm0 0"/><path d="M40.156 47.867c-3.847 1.102-7.883.918-11.73-.367l-5.5 5.5c-3.301 3.3-8.801 3.3-12.098 0-3.3-3.297-3.3-8.797 0-12.098l12.098-12.097c1.101-1.102 2.383-1.836 3.851-2.2 2.746-.734 6.047 0 8.246 2.2 1.47 1.465 2.383 3.48 2.383 5.5.551-.368 1.285-.735 1.836-1.102l5.317-5.316c-.735-1.832-2.02-3.485-3.485-4.95-2.199-2.199-4.765-3.667-7.699-4.398-4.398-1.102-9.164-.55-13.016 1.832-1.28.734-2.382 1.649-3.3 2.567L4.96 35.035c-6.598 6.602-6.598 17.414 0 24.016 6.598 6.597 17.414 6.597 24.016 0zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="52" xmlns="http://www.w3.org/2000/svg"><path d="M48.793 26.879h-4.629V18.05C44.164 7.988 35.973.043 26 .043S7.836 8.164 7.836 18.051v8.828H3.207A3.181 3.181 0 0 0 0 30.059V60.78c0 1.762 1.426 3.176 3.207 3.176h45.586c1.781 0 3.207-1.414 3.207-3.176V29.883c0-1.59-1.426-3.004-3.207-3.004zM29.918 52.305c.355 1.058-.535 1.941-1.602 1.941h-4.808c-1.07 0-1.781-1.059-1.606-1.941l1.426-5.649c-1.781-.883-3.027-2.648-3.027-4.945 0-3 2.492-5.473 5.52-5.473 3.027 0 5.523 2.473 5.523 5.473 0 2.117-1.246 4.062-3.028 4.945zm5.164-25.426H16.918V18.05c0-4.942 4.098-9.004 9.082-9.004s9.082 4.062 9.082 9.004zm0 0" fill="#999"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="76" xmlns="http://www.w3.org/2000/svg"><path d="M.176 52.977h75.648V64H.176zm0-26.309h75.648v11.02H.176zM.176 0h75.648v11.023H.176zm0 0" fill="#999"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M27.91 64A27.846 27.846 0 0 1 0 36.09C0 20.62 12.445 8 28.445 8.18c15.11.355 27.2 12.441 27.2 27.91C55.645 51.555 43.199 64 27.91 64zm11.38-47.645c-4.446 0-8.356 3.91-8.356 8.356 0 4.445 3.554 8.355 8.355 8.355 4.445 0 8.356-3.554 8.356-8.355 0-4.621-3.555-8.356-8.356-8.356zm16.355 0c-4.446 0-8.356-3.554-8-8.355 0-4.445 3.554-8 8.355-8 4.445 0 8 3.91 8 8.355 0 4.446-3.91 8-8.355 8zm0 0" fill="navy"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="83" height="63"><path style="stroke:none;fill-rule:nonzero;fill:#999;fill-opacity:1" d="M.125 0h69.586v8.184H.125zm13.164 18.273h69.586v8.18H13.289zM.125 36.543h69.586v8.184H.125zm13.164 18.273h69.586V63H13.289zm0 0"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M.238 64h83.524V0H.238zm16.16-4.91H6.41V52h9.988zm30.688 0h-9.988V52h9.988zM67.602 4.363h9.988v7.274h-9.988zm0 47.453h9.988v7.094h-9.988zM52.168 4.363h9.805v7.09h-9.985v-7.09zm0 47.453h9.805v7.094h-9.985zM36.914 4.363h9.988v7.09h-9.988zM35.464 22l13.071 7.453c2.363 1.457 2.363 3.637 0 5.094L35.465 42c-2.363 1.453-4.36.184-4.36-2.547v-15.09c0-2.547 1.997-3.816 4.36-2.363zM21.485 4.363h9.805v7.09h-9.805zm0 47.453h9.805v7.094h-9.805zM6.41 4.363h9.988v7.274H6.41zm0 0" fill="#f60"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="83" height="63"><path style="stroke:none;fill-rule:nonzero;fill:#039;fill-opacity:1" d="M4.059 10.39h40.254c2.109 0 3.69-1.613 3.69-3.761 0-2.149-1.581-3.758-3.69-3.758H4.059c-2.11 0-3.692 1.61-3.692 3.758 0 2.152 1.582 3.762 3.692 3.762zm0 19.891h40.254c2.109 0 3.69-1.613 3.69-3.765 0-2.149-1.581-3.762-3.69-3.762H4.059c-2.11 0-3.692 1.613-3.692 3.762 0 2.148 1.582 3.765 3.692 3.765zm19.336 10.57H4.059c-2.11 0-3.692 1.614-3.692 3.762 0 2.149 1.582 3.766 3.692 3.766h19.336c2.109 0 3.69-1.617 3.69-3.766 0-2.148-1.581-3.761-3.69-3.761zm0 0"/><path style="stroke:none;fill-rule:nonzero;fill:#039;fill-opacity:1" d="M70.68 9.496c-2.813-1.434-6.504-3.582-7.91-6.629C62.77 1.254 61.54 0 59.957 0c-1.582 0-2.812 1.254-2.812 2.867v38.52c-2.989-1.614-8.614-1.075-12.833 1.433-6.68 3.766-9.492 10.93-6.68 15.766 2.813 4.84 10.723 5.914 17.4 2.152 4.573-2.687 7.738-6.988 7.913-11.289V16.305c9.492 0 15.29 3.941 13.18 13.437-.352 1.793-1.05 3.403-1.754 5.195-.355.54-.355 1.254.176 1.793.527.536 1.402.356 2.11-.359 3.515-3.582 5.796-8.242 5.976-13.437-.18-6.805-6.508-10.75-11.953-13.438zm0 0"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="83" height="63"><path style="stroke:none;fill-rule:nonzero;fill:#039;fill-opacity:1" d="M4.059 10.39h40.254c2.109 0 3.69-1.613 3.69-3.761 0-2.149-1.581-3.758-3.69-3.758H4.059c-2.11 0-3.692 1.61-3.692 3.758 0 2.152 1.582 3.762 3.692 3.762zm0 19.891h40.254c2.109 0 3.69-1.613 3.69-3.765 0-2.149-1.581-3.762-3.69-3.762H4.059c-2.11 0-3.692 1.613-3.692 3.762 0 2.148 1.582 3.765 3.692 3.765zm19.336 10.57H4.059c-2.11 0-3.692 1.614-3.692 3.762 0 2.149 1.582 3.766 3.692 3.766h19.336c2.109 0 3.69-1.617 3.69-3.766 0-2.148-1.581-3.761-3.69-3.761zm0 0"/><path style="stroke:none;fill-rule:nonzero;fill:#039;fill-opacity:1" d="M70.68 9.496c-2.813-1.434-6.504-3.582-7.91-6.629C62.77 1.254 61.54 0 59.957 0c-1.582 0-2.812 1.254-2.812 2.867v38.52c-2.989-1.614-8.614-1.075-12.833 1.433-6.68 3.766-9.492 10.93-6.68 15.766 2.813 4.84 10.723 5.914 17.4 2.152 4.573-2.687 7.738-6.988 7.913-11.289V16.305c9.492 0 15.29 3.941 13.18 13.437-.352 1.793-1.05 3.403-1.754 5.195-.355.54-.355 1.254.176 1.793.527.536 1.402.356 2.11-.359 3.515-3.582 5.796-8.242 5.976-13.437-.18-6.805-6.508-10.75-11.953-13.438zm0 0"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="m60.137 40.719-.184-.36-.36-.359c0-5.395-3.234-10.066-7.73-12.406-.539-1.977-.18-2.696-.18-2.696.18-.18.18-.539.364-.718h4.672c1.078 0 2.156-.36 2.875-1.258 2.52-2.516 3.777-5.754 3.777-9.348 0-6.652-4.676-12.047-11.144-12.945-.364 0-.723-.18-1.082-.18h-37.57C6.382.45.448 6.383.448 13.574c0 .54 0 1.078.18 1.797.36 12.223 9.527 22.113 14.383 26.606H5.664c-1.437 0-2.879.718-3.418 2.16C1.168 46.113.45 48.27.45 50.426c0 7.191 5.934 13.125 13.125 13.125h37.93c6.832-.719 12.047-6.473 12.047-13.125-.18-3.414-1.438-7.192-3.414-9.707M51.145 4.586c4.675.539 8.449 4.312 8.449 9.348 0 2.695-1.078 4.851-2.875 6.652H22.563c1.437-1.98 2.335-4.137 2.335-6.652 0-3.778-1.976-7.192-4.671-9.348zM4.227 50.426c0-1.617.539-3.235 1.257-4.313h15.82c.72 1.438 1.259 2.875 1.259 4.313 0 5.035-4.137 9.168-9.348 9.168-5.215 0-8.988-4.313-8.988-9.168m46.918 9.168H19.863c3.059-2.156 4.856-5.39 4.856-9.348 0-3.773-1.977-7.191-4.672-9.348h.18S4.766 29.395 4.586 14.832c0-.539-.18-.898-.18-1.437 0-5.036 4.133-9.348 9.348-9.348 5.21 0 9.348 4.133 9.348 9.348v.539c0 .898-.18 1.796-.54 2.515-.359 1.078-.898 1.977-1.617 2.875l-2.34 3.239H48.63c0 .18-.18.359-.36.539-.539 1.078-.718 2.156-.718 3.234-.54 0-1.258-.18-1.977-.18-7.55 0-13.844 6.114-13.844 13.844s6.114 13.844 13.844 13.844c5.57 0 10.426-3.239 12.582-8.27.719 1.617 1.258 3.235 1.258 4.852.18 4.676-3.594 8.808-8.27 9.168M51.685 40l-9.168 6.832V32.988zm0 0" fill="#999" stroke="#999" stroke-miterlimit="10" stroke-width=".898875"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><g fill="#039"><path d="M.324 12.07C-.777 14.828 1.43 23.102 1.43 23.102c4.226 11.77 14.156 21.882 14.156 21.882 9.746 10.114 19.492 16.364 28.133 18.387 8.64 2.02 10.297-1.473 10.297-1.473s7.168-6.988 9.191-9.375c2.023-2.574-.55-4.046-.55-4.046s-12.505-7.54-14.524-8.274c-2.024-.918-3.13.55-4.414 1.656-1.29 1.102-3.864 3.493-3.864 3.493-1.468.183-4.226-.918-8.64-4.414C26.8 37.444 21.469 30.823 20 28.434c-1.473-2.204-1.473-4.594-1.473-4.594s1.84-1.473 3.68-3.496c1.836-2.02 1.285-3.86 1.285-3.86l-5.699-10.48C14.301-1.352 13.379.12 13.379.12c-2.39.918-4.41 2.758-5.7 4.043-.917.922-5.882 5.149-7.355 7.906zM49.97 27.7c1.472 0 2.758-1.102 2.758-2.759 0-8.09-6.618-15.078-15.075-15.078-1.472 0-2.761 1.106-2.761 2.758 0 1.473 1.105 2.762 2.761 2.762 5.145 0 9.375 4.226 9.375 9.375 0 1.656 1.473 2.941 2.942 2.941zm0 0"/><path d="M38.938 1.223c-1.473 0-2.758 1.105-2.758 2.757 0 1.473 1.101 2.758 2.757 2.758a16.87 16.87 0 0 1 16.915 16.918c0 1.469 1.105 2.758 2.757 2.758 1.657 0 2.762-1.105 2.762-2.758 0-12.32-10.113-22.433-22.434-22.433zm-3.676 16.363c-1.473 0-2.758 1.105-2.758 2.758 0 1.656 1.101 2.758 2.758 2.758 2.39 0 4.41 2.023 4.41 4.414 0 1.472 1.105 2.757 2.758 2.757 1.472 0 2.757-1.101 2.757-2.757-.183-5.516-4.593-9.93-9.925-9.93zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M.238 64h83.524V0H.238zm16.16-4.91H6.41V52h9.988zm30.688 0h-9.988V52h9.988zM67.602 4.363h9.988v7.274h-9.988zm0 47.453h9.988v7.094h-9.988zM52.168 4.363h9.805v7.09h-9.985v-7.09zm0 47.453h9.805v7.094h-9.985zM36.914 4.363h9.988v7.09h-9.988zM35.464 22l13.071 7.453c2.363 1.457 2.363 3.637 0 5.094L35.465 42c-2.363 1.453-4.36.184-4.36-2.547v-15.09c0-2.547 1.997-3.816 4.36-2.363zM21.485 4.363h9.805v7.09h-9.805zm0 47.453h9.805v7.094h-9.805zM6.41 4.363h9.988v7.274H6.41zm0 0" fill="#f60"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><g fill="#999"><path d="M56.797 45.254c-.356-.531-.711-.707-1.242-.707H38.91c-.531 1.238-1.238 2.297-1.77 3.535-1.417 2.828-3.011 5.832-4.425 8.305v.18c-.887 1.413-2.305 2.472-4.074 2.472s-3.188-.883-4.07-2.473c-.532-.886-2.305-4.242-4.43-8.484-.707-1.238-1.239-2.473-1.77-3.71H9.34c-.531 0-1.063.35-1.414.882L.133 61.69c-.176.528-.176 1.059 0 1.414.355.528.707.708 1.238.708h46.215c.531 0 1.062-.356 1.418-.887l7.793-16.258c.351-.352.176-1.059 0-1.414zm0 0"/><path d="M28.465.188c-9.387 0-17.176 7.601-17.176 17.144 0 5.656 6.195 19.086 11.332 29.512 2.48 4.773 4.426 8.308 4.426 8.484.355.531.71.883 1.418.883.707 0 1.062-.352 1.414-.883 0 0 1.95-3.535 4.43-8.484 5.132-10.25 11.332-23.68 11.332-29.512C45.64 7.789 37.848.187 28.465.187zm0 27.57c-4.25 0-7.969-3.356-8.324-7.598v-.883c0-4.597 3.718-8.308 8.324-8.308 4.25 0 7.969 3.36 8.32 7.422v.886c0 4.594-3.719 8.48-8.32 8.48zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M64 32c0 17.645-14.355 32-32 32S0 49.645 0 32 14.355 0 32 0s32 14.355 32 32" fill="#999"/><g fill="#fff"><path d="M54.313 34.422c-1.036-6.746-8.13-11.242-13.493-14.531-2.246-1.383-6.054-3.286-6.57-6.399-.176-1.21-.176-2.594-.176-3.805V8.13c0-.692-.691.172-1.035-.344-.867-1.387-.52.344-.52 1.211.172 1.727.52 3.457.52 5.188 0 3.285-.52 6.574-1.387 9.687-1.902 7.438-3.457 15.223-1.554 22.832a24.518 24.518 0 0 0 1.554 4.668c.176.52.52 1.73 1.211 1.906 2.078.516 3.633.692 5.192 2.246 1.039.868 1.73.348 2.941 0 3.633-1.382 6.746-3.285 9.34-6.226 3.285-4.496 4.844-9.512 3.977-14.875m-3.805 6.746c-.344 2.766-2.074 5.363-3.805 7.437-1.383 1.56-3.113 3.461-5.016 4.153-.69.172.172-1.211.172-1.211.52-.867 1.383-1.73 2.075-2.594 1.039-1.21 1.902-2.598 2.421-3.98 1.903-5.016 1.56-10.899-1.382-15.395-1.555-2.422-3.805-4.496-5.88-6.398-1.038-.868-2.077-1.73-2.94-2.77-.176-.172-2.079-2.594-1.387-2.941.175-.172 4.152 3.98 4.5 4.324 1.554 1.21 3.285 2.422 4.843 3.809 2.075 1.902 4.149 3.976 5.36 6.57 1.21 2.77 1.386 6.055 1.039 8.996"/><path d="M30.79.863c.519.348.69 2.77.69 4.844 0 2.078.172 11.246-.52 13.664-.69 2.422-2.245 5.192-3.804 7.613-1.73 2.422-3.633 7.438-3.457 10.551 0 3.113 1.903 8.13 3.285 10.38 1.383 2.073 3.805 5.015 3.286 5.706-.864 1.211-4.668-2.941-6.747-5.363-1.902-2.422-3.976-7.262-3.976-11.07 0-3.805 2.074-7.262 3.633-9.34 1.554-2.075 4.496-5.707 5.36-7.438.866-1.73 1.73-3.457 1.901-5.707.348-2.25 0-10.55 0-10.55S30.27.52 30.79.862"/><path d="M29.234 4.844c.516.343.692 1.039.692 1.73 0 .692-.176 3.633-.348 6.57-.172 2.942-2.594 5.364-4.152 7.094-1.727 1.73-6.746 7.09-8.473 9.688-1.906 2.594-2.77 6.05-2.598 8.992.176 2.941.868 5.883 3.633 8.996 2.77 3.113 4.672 4.496 6.227 5.363 1.387.692 2.941 1.211 2.597 1.903-.347.691-1.73.172-3.289-.348-1.554-.52-6.746-2.594-9.687-6.055-2.938-3.457-4.496-7.957-4.324-12.105.175-4.324 1.386-6.055 3.289-8.824 1.902-2.766 7.437-6.918 9.168-7.957 1.73-1.036 3.976-2.766 5.187-4.325 1.211-1.382 1.73-2.593 1.73-4.668 0-1.902.173-3.804 0-4.5-.171-.515-.171-1.902.348-1.554m.172 51.89c.344 0 .172 1.211-.347 1.73-.52.52-1.211.864-1.383.692s.52-.343 1.039-.863c.52-.691.344-1.559.691-1.559m5.36-.172c-.344 0-.172 1.211.347 1.731s1.211.863 1.383.691c.176-.172-.52-.347-1.035-.867-.52-.515-.348-1.554-.695-1.554m-2.418 1.382c0 1.04 0 1.903-.176 1.903-.344 0-.172-.864-.172-1.903 0-1.039-.172-1.902.172-1.902.348 0 .176.863.176 1.902"/></g></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="84" height="39"><path style="stroke:none;fill-rule:nonzero;fill:#999;fill-opacity:1" d="M0 38.824V.176h11.2l11.198 14.183L33.602.176H44.8v38.648H33.6v-22.16l-11.203 14.18-11.195-14.18v22.16zm67.2 0L50.397 20.031h11.204V.176h11.195V20.03H84zm0 0"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="67" xmlns="http://www.w3.org/2000/svg"><path d="M66.824 40.465c-.176 1.59-2.097 2.824-5.945 3.707-3.852.879-8.75 1.41-14.52 1.41h-4.898v9.172c1.574.176 3.324.176 4.898.176 5.77 0 10.668-.528 14.52-1.586 3.848-1.059 5.945-2.293 6.121-3.707-.176-.352-.176-9.172-.176-9.172zm-20.64-6.7c-1.75 0-3.325 0-4.899-.18v9.352h4.899c5.773 0 10.671-.53 14.52-1.59s5.944-2.292 5.944-3.702v-8.997c-.171 1.586-2.097 2.825-6.12 3.704-3.673 1.058-8.571 1.59-14.344 1.414zm0-11.468c-1.75 0-3.325 0-4.899-.176v9.352c1.574.175 3.324.175 4.899.175 5.773 0 10.671-.53 14.695-1.59C64.727 29 66.824 27.767 67 26.356V17.36c-.176 1.59-2.098 2.825-6.121 3.704-4.024.707-8.922 1.234-14.695 1.234zm0-13.05c-1.75 0-3.325 0-4.899.175v10.406c1.574.176 3.324.176 4.899.176 5.773 0 10.671-.527 14.695-1.586 3.848-1.059 5.945-2.293 6.121-3.703-.176-1.59-2.098-2.824-6.121-3.883-4.024-1.055-8.922-1.41-14.695-1.586zM18.02 23.886c-.176.527-.528 2.293-1.227 5.293l-1.223 5.113h5.07l-1.222-5.113c-.7-3-1.227-4.766-1.227-5.293zM0 7.129v49.918l37.785 6.527V.426zm23.09 37.219-1.399-5.645-6.996-.176-1.398 5.29-4.375-.352 6.648-23.813 5.07-.351 7.348 25.222zm0 0" fill="#a03537"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M21.344 36.297c-1.871 1.527-3.739 2.887-5.61 4.246L4.52 49.211c-.512.34-.852.508-1.36.168A15.884 15.884 0 0 0 .781 48.19c-.511-.171-.68-.511-.68-1.02V17.267c0-.34.34-.852.508-1.02.852d5006e"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="76" xmlns="http://www.w3.org/2000/svg"><path d="M.176 52.977h75.648V64H.176zm0-26.309h75.648v11.02H.176zM.176 0h75.648v11.023H.176zm0 0" fill="#999"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M64 32c0 17.645-14.355 32-32 32S0 49.645 0 32 14.355 0 32 0s32 14.355 32 32" fill="#999"/><g fill="#fff"><path d="M54.313 34.422c-1.036-6.746-8.13-11.242-13.493-14.531-2.246-1.383-6.054-3.286-6.57-6.399-.176-1.21-.176-2.594-.176-3.805V8.13c0-.692-.691.172-1.035-.344-.867-1.387-.52.344-.52 1.211.172 1.727.52 3.457.52 5.188 0 3.285-.52 6.574-1.387 9.687-1.902 7.438-3.457 15.223-1.554 22.832a24.518 24.518 0 0 0 1.554 4.668c.176.52.52 1.73 1.211 1.906 2.078.516 3.633.692 5.192 2.246 1.039.868 1.73.348 2.941 0 3.633-1.382 6.746-3.285 9.34-6.226 3.285-4.496 4.844-9.512 3.977-14.875m-3.805 6.746c-.344 2.766-2.074 5.363-3.805 7.437-1.383 1.56-3.113 3.461-5.016 4.153-.69.172.172-1.211.172-1.211.52-.867 1.383-1.73 2.075-2.594 1.039-1.21 1.902-2.598 2.421-3.98 1.903-5.016 1.56-10.899-1.382-15.395-1.555-2.422-3.805-4.496-5.88-6.398-1.038-.868-2.077-1.73-2.94-2.77-.176-.172-2.079-2.594-1.387-2.941.175-.172 4.152 3.98 4.5 4.324 1.554 1.21 3.285 2.422 4.843 3.809 2.075 1.902 4.149 3.976 5.36 6.57 1.21 2.77 1.386 6.055 1.039 8.996"/><path d="M30.79.863c.519.348.69 2.77.69 4.844 0 2.078.172 11.246-.52 13.664-.69 2.422-2.245 5.192-3.804 7.613-1.73 2.422-3.633 7.438-3.457 10.551 0 3.113 1.903 8.13 3.285 10.38 1.383 2.073 3.805 5.015 3.286 5.706-.864 1.211-4.668-2.941-6.747-5.363-1.902-2.422-3.976-7.262-3.976-11.07 0-3.805 2.074-7.262 3.633-9.34 1.554-2.075 4.496-5.707 5.36-7.438.866-1.73 1.73-3.457 1.901-5.707.348-2.25 0-10.55 0-10.55S30.27.52 30.79.862"/><path d="M29.234 4.844c.516.343.692 1.039.692 1.73 0 .692-.176 3.633-.348 6.57-.172 2.942-2.594 5.364-4.152 7.094-1.727 1.73-6.746 7.09-8.473 9.688-1.906 2.594-2.77 6.05-2.598 8.992.176 2.941.868 5.883 3.633 8.996 2.77 3.113 4.672 4.496 6.227 5.363 1.387.692 2.941 1.211 2.597 1.903-.347.691-1.73.172-3.289-.348-1.554-.52-6.746-2.594-9.687-6.055-2.938-3.457-4.496-7.957-4.324-12.105.175-4.324 1.386-6.055 3.289-8.824 1.902-2.766 7.437-6.918 9.168-7.957 1.73-1.036 3.976-2.766 5.187-4.325 1.211-1.382 1.73-2.593 1.73-4.668 0-1.902.173-3.804 0-4.5-.171-.515-.171-1.902.348-1.554m.172 51.89c.344 0 .172 1.211-.347 1.73-.52.52-1.211.864-1.383.692s.52-.343 1.039-.863c.52-.691.344-1.559.691-1.559m5.36-.172c-.344 0-.172 1.211.347 1.731s1.211.863 1.383.691c.176-.172-.52-.347-1.035-.867-.52-.515-.348-1.554-.695-1.554m-2.418 1.382c0 1.04 0 1.903-.176 1.903-.344 0-.172-.864-.172-1.903 0-1.039-.172-1.902.172-1.902.348 0 .176.863.176 1.902"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="79" xmlns="http://www.w3.org/2000/svg"><path d="m42.852 35.445 4.695 1.344 2.851-10.418-4.695-1.344c0-1.68-.168-3.359-.672-5.039l4.192-2.52-5.364-9.405-4.359 2.519a18.036 18.036 0 0 0-4.023-3.023l1.34-4.704L26.421 0l-1.34 4.703c-1.676 0-3.352.168-5.027.672l-2.516-4.2-9.387 5.376 2.512 4.199a18.053 18.053 0 0 0-3.016 4.031l-4.695-1.343L.105 23.852l4.692 1.343c0 1.68.168 3.36.672 5.04l-4.192 2.523 5.364 9.406 4.191-2.52a18.126 18.126 0 0 0 4.023 3.024l-1.34 4.703 10.395 2.856 1.34-4.704c1.676 0 3.352-.168 5.031-.671l2.512 4.199 9.39-5.375-2.515-4.2c1.172-1.175 2.348-2.519 3.184-4.03zm-25.985-5.547c-2.68-4.535-1.004-10.414 3.52-13.101 4.527-2.688 10.394-1.008 13.078 3.527 2.683 4.535 1.004 10.414-3.52 13.106-4.527 2.687-10.394 1.175-13.078-3.532zm50.63 33.262 6.034-3.527-1.676-2.856c.84-.84 1.508-1.68 2.012-2.687l3.184.84 1.844-6.887-3.184-.84c0-1.176-.168-2.183-.504-3.36l2.852-1.679-3.52-6.047-2.852 1.68c-.84-.84-1.675-1.512-2.683-2.016l.84-3.191-6.875-1.852-.836 3.196c-1.176 0-2.18.168-3.356.504l-1.675-2.86-5.7 3.7 1.676 2.855c-.836.84-1.508 1.68-2.012 2.687l-3.183-1.007-1.844 6.886 3.184.84c0 1.176.168 2.184.504 3.36l-2.852 1.68 3.523 6.046 2.848-1.68c.84.84 1.676 1.512 2.684 2.016l-.84 3.191L61.965 64l.836-3.191c1.176 0 2.18-.168 3.355-.504-.336 0 1.34 2.855 1.34 2.855zM57.101 50.563c-1.676-3.024-.668-6.887 2.347-8.567 3.02-1.68 6.875-.672 8.551 2.352 1.676 3.023.672 6.886-2.348 8.566-3.015 1.68-6.875.672-8.55-2.352zm0 0" fill="#999"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M.238 64h83.524V0H.238zm16.16-4.91H6.41V52h9.988zm30.688 0h-9.988V52h9.988zM67.602 4.363h9.988v7.274h-9.988zm0 47.453h9.988v7.094h-9.988zM52.168 4.363h9.805v7.09h-9.985v-7.09zm0 47.453h9.805v7.094h-9.985zM36.914 4.363h9.988v7.09h-9.988zM35.464 22l13.071 7.453c2.363 1.457 2.363 3.637 0 5.094L35.465 42c-2.363 1.453-4.36.184-4.36-2.547v-15.09c0-2.547 1.997-3.816 4.36-2.363zM21.485 4.363h9.805v7.09h-9.805zm0 47.453h9.805v7.094h-9.805zM6.41 4.363h9.988v7.274H6.41zm0 0" fill="#f60"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="83" height="63"><path style="stroke:none;fill-rule:nonzero;fill:#999;fill-opacity:1" d="M.125 0h69.586v8.184H.125zm13.164 18.273h69.586v8.18H13.289zM.125 36.543h69.586v8.184H.125zm13.164 18.273h69.586V63H13.289zm0 0"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M62.14 63.773H1.86a1.627 1.627 0 0 1-1.633-1.632V1.859C.227.953.953.227 1.859.227h60.282c.906 0 1.632.726 1.632 1.632v60.282c0 .906-.726 1.632-1.632 1.632zM3.314 59.777c0 .547.363.727.726.727h55.559c.543 0 .726-.363.726-.727V45.434c0-.543-.363-.723-.726-.723H4.223c-.547 0-.727.363-.727.723v14.343zm56.464-56.28H4.223c-.547 0-.727.362-.727.726v36.492c0 .18 0 .363.18.363l11.8-14.707 11.985 7.082 13.434-15.976 19.793 15.43V4.222c0-.547-.364-.727-.91-.727zm-48.476 44.3c2.543 0 4.722 2.176 4.722 4.719s-2.18 4.722-4.722 4.722c-2.54 0-4.719-2-4.719-4.539 0-2.543 2.18-4.902 4.719-4.902zm8.715 3.266h36.496c.543 0 .726.363.726.726v1.637c0 .543-.363.722-.726.722H20.016c-.543 0-.727-.359-.727-.722v-1.637c0-.363.363-.726.727-.726zm0 0" fill="#3c3" stroke="#3c3" stroke-miterlimit="10" stroke-width=".4539"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="80" xmlns="http://www.w3.org/2000/svg"><path d="M38.027 37.414c-5.011-4.812-9.425-9.223-12.03-19.25H43.64v-7.219H26.195V1.121h-7.617v10.024H.93v7.421h18.047s-.2 1.403-.399 2.606C15.968 30.996 13.164 37.215.93 43.23l2.61 7.418c11.429-6.015 17.444-13.835 20.05-22.257 2.605 6.418 6.816 11.629 11.629 16.441zM61.29 13.352H51.262L33.617 62.879h7.617l5.016-14.836H66.3l5.013 14.836h7.62zm-12.434 27.27 7.622-19.65 7.617 19.852zm0 0" fill="#a87c2d" stroke="#a87c2d" stroke-miterlimit="10" stroke-width="1.5039150000000001"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="70" xmlns="http://www.w3.org/2000/svg"><path d="M69.723 24.898c-.336-.851-1.012-1.535-1.688-2.222-.168.687-.336 1.37-.844 2.054L46.098 57.723c-.844 1.199-2.532 1.539-3.88 1.199l-33.75-9.574c-2.023-.512-4.386-1.711-4.554-4.106 0-.851 0-1.195.504-1.535.508-.344 1.016-.344 1.52-.172l31.726 8.89c4.555 1.368 5.902.34 9.277-4.788l19.239-30.09a5.83 5.83 0 0 0 .675-4.957c-.507-1.54-1.855-2.735-3.543-3.246L35.47 1.48c-.676-.171-1.352-.171-2.024-.171v-.172c-4.218-2.563-5.906 2.222-8.101 4.101-.844.684-1.856 1.2-2.196 1.883-.336.684-.168 1.367-.336 1.879-.843 1.883-3.207 4.957-4.386 5.813-.676.515-1.688.683-2.196 1.539-.335.511-.335 1.539-.503 2.222-.676 1.711-2.872 4.617-4.387 5.985-.508.511-1.352.855-1.688 1.539-.34.511-.172 1.539-.675 2.05-1.012 1.711-3.04 4.446-4.559 5.985-.844.855-1.856 1.195-2.191 2.05-.168.34 0 1.028-.168 1.54-.34.855-.676 1.539-.844 2.222C.37 41.141-.137 42.852.03 44.56c.34 4.105 3.375 8.207 7.09 9.234l33.746 9.574c3.207.852 7.09-.683 8.778-3.422l19.402-30.258c1.016-1.367 1.183-3.25.676-4.789zm-38.98-10.941 1.35-2.05c.337-.512 1.18-.856 1.856-.684l22.274 6.324c.675.172.843.855.507 1.371l-1.351 2.05c-.336.512-1.18.856-1.856.684L31.25 15.328c-.676-.172-.844-.687-.508-1.371zm-5.567 8.55 1.347-2.054c.34-.512 1.184-.851 1.86-.683l22.273 6.328c.676.172.844.855.504 1.367l-1.347 2.05c-.34.512-1.184.856-1.856.684L25.68 23.875c-.672-.172-1.012-.855-.504-1.367zm0 0" fill="#963"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M.238 64h83.524V0H.238zm16.16-4.91H6.41V52h9.988zm30.688 0h-9.988V52h9.988zM67.602 4.363h9.988v7.274h-9.988zm0 47.453h9.988v7.094h-9.988zM52.168 4.363h9.805v7.09h-9.985v-7.09zm0 47.453h9.805v7.094h-9.985zM36.914 4.363h9.988v7.09h-9.988zM35.464 22l13.071 7.453c2.363 1.457 2.363 3.637 0 5.094L35.465 42c-2.363 1.453-4.36.184-4.36-2.547v-15.09c0-2.547 1.997-3.816 4.36-2.363zM21.485 4.363h9.805v7.09h-9.805zm0 47.453h9.805v7.094h-9.805zM6.41 4.363h9.988v7.274H6.41zm0 0" fill="#f60"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M.238 64h83.524V0H.238zm16.16-4.91H6.41V52h9.988zm30.688 0h-9.988V52h9.988zM67.602 4.363h9.988v7.274h-9.988zm0 47.453h9.988v7.094h-9.988zM52.168 4.363h9.805v7.09h-9.985v-7.09zm0 47.453h9.805v7.094h-9.985zM36.914 4.363h9.988v7.09h-9.988zM35.464 22l13.071 7.453c2.363 1.457 2.363 3.637 0 5.094L35.465 42c-2.363 1.453-4.36.184-4.36-2.547v-15.09c0-2.547 1.997-3.816 4.36-2.363zM21.485 4.363h9.805v7.09h-9.805zm0 47.453h9.805v7.094h-9.805zM6.41 4.363h9.988v7.274H6.41zm0 0" fill="#f60"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="67" xmlns="http://www.w3.org/2000/svg"><g fill="#999"><path d="M0 7.336 37.754.008v63.984L0 57.02zm0 0"/><path d="M64.164 57.734H32.082c-1.594 0-2.836-1.25-2.836-2.859V9.305c0-1.61 1.242-2.864 2.836-2.864h32.082C65.758 6.441 67 7.695 67 9.305v45.57c0 1.61-1.242 2.86-2.836 2.86zM32.082 9.125c-.176 0-.355.18-.355.355v45.575c0 .18.18.36.355.36h32.082c.176 0 .356-.18.356-.36V9.305c0-.18-.18-.36-.356-.36 0 .18-32.082.18-32.082.18zm0 0"/><path d="M59.555 34.324H55.3V19.313H35.629v-4.29h23.926zm0 0"/><path d="m57.25 38.078-7.621-8.402h15.066zM37.719 42.578l8.144-8.215 8.149 8.215-8.149 8.215zm0 0"/></g><path d="M23.574 22.348c-.71-.715-1.418-1.07-2.48-1.43-.887-.355-2.13-.176-3.192-.176-2.129 0-5.847.356-5.847.356l-.18 20.73 3.898.36v-7.329s2.305.36 4.254-.18c1.067-.355 2.13-.89 2.66-1.429.711-.715 1.243-1.43 1.594-2.145.535-1.07.711-2.144.711-3.753.356-1.965-.176-3.75-1.418-5.004zm-3.012 7.148c-.71 1.61-2.66 1.61-2.66 1.61h-2.129v-6.614s1.418-.176 2.485 0c.531.18 1.062.36 1.418.54 1.062.89 1.594 3.034.886 4.464zm0 0" fill="#fff"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M.238 64h83.524V0H.238zm16.16-4.91H6.41V52h9.988zm30.688 0h-9.988V52h9.988zM67.602 4.363h9.988v7.274h-9.988zm0 47.453h9.988v7.094h-9.988zM52.168 4.363h9.805v7.09h-9.985v-7.09zm0 47.453h9.805v7.094h-9.985zM36.914 4.363h9.988v7.09h-9.988zM35.464 22l13.071 7.453c2.363 1.457 2.363 3.637 0 5.094L35.465 42c-2.363 1.453-4.36.184-4.36-2.547v-15.09c0-2.547 1.997-3.816 4.36-2.363zM21.485 4.363h9.805v7.09h-9.805zm0 47.453h9.805v7.094h-9.805zM6.41 4.363h9.988v7.274H6.41zm0 0" fill="#f60"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M.238 64h83.524V0H.238zm16.16-4.91H6.41V52h9.988zm30.688 0h-9.988V52h9.988zM67.602 4.363h9.988v7.274h-9.988zm0 47.453h9.988v7.094h-9.988zM52.168 4.363h9.805v7.09h-9.985v-7.09zm0 47.453h9.805v7.094h-9.985zM36.914 4.363h9.988v7.09h-9.988zM35.464 22l13.071 7.453c2.363 1.457 2.363 3.637 0 5.094L35.465 42c-2.363 1.453-4.36.184-4.36-2.547v-15.09c0-2.547 1.997-3.816 4.36-2.363zM21.485 4.363h9.805v7.09h-9.805zm0 47.453h9.805v7.094h-9.805zM6.41 4.363h9.988v7.274H6.41zm0 0" fill="#f60"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M.238 64h83.524V0H.238zm16.16-4.91H6.41V52h9.988zm30.688 0h-9.988V52h9.988zM67.602 4.363h9.988v7.274h-9.988zm0 47.453h9.988v7.094h-9.988zM52.168 4.363h9.805v7.09h-9.985v-7.09zm0 47.453h9.805v7.094h-9.985zM36.914 4.363h9.988v7.09h-9.988zM35.464 22l13.071 7.453c2.363 1.457 2.363 3.637 0 5.094L35.465 42c-2.363 1.453-4.36.184-4.36-2.547v-15.09c0-2.547 1.997-3.816 4.36-2.363zM21.485 4.363h9.805v7.09h-9.805zm0 47.453h9.805v7.094h-9.805zM6.41 4.363h9.988v7.274H6.41zm0 0" fill="#f60"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="67" xmlns="http://www.w3.org/2000/svg"><g fill="#2d7136"><path d="M0 7.336 37.754.008v63.984L0 57.02zm0 0"/><path d="M64.164 57.734H32.082c-1.594 0-2.836-1.25-2.836-2.859V9.305c0-1.61 1.242-2.864 2.836-2.864h32.082C65.758 6.441 67 7.695 67 9.305v45.57c0 1.61-1.242 2.86-2.836 2.86zM32.082 9.125c-.176 0-.355.18-.355.355v45.575c0 .18.18.36.355.36h32.082c.176 0 .356-.18.356-.36V9.305c0-.18-.18-.36-.356-.36 0 .18-32.082.18-32.082.18zm0 0"/><path d="M59.555 34.324H55.3V19.313H35.629v-4.29h23.926zm0 0"/><path d="m57.25 38.078-7.621-8.402h15.066zM37.719 42.578l8.144-8.215 8.149 8.215-8.149 8.215zm0 0"/></g><path d="M23.574 22.348c-.71-.715-1.418-1.07-2.48-1.43-.887-.355-2.13-.176-3.192-.176-2.129 0-5.847.356-5.847.356l-.18 20.73 3.898.36v-7.329s2.305.36 4.254-.18c1.067-.355 2.13-.89 2.66-1.429.711-.715 1.243-1.43 1.594-2.145.535-1.07.711-2.144.711-3.753.356-1.965-.176-3.75-1.418-5.004zm-3.012 7.148c-.71 1.61-2.66 1.61-2.66 1.61h-2.129v-6.614s1.418-.176 2.485 0c.531.18 1.062.36 1.418.54 1.062.89 1.594 3.034.886 4.464zm0 0" fill="#fff"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="67" xmlns="http://www.w3.org/2000/svg"><g fill="#2d7136"><path d="M0 7.336 37.754.008v63.984L0 57.02zm0 0"/><path d="M64.164 57.734H32.082c-1.594 0-2.836-1.25-2.836-2.859V9.305c0-1.61 1.242-2.864 2.836-2.864h32.082C65.758 6.441 67 7.695 67 9.305v45.57c0 1.61-1.242 2.86-2.836 2.86zM32.082 9.125c-.176 0-.355.18-.355.355v45.575c0 .18.18.36.355.36h32.082c.176 0 .356-.18.356-.36V9.305c0-.18-.18-.36-.356-.36 0 .18-32.082.18-32.082.18zm0 0"/><path d="M59.555 34.324H55.3V19.313H35.629v-4.29h23.926zm0 0"/><path d="m57.25 38.078-7.621-8.402h15.066zM37.719 42.578l8.144-8.215 8.149 8.215-8.149 8.215zm0 0"/></g><path d="M23.574 22.348c-.71-.715-1.418-1.07-2.48-1.43-.887-.355-2.13-.176-3.192-.176-2.129 0-5.847.356-5.847.356l-.18 20.73 3.898.36v-7.329s2.305.36 4.254-.18c1.067-.355 2.13-.89 2.66-1.429.711-.715 1.243-1.43 1.594-2.145.535-1.07.711-2.144.711-3.753.356-1.965-.176-3.75-1.418-5.004zm-3.012 7.148c-.71 1.61-2.66 1.61-2.66 1.61h-2.129v-6.614s1.418-.176 2.485 0c.531.18 1.062.36 1.418.54 1.062.89 1.594 3.034.886 4.464zm0 0" fill="#fff"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="84" height="60"><path style="fill-rule:nonzero;fill:#1d6fb5;fill-opacity:1;stroke-width:.75;stroke-linecap:butt;stroke-linejoin:miter;stroke:#1d6fb5;stroke-opacity:1;stroke-miterlimit:10" d="M6.274 25.574h28.3l-9.698-9.3-4.501 3.802-4.5-3.802zm34.1-25.2v28.002H.376V.374zM26.976 14.576l10.7 10.298v-19.3zm-24.2 10.298 10.7-10.298-10.7-9.002zm1.4-21.7 15.9 13.4 15.9-13.4zm0 0" transform="matrix(2.06135 0 0 2.08166 0 .076)"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="74" xmlns="http://www.w3.org/2000/svg"><path d="m49.332 34.941-12.25-5.714L61.75 17.633 74 23.348l-12.25 5.879zM61.75 6.207 49.5.492 37.25 6.207l24.5 11.594L74 12.086zm-37.082 17.14-12.25-5.714-12.25 5.715L24.836 34.94l12.246-5.714zm0-11.429 12.25-5.711L24.668.492 0 12.086 12.25 17.8zM61.75 32.59l-11.074 5.039-1.344.672-1.34-.672-11.074-5.04-11.078 5.04-1.34.672-1.344-.672-11.074-5.04v17.977L36.75 63.508l25-12.942zm0 0" fill="#4d1b9b"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="74" xmlns="http://www.w3.org/2000/svg"><path d="m49.332 34.941-12.25-5.714L61.75 17.633 74 23.348l-12.25 5.879zM61.75 6.207 49.5.492 37.25 6.207l24.5 11.594L74 12.086zm-37.082 17.14-12.25-5.714-12.25 5.715L24.836 34.94l12.246-5.714zm0-11.429 12.25-5.711L24.668.492 0 12.086 12.25 17.8zM61.75 32.59l-11.074 5.039-1.344.672-1.34-.672-11.074-5.04-11.078 5.04-1.34.672-1.344-.672-11.074-5.04v17.977L36.75 63.508l25-12.942zm0 0" fill="#55486d"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="82" xmlns="http://www.w3.org/2000/svg"><g fill="#3c3"><path d="M0 .094v63.812h82V.094zM77.34 4.8v27.86L57.773 17.6 36.34 39.247l-15.094-8.469L4.844 43.953V4.801zm0 0"/><path d="M22.55 17.223c0 3.222-2.585 5.836-5.777 5.836-3.191 0-5.777-2.614-5.777-5.836s2.586-5.836 5.777-5.836c3.192 0 5.778 2.613 5.778 5.836zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><g fill="#ff0021"><path d="M49.453.188h-14.45V64h14.45c7.883 0 14.453-6.383 14.453-14.453V14.453C63.906 6.57 57.523.188 49.453.188zm0 41.289c-4.129 0-7.508-3.375-7.508-7.508 0-4.13 3.38-7.504 7.508-7.504s7.508 3.375 7.508 7.504c0 4.133-3.379 7.508-7.508 7.508zM31.437 64h-16.89C6.664 64 .094 57.617.094 49.547V14.453C.094 6.383 6.477 0 14.547 0h16.89zM14.547 3.941c-5.82 0-10.7 4.692-10.7 10.7v35.093c0 5.82 4.692 10.7 10.7 10.7H27.87V3.94zm0 0"/><path d="M15.672 26.465c-4.129 0-7.508-3.38-7.508-7.508 0-4.129 3.379-7.508 7.508-7.508s7.508 3.38 7.508 7.508c0 4.129-3.38 7.508-7.508 7.508zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="66" xmlns="http://www.w3.org/2000/svg"><g fill="#bababa" stroke-miterlimit="10"><path d="M58 47.3v4.2H14.4v-4.2m43.2 10.1V61.6H14V57.4M57.6 68v4.1H14V68M57.6 78.5v4.2H14v-4.2" stroke="#bababa" transform="matrix(1.46667 0 0 1.48837 -19.8 -64.744)"/><path d="M29.8 60.9v-1.8c.5-.2 1.2-.399 2.2-.7.9-.3 1.8-.4 2.799-.599 1.001-.202 2-.302 2.9-.402.9-.1 1.8-.2 2.602-.2l.898.602-4.8 22.8h3.7v1.9c-.4.298-.999.6-1.598.9-.602.299-1.3.498-2 .8-.7.3-1.401.399-2.102.499-.7.1-1.398.199-2 .199-1.398 0-2.2-.3-2.799-.798-.4-.501-.6-1.102-.6-1.7 0-.701.1-1.402.2-2.1.099-.7.299-1.402.4-2.202L33.2 61.7zm4.5-11.999c0-1.202.4-2.202 1.2-2.8.801-.7 1.8-1 3.1-1 1.4 0 2.4.3 3.2 1 .8.698 1.2 1.598 1.2 2.8 0 1.1-.4 2.1-1.2 2.698-.8.701-1.9 1-3.2 1-1.2 0-2.2-.299-3.1-1-.701-.598-1.2-1.498-1.2-2.698zm0 0" stroke="#fff" stroke-width="3" transform="matrix(1.46667 0 0 1.48837 -19.8 -64.744)"/></g></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="83" height="63"><path style="stroke:none;fill-rule:nonzero;fill:#666;fill-opacity:1" d="M.125 0h69.586v8.184H.125zm13.164 18.273h69.586v8.18H13.289zM.125 36.543h69.586v8.184H.125zm13.164 18.273h69.586V63H13.289zm0 0"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M54.633 9.367C42.145-3.12 21.855-3.12 9.367 9.367s-12.488 32.778 0 45.266 32.778 12.488 45.266 0 12.488-32.778 0-45.266zM12.176 44.801c-5.934-9.211-4.84-21.543 3.12-29.504s20.294-9.055 29.505-3.121zm7.023 7.023L51.824 19.2c5.934 9.211 4.84 21.543-3.12 29.504s-20.294 9.055-29.505 3.121zm0 0" fill="#bababa"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M60.887 19.578c2.941-7.27 3.285-13.152-.348-16.789C56.56-1.19 46.867.02 36.656 4.867h-1.21c-7.27 0-14.192 2.598-19.383 7.27-4.325 3.98-7.614 9.172-9 15.054 1.039-1.21 6.578-7.789 12.98-11.421.172 0 1.73-1.04 1.73-1.04-.171 0-3.289 2.942-3.808 3.637C3.949 32.73-4.184 54.535 2.219 60.937c4.152 4.153 11.765 3.29 20.593-1.558 3.81 1.73 7.961 2.598 12.633 2.598 6.059 0 11.594-1.559 16.442-4.848 5.02-3.285 8.652-8.133 10.73-14.016H47.04c-2.074 3.809-6.574 6.403-11.422 6.403-6.746 0-12.457-5.54-12.633-11.942v-.52h40.844v-.863c0-1.039.172-2.25.172-2.941 0-4.848-1.04-9.52-3.113-13.672zM6.719 59.555c-3.29-3.29-2.25-9.348 1.554-16.79 1.735 5.02 4.848 9.348 8.657 12.633 1.21 1.04 2.593 2.079 3.98 2.77-6.406 3.46-11.598 3.98-14.191 1.387zm41.015-30.461H23.332v-.172c.344-6.23 6.23-11.594 12.98-11.594 6.403 0 11.594 5.02 11.938 11.594v.172zM59.848 18.02c-1.211-2.079-2.77-3.98-4.672-5.54a29.6 29.6 0 0 0-9.692-6.054c6.403-2.942 11.766-3.461 14.536-.52 2.421 2.422 2.25 6.75-.172 12.114 0 .171 0 .171 0 0zm0 0" fill="#999"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><g fill="#a03537"><path d="M38.684 63.957c-8.098-.34-15.356-2.875-19.239-6.77-1.183-1.011-2.363-2.535-2.87-3.55l-.337-.676v-7.617c0-7.614 0-7.614.168-6.934.34 1.692 1.352 3.383 2.871 4.735 1.012.847 3.035 2.37 4.723 3.214 2.871 1.524 6.586 2.54 10.465 3.047 2.363.34 3.207.34 6.582.34s4.223 0 6.582-.34c3.883-.508 7.43-1.691 10.465-3.047 1.687-.843 3.715-2.199 4.726-3.214 1.352-1.352 2.532-3.043 2.871-4.735.168-.508.168-.508.168 6.934v7.445l-.34.68c-1.18 2.367-3.207 4.398-5.906 6.09-5.23 3.046-13.164 4.738-20.93 4.398zm0-18.95c-7.086-.339-13.668-2.37-17.887-5.413-1.016-.68-2.363-2.032-2.871-2.707a10.877 10.877 0 0 1-1.352-2.371l-.336-.676v-7.445c0-7.446 0-7.446.168-6.938.34 1.184.844 2.54 1.856 3.555.508.675 1.351 1.523 1.86 1.86.167.171.675.339 1.01.679 3.376 2.367 8.102 4.058 13.5 4.906 2.364.336 3.208.336 6.587.336 3.375 0 4.218 0 6.582-.336 3.879-.508 7.426-1.691 10.46-3.047 1.692-.847 3.716-2.2 4.727-3.215 1.352-1.351 2.364-3.047 2.871-4.738.168-.508.168-.508.168 6.938v7.445l-.507 1.015c-.844 1.524-1.348 2.368-2.364 3.383-1.011 1.016-2.023 1.864-3.375 2.54-5.398 3.046-13.332 4.738-21.097 4.23zm-.504-18.78c-4.727-.34-8.438-1.184-11.985-2.54-4.218-1.69-7.257-3.89-8.777-6.597a5.733 5.733 0 0 1-.844-2.031c-.168-.676-.336-2.368-.168-3.383C17.418 6.262 24.676 1.859 34.465.34 36.828 0 37.672 0 41.047 0s4.223 0 6.582.34c3.883.508 7.43 1.691 10.465 3.043 4.39 2.199 7.09 5.078 7.597 8.12.168.849.168 2.708-.171 3.388-.504 1.691-1.18 2.707-2.532 4.058-3.543 3.723-9.789 6.094-17.55 6.938-1.016.34-6.247.34-7.258.34zm0 0"/><path d="M38.5 55.7h1.7c2.501.2 4.5.8 6.5 1.6 3.699-1.7 9.1-.399 12.399.9-4.298-.4-9.3 0-12.2 1.7-2.9-2.4-8.498-2.999-13.699-2.4 1.4-1 3.1-1.5 5.3-1.8zm-1.3 6.601c-3 .199-5.5 1.198-7.2 2.6-5-2.302-13.7-1.3-17 1.798-.299.201-.6.402-.5.702 2.8-.9 6.3-1.6 9.901-1.302 3.5.3 6.198 1.5 8.2 3.1 3.6-3.299 8.999-5.1 15.898-5-2.4-1.4-5.8-2.3-9.3-1.898zm0 0" stroke="#fff" stroke-miterlimit="10" stroke-width=".75" transform="matrix(1.68776 0 0 1.692 -20.28 -79.405)"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="83" xmlns="http://www.w3.org/2000/svg"><path d="M62.797 9.066H82.93v13.512H62.797zm0 20.801H82.93V43.38H62.797zm0 20.621H82.93V64H62.797zm-27.371 0h20.308V64H35.426zm-27.196 0h20.13V64H8.23zM43.371 0h2.824c4.239.355 7.594 1.422 10.95 2.668 6.359-2.848 15.187-.711 20.84 1.422-7.063-.711-15.54 0-20.485 2.844-4.945-4.09-14.305-5.157-22.957-4.09A22.506 22.506 0 0 1 43.371 0zM41.43 10.844c-5.121.355-9.36 1.957-12.008 4.265C20.945 11.2 6.465 12.977.988 18.133c-.531.355-1.058.71-.883 1.246 4.77-1.422 10.598-2.668 16.602-2.133 6.004.531 10.418 2.488 13.773 5.152 6.18-5.507 15.188-8.71 26.665-8.53-4.06-1.778-9.887-3.38-15.715-3.024zm-5.828 19.199h20.132v13.512H35.602zm-27.196 0H28.54v13.512H8.406zm0 0" fill="#1f7244"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="83" height="63"><path style="fill-rule:nonzero;fill:#1a75ce;fill-opacity:1;stroke-width:.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#1a75ce;stroke-opacity:1;stroke-miterlimit:10" d="M43.399 59.6h15.802v2.498H43.399zm-30.9 6.902h46.702V69.3H12.499zm0 6.799h46.702v2.798H12.499zm0 0" transform="matrix(1.7529 0 0 1.7867 -21.473 -85.752)"/><path style="stroke:none;fill-rule:nonzero;fill:#1a75ce;fill-opacity:1" d="M46.363.363h2.985c4.554.36 8.058 1.434 11.566 2.864C67.574.187 77.043 2.512 83 4.832c-7.54-.715-16.477 0-21.738 3.04-5.258-4.286-15.075-5.54-24.364-4.286 2.63-1.79 5.786-2.863 9.465-3.223zM44.262 11.98c-5.434.36-9.82 2.145-12.797 4.649-8.942-4.113-24.367-2.324-30.149 3.21-.527.36-1.054.72-.879 1.25 5.086-1.605 11.22-2.855 17.528-2.32 6.312.536 11.047 2.68 14.55 5.54 6.485-5.899 16.13-9.29 28.223-9.114-4.207-1.965-10.343-3.57-16.476-3.215zm0 0"/><path style="fill-rule:nonzero;fill:#1a75ce;fill-opacity:1;stroke-width:.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#1a75ce;stroke-opacity:1;stroke-miterlimit:10" d="M12.5 80h46.7v2.8H12.5zm0 0" transform="matrix(1.7529 0 0 1.7867 -21.473 -85.752)"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M.238 64h83.524V0H.238zm16.16-4.91H6.41V52h9.988zm30.688 0h-9.988V52h9.988zM67.602 4.363h9.988v7.274h-9.988zm0 47.453h9.988v7.094h-9.988zM52.168 4.363h9.805v7.09h-9.985v-7.09zm0 47.453h9.805v7.094h-9.985zM36.914 4.363h9.988v7.09h-9.988zM35.464 22l13.071 7.453c2.363 1.457 2.363 3.637 0 5.094L35.465 42c-2.363 1.453-4.36.184-4.36-2.547v-15.09c0-2.547 1.997-3.816 4.36-2.363zM21.485 4.363h9.805v7.09h-9.805zm0 47.453h9.805v7.094h-9.805zM6.41 4.363h9.988v7.274H6.41zm0 0" fill="#f60"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="69" xmlns="http://www.w3.org/2000/svg"><g fill="#1d6fb5"><path d="M18.754 25.742c-2.668.36-4.8 3.219-4.8 6.258s2.132 6.078 4.8 6.258c2.668.355 4.805-2.504 4.805-6.258s-2.137-6.613-4.805-6.258zm0 0"/><path d="M.074 7.508v49.52L38.504 64V0zm18.68 34.683c-4.27-.539-7.649-5.187-7.649-10.191 0-5.184 3.38-9.652 7.649-10.191 4.27-.536 7.652 4.113 7.652 10.191 0 6.258-3.383 10.727-7.652 10.191zm50.172-27.175L47.754 32.715l-5.691-4.649v-14.66h26.863zm0 0"/><path d="m68.926 18.414-21.172 17.7-5.691-4.65V51.31h26.863zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="84" height="48"><path style="stroke:none;fill-rule:nonzero;fill:#7291a1;fill-opacity:1" d="M28.621 33.172h-16.32l-2.012 4.45c-.55 1.483-.918 2.593-.918 3.706 0 1.297.547 2.223 1.649 2.781.55.371 2.203.555 4.582.743v1.293H.203v-1.293c1.652-.188 2.934-.93 4.035-2.04 1.098-1.113 2.383-3.34 3.848-6.859L24.586 0h.73L42 36.879c1.648 3.52 2.934 5.746 3.852 6.672.73.742 1.832 1.113 3.296 1.113v1.297h-22.18v-1.297h.919c1.832 0 3.113-.184 3.847-.742.551-.371.735-.926.735-1.48 0-.372 0-.743-.184-1.301 0-.184-.367-1.11-1.101-2.407zm-1.101-2.406-6.786-15.57-7.148 15.57zm0 0"/><path style="stroke:none;fill-rule:nonzero;fill:#36454d;fill-opacity:1" d="m83.797 16.309-6.602 22.054-.734 2.778c0 .375-.184.558-.184.742 0 .187.184.558.371.742.184.188.368.371.547.371.551 0 1.102-.371 2.016-1.113.371-.367 1.102-1.297 2.387-2.965l1.097.559c-1.648 2.964-3.3 5.003-5.132 6.3-1.833 1.297-3.852 2.04-5.864 2.04-1.285 0-2.203-.372-2.933-.93-.735-.742-1.102-1.485-1.102-2.407 0-.93.367-2.41 1.102-4.82l.73-2.781c-2.562 4.45-5.133 7.601-7.516 9.453C60.516 47.442 59.05 48 57.582 48c-2.016 0-3.668-.926-4.582-2.594-.918-1.668-1.465-3.523-1.465-5.746 0-3.152.914-6.672 2.934-10.75 2.011-4.074 4.582-7.226 7.695-9.82 2.566-2.04 5.133-2.965 7.332-2.965 1.285 0 2.203.367 3.121 1.11.73.742 1.281 2.038 1.649 3.89l1.28-4.074zM72.98 22.797c0-1.856-.367-3.152-.918-3.895-.367-.554-.914-.742-1.648-.742-.734 0-1.469.375-2.2.93-1.464 1.297-3.116 4.074-4.948 8.336-1.832 4.265-2.57 7.785-2.57 10.937 0 1.11.183 2.035.554 2.594.363.559.914.742 1.281.742 1.098 0 2.016-.558 3.117-1.668 1.465-1.668 2.934-3.707 4.032-5.93 2.199-4.449 3.3-8.156 3.3-11.304zm0 0"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="83" height="63"><path style="fill-rule:nonzero;fill:#1a75ce;fill-opacity:1;stroke-width:.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#1a75ce;stroke-opacity:1;stroke-miterlimit:10" d="M43.399 59.6h15.802v2.498H43.399zm-30.9 6.902h46.702V69.3H12.499zm0 6.799h46.702v2.798H12.499zm0 0" transform="matrix(1.7529 0 0 1.7867 -21.473 -85.752)"/><path style="stroke:none;fill-rule:nonzero;fill:#1a75ce;fill-opacity:1" d="M46.363.363h2.985c4.554.36 8.058 1.434 11.566 2.864C67.574.187 77.043 2.512 83 4.832c-7.54-.715-16.477 0-21.738 3.04-5.258-4.286-15.075-5.54-24.364-4.286 2.63-1.79 5.786-2.863 9.465-3.223zM44.262 11.98c-5.434.36-9.82 2.145-12.797 4.649-8.942-4.113-24.367-2.324-30.149 3.21-.527.36-1.054.72-.879 1.25 5.086-1.605 11.22-2.855 17.528-2.32 6.312.536 11.047 2.68 14.55 5.54 6.485-5.899 16.13-9.29 28.223-9.114-4.207-1.965-10.343-3.57-16.476-3.215zm0 0"/><path style="fill-rule:nonzero;fill:#1a75ce;fill-opacity:1;stroke-width:.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#1a75ce;stroke-opacity:1;stroke-miterlimit:10" d="M12.5 80h46.7v2.8H12.5zm0 0" transform="matrix(1.7529 0 0 1.7867 -21.473 -85.752)"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="74" xmlns="http://www.w3.org/2000/svg"><g fill="#4d1b9b"><path d="M73.734 51.555c0-2.844-2.289-5.157-5.109-5.157H5.375c-2.82 0-5.11 2.313-5.11 5.157v7.289c0 2.843 2.29 5.156 5.11 5.156h63.25c2.82 0 5.11-2.313 5.11-5.156zm-27.308 6.757a2.985 2.985 0 0 1-2.996-3.023 2.985 2.985 0 0 1 2.996-3.023 2.985 2.985 0 0 1 2.996 3.023c0 1.777-1.234 3.023-2.996 3.023zm8.984 0a2.984 2.984 0 0 1-2.992-3.023c0-1.777 1.23-3.023 2.992-3.023a2.985 2.985 0 0 1 2.996 3.023 2.985 2.985 0 0 1-2.996 3.023zm8.813 0a2.985 2.985 0 0 1-2.996-3.023c0-1.777 1.234-3.023 2.996-3.023a2.981 2.981 0 0 1 2.992 3.023 2.981 2.981 0 0 1-2.992 3.023zM5.375 43.38h63.25c1.41 0 2.82.355 3.879 1.066l-6.168-12.98c-1.762-3.73-4.582-5.153-7.398-5.153h-6.876L42.2 36.623c-.707.71-1.586 1.245-2.469 1.6-.878.356-1.937.532-2.82.532-1.055 0-1.937-.176-2.816-.531h-.352c-.707-.356-1.41-.891-2.117-1.422l-9.867-10.668h-6.871c-2.817 0-5.461 1.601-7.399 5.156L1.32 44.266c1.235-.532 2.47-.887 4.055-.887zm0 0"/><path d="M51.71 21.332c.352-.355.532-.71.884-1.242.176-.535.351-.89.351-1.602 0-.531-.175-1.066-.351-1.422-.176-.53-.532-.886-.883-1.246a5.273 5.273 0 0 0-1.23-.886c-.356-.18-.883-.356-1.41-.356-.532 0-1.06.176-1.41.356-.528.175-.884.53-1.235.886l-5.637 5.692V3.734c0-.535-.176-1.066-.352-1.421-.18-.536-.53-.891-.882-1.247-.352-.355-.703-.71-1.235-.886C37.97 0 37.441 0 36.91 0c-.527 0-1.055 0-1.406.18-.531.175-.883.53-1.234.886-.352.356-.708.711-.883 1.246-.176.532-.352.887-.352 1.422v17.953L27.398 16c-.351-.355-.707-.71-1.234-.89-.352-.176-.879-.356-1.41-.356-.527 0-1.055.18-1.41.355-.352.18-.88.536-1.23.891-.356.355-.708.71-.884 1.246-.175.531-.351.887-.351 1.422 0 .531.176 1.066.351 1.598.176.535.528.89.883 1.246L34.27 33.957c.351.355.703.711 1.234.887.351.18.879.355 1.406.355.531 0 1.059-.176 1.41-.355.532-.176.883-.532 1.235-.887zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="74" xmlns="http://www.w3.org/2000/svg"><g fill="#4d1b9b"><path d="M73.734 51.555c0-2.844-2.289-5.157-5.109-5.157H5.375c-2.82 0-5.11 2.313-5.11 5.157v7.289c0 2.843 2.29 5.156 5.11 5.156h63.25c2.82 0 5.11-2.313 5.11-5.156zm-27.308 6.757a2.985 2.985 0 0 1-2.996-3.023 2.985 2.985 0 0 1 2.996-3.023 2.985 2.985 0 0 1 2.996 3.023c0 1.777-1.234 3.023-2.996 3.023zm8.984 0a2.984 2.984 0 0 1-2.992-3.023c0-1.777 1.23-3.023 2.992-3.023a2.985 2.985 0 0 1 2.996 3.023 2.985 2.985 0 0 1-2.996 3.023zm8.813 0a2.985 2.985 0 0 1-2.996-3.023c0-1.777 1.234-3.023 2.996-3.023a2.981 2.981 0 0 1 2.992 3.023 2.981 2.981 0 0 1-2.992 3.023zM5.375 43.38h63.25c1.41 0 2.82.355 3.879 1.066l-6.168-12.98c-1.762-3.73-4.582-5.153-7.398-5.153h-6.876L42.2 36.623c-.707.71-1.586 1.245-2.469 1.6-.878.356-1.937.532-2.82.532-1.055 0-1.937-.176-2.816-.531h-.352c-.707-.356-1.41-.891-2.117-1.422l-9.867-10.668h-6.871c-2.817 0-5.461 1.601-7.399 5.156L1.32 44.266c1.235-.532 2.47-.887 4.055-.887zm0 0"/><path d="M51.71 21.332c.352-.355.532-.71.884-1.242.176-.535.351-.89.351-1.602 0-.531-.175-1.066-.351-1.422-.176-.53-.532-.886-.883-1.246a5.273 5.273 0 0 0-1.23-.886c-.356-.18-.883-.356-1.41-.356-.532 0-1.06.176-1.41.356-.528.175-.884.53-1.235.886l-5.637 5.692V3.734c0-.535-.176-1.066-.352-1.421-.18-.536-.53-.891-.882-1.247-.352-.355-.703-.71-1.235-.886C37.97 0 37.441 0 36.91 0c-.527 0-1.055 0-1.406.18-.531.175-.883.53-1.234.886-.352.356-.708.711-.883 1.246-.176.532-.352.887-.352 1.422v17.953L27.398 16c-.351-.355-.707-.71-1.234-.89-.352-.176-.879-.356-1.41-.356-.527 0-1.055.18-1.41.355-.352.18-.88.536-1.23.891-.356.355-.708.71-.884 1.246-.175.531-.351.887-.351 1.422 0 .531.176 1.066.351 1.598.176.535.528.89.883 1.246L34.27 33.957c.351.355.703.711 1.234.887.351.18.879.355 1.406.355.531 0 1.059-.176 1.41-.355.532-.176.883-.532 1.235-.887zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M31.816 6.078c5.094 5.094 6.547 12.184 4.73 18.547l26.907 26.91.547 12-15.09-1.273v-7.637h-7.637v-7.637h-7.457L24 37.172c-6.363 1.816-13.637.363-18.547-4.73-7.27-7.27-7.27-19.27 0-26.544a18.494 18.494 0 0 1 26.363.18zM18 11.172c-2.184-2.184-5.453-2.184-7.637 0-2.18 2.18-2.18 5.453 0 7.637 2.184 2.18 5.453 2.18 7.637 0 2.184-2.184 2.184-5.637 0-7.637zm0 0" fill="#696"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M31.816 6.078c5.094 5.094 6.547 12.184 4.73 18.547l26.907 26.91.547 12-15.09-1.273v-7.637h-7.637v-7.637h-7.457L24 37.172c-6.363 1.816-13.637.363-18.547-4.73-7.27-7.27-7.27-19.27 0-26.544a18.494 18.494 0 0 1 26.363.18zM18 11.172c-2.184-2.184-5.453-2.184-7.637 0-2.18 2.18-2.18 5.453 0 7.637 2.184 2.18 5.453 2.18 7.637 0 2.184-2.184 2.184-5.637 0-7.637zm0 0" fill="#696"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="84" height="63"><path style="stroke:none;fill-rule:nonzero;fill:#bababa;fill-opacity:1" d="M78.953 17.746c-.969-.191-1.742-.387-2.707-.191-2.125.191-4.441 1.36-6.566 1.746-1.543.199-2.895-.973-3.09-2.719a102.076 102.076 0 0 1 0-15.379c0-.777-.578-1.168-1.156-1.168C59.64-.156 54.039.425 48.05 1.79c-1.547.387-2.7 1.754-2.7 3.113.188 3.118 2.313 6.618 1.348 9.926-.773 2.918-3.09 5.059-6.18 5.645-2.894.586-5.988-.778-7.53-3.114-1.93-2.726-.966-6.62-1.739-9.925-.383-1.559-1.93-2.34-3.473-2.145a62.499 62.499 0 0 0-16.804 4.09c-.77.195-1.157.973-.77 1.555 2.125 4.671 3.664 9.539 5.02 14.597.386 1.559-.578 3.117-2.125 3.504-2.125.586-4.637.195-6.758.777-.969.196-1.738.586-2.508 1.168-2.707 1.754-3.867 4.672-3.48 7.59.39 2.727 2.507 5.063 5.02 6.23 3.284 1.165 6.183-.972 9.464-1.167 1.543-.192 2.898.972 3.09 2.726.387 5.059.387 10.313 0 15.371 0 .782.578 1.168 1.16 1.168 5.789.391 11.586-.386 17.379-1.75 1.543-.39 2.703-1.75 2.703-3.113-.195-3.308-2.508-6.617-1.543-10.12.77-2.727 3.473-5.06 6.18-5.454 2.699-.387 5.988.781 7.53 3.117 2.122 2.727.966 6.813 1.74 10.121.382 1.555 1.929 2.336 3.472 2.14 5.797-.585 11.59-1.753 16.805-4.089.77-.195 1.156-.973.77-1.555-2.126-4.672-3.669-9.535-5.02-14.597-.387-1.559.578-3.114 2.125-3.5 3.09-.782 6.566.195 9.46-1.95 2.126-1.75 3.477-4.671 2.895-7.394.195-3.695-2.121-6.227-4.629-7.008zm0 0"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="51" xmlns="http://www.w3.org/2000/svg"><path d="M23.023 63.957c-8.199-.34-15.543-2.875-19.468-6.77-1.196-1.011-2.39-2.535-2.903-3.55L.31 52.96v-7.617c0-7.614 0-7.614.171-6.934.34 1.692 1.368 3.383 2.903 4.735 1.023.847 3.074 2.37 4.781 3.214 2.906 1.524 6.66 2.54 10.59 3.047 2.39.34 3.246.34 6.66.34 3.418 0 4.27 0 6.66-.34 3.93-.508 7.516-1.691 10.59-3.047 1.707-.843 3.758-2.199 4.781-3.214 1.368-1.352 2.563-3.043 2.903-4.735.172-.508.172-.508.172 6.934v7.445l-.34.68c-1.196 2.367-3.246 4.398-5.98 6.09-5.294 3.046-13.321 4.738-21.177 4.398zm0-18.95c-7.171-.339-13.832-2.37-18.101-5.413-1.027-.68-2.39-2.032-2.906-2.707-.512-.68-1.024-1.524-1.364-2.371L.31 33.84v-7.445c0-7.446 0-7.446.171-6.938.34 1.184.852 2.54 1.88 3.555.511.675 1.367 1.523 1.878 1.86.168.171.684.339 1.024.679 3.414 2.367 8.199 4.058 13.664 4.906 2.39.336 3.242.336 6.66.336 3.414 0 4.27 0 6.66-.336 3.93-.508 7.516-1.691 10.59-3.047 1.707-.847 3.758-2.2 4.781-3.215 1.367-1.351 2.39-3.047 2.903-4.738.171-.508.171-.508.171 6.938v7.445l-.511 1.015c-.856 1.524-1.368 2.368-2.39 3.383-1.028 1.016-2.052 1.864-3.419 2.54-5.465 3.046-13.492 4.738-21.348 4.23zm-.511-18.78c-4.782-.34-8.54-1.184-12.125-2.54-4.27-1.69-7.344-3.89-8.883-6.597a5.594 5.594 0 0 1-.852-2.031C.48 14.383.31 12.69.48 11.676 1.504 6.262 8.848 1.859 18.754.34 21.144 0 22 0 25.414 0c3.418 0 4.27 0 6.66.34 3.93.508 7.516 1.691 10.59 3.043 4.441 2.199 7.172 5.078 7.684 8.12.172.849.172 2.708-.168 3.388-.512 1.691-1.196 2.707-2.563 4.058-3.586 3.723-9.906 6.094-17.762 6.938-1.023.34-6.32.34-7.343.34zm0 0" fill="#a03537"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M27.762.637c-3.899 0-6.95 3.218-6.95 6.949 0 4.746 2.711 10.68 5.422 16.277-2.203 6.782-4.574 14.07-7.797 20.172-6.44 2.547-12.207 4.41-15.597 7.293l-.168.168C1.484 52.852.637 54.546.637 56.414c0 3.898 3.218 6.95 6.949 6.95 1.867 0 3.73-.677 4.918-2.036 0 0 .168 0 .168-.168 2.543-3.05 5.594-8.644 8.308-13.562 6.102-2.375 12.715-4.918 18.817-6.442 4.578 3.73 11.191 6.102 16.617 6.102 3.898 0 6.95-3.223 6.95-6.95 0-3.902-3.22-6.953-6.95-6.953-4.41 0-10.68 1.528-15.43 3.223a56.197 56.197 0 0 1-10.172-13.223c1.868-5.765 4.07-11.359 4.07-15.77-.171-3.898-3.222-6.948-7.12-6.948zm0 4.066c1.527 0 2.71 1.188 2.71 2.715 0 2.035-1.183 5.934-2.37 10-1.696-4.066-3.223-7.965-3.223-10 .172-1.356 1.355-2.715 2.883-2.715zm1.187 23.906c2.035 3.391 4.578 6.442 7.29 9.157a171.201 171.201 0 0 0-12.208 4.066c2.035-4.238 3.563-8.816 4.918-13.223zm27.465 8.985a2.679 2.679 0 0 1 2.711 2.715 2.678 2.678 0 0 1-2.71 2.71c-3.224 0-7.63-1.355-11.192-3.39 4.07-1.016 8.648-2.035 11.191-2.035zM14.875 49.973c-2.031 3.558-3.898 6.78-5.254 8.476-.508.508-1.016.676-1.863.676a2.679 2.679 0 0 1-2.715-2.71c0-.68.34-1.528.68-1.868 1.523-1.356 5.086-2.879 9.152-4.574zm0 0" fill="#c11e07" stroke="#c11e07" stroke-miterlimit="10" stroke-width="1.27152"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="52" xmlns="http://www.w3.org/2000/svg"><path d="M48.793 26.879h-4.629V18.05C44.164 7.988 35.973.043 26 .043S7.836 8.164 7.836 18.051v8.828H3.207A3.181 3.181 0 0 0 0 30.059V60.78c0 1.762 1.426 3.176 3.207 3.176h45.586c1.781 0 3.207-1.414 3.207-3.176V29.883c0-1.59-1.426-3.004-3.207-3.004zM29.918 52.305c.355 1.058-.535 1.941-1.602 1.941h-4.808c-1.07 0-1.781-1.059-1.606-1.941l1.426-5.649c-1.781-.883-3.027-2.648-3.027-4.945 0-3 2.492-5.473 5.52-5.473 3.027 0 5.523 2.473 5.523 5.473 0 2.117-1.246 4.062-3.028 4.945zm5.164-25.426H16.918V18.05c0-4.942 4.098-9.004 9.082-9.004s9.082 4.062 9.082 9.004zm0 0" fill="#696"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M31.816 6.078c5.094 5.094 6.547 12.184 4.73 18.547l26.907 26.91.547 12-15.09-1.273v-7.637h-7.637v-7.637h-7.457L24 37.172c-6.363 1.816-13.637.363-18.547-4.73-7.27-7.27-7.27-19.27 0-26.544a18.494 18.494 0 0 1 26.363.18zM18 11.172c-2.184-2.184-5.453-2.184-7.637 0-2.18 2.18-2.18 5.453 0 7.637 2.184 2.18 5.453 2.18 7.637 0 2.184-2.184 2.184-5.637 0-7.637zm0 0" fill="#696"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M31.816 6.078c5.094 5.094 6.547 12.184 4.73 18.547l26.907 26.91.547 12-15.09-1.273v-7.637h-7.637v-7.637h-7.457L24 37.172c-6.363 1.816-13.637.363-18.547-4.73-7.27-7.27-7.27-19.27 0-26.544a18.494 18.494 0 0 1 26.363.18zM18 11.172c-2.184-2.184-5.453-2.184-7.637 0-2.18 2.18-2.18 5.453 0 7.637 2.184 2.18 5.453 2.18 7.637 0 2.184-2.184 2.184-5.637 0-7.637zm0 0" fill="#696"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M64 32c0 17.645-14.355 32-32 32S0 49.645 0 32 14.355 0 32 0s32 14.355 32 32" fill="#999"/><g fill="#fff"><path d="M54.313 34.422c-1.036-6.746-8.13-11.242-13.493-14.531-2.246-1.383-6.054-3.286-6.57-6.399-.176-1.21-.176-2.594-.176-3.805V8.13c0-.692-.691.172-1.035-.344-.867-1.387-.52.344-.52 1.211.172 1.727.52 3.457.52 5.188 0 3.285-.52 6.574-1.387 9.687-1.902 7.438-3.457 15.223-1.554 22.832a24.518 24.518 0 0 0 1.554 4.668c.176.52.52 1.73 1.211 1.906 2.078.516 3.633.692 5.192 2.246 1.039.868 1.73.348 2.941 0 3.633-1.382 6.746-3.285 9.34-6.226 3.285-4.496 4.844-9.512 3.977-14.875m-3.805 6.746c-.344 2.766-2.074 5.363-3.805 7.437-1.383 1.56-3.113 3.461-5.016 4.153-.69.172.172-1.211.172-1.211.52-.867 1.383-1.73 2.075-2.594 1.039-1.21 1.902-2.598 2.421-3.98 1.903-5.016 1.56-10.899-1.382-15.395-1.555-2.422-3.805-4.496-5.88-6.398-1.038-.868-2.077-1.73-2.94-2.77-.176-.172-2.079-2.594-1.387-2.941.175-.172 4.152 3.98 4.5 4.324 1.554 1.21 3.285 2.422 4.843 3.809 2.075 1.902 4.149 3.976 5.36 6.57 1.21 2.77 1.386 6.055 1.039 8.996"/><path d="M30.79.863c.519.348.69 2.77.69 4.844 0 2.078.172 11.246-.52 13.664-.69 2.422-2.245 5.192-3.804 7.613-1.73 2.422-3.633 7.438-3.457 10.551 0 3.113 1.903 8.13 3.285 10.38 1.383 2.073 3.805 5.015 3.286 5.706-.864 1.211-4.668-2.941-6.747-5.363-1.902-2.422-3.976-7.262-3.976-11.07 0-3.805 2.074-7.262 3.633-9.34 1.554-2.075 4.496-5.707 5.36-7.438.866-1.73 1.73-3.457 1.901-5.707.348-2.25 0-10.55 0-10.55S30.27.52 30.79.862"/><path d="M29.234 4.844c.516.343.692 1.039.692 1.73 0 .692-.176 3.633-.348 6.57-.172 2.942-2.594 5.364-4.152 7.094-1.727 1.73-6.746 7.09-8.473 9.688-1.906 2.594-2.77 6.05-2.598 8.992.176 2.941.868 5.883 3.633 8.996 2.77 3.113 4.672 4.496 6.227 5.363 1.387.692 2.941 1.211 2.597 1.903-.347.691-1.73.172-3.289-.348-1.554-.52-6.746-2.594-9.687-6.055-2.938-3.457-4.496-7.957-4.324-12.105.175-4.324 1.386-6.055 3.289-8.824 1.902-2.766 7.437-6.918 9.168-7.957 1.73-1.036 3.976-2.766 5.187-4.325 1.211-1.382 1.73-2.593 1.73-4.668 0-1.902.173-3.804 0-4.5-.171-.515-.171-1.902.348-1.554m.172 51.89c.344 0 .172 1.211-.347 1.73-.52.52-1.211.864-1.383.692s.52-.343 1.039-.863c.52-.691.344-1.559.691-1.559m5.36-.172c-.344 0-.172 1.211.347 1.731s1.211.863 1.383.691c.176-.172-.52-.347-1.035-.867-.52-.515-.348-1.554-.695-1.554m-2.418 1.382c0 1.04 0 1.903-.176 1.903-.344 0-.172-.864-.172-1.903 0-1.039-.172-1.902.172-1.902.348 0 .176.863.176 1.902"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="67" xmlns="http://www.w3.org/2000/svg"><path d="M65.66 13.137 33.5.168 20.77 5.391l32.16 12.8zM12.73 8.59 1.34 13.137 33.5 26.105l11.39-4.546zM0 50.695l32.496 13.137V27.789L0 14.652zm54.27-30.82V29.98l-1.34-.843-1.34 1.851-1.34-.672-1.34 1.852-1.34-.84-1.34 1.852V23.074L34.504 27.79v36.043L67 50.695V14.652zm0 0" fill="#6781b2"/><path d="M7.371 36.21c.668.337 1.34.337 1.676.169.332-.168.836-.504 1.172-1.012.332-.504.5-1.008.332-1.176-.164-.171-.5-.675-1.172-.843l-1.004-.676-1.844 3.035zm-5.195 2.528c-.164-.168-.164-.168 0-.34l4.86-8.082.167-.168 3.516 1.348c1.172.504 1.844 1.008 2.18 1.852.335.843.167 1.683-.504 2.695-.168.336-.504.84-.836 1.008-.336.34-.672.508-1.172.676-.504.168-1.008.336-1.508.336-.504 0-1.176-.168-1.844-.504l-1.508-.508-1.34 2.023-.167.168zm14.238 2.864c-.168-.172-.168-.172 0-.34l2.18-3.535c.168-.336.332-.676.168-.676 0-.168-.168-.336-.672-.504l-1.34-.504-2.68 4.379-.168.168-1.843-.676s-.168 0-.168-.168v-.168l4.859-8.082.168-.168 1.844.672s.164 0 .164.168v.168l-1.172 2.023 1.34.504c1.008.336 1.676.844 2.011 1.516.336.504.168 1.348-.335 2.02l-2.344 3.706-.168.168zm7.707 1.007c.668.34 1.34.34 1.84.168.504-.168.84-.504 1.176-1.007.332-.508.5-1.012.332-1.18-.168-.336-.5-.676-1.172-.844l-1.172-.504-1.844 3.031zm-5.36 2.528c-.167-.168-.167-.168-.167-.336l5.023-8.086s.168-.168.336 0l3.684 1.347c1.172.508 1.843 1.012 2.18 1.852.331.844.167 1.688-.504 2.695-.168.34-.504.844-.836 1.012-.336.336-.672.504-1.176.672-.5.172-1.172.34-1.672.34-.504 0-1.176-.168-2.012-.508l-1.34-.336-1.34 2.02s-.167.171-.335 0zm0 0" fill="#fff"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="83" height="52"><path style="stroke:none;fill-rule:nonzero;fill:#6781b2;fill-opacity:1" d="M36.18 38.57c3.308 1.235 8.703 1.063 12.535.528.7 1.593-.348 3.715.347 5.48.352.887 1.395 1.594 3.137 2.477.348.18.867.18 1.219.355l.348.352c.695.531 2.09 1.418 2.437 1.418.524.172 1.047.172 1.39.172h1.747c2.433-.172 4.87-.883 5.57-1.766 1.219-1.59.524-5.125.348-8.309-.176-2.652-.524-6.187 0-8.308.176-.707.87-1.418 1.215-2.301 1.394-3.004 2.789-7.957 2.27-12.73-.352-2.122-1.395-4.063-1.571-5.653 3.308.352 6.441-.355 9.226 0 1.747.172 3.137 1.41 4.704 1.235.351-.883 1.39-1.415 1.39-2.473.176-1.238-.344-2.656-.867-3.54-2.266-.35-4.004 1.77-6.266 1.95-.703 0-1.57-.18-2.441-.355-2.613-.18-6.266.527-8.531 0-1.567-.356-2.961-2.122-4.528-2.829-.347-.18-1.043 0-1.394-.355-.52-.176-.871-.531-1.215-.531-1.742-.703-3.66-1.414-5.402-1.59C48.543.91 44.016.91 39.836 1.266c-1.39.18-2.61.882-4.004.53C34.785 1.618 34.613.91 33.918.56c-2.965-1.414-5.922.175-7.84 1.238-1.39.707-3.129 1.766-4.527 1.945-1.39.352-3.48 0-4.7 0-1.566 0-3.656.352-5.398.531-1.566.352-3.828.528-4.7 1.235-2.437 1.414-3.132 7.957-4.007 11.847-.344 1.415-.867 2.829-1.215 4.243-.523 3.18-.875 6.543-.875 9.547-.172 6.187-.867 14.851 2.27 17.148.695.531 2.957 1.238 3.652.887.176 0 1.047-.887 1.219-1.239.176-.53-.344-1.238-.344-1.945 0-1.418-.351-3.184-.351-4.598 0-3.71.695-7.777 1.566-9.37 0-.176.523-.176.523-.352.176-.352 0-.707.352-.887.695-.703 1.738-1.414 2.434-1.59 2.09-.883 3.308.176 4.18 1.414 1.741 2.301 2.09 6.188 2.265 9.903v2.297c0 .882-.352 1.765-.352 2.296.524 1.414 2.961 2.125 4.008 2.832 0 .528.176 1.239.52 1.59.523.887 1.394 1.414 1.918 1.766 2.609 1.418 9.226.531 10.449-1.234.172-.18.344-.356.344-.708.171-.53.523-1.062.523-1.414 1.047-3.183-.172-6.011.348-9.37zM32.523 6.922c-.171.18-.171.18 0 0"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M62.887 38.266c-2.684-.84-4.532-3.36-4.532-6.215 0-2.852 1.848-5.371 4.532-6.211.84-.336 1.343-1.172 1.008-2.012-.84-3.023-1.848-5.707-3.524-8.394-.504-.84-1.344-1.008-2.184-.672-1.007.504-2.015.84-3.19.84-3.692 0-6.548-3.024-6.548-6.547 0-1.176.336-2.184.84-3.188.504-.84.168-1.68-.672-2.183a40.47 40.47 0 0 0-8.39-3.528c-.84-.168-1.68.168-2.016 1.008C37.37 3.852 34.855 5.7 32 5.7s-5.371-1.847-6.21-4.535C25.452.324 24.612-.18 23.772.156c-3.02.84-5.707 1.848-8.39 3.528-.84.503-1.008 1.343-.672 2.183.504 1.004.84 2.012.84 3.188 0 3.691-3.024 6.547-6.547 6.547-1.176 0-2.184-.336-3.191-.84-.84-.504-1.68-.168-2.184.672a40.699 40.699 0 0 0-3.524 8.394c-.167.84.168 1.676 1.008 2.012 2.684.84 4.532 3.36 4.532 6.21 0 2.856-1.848 5.376-4.532 6.216-.84.332-1.343 1.172-1.008 2.011.84 3.024 1.848 5.707 3.524 8.395.504.84 1.344 1.008 2.184.672 1.007-.504 2.015-.84 3.19-.84 3.692 0 6.548 3.02 6.548 6.547 0 1.176-.336 2.183-.84 3.187-.504.84-.168 1.68.672 2.184a40.47 40.47 0 0 0 8.39 3.527h.336c.672 0 1.344-.504 1.512-1.176.84-2.687 3.356-4.535 6.211-4.535s5.371 1.848 6.211 4.535c.336.84 1.176 1.344 2.016 1.008 3.02-.84 5.707-1.847 8.39-3.527.84-.504 1.008-1.344.672-2.184-.504-1.004-.84-2.011-.84-3.187 0-3.692 3.024-6.547 6.547-6.547 1.176 0 2.184.336 3.192.84.84.504 1.68.168 2.183-.672a40.698 40.698 0 0 0 3.524-8.395c.503-.672 0-1.511-.84-1.843zm-30.719 3.691c-5.371 0-9.902-4.363-9.902-9.906 0-5.371 4.363-9.903 9.902-9.903 5.371 0 9.902 4.364 9.902 9.903 0 5.375-4.53 9.906-9.902 9.906zm0 0" fill="#999"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="74" xmlns="http://www.w3.org/2000/svg"><path d="m49.332 34.941-12.25-5.714L61.75 17.633 74 23.348l-12.25 5.879zM61.75 6.207 49.5.492 37.25 6.207l24.5 11.594L74 12.086zm-37.082 17.14-12.25-5.714-12.25 5.715L24.836 34.94l12.246-5.714zm0-11.429 12.25-5.711L24.668.492 0 12.086 12.25 17.8zM61.75 32.59l-11.074 5.039-1.344.672-1.34-.672-11.074-5.04-11.078 5.04-1.34.672-1.344-.672-11.074-5.04v17.977L36.75 63.508l25-12.942zm0 0" fill="#4d1b9b"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M64 32c0 17.645-14.355 32-32 32S0 49.645 0 32 14.355 0 32 0s32 14.355 32 32" fill="#3a3c5b"/><g fill="#fff"><path d="M54.313 34.422c-1.036-6.746-8.13-11.242-13.493-14.531-2.246-1.383-6.054-3.286-6.57-6.399-.176-1.21-.176-2.594-.176-3.805V8.13c0-.692-.691.172-1.035-.344-.867-1.387-.52.344-.52 1.211.172 1.727.52 3.457.52 5.188 0 3.285-.52 6.574-1.387 9.687-1.902 7.438-3.457 15.223-1.554 22.832a24.518 24.518 0 0 0 1.554 4.668c.176.52.52 1.73 1.211 1.906 2.078.516 3.633.692 5.192 2.246 1.039.868 1.73.348 2.941 0 3.633-1.382 6.746-3.285 9.34-6.226 3.285-4.496 4.844-9.512 3.977-14.875m-3.805 6.746c-.344 2.766-2.074 5.363-3.805 7.437-1.383 1.56-3.113 3.461-5.016 4.153-.69.172.172-1.211.172-1.211.52-.867 1.383-1.73 2.075-2.594 1.039-1.21 1.902-2.598 2.421-3.98 1.903-5.016 1.56-10.899-1.382-15.395-1.555-2.422-3.805-4.496-5.88-6.398-1.038-.868-2.077-1.73-2.94-2.77-.176-.172-2.079-2.594-1.387-2.941.175-.172 4.152 3.98 4.5 4.324 1.554 1.21 3.285 2.422 4.843 3.809 2.075 1.902 4.149 3.976 5.36 6.57 1.21 2.77 1.386 6.055 1.039 8.996"/><path d="M30.79.863c.519.348.69 2.77.69 4.844 0 2.078.172 11.246-.52 13.664-.69 2.422-2.245 5.192-3.804 7.613-1.73 2.422-3.633 7.438-3.457 10.551 0 3.113 1.903 8.13 3.285 10.38 1.383 2.073 3.805 5.015 3.286 5.706-.864 1.211-4.668-2.941-6.747-5.363-1.902-2.422-3.976-7.262-3.976-11.07 0-3.805 2.074-7.262 3.633-9.34 1.554-2.075 4.496-5.707 5.36-7.438.866-1.73 1.73-3.457 1.901-5.707.348-2.25 0-10.55 0-10.55S30.27.52 30.79.862"/><path d="M29.234 4.844c.516.343.692 1.039.692 1.73 0 .692-.176 3.633-.348 6.57-.172 2.942-2.594 5.364-4.152 7.094-1.727 1.73-6.746 7.09-8.473 9.688-1.906 2.594-2.77 6.05-2.598 8.992.176 2.941.868 5.883 3.633 8.996 2.77 3.113 4.672 4.496 6.227 5.363 1.387.692 2.941 1.211 2.597 1.903-.347.691-1.73.172-3.289-.348-1.554-.52-6.746-2.594-9.687-6.055-2.938-3.457-4.496-7.957-4.324-12.105.175-4.324 1.386-6.055 3.289-8.824 1.902-2.766 7.437-6.918 9.168-7.957 1.73-1.036 3.976-2.766 5.187-4.325 1.211-1.382 1.73-2.593 1.73-4.668 0-1.902.173-3.804 0-4.5-.171-.515-.171-1.902.348-1.554m.172 51.89c.344 0 .172 1.211-.347 1.73-.52.52-1.211.864-1.383.692s.52-.343 1.039-.863c.52-.691.344-1.559.691-1.559m5.36-.172c-.344 0-.172 1.211.347 1.731s1.211.863 1.383.691c.176-.172-.52-.347-1.035-.867-.52-.515-.348-1.554-.695-1.554m-2.418 1.382c0 1.04 0 1.903-.176 1.903-.344 0-.172-.864-.172-1.903 0-1.039-.172-1.902.172-1.902.348 0 .176.863.176 1.902"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="74" xmlns="http://www.w3.org/2000/svg"><path d="M69.5 0H4.633C2.125 0 .285 2.008.285 4.352V49.39c0 2.511 2.004 4.351 4.348 4.351h64.699c2.508 0 4.348-2.008 4.348-4.351V4.52C74.016 2.008 72.008 0 69.5 0zm0 0" fill="#ced2d8"/><path d="M4.633 10.883H69.5V49.39H4.633zm0 0" fill="#f2f2f2"/><path d="M18.008 5.86c0 .831-.676 1.507-1.508 1.507a1.508 1.508 0 0 1 0-3.015c.832 0 1.508.675 1.508 1.507zm0 0" fill="#54b845"/><path d="M12.824 5.86c0 .831-.676 1.507-1.504 1.507a1.509 1.509 0 0 1 0-3.015c.828 0 1.504.675 1.504 1.507zm0 0" fill="#fbd303"/><path d="M7.977 5.86c0 .831-.676 1.507-1.508 1.507a1.508 1.508 0 0 1 0-3.015c.832 0 1.508.675 1.508 1.507zm0 0" fill="#f0582f"/><path d="M27.703 63.285c-.836-.668-1.672-1.336-2.34-2.176-.668-.836-1.34-1.84-2.008-2.68-1.503-2.175-2.507-4.519-3.343-6.863-1.004-2.843-1.336-5.523-1.336-8.203 0-3.015.668-5.523 1.84-7.703 1-1.672 2.34-3.18 4.011-4.183 1.672-1.004 3.512-1.508 5.348-1.676.672 0 1.34.168 2.176.336.5.168 1.168.336 2.004.668 1.004.336 1.672.672 1.84.672.667.168 1.171.335 1.503.335.336 0 .672-.167 1.172-.167.336-.168.836-.336 1.504-.672.668-.332 1.34-.5 1.84-.668l2.008-.504c.668-.168 1.504-.168 2.172-.168 1.336.168 2.508.336 3.68.84 2.003.836 3.507 2.007 4.68 3.683-.5.332-1.005.668-1.337 1.004-1.004.836-1.672 1.84-2.344 2.844-.836 1.508-1.168 3.184-1.168 4.855 0 2.012.5 3.852 1.672 5.36a7.757 7.757 0 0 0 2.84 2.847c.672.332 1.172.668 1.672.836-.164.668-.5 1.34-.836 2.008-.668 1.508-1.504 3.016-2.34 4.356-.836 1.172-1.504 2.007-2.004 2.675-.836.84-1.507 1.676-2.175 2.012-.836.5-1.84.836-2.676.836-.668 0-1.336 0-2.004-.168-.504-.168-1.172-.336-1.672-.668-.504-.336-1.172-.504-1.672-.672-.668-.168-1.504-.332-2.176-.332-.836 0-1.504.164-2.172.332s-1.171.336-1.671.672c-.836.332-1.336.5-1.672.668-.668.168-1.172.336-1.84.336-1.336.168-2.34-.168-3.176-.672zm13.04-34.992c-1.337.672-2.509.84-3.677.84-.168-1.172 0-2.512.5-3.852.504-1.172 1.004-2.176 1.84-3.18.836-1.007 1.84-1.843 3.008-2.343 1.172-.672 2.508-1.008 3.512-1.008.168 1.34 0 2.512-.5 3.852-.504 1.171-1.004 2.343-1.84 3.347-.836.84-1.84 1.676-2.844 2.344zm0 0" fill="#c6a8e5"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M64 32c0 17.645-14.355 32-32 32S0 49.645 0 32 14.355 0 32 0s32 14.355 32 32" fill="#999"/><g fill="#fff"><path d="M54.313 34.422c-1.036-6.746-8.13-11.242-13.493-14.531-2.246-1.383-6.054-3.286-6.57-6.399-.176-1.21-.176-2.594-.176-3.805V8.13c0-.692-.691.172-1.035-.344-.867-1.387-.52.344-.52 1.211.172 1.727.52 3.457.52 5.188 0 3.285-.52 6.574-1.387 9.687-1.902 7.438-3.457 15.223-1.554 22.832a24.518 24.518 0 0 0 1.554 4.668c.176.52.52 1.73 1.211 1.906 2.078.516 3.633.692 5.192 2.246 1.039.868 1.73.348 2.941 0 3.633-1.382 6.746-3.285 9.34-6.226 3.285-4.496 4.844-9.512 3.977-14.875m-3.805 6.746c-.344 2.766-2.074 5.363-3.805 7.437-1.383 1.56-3.113 3.461-5.016 4.153-.69.172.172-1.211.172-1.211.52-.867 1.383-1.73 2.075-2.594 1.039-1.21 1.902-2.598 2.421-3.98 1.903-5.016 1.56-10.899-1.382-15.395-1.555-2.422-3.805-4.496-5.88-6.398-1.038-.868-2.077-1.73-2.94-2.77-.176-.172-2.079-2.594-1.387-2.941.175-.172 4.152 3.98 4.5 4.324 1.554 1.21 3.285 2.422 4.843 3.809 2.075 1.902 4.149 3.976 5.36 6.57 1.21 2.77 1.386 6.055 1.039 8.996"/><path d="M30.79.863c.519.348.69 2.77.69 4.844 0 2.078.172 11.246-.52 13.664-.69 2.422-2.245 5.192-3.804 7.613-1.73 2.422-3.633 7.438-3.457 10.551 0 3.113 1.903 8.13 3.285 10.38 1.383 2.073 3.805 5.015 3.286 5.706-.864 1.211-4.668-2.941-6.747-5.363-1.902-2.422-3.976-7.262-3.976-11.07 0-3.805 2.074-7.262 3.633-9.34 1.554-2.075 4.496-5.707 5.36-7.438.866-1.73 1.73-3.457 1.901-5.707.348-2.25 0-10.55 0-10.55S30.27.52 30.79.862"/><path d="M29.234 4.844c.516.343.692 1.039.692 1.73 0 .692-.176 3.633-.348 6.57-.172 2.942-2.594 5.364-4.152 7.094-1.727 1.73-6.746 7.09-8.473 9.688-1.906 2.594-2.77 6.05-2.598 8.992.176 2.941.868 5.883 3.633 8.996 2.77 3.113 4.672 4.496 6.227 5.363 1.387.692 2.941 1.211 2.597 1.903-.347.691-1.73.172-3.289-.348-1.554-.52-6.746-2.594-9.687-6.055-2.938-3.457-4.496-7.957-4.324-12.105.175-4.324 1.386-6.055 3.289-8.824 1.902-2.766 7.437-6.918 9.168-7.957 1.73-1.036 3.976-2.766 5.187-4.325 1.211-1.382 1.73-2.593 1.73-4.668 0-1.902.173-3.804 0-4.5-.171-.515-.171-1.902.348-1.554m.172 51.89c.344 0 .172 1.211-.347 1.73-.52.52-1.211.864-1.383.692s.52-.343 1.039-.863c.52-.691.344-1.559.691-1.559m5.36-.172c-.344 0-.172 1.211.347 1.731s1.211.863 1.383.691c.176-.172-.52-.347-1.035-.867-.52-.515-.348-1.554-.695-1.554m-2.418 1.382c0 1.04 0 1.903-.176 1.903-.344 0-.172-.864-.172-1.903 0-1.039-.172-1.902.172-1.902.348 0 .176.863.176 1.902"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="82" xmlns="http://www.w3.org/2000/svg"><g fill="#3c3"><path d="M0 .094v63.812h82V.094zM77.34 4.8v27.86L57.773 17.6 36.34 39.247l-15.094-8.469L4.844 43.953V4.801zm0 0"/><path d="M22.55 17.223c0 3.222-2.585 5.836-5.777 5.836-3.191 0-5.777-2.614-5.777-5.836s2.586-5.836 5.777-5.836c3.192 0 5.778 2.613 5.778 5.836zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="80" xmlns="http://www.w3.org/2000/svg"><path d="M38.027 37.414c-5.011-4.812-9.425-9.223-12.03-19.25H43.64v-7.219H26.195V1.121h-7.617v10.024H.93v7.421h18.047s-.2 1.403-.399 2.606C15.968 30.996 13.164 37.215.93 43.23l2.61 7.418c11.429-6.015 17.444-13.835 20.05-22.257 2.605 6.418 6.816 11.629 11.629 16.441zM61.29 13.352H51.262L33.617 62.879h7.617l5.016-14.836H66.3l5.013 14.836h7.62zm-12.434 27.27 7.622-19.65 7.617 19.852zm0 0" fill="#a87c2d" stroke="#a87c2d" stroke-miterlimit="10" stroke-width="1.5039150000000001"/></svg> |
| 1 | ||
| 1 | <svg height="63" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M55.809.504S31.965.832 16.73 19.992c-.828 1.145-1.656 2.13-2.484 3.274-.496.656-.996 7.207-.996 7.207s-.66-.493-.992-1.309c-.496-.984-.664-2.129-.664-2.129C2.984 40.953 5.469 48.16 5.469 48.16c-.664 1.637-1.989 2.617-3.809 6.387C-.16 58.313.004 61.914.004 61.914c0 .656.164.82.496.164 0 0 1.988-3.766 3.477-6.223.996-1.636 3.976-5.402 3.976-5.402s4.969.16 10.93-1.312c-.496-.164-2.153-.657-3.313-1.145-1.16-.492-1.82-1.312-1.82-1.312l21.36-4.91c2.98-1.801 5.628-3.93 7.785-6.551 11.257-13.266 14.074-33.57 14.074-33.57.164-.657-.332-1.15-1.16-1.15zM34.613 21.629s-9.937 8.68-14.902 13.266C14.742 39.48 8.117 50.453 8.117 50.453L5.633 48.16s1.824-4.422 9.11-13.265c7.12-8.68 19.538-14.083 19.538-14.083 1.492-.656 1.657-.328.332.817zm0 0" fill="#ef712f"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="80" xmlns="http://www.w3.org/2000/svg"><path d="M38.027 37.414c-5.011-4.812-9.425-9.223-12.03-19.25H43.64v-7.219H26.195V1.121h-7.617v10.024H.93v7.421h18.047s-.2 1.403-.399 2.606C15.968 30.996 13.164 37.215.93 43.23l2.61 7.418c11.429-6.015 17.444-13.835 20.05-22.257 2.605 6.418 6.816 11.629 11.629 16.441zM61.29 13.352H51.262L33.617 62.879h7.617l5.016-14.836H66.3l5.013 14.836h7.62zm-12.434 27.27 7.622-19.65 7.617 19.852zm0 0" fill="#c93" stroke="#c93" stroke-miterlimit="10" stroke-width="1.5039150000000001"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="70" xmlns="http://www.w3.org/2000/svg"><g fill="#f57e00" stroke="#f57e00" stroke-miterlimit="10"><path d="M53 47.7H19a3.116 3.116 0 0 0-3.101 3.1v21.8c0 1.7 1.4 3.1 3.101 3.1h14.2L31.8 81h-1.6c-.7 0-1.2.501-1.2 1.2s.5 1.2 1.2 1.2h11.5c.7 0 1.2-.501 1.2-1.2s-.5-1.2-1.2-1.2H40l-1.4-5.4H53c1.7 0 3.101-1.4 3.101-3.1V50.8c0-1.7-1.4-3.1-3.101-3.1zm.3 25.1H18.7V50.6h34.5zm0 0" transform="matrix(1.69903 0 0 1.72133 -26.165 -80.833)"/><path d="M27.6 63.9h2.8v5.6h-2.8zm4.7-1.8h2.801v7.4h-2.8zM36.9 60.2h2.8v9.302h-2.8zm4.6-1.8h2.8v11.102h-2.8zm-.2-4.098L36.4 56.999l-3.6-1.198-6.1 3.3.9.998 5.4-2.798 3.6 1.198 5.6-3.1.9 1.001 2.101-3.5-4.8.3zm0 0" transform="matrix(1.69903 0 0 1.72133 -26.165 -80.833)"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="70" xmlns="http://www.w3.org/2000/svg"><g fill="#f57e00" stroke="#f57e00" stroke-miterlimit="10"><path d="M53 47.7H19a3.116 3.116 0 0 0-3.101 3.1v21.8c0 1.7 1.4 3.1 3.101 3.1h14.2L31.8 81h-1.6c-.7 0-1.2.501-1.2 1.2s.5 1.2 1.2 1.2h11.5c.7 0 1.2-.501 1.2-1.2s-.5-1.2-1.2-1.2H40l-1.4-5.4H53c1.7 0 3.101-1.4 3.101-3.1V50.8c0-1.7-1.4-3.1-3.101-3.1zm.3 25.1H18.7V50.6h34.5zm0 0" transform="matrix(1.69903 0 0 1.72133 -26.165 -80.833)"/><path d="M27.6 63.9h2.8v5.6h-2.8zm4.7-1.8h2.801v7.4h-2.8zM36.9 60.2h2.8v9.302h-2.8zm4.6-1.8h2.8v11.102h-2.8zm-.2-4.098L36.4 56.999l-3.6-1.198-6.1 3.3.9.998 5.4-2.798 3.6 1.198 5.6-3.1.9 1.001 2.101-3.5-4.8.3zm0 0" transform="matrix(1.69903 0 0 1.72133 -26.165 -80.833)"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="70" xmlns="http://www.w3.org/2000/svg"><g fill="#f57e00" stroke="#f57e00" stroke-miterlimit="10"><path d="M53 47.7H19a3.116 3.116 0 0 0-3.101 3.1v21.8c0 1.7 1.4 3.1 3.101 3.1h14.2L31.8 81h-1.6c-.7 0-1.2.501-1.2 1.2s.5 1.2 1.2 1.2h11.5c.7 0 1.2-.501 1.2-1.2s-.5-1.2-1.2-1.2H40l-1.4-5.4H53c1.7 0 3.101-1.4 3.101-3.1V50.8c0-1.7-1.4-3.1-3.101-3.1zm.3 25.1H18.7V50.6h34.5zm0 0" transform="matrix(1.69903 0 0 1.72133 -26.165 -80.833)"/><path d="M27.6 63.9h2.8v5.6h-2.8zm4.7-1.8h2.801v7.4h-2.8zM36.9 60.2h2.8v9.302h-2.8zm4.6-1.8h2.8v11.102h-2.8zm-.2-4.098L36.4 56.999l-3.6-1.198-6.1 3.3.9.998 5.4-2.798 3.6 1.198 5.6-3.1.9 1.001 2.101-3.5-4.8.3zm0 0" transform="matrix(1.69903 0 0 1.72133 -26.165 -80.833)"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="70" xmlns="http://www.w3.org/2000/svg"><g fill="#f57e00" stroke="#f57e00" stroke-miterlimit="10"><path d="M53 47.7H19a3.116 3.116 0 0 0-3.101 3.1v21.8c0 1.7 1.4 3.1 3.101 3.1h14.2L31.8 81h-1.6c-.7 0-1.2.501-1.2 1.2s.5 1.2 1.2 1.2h11.5c.7 0 1.2-.501 1.2-1.2s-.5-1.2-1.2-1.2H40l-1.4-5.4H53c1.7 0 3.101-1.4 3.101-3.1V50.8c0-1.7-1.4-3.1-3.101-3.1zm.3 25.1H18.7V50.6h34.5zm0 0" transform="matrix(1.69903 0 0 1.72133 -26.165 -80.833)"/><path d="M27.6 63.9h2.8v5.6h-2.8zm4.7-1.8h2.801v7.4h-2.8zM36.9 60.2h2.8v9.302h-2.8zm4.6-1.8h2.8v11.102h-2.8zm-.2-4.098L36.4 56.999l-3.6-1.198-6.1 3.3.9.998 5.4-2.798 3.6 1.198 5.6-3.1.9 1.001 2.101-3.5-4.8.3zm0 0" transform="matrix(1.69903 0 0 1.72133 -26.165 -80.833)"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="70" xmlns="http://www.w3.org/2000/svg"><g fill="#f57e00" stroke="#f57e00" stroke-miterlimit="10"><path d="M53 47.7H19a3.116 3.116 0 0 0-3.101 3.1v21.8c0 1.7 1.4 3.1 3.101 3.1h14.2L31.8 81h-1.6c-.7 0-1.2.501-1.2 1.2s.5 1.2 1.2 1.2h11.5c.7 0 1.2-.501 1.2-1.2s-.5-1.2-1.2-1.2H40l-1.4-5.4H53c1.7 0 3.101-1.4 3.101-3.1V50.8c0-1.7-1.4-3.1-3.101-3.1zm.3 25.1H18.7V50.6h34.5zm0 0" transform="matrix(1.69903 0 0 1.72133 -26.165 -80.833)"/><path d="M27.6 63.9h2.8v5.6h-2.8zm4.7-1.8h2.801v7.4h-2.8zM36.9 60.2h2.8v9.302h-2.8zm4.6-1.8h2.8v11.102h-2.8zm-.2-4.098L36.4 56.999l-3.6-1.198-6.1 3.3.9.998 5.4-2.798 3.6 1.198 5.6-3.1.9 1.001 2.101-3.5-4.8.3zm0 0" transform="matrix(1.69903 0 0 1.72133 -26.165 -80.833)"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="70" xmlns="http://www.w3.org/2000/svg"><g fill="#f57e00" stroke="#f57e00" stroke-miterlimit="10"><path d="M53 47.7H19a3.116 3.116 0 0 0-3.101 3.1v21.8c0 1.7 1.4 3.1 3.101 3.1h14.2L31.8 81h-1.6c-.7 0-1.2.501-1.2 1.2s.5 1.2 1.2 1.2h11.5c.7 0 1.2-.501 1.2-1.2s-.5-1.2-1.2-1.2H40l-1.4-5.4H53c1.7 0 3.101-1.4 3.101-3.1V50.8c0-1.7-1.4-3.1-3.101-3.1zm.3 25.1H18.7V50.6h34.5zm0 0" transform="matrix(1.69903 0 0 1.72133 -26.165 -80.833)"/><path d="M27.6 63.9h2.8v5.6h-2.8zm4.7-1.8h2.801v7.4h-2.8zM36.9 60.2h2.8v9.302h-2.8zm4.6-1.8h2.8v11.102h-2.8zm-.2-4.098L36.4 56.999l-3.6-1.198-6.1 3.3.9.998 5.4-2.798 3.6 1.198 5.6-3.1.9 1.001 2.101-3.5-4.8.3zm0 0" transform="matrix(1.69903 0 0 1.72133 -26.165 -80.833)"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="54" xmlns="http://www.w3.org/2000/svg"><path d="M10.867 48.152c0 1.551 1.04 2.582 2.602 2.582h2.773v9.305c0 2.066 1.91 3.961 3.992 3.961s3.989-1.895 3.989-3.96v-9.306h5.379v9.305c0 2.066 1.91 3.961 3.992 3.961s3.988-1.895 3.988-3.96v-9.306h2.602c1.562 0 2.605-1.03 2.605-2.757V21.449H10.867zM4.097 21.45C2.017 21.45.11 23.344.11 25.41v18.606c0 2.066 1.907 3.96 3.989 3.96s3.992-1.894 3.992-3.96V25.41c0-2.066-1.735-3.96-3.992-3.96zm45.805 0c-2.082 0-3.992 1.895-3.992 3.961v18.606c0 2.066 1.91 3.96 3.992 3.96s3.989-1.894 3.989-3.96V25.41c0-2.066-1.907-3.96-3.989-3.96zM36.367 5.945l3.473-3.449c.52-.516.52-1.375 0-1.894a1.373 1.373 0 0 0-1.91 0L33.94 4.566c-1.91-1.379-4.34-1.894-6.941-1.894-2.777 0-5.031.515-7.285 1.55L15.898.259c-.523-.344-1.562-.344-2.082 0-.347.515-.347 1.55 0 2.066l3.47 3.446c-3.817 2.93-6.419 7.41-6.419 12.75h32.266c0-5.168-2.602-9.82-6.766-12.575zm-14.746 7.407h-2.773v-2.586h2.773zm13.531 0H32.38v-2.586h2.773zm0 0" fill="#999"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M16.223 21.805.09 55.844l3.012 3.015 20.035-20.035c-.711-1.594-.532-3.543.886-4.96 1.774-1.774 4.43-1.774 6.204 0 1.773 1.769 1.773 4.429 0 6.202-1.243 1.243-3.368 1.594-4.965.887L5.23 60.984 8.242 64l34.04-16.133L49.73 27.48 36.61 14.36zm46.625-4.075L46.184 1.062c-1.418-1.417-3.547-1.417-4.965 0L37.32 4.966c-1.422 1.418-1.422 3.543 0 4.965l16.664 16.664c1.418 1.418 3.543 1.418 4.965 0l3.899-3.903c1.418-1.418 1.418-3.543 0-4.96zm0 0" fill="#fea500"/></svg> |
| 1 | ||
| 1 | <svg height="63" width="51" xmlns="http://www.w3.org/2000/svg"><g fill="#737373"><path d="M28.21 1.082 6.696 13.367v24.414l21.516 12.285 21.516-12.285V13.367zm0 0"/><path d="m6.695 13.367 21.516 12.285 21.516-12.285L28.21 1.082zM6.695 37.781l21.516 12.285 21.516-12.285L28.21 25.652zm0 0"/></g><path d="M6.055 39.04 27.57 51.167c.16.156.48.156.64.156.157 0 .477-.156.638-.156l21.515-12.285c.477-.156.637-.63.637-1.102V13.367c0-.472-.16-.785-.637-1.101L28.848.136c-.48-.156-.797-.156-1.278 0L6.055 12.423c-.477.16-.637.633-.637 1.101v24.57c0 .16.16.634.637.946zM28.21 2.5l18.965 10.867L28.21 24.395 9.242 13.367zm2.547 23.152 17.691-10.078v21.574L29.484 48.02V26.44M7.97 35.574v-20L25.66 25.652l1.274.79V48.02L7.969 37.148" fill="#fff"/><path d="M11.953 35.102.637 41.559v12.757l11.316 6.457 11.156-6.457V41.56zm0 0" fill="#fff"/><path d="m.637 41.559 11.316 6.3 11.156-6.3-11.156-6.457zm0 12.757 11.316 6.457 11.156-6.457-11.156-6.457zm0 0" fill="#fff"/><path d="m.32 54.95 11.313 6.456c.16.157.16.157.32.157s.16 0 .32-.157l11.313-6.457c.16-.16.32-.316.32-.472V41.559c0-.157-.16-.473-.32-.473l-11.313-6.457a.496.496 0 0 0-.64 0L.32 41.086c-.16.16-.32.316-.32.473v12.757c0 .16.16.473.32.633zm11.633-19.06 9.883 5.669-9.883 5.828-9.883-5.828zm1.274 11.97 9.246-5.196v11.34l-9.883 5.512v-11.34M1.434 53.215v-10.55l9.246 5.194.636.473v11.34l-9.882-5.668" fill="#444"/><path d="m24.383 45.656-7.328 4.094v8.348l7.328 4.254 7.332-4.254V49.75zm0 0" fill="#517889"/><path d="m17.055 49.75 7.328 4.094 7.332-4.094-7.332-4.094zm0 8.348 7.328 4.254 7.332-4.254-7.332-4.254zm0 0" fill="#517889"/><path d="m16.895 58.57 7.332 4.254c.156 0 .156.156.156.156s.16 0 .16-.156l7.332-4.254c.16-.156.16-.156.16-.472V49.75c0-.156-.16-.316-.16-.473l-7.332-4.254c-.16-.156-.316-.156-.477 0l-7.332 4.254c-.16.157-.16.157-.16.473v8.348c.16.156.16.316.32.472zm7.488-12.441 6.535 3.621-6.535 3.621-6.531-3.777zm.957 7.715 5.898-3.465v7.402l-6.535 3.625V54.16m-7.172 3.149v-6.77l5.899 3.465.476.156v7.246l-6.535-3.625" fill="#fff"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="74" xmlns="http://www.w3.org/2000/svg"><path d="M7.225 18.125c-1 0-2-.1-2.8-.3v12.1h-3.8v-27.7v12.1m19.5 27.5m0 0miterlimit="10transform="matrix(2.05225 0 0 2.0612 .316 0)"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="82" xmlns="http://www.w3.org/2000/svg"><g fill="#3c3"><path d="M0 .094v63.812h82V.094zM77.34 4.8v27.86L57.773 17.6 36.34 39.247l-15.094-8.469L4.844 43.953V4.801zm0 0"/><path d="M22.55 17.223c0 3.222-2.585 5.836-5.777 5.836-3.191 0-5.777-2.614-5.777-5.836s2.586-5.836 5.777-5.836c3.192 0 5.778 2.613 5.778 5.836zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="69" xmlns="http://www.w3.org/2000/svg"><g fill="#1d6fb5"><path d="M18.754 25.742c-2.668.36-4.8 3.219-4.8 6.258s2.132 6.078 4.8 6.258c2.668.355 4.805-2.504 4.805-6.258s-2.137-6.613-4.805-6.258zm0 0"/><path d="M.074 7.508v49.52L38.504 64V0zm18.68 34.683c-4.27-.539-7.649-5.187-7.649-10.191 0-5.184 3.38-9.652 7.649-10.191 4.27-.536 7.652 4.113 7.652 10.191 0 6.258-3.383 10.727-7.652 10.191zm50.172-27.175L47.754 32.715l-5.691-4.649v-14.66h26.863zm0 0"/><path d="m68.926 18.414-21.172 17.7-5.691-4.65V51.31h26.863zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><g fill="#077265"><path d="M23.91 25.406c0-4.746-2.285-7.031-5.976-7.031-1.407 0-2.461.176-3.164.527V32.97c.703.351 1.582.527 2.636.527 4.219-.351 6.504-2.992 6.504-8.09zm0 0"/><path d="m0 53.715 38.68 9.844V.44L0 10.285zm11.605-38.508c1.582-.527 3.692-.703 6.153-.703 3.34 0 5.625 1.055 7.035 2.992 1.406 1.758 2.285 4.219 2.285 7.559s-.703 5.976-1.933 7.738c-1.762 2.637-4.575 4.043-7.739 4.043-1.054 0-1.933 0-2.636-.352v14.418h-3.34V15.207zm30.418-6.855v3.867h13.008V23.12H42.023v4.043h13.008v4.746H42.023v3.871h13.008v4.922H42.023v4.219h13.008v4.926H42.023v8.086H64V8.352zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg height="63" width="62" xmlns="http://www.w3.org/2000/svg"><path d="M29.816 62.316c-7.492-.168-12.261-2.523-13.453-6.398l-.172-.504V47.84c0-8.758 0-8.926.512-10.27.852-2.527 2.895-4.21 5.961-4.882l.68-.168h8.687c6.301 0 8.852 0 9.196-.168 1.87-.34 2.894-.676 3.914-1.516 1.363-1.012 2.386-2.695 2.726-4.379.34-1.348.34-1.18.34-5.89v-4.212h6.129l.684.168c3.234 1.012 5.617 3.872 6.64 8.586.34 1.852.34 1.852.34 6.399 0 4.379 0 4.379-.34 5.89-.34 1.348-.683 2.696-1.363 3.875-1.192 2.356-3.067 4.04-5.277 4.715-1.364.504-.172.336-12.774.504h-11.41v2.02h14.988v7.746c-.172.504-.172 1.008-.683 1.683-.508.672-1.36 1.512-1.871 2.02-2.043 1.348-5.11 2.187-9.196 2.355zm10.387-4.714c1.363-.168 2.555-1.684 2.215-3.028-.172-1.18-1.023-2.023-2.215-2.191-1.871-.168-3.406 1.347-3.066 3.031.172 1.348 1.363 2.188 2.726 2.188zM7.848 46.66c-1.703-.336-3.403-1.347-4.598-2.863C1.04 41.105-.152 36.39.016 30.668c.172-3.54.68-6.23 1.875-8.59 1.359-3.027 3.574-4.543 6.468-5.219.684-.168.684-.168 11.75-.168h11.239c.172 0 .172-.168.172-1.007v-1.012H16.535V10.8c0-4.211 0-4.211.34-5.051 1.363-2.695 5.11-4.379 11.066-4.883.512 0 1.536-.168 2.727-.168 6.64-.168 11.578 1.008 14.133 3.367l.851.84c.34.508.852 1.348 1.024 2.192l.168.504v8.082c0 7.406 0 8.078-.168 8.586-.172.671-.512 1.683-.684 2.187-1.02 1.852-2.722 3.031-4.937 3.703-1.364.336-.852.336-10.387.508-9.535 0-9.027 0-10.387.336-2.726.672-4.597 2.691-5.281 5.555-.34 1.347-.34 1.18-.34 5.89v4.38h-2.894c-2.895 0-3.746 0-3.918-.169zm16.007-36.027c1.024-.508 1.875-1.852 1.532-2.863-.34-1.012-1.02-1.852-1.871-2.188-1.532-.508-3.235.504-3.407 2.188-.168 1.347.512 2.695 1.875 3.03.168.169.508.169 1.02.169.34-.168.34-.168.851-.336zm0 0" fill="#fed142"/><path d="M7.848 46.66c-1.703-.336-3.403-1.347-4.598-2.863C1.04 41.105-.152 36.39.016 30.668c.171-3.54.68-6.23 1.875-8.59 1.359-3.027 3.574-4.543 6.468-5.219.684-.168.684-.168 11.75-.168h11.239c.172 0 .172-.168.172-1.007v-1.012H16.535V10.8c0-4.211 0-4.211.34-5.051 1.363-2.695 5.11-4.379 11.066-4.883.512 0 1.536-.168 2.727-.168 6.64-.168 11.578 1.008 14.133 3.367l.851.84c.34.508.852 1.348 1.024 2.192l.168.504v8.082c0 7.406 0 8.078-.168 8.586-.172.671-.512 1.683-.684 2.187-1.02 1.852-2.722 3.031-4.937 3.703-1.364.336-.852.336-10.387.508-9.535 0-9.027 0-10.387.336-2.726.672-4.597 2.691-5.281 5.555-.34 1.347-.34 1.18-.34 5.89v4.38h-2.894c-2.895 0-3.746 0-3.918-.169zm16.007-36.027c1.024-.508 1.875-1.852 1.532-2.863-.34-1.012-1.02-1.852-1.871-2.188-1.532-.508-3.235.504-3.407 2.188-.168 1.347.512 2.695 1.875 3.03.168.169.508.169 1.02.169.34-.168.34-.168.851-.336zm0 0" fill="#3571a3"/></svg> |
| 1 | ||
| 1 | <svg height="63" width="62" xmlns="http://www.w3.org/2000/svg"><g fill="#666"><path d="M29.816 62.316c-7.492-.168-12.261-2.523-13.453-6.398l-.172-.504V47.84c0-8.758 0-8.926.512-10.27.852-2.527 2.895-4.21 5.961-4.882l.68-.168h8.687c6.301 0 8.852 0 9.196-.168 1.87-.34 2.894-.676 3.914-1.516 1.363-1.012 2.386-2.695 2.726-4.379.34-1.348.34-1.18.34-5.89v-4.212h6.129l.684.168c3.234 1.012 5.617 3.872 6.64 8.586.34 1.852.34 1.852.34 6.399 0 4.379 0 4.379-.34 5.89-.34 1.348-.683 2.696-1.363 3.875-1.192 2.356-3.067 4.04-5.277 4.715-1.364.504-.172.336-12.774.504h-11.41v2.02h14.988v7.746c-.172.504-.172 1.008-.683 1.683-.508.672-1.36 1.512-1.871 2.02-2.043 1.348-5.11 2.187-9.196 2.355zm10.387-4.714c1.363-.168 2.555-1.684 2.215-3.028-.172-1.18-1.023-2.023-2.215-2.191-1.871-.168-3.406 1.347-3.066 3.031.172 1.348 1.363 2.188 2.726 2.188zM7.848 46.66c-1.703-.336-3.403-1.347-4.598-2.863C1.04 41.105-.152 36.39.016 30.668c.172-3.54.68-6.23 1.875-8.59 1.359-3.027 3.574-4.543 6.468-5.219.684-.168.684-.168 11.75-.168h11.239c.172 0 .172-.168.172-1.007v-1.012H16.535V10.8c0-4.211 0-4.211.34-5.051 1.363-2.695 5.11-4.379 11.066-4.883.512 0 1.536-.168 2.727-.168 6.64-.168 11.578 1.008 14.133 3.367l.851.84c.34.508.852 1.348 1.024 2.192l.168.504v8.082c0 7.406 0 8.078-.168 8.586-.172.671-.512 1.683-.684 2.187-1.02 1.852-2.722 3.031-4.937 3.703-1.364.336-.852.336-10.387.508-9.535 0-9.027 0-10.387.336-2.726.672-4.597 2.691-5.281 5.555-.34 1.347-.34 1.18-.34 5.89v4.38h-2.894c-2.895 0-3.746 0-3.918-.169zm16.007-36.027c1.024-.508 1.875-1.852 1.532-2.863-.34-1.012-1.02-1.852-1.871-2.188-1.532-.508-3.235.504-3.407 2.188-.168 1.347.512 2.695 1.875 3.03.168.169.508.169 1.02.169.34-.168.34-.168.851-.336zm0 0"/><path d="M7.848 46.66c-1.703-.336-3.403-1.347-4.598-2.863C1.04 41.105-.152 36.39.016 30.668c.171-3.54.68-6.23 1.875-8.59 1.359-3.027 3.574-4.543 6.468-5.219.684-.168.684-.168 11.75-.168h11.239c.172 0 .172-.168.172-1.007v-1.012H16.535V10.8c0-4.211 0-4.211.34-5.051 1.363-2.695 5.11-4.379 11.066-4.883.512 0 1.536-.168 2.727-.168 6.64-.168 11.578 1.008 14.133 3.367l.851.84c.34.508.852 1.348 1.024 2.192l.168.504v8.082c0 7.406 0 8.078-.168 8.586-.172.671-.512 1.683-.684 2.187-1.02 1.852-2.722 3.031-4.937 3.703-1.364.336-.852.336-10.387.508-9.535 0-9.027 0-10.387.336-2.726.672-4.597 2.691-5.281 5.555-.34 1.347-.34 1.18-.34 5.89v4.38h-2.894c-2.895 0-3.746 0-3.918-.169zm16.007-36.027c1.024-.508 1.875-1.852 1.532-2.863-.34-1.012-1.02-1.852-1.871-2.188-1.532-.508-3.235.504-3.407 2.188-.168 1.347.512 2.695 1.875 3.03.168.169.508.169 1.02.169.34-.168.34-.168.851-.336zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M.238 64h83.524V0H.238zm16.16-4.91H6.41V52h9.988zm30.688 0h-9.988V52h9.988zM67.602 4.363h9.988v7.274h-9.988zm0 47.453h9.988v7.094h-9.988zM52.168 4.363h9.805v7.09h-9.985v-7.09zm0 47.453h9.805v7.094h-9.985zM36.914 4.363h9.988v7.09h-9.988zM35.464 22l13.071 7.453c2.363 1.457 2.363 3.637 0 5.094L35.465 42c-2.363 1.453-4.36.184-4.36-2.547v-15.09c0-2.547 1.997-3.816 4.36-2.363zM21.485 4.363h9.805v7.09h-9.805zm0 47.453h9.805v7.094h-9.805zM6.41 4.363h9.988v7.274H6.41zm0 0" fill="#f60"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="83" xmlns="http://www.w3.org/2000/svg"><linearGradient id="a" gradientTransform="matrix(.14059 0 0 .09419 -.088 -.345)" gradientUnits="userSpaceOnUse" x1=".741" x2="590.86" y1="3.666" y2="593.79"><stop offset="0" stop-color="#cbced0"/><stop offset="1" stop-color="#84838b"/></linearGradient><linearGradient id="b" gradientTransform="matrix(.1139 0 0 .11627 -.088 -.345)" gradientUnits="userSpaceOnUse" x1="301.03" x2="703.07" y1="151.4" y2="553.44"><stop offset="0" stop-color="#276dc3"/><stop offset="1" stop-color="#165caa"/></linearGradient><g fill-rule="evenodd"><path d="M41.5 55.586C18.59 55.586.016 43.14.016 27.793.016 12.441 18.59 0 41.5 0s41.484 12.441 41.484 27.793c0 15.348-18.574 27.793-41.484 27.793zm6.352-44.719c-17.414 0-31.536 8.504-31.536 19 0 10.492 14.122 19 31.536 19s30.265-5.816 30.265-19c0-13.18-12.851-19-30.265-19zm0 0" fill="url(#a)"/><path d="M63.195 43.047s2.508.758 3.97 1.496c.503.254 1.382.766 2.01 1.437.622.657.923 1.325.923 1.325l9.894 16.687L64 64l-7.48-14.047s-1.532-2.633-2.473-3.398c-.785-.637-1.121-.864-1.899-.864h-3.8l.004 18.297-14.153.008V17.258h28.418s12.946.23 12.946 12.55-12.368 13.235-12.368 13.235zM57.04 27.395l-8.566-.004-.008 7.945 8.574-.004s3.969-.012 3.969-4.039c0-4.113-3.969-3.898-3.969-3.898zm0 0" fill="url(#b)"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="84" height="54"><path style="fill-rule:nonzero;fill:#039;fill-opacity:1;stroke-width:.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#039;stroke-opacity:1;stroke-miterlimit:10" d="m10.45 23.48-7.7-8.5v-.1l7.7-8.5V.68L.25 12.681v4.5l10.2 11.898zM36.25.679V6.38l7.9 8.5v.1l-7.9 8.5v5.6l10.2-11.7v-4.9zM28.549 5.08c-1.299-.6-3-1.6-3.598-3 0-.7-.602-1.3-1.301-1.3-.7 0-1.299.6-1.299 1.3v17.3c-1.3-.7-3.9-.5-5.9.6-3.002 1.7-4.3 4.899-3.002 7.2 1.301 2.2 5.002 2.7 8 1 2.1-1.2 3.502-3.2 3.601-5.1v-15c4.4 0 7 1.8 6 6-.199.8-.401 1.6-.8 2.299-.2.302-.2.5.1.802.2.198.6.198 1-.2 1.7-1.6 2.7-3.7 2.7-6.001 0-2.9-2.9-4.8-5.501-5.9zm0 0" transform="matrix(1.79872 0 0 1.81157 0 .047)"/></svg> |
| 1 | ||
| 1 | <svg height="63" width="54" xmlns="http://www.w3.org/2000/svg"><path d="M53.344 18.172H44.02V8.965zM28.309 8.965v33.437h25.199V20.434H41.727V8.964zm3.93-8.723H4.417v6.461h10.965l-6.875 5.332v5.652l10.148-7.753V6.867H54V4.281zM18.655 14.297 8.508 22.05v5.652l10.148-7.754zM8.344 37.559l10.148-7.754v-5.657L8.344 31.902zm10.312 2.261v-5.656L8.508 41.918v2.91h-4.09v6.461h6.219v4.523H7.035c-.652-1.132-1.797-1.937-3.273-1.937C1.637 53.875 0 55.488 0 57.59c0 2.097 1.637 3.715 3.762 3.715 1.476 0 2.62-.809 3.273-1.938h3.602v3.39h5.562v-3.39h3.602c.652 1.13 1.8 1.938 3.273 1.938 2.125 0 3.762-1.618 3.762-3.715 0-2.102-1.637-3.715-3.762-3.715-1.472 0-2.62.805-3.273 1.938h-3.602v-4.524h15.875l21.762-3.879v-2.582H11.78zm0 0" fill="#90c"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="82" xmlns="http://www.w3.org/2000/svg"><g fill="#3c3"><path d="M0 .094v63.812h82V.094zM77.34 4.8v27.86L57.773 17.6 36.34 39.247l-15.094-8.469L4.844 43.953V4.801zm0 0"/><path d="M22.55 17.223c0 3.222-2.585 5.836-5.777 5.836-3.191 0-5.777-2.614-5.777-5.836s2.586-5.836 5.777-5.836c3.192 0 5.778 2.613 5.778 5.836zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M61.988 2.012v59.976L46.996 17.004zM2.012 61.988h59.976L17.004 46.996zm14.992-14.992 44.984 14.992L32 32zM32 32l29.988 29.988-14.992-44.984zM2.012 46.996v14.992l14.992-14.992zM32 32H17.004v14.996zm14.996-14.996H32V32zM61.988 2.012H46.996v14.992zM17.004 32 2.012 46.996h14.992zM32 17.004 17.004 32H32zM46.996 2.012 32 17.004h14.996zm0 0" fill="#992315" stroke="#fff" stroke-width="1.66605"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="83" height="54"><path style="fill-rule:nonzero;fill:#999;fill-opacity:1;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#999;stroke-opacity:1;stroke-miterlimit:10" d="M11.242 25.867c-.5 0-1.1-.2-1.498-.6l-8.4-8.401c-.802-.799-.802-2.099 0-3l8.4-8.398c.8-.8 2.098-.8 2.999 0 .8.8.8 2.098 0 2.999l-6.9 6.9 6.9 6.9c.8.801.8 2.1 0 3-.401.4-1 .6-1.5.6zm25.1 0c-.499 0-1.099-.2-1.5-.6-.8-.8-.8-2.099 0-3.002l6.9-6.898-6.9-6.9c-.8-.8-.8-2.101 0-3 .8-.8 2.1-.8 3.001 0l8.398 8.4c.802.8.802 2.1 0 3l-8.398 8.4c-.4.4-1.001.6-1.5.6zm-16.7 4.1c-.199 0-.398 0-.698-.1-1.102-.401-1.702-1.5-1.301-2.6l8.398-25.1c.4-1.1 1.5-1.699 2.6-1.301 1.102.4 1.702 1.5 1.301 2.601l-8.398 25.1c-.202.899-1.102 1.4-1.901 1.4zm0 0" transform="matrix(1.74425 0 0 1.75713 0 .013)"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="83" height="54"><path style="fill-rule:nonzero;fill:#999;fill-opacity:1;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#999;stroke-opacity:1;stroke-miterlimit:10" d="M11.242 25.867c-.5 0-1.1-.2-1.498-.6l-8.4-8.401c-.802-.799-.802-2.099 0-3l8.4-8.398c.8-.8 2.098-.8 2.999 0 .8.8.8 2.098 0 2.999l-6.9 6.9 6.9 6.9c.8.801.8 2.1 0 3-.401.4-1 .6-1.5.6zm25.1 0c-.499 0-1.099-.2-1.5-.6-.8-.8-.8-2.099 0-3.002l6.9-6.898-6.9-6.9c-.8-.8-.8-2.101 0-3 .8-.8 2.1-.8 3.001 0l8.398 8.4c.802.8.802 2.1 0 3l-8.398 8.4c-.4.4-1.001.6-1.5.6zm-16.7 4.1c-.199 0-.398 0-.698-.1-1.102-.401-1.702-1.5-1.301-2.6l8.398-25.1c.4-1.1 1.5-1.699 2.6-1.301 1.102.4 1.702 1.5 1.301 2.601l-8.398 25.1c-.202.899-1.102 1.4-1.901 1.4zm0 0" transform="matrix(1.74425 0 0 1.75713 0 .013)"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M0 56.355v-7.644h15.29V64H0zm22.754 0v-7.644h15.289V64h-15.29zm22.933 0v-7.644h15.29V64h-15.29zM48 38.934l-5.332-5.332L48 28.266l5.332-5.332 5.336 5.332L64 33.602l-5.332 5.332a125.106 125.106 0 0 1-5.336 5.332zM0 33.602v-7.645h15.29v15.29H0zm22.754 0v-7.645h15.289v15.29h-15.29zM25.066 16l-5.332-5.332 5.332-5.336L30.398 0l5.336 5.332 5.332 5.336L35.734 16c-2.843 3.023-5.336 5.332-5.336 5.332zM0 10.668V3.023h15.29v15.29H0zm0 0" fill="#3a898d"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M21.344 36.297c-1.871 1.527-3.739 2.887-5.61 4.246L4.52 49.211c-.512.34-.852.508-1.36.168A15.884 15.884 0 0 0 .781 48.19c-.511-.171-.68-.511-.68-1.02V17.267c0-.34.34-.852.508-1.02.852d5006e"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="54" xmlns="http://www.w3.org/2000/svg"><path d="M54 36.781c0 14.856-12.04 26.813-27 26.813S0 51.637 0 36.78c0-5.12 1.547-9.906 4.129-14.004l8.77 4.953a16.11 16.11 0 0 0-2.75 9.051c0 9.223 7.566 16.735 16.851 16.735s16.852-7.512 16.852-16.735c0-7.683-5.329-14.172-12.551-16.222v8.539L6.19 14.754 31.301.406v9.906C44.199 12.364 54 23.462 54 36.782zm0 0" fill="#bababa"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M.238 64h83.524V0H.238zm16.16-4.91H6.41V52h9.988zm30.688 0h-9.988V52h9.988zM67.602 4.363h9.988v7.274h-9.988zm0 47.453h9.988v7.094h-9.988zM52.168 4.363h9.805v7.09h-9.985v-7.09zm0 47.453h9.805v7.094h-9.985zM36.914 4.363h9.988v7.09h-9.988zM35.464 22l13.071 7.453c2.363 1.457 2.363 3.637 0 5.094L35.465 42c-2.363 1.453-4.36.184-4.36-2.547v-15.09c0-2.547 1.997-3.816 4.36-2.363zM21.485 4.363h9.805v7.09h-9.805zm0 47.453h9.805v7.094h-9.805zM6.41 4.363h9.988v7.274H6.41zm0 0" fill="#f60"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="76" xmlns="http://www.w3.org/2000/svg"><linearGradient id="a" gradientTransform="matrix(.08235 0 0 .05573 -.06 .108)" gradientUnits="userSpaceOnUse" x1=".741" x2="590.86" y1="3.666" y2="593.79"><stop offset="0" stop-color="#cbced0"/><stop offset="1" stop-color="#84838b"/></linearGradient><linearGradient id="b" gradientTransform="matrix(.06671 0 0 .0688 -.06 .108)" gradientUnits="userSpaceOnUse" x1="301.03" x2="703.07" y1="151.4" y2="553.44"><stop offset="0" stop-color="#276dc3"/><stop offset="1" stop-color="#165caa"/></linearGradient><path d="M27.406 63.688V41.383h6.48l6.477 8.187 6.48-8.187h6.481v22.304h-6.48V50.898l-6.48 8.184-6.477-8.184v12.79zm38.875 0-9.719-10.844h6.481V41.383h6.477v11.46H76zm0 0" fill="#999"/><g fill-rule="evenodd"><path d="M24.297 33.2C10.879 33.2 0 25.84 0 16.757S10.879.312 24.297.312c13.422 0 24.3 7.364 24.3 16.446s-10.878 16.441-24.3 16.441zm3.719-26.458c-10.2 0-18.47 5.031-18.47 11.242 0 6.207 8.27 11.243 18.47 11.243s17.73-3.442 17.73-11.243c0-7.797-7.531-11.242-17.73-11.242zm0 0" fill="url(#a)"/><path d="M37.004 25.781s1.473.45 2.324.887c.297.152.813.453 1.18.852.363.386.539.78.539.78l5.797 9.876-9.367.004-4.38-8.313s-.898-1.555-1.449-2.008c-.46-.375-.66-.511-1.113-.511H28.31l.003 10.828-8.289.004V10.523h16.645s7.582.137 7.582 7.426c0 7.29-7.246 7.832-7.246 7.832zm-3.606-9.258-5.015-.003-.004 4.703 5.02-.004s2.324-.008 2.324-2.39c0-2.434-2.325-2.306-2.325-2.306zm0 0" fill="url(#b)"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M68.633.102H16.39v7.226H5.738v2.274H0v2.062h5.738v2.684h10.653V26.94H5.738v2.477H0v2.066h5.738v2.27h10.653v13.625H5.738v2.48H0v2.063h5.738v2.273h10.653v9.703h52.242v-9.703h9.629v-2.48H84v-2.063h-5.738v-2.476h-9.63v-13.63h9.63v-2.062H84v-2.066h-5.738v-2.684h-9.63V14.141h9.63v-2.684H84V9.395h-5.738V7.12h-9.63zm-10.04 17.136c-2.253 0-4.097-1.86-4.097-4.129S56.34 8.98 58.594 8.98s4.097 1.86 4.097 4.13c0 2.476-1.843 4.128-4.097 4.128zm0 0" fill="#099"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="74" xmlns="http://www.w3.org/2000/svg"><path d="m49.332 34.941-12.25-5.714L61.75 17.633 74 23.348l-12.25 5.879zM61.75 6.207 49.5.492 37.25 6.207l24.5 11.594L74 12.086zm-37.082 17.14-12.25-5.714-12.25 5.715L24.836 34.94l12.246-5.714zm0-11.429 12.25-5.711L24.668.492 0 12.086 12.25 17.8zM61.75 32.59l-11.074 5.039-1.344.672-1.34-.672-11.074-5.04-11.078 5.04-1.34.672-1.344-.672-11.074-5.04v17.977L36.75 63.508l25-12.942zm0 0" fill="#55486d"/></svg> |
| 1 | ||
| 1 | <svg height="63" width="47" xmlns="http://www.w3.org/2000/svg"><path d="M10.62.6c-.398 0-.8.3-.998.7l-1 1.901h-6.8c-.7 0-1.302.6-1.302 1.2-.098 10.6.2 21.299 0 31.899 0 .7.602 1.3 1.302 1.3H26.02c.7 0 1.302-.6 1.302-1.3V4.4c0-.6-.602-1.302-1.302-1.302h-6.799l-1-1.899c-.2-.4-.7-.7-1.2-.7-2.2.1-4.501.1-6.4.1zm0 0" fill="#666" stroke="#666" stroke-miterlimit="10" transform="matrix(1.67417 0 0 1.65354 .211 0)"/><path d="M5.438 9.426h7.53c0 2.148.169 4.133 2.18 4.133h17.075c2.175 0 2.175-2.149 2.175-4.133h7.536v48.449H5.605c-.168-16.207-.168-32.41-.168-48.45zm0 0" fill="#fff"/><path d="M10.793 21H36.41v4.3H10.793zm0 8.434H36.41v4.296H10.793zm0 8.433H36.41V42H10.793zm0 8.434h17.078v4.297H10.793zm0 0" fill="#666"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="52" xmlns="http://www.w3.org/2000/svg"><path d="M48.793 26.879h-4.629V18.05C44.164 7.988 35.973.043 26 .043S7.836 8.164 7.836 18.051v8.828H3.207A3.181 3.181 0 0 0 0 30.059V60.78c0 1.762 1.426 3.176 3.207 3.176h45.586c1.781 0 3.207-1.414 3.207-3.176V29.883c0-1.59-1.426-3.004-3.207-3.004zM29.918 52.305c.355 1.058-.535 1.941-1.602 1.941h-4.808c-1.07 0-1.781-1.059-1.606-1.941l1.426-5.649c-1.781-.883-3.027-2.648-3.027-4.945 0-3 2.492-5.473 5.52-5.473 3.027 0 5.523 2.473 5.523 5.473 0 2.117-1.246 4.062-3.028 4.945zm5.164-25.426H16.918V18.05c0-4.942 4.098-9.004 9.082-9.004s9.082 4.062 9.082 9.004zm0 0" fill="#696"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M14.54 49.375c1.593 1.594 2.48 3.723 2.48 6.027 0 2.305-.887 4.43-2.48 6.028a8.46 8.46 0 0 1-6.032 2.48 8.451 8.451 0 0 1-6.028-2.48C.887 59.832 0 57.883 0 55.402c0-2.304.887-4.433 2.48-6.027a8.439 8.439 0 0 1 6.028-2.484c2.484 0 4.433 1.066 6.031 2.484zM.175 21.719v12.23c7.98 0 15.426 3.192 21.097 8.688 5.676 5.672 8.688 13.12 8.688 21.097h12.234c0-11.523-4.789-22.16-12.41-29.785C22.16 26.504 11.7 21.72.175 21.72zm0-21.63V12.32c28.367 0 51.59 23.227 51.59 51.59H64c0-17.55-7.09-33.504-18.793-45.027C33.684 7.18 17.73.09.176.09zm0 0" fill="#dd7d36"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="76" xmlns="http://www.w3.org/2000/svg"><path d="M.176 52.977h75.648V64H.176zm0-26.309h75.648v11.02H.176zM.176 0h75.648v11.023H.176zm0 0" fill="#999"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="76" xmlns="http://www.w3.org/2000/svg"><path d="M.176 52.977h75.648V64H.176zm0-26.309h75.648v11.02H.176zM.176 0h75.648v11.023H.176zm0 0" fill="#666"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M61.988 2.012v59.976L46.996 17.004zM2.012 61.988h59.976L17.004 46.996zm14.992-14.992 44.984 14.992L32 32zM32 32l29.988 29.988-14.992-44.984zM2.012 46.996v14.992l14.992-14.992zM32 32H17.004v14.996zm14.996-14.996H32V32zM61.988 2.012H46.996v14.992zM17.004 32 2.012 46.996h14.992zM32 17.004 17.004 32H32zM46.996 2.012 32 17.004h14.996zm0 0" fill="#666" stroke="#fff" stroke-width="1.66605"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M61.988 2.012v59.976L46.996 17.004zM2.012 61.988h59.976L17.004 46.996zm14.992-14.992 44.984 14.992L32 32zM32 32l29.988 29.988-14.992-44.984zM2.012 46.996v14.992l14.992-14.992zM32 32H17.004v14.996zm14.996-14.996H32V32zM61.988 2.012H46.996v14.992zM17.004 32 2.012 46.996h14.992zM32 17.004 17.004 32H32zM46.996 2.012 32 17.004h14.996zm0 0" fill="#992315" stroke="#fff" stroke-width="1.66605"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="71" xmlns="http://www.w3.org/2000/svg"><linearGradient id="a" gradientTransform="matrix(.07693 0 0 .05184 -.057 .13)" gradientUnits="userSpaceOnUse" x1=".741" x2="590.86" y1="3.666" y2="593.79"><stop offset="0" stop-color="#cbced0"/><stop offset="1" stop-color="#84838b"/></linearGradient><linearGradient id="b" gradientTransform="matrix(.06233 0 0 .064 -.057 .13)" gradientUnits="userSpaceOnUse" x1="301.03" x2="703.07" y1="151.4" y2="553.44"><stop offset="0" stop-color="#276dc3"/><stop offset="1" stop-color="#165caa"/></linearGradient><path d="M22.7 30.914C10.163 30.914 0 24.066 0 15.617 0 7.168 10.164.32 22.7.32c12.534 0 22.698 6.848 22.698 15.297 0 8.45-10.16 15.297-22.699 15.297zm3.476-24.613c-9.531 0-17.254 4.683-17.254 10.457 0 5.777 7.723 10.46 17.254 10.46 9.527 0 16.558-3.202 16.558-10.46 0-7.254-7.03-10.457-16.558-10.457zm0 0" fill="url(#a)" fill-rule="evenodd"/><path d="M34.57 24.016s1.375.414 2.172.82c.278.144.758.426 1.102.793.34.363.504.73.504.73l5.414 9.184-8.75.004-4.094-7.73s-.836-1.45-1.352-1.872c-.43-.347-.613-.472-1.039-.472H26.45v10.07l-7.742.004V9.82h15.55s7.083.13 7.083 6.907c0 6.78-6.77 7.285-6.77 7.285zm-3.367-8.618h-4.687l-.004 4.372h4.691s2.172-.008 2.172-2.227c0-2.262-2.172-2.145-2.172-2.145zm0 0" fill="url(#b)" fill-rule="evenodd"/><path d="M-24.46 120.549a1.43 1.43 0 0 1-.97-.386l-5.364-5.43c-.517-.517-.517-1.357 0-1.94l5.43-5.43c.515-.517 1.357-.517 1.938 0 .518.517.518 1.36 0 1.94l-4.46 4.461 4.46 4.46c.518.517.518 1.356 0 1.939-.322.257-.71.386-1.035.386zm16.222 0a1.43 1.43 0 0 1-.97-.386c-.517-.517-.517-1.357 0-1.94l4.461-4.459-4.46-4.461c-.518-.517-.518-1.357 0-1.94.517-.517 1.357-.517 1.94 0l5.428 5.43c.517.517.517 1.357 0 1.94l-5.427 5.43a1.432 1.432 0 0 1-.972.386zm-10.793 2.65c-.13 0-.26 0-.452-.062-.71-.26-1.098-.971-.84-1.683l5.427-16.222c.26-.711.972-1.1 1.683-.84.71.257 1.098.969.84 1.68l-5.43 16.222c-.13.583-.71.906-1.228.906zm0 0" fill="#999" stroke="#999" stroke-miterlimit="10" stroke-width=".97" transform="matrix(1.47916 0 0 1.48836 72.435 -120.409)"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="83" height="63"><path style="fill-rule:nonzero;fill:#cd6799;fill-opacity:1;stroke-width:.25;stroke-linecap:butt;stroke-linejoin:miter;stroke:#cd6799;stroke-opacity:1;stroke-miterlimit:10" d="M40.764 20.63c-1.602 0-3.101.4-4.3 1-.4-.9-.9-1.601-1.001-2.198-.1-.7-.2-1.001-.1-1.8.1-.804.599-1.904.599-2.003 0-.098-.1-.498-1-.498-.998 0-1.797.099-1.797.4-.101.197-.302.799-.4 1.398-.102.9-1.903 3.901-2.903 5.502-.3-.7-.6-1.201-.7-1.6-.1-.701-.2-1.002-.1-1.8.1-.802.6-1.902.6-2.001 0-.101-.1-.498-1-.498s-1.801.098-1.801.4c-.096.3-.197.798-.398 1.4-.2.597-2.5 5.598-3.1 6.999-.302.698-.6 1.2-.7 1.598v.101c-.099.301-.3.5-.3.5-.1.2-.3.4-.4.4-.101 0-.101-.599 0-1.5.4-1.8 1.199-4.5 1.199-4.6 0-.1.1-.5-.5-.8-.7-.2-.9.101-.997.101-.103 0-.103.099-.103.099s.7-3.1-1.399-3.1c-1.3 0-3.2 1.5-4.2 2.801-.6.299-1.8.997-3.2 1.697-.499.301-1 .602-1.5.802l-.1-.101c-2.598-2.8-7.5-4.8-7.3-8.6.099-1.398.5-4.999 9.3-9.3 7.202-3.598 13-2.6 13.9-.4 1.4 3.2-3.1 9.002-10.6 9.799-2.901.303-4.3-.797-4.7-1.199-.4-.4-.4-.4-.6-.4-.2.102-.098.501 0 .701.2.6 1.202 1.6 2.699 2.101 1.4.397 4.7.698 8.702-.9 4.498-1.8 8.099-6.602 6.998-10.7-1-4.102-7.9-5.5-14.4-3.202-3.898 1.401-8.098 3.5-11.1 6.4-3.6 3.4-4.099 6.2-3.9 7.502.801 4.299 6.8 7.1 9.202 9.199-.1.1-.201.1-.302.1-1.2.6-5.7 2.901-6.897 5.5-1.3 2.9.197 4.898 1.2 5.1 3.099.898 6.198-.7 7.897-3.2 1.7-2.501 1.501-5.8.702-7.3v-.101c.3-.1.7-.4.998-.499.6-.4 1.2-.7 1.7-1-.299.8-.5 1.8-.599 3.2-.098 1.6.5 3.7 1.399 4.5.4.4.8.4 1.103.4.998 0 1.497-.801 1.998-1.8.6-1.2 1.2-2.6 1.2-2.6s-.7 3.799 1.2 3.799c.7 0 1.4-.9 1.7-1.3l.1-.099.1-.1c.299-.501.9-1.5 1.8-3.401 1.2-2.3 2.3-5.298 2.3-5.298s.1.698.4 1.899c.2.7.7 1.5 1 2.2-.3.4-.401.6-.401.6-.2.3-.398.599-.698.998-1 1.1-2.101 2.402-2.2 2.802-.1.4-.1.7.197 1 .201.2.703.2 1.202.2.8-.1 1.499-.3 1.698-.4.4-.1 1-.4 1.502-.8 1-.7 1.499-1.601 1.4-2.9 0-.701-.3-1.4-.5-2.1.1-.1.1-.2.2-.4 1.5-2.1 2.6-4.5 2.6-4.5s.1.7.4 1.9c.1.6.5 1.2.8 1.9-1.4 1.1-2.202 2.4-2.5 3.2-.5 1.501-.1 2.3.699 2.399.4.1.9-.101 1.202-.299.499-.1 1-.4 1.6-.801 1-.698 1.799-1.6 1.799-2.898 0-.602-.1-1.203-.4-1.701 1.2-.501 2.602-.7 4.5-.501 4.099.5 4.9 3.001 4.8 4.101-.1 1.1-1 1.7-1.3 1.8-.3.1-.4.2-.4.4s.1.1.4.1c.4-.1 2.1-.9 2.199-2.9.201-2.2-2.2-4.9-6.4-4.9zm-31.5 10.701c-1.3 1.5-3.203 2.099-4.002 1.5-.9-.501-.499-2.7 1.101-4.301.998-1 2.3-1.8 3.2-2.299.2-.1.5-.3.799-.5.1 0 .1-.101.1-.101.101-.101.101-.101.202-.101.6 2.2 0 4.1-1.4 5.802zm9.9-6.801c-.401 1.2-1.5 4.1-2.1 4-.501-.101-.801-2.301-.1-4.5.4-1.1 1.199-2.4 1.6-2.901.7-.8 1.499-1.1 1.799-.7.2.202-.9 3.4-1.2 4.1zm8.1 3.899c-.202.1-.403.1-.403.1l.1-.1s1-1.1 1.402-1.599c.199-.298.5-.7.8-1v.1c-.1 1.199-1.4 2.1-1.9 2.5zm6.2-1.401c-.1-.099-.1-.4.399-1.5.2-.399.7-1.1 1.4-1.8.1.301.1.503.1.802 0 1.6-1.102 2.2-1.9 2.498zm0 0" transform="matrix(1.7456 0 0 1.77926 .217 0)"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="83" height="63"><path style="fill-rule:nonzero;fill:#cd6799;fill-opacity:1;stroke-width:.25;stroke-linecap:butt;stroke-linejoin:miter;stroke:#cd6799;stroke-opacity:1;stroke-miterlimit:10" d="M40.764 20.63c-1.602 0-3.101.4-4.3 1-.4-.9-.9-1.601-1.001-2.198-.1-.7-.2-1.001-.1-1.8.1-.804.599-1.904.599-2.003 0-.098-.1-.498-1-.498-.998 0-1.797.099-1.797.4-.101.197-.302.799-.4 1.398-.102.9-1.903 3.901-2.903 5.502-.3-.7-.6-1.201-.7-1.6-.1-.701-.2-1.002-.1-1.8.1-.802.6-1.902.6-2.001 0-.101-.1-.498-1-.498s-1.801.098-1.801.4c-.096.3-.197.798-.398 1.4-.2.597-2.5 5.598-3.1 6.999-.302.698-.6 1.2-.7 1.598v.101c-.099.301-.3.5-.3.5-.1.2-.3.4-.4.4-.101 0-.101-.599 0-1.5.4-1.8 1.199-4.5 1.199-4.6 0-.1.1-.5-.5-.8-.7-.2-.9.101-.997.101-.103 0-.103.099-.103.099s.7-3.1-1.399-3.1c-1.3 0-3.2 1.5-4.2 2.801-.6.299-1.8.997-3.2 1.697-.499.301-1 .602-1.5.802l-.1-.101c-2.598-2.8-7.5-4.8-7.3-8.6.099-1.398.5-4.999 9.3-9.3 7.202-3.598 13-2.6 13.9-.4 1.4 3.2-3.1 9.002-10.6 9.799-2.901.303-4.3-.797-4.7-1.199-.4-.4-.4-.4-.6-.4-.2.102-.098.501 0 .701.2.6 1.202 1.6 2.699 2.101 1.4.397 4.7.698 8.702-.9 4.498-1.8 8.099-6.602 6.998-10.7-1-4.102-7.9-5.5-14.4-3.202-3.898 1.401-8.098 3.5-11.1 6.4-3.6 3.4-4.099 6.2-3.9 7.502.801 4.299 6.8 7.1 9.202 9.199-.1.1-.201.1-.302.1-1.2.6-5.7 2.901-6.897 5.5-1.3 2.9.197 4.898 1.2 5.1 3.099.898 6.198-.7 7.897-3.2 1.7-2.501 1.501-5.8.702-7.3v-.101c.3-.1.7-.4.998-.499.6-.4 1.2-.7 1.7-1-.299.8-.5 1.8-.599 3.2-.098 1.6.5 3.7 1.399 4.5.4.4.8.4 1.103.4.998 0 1.497-.801 1.998-1.8.6-1.2 1.2-2.6 1.2-2.6s-.7 3.799 1.2 3.799c.7 0 1.4-.9 1.7-1.3l.1-.099.1-.1c.299-.501.9-1.5 1.8-3.401 1.2-2.3 2.3-5.298 2.3-5.298s.1.698.4 1.899c.2.7.7 1.5 1 2.2-.3.4-.401.6-.401.6-.2.3-.398.599-.698.998-1 1.1-2.101 2.402-2.2 2.802-.1.4-.1.7.197 1 .201.2.703.2 1.202.2.8-.1 1.499-.3 1.698-.4.4-.1 1-.4 1.502-.8 1-.7 1.499-1.601 1.4-2.9 0-.701-.3-1.4-.5-2.1.1-.1.1-.2.2-.4 1.5-2.1 2.6-4.5 2.6-4.5s.1.7.4 1.9c.1.6.5 1.2.8 1.9-1.4 1.1-2.202 2.4-2.5 3.2-.5 1.501-.1 2.3.699 2.399.4.1.9-.101 1.202-.299.499-.1 1-.4 1.6-.801 1-.698 1.799-1.6 1.799-2.898 0-.602-.1-1.203-.4-1.701 1.2-.501 2.602-.7 4.5-.501 4.099.5 4.9 3.001 4.8 4.101-.1 1.1-1 1.7-1.3 1.8-.3.1-.4.2-.4.4s.1.1.4.1c.4-.1 2.1-.9 2.199-2.9.201-2.2-2.2-4.9-6.4-4.9zm-31.5 10.701c-1.3 1.5-3.203 2.099-4.002 1.5-.9-.501-.499-2.7 1.101-4.301.998-1 2.3-1.8 3.2-2.299.2-.1.5-.3.799-.5.1 0 .1-.101.1-.101.101-.101.101-.101.202-.101.6 2.2 0 4.1-1.4 5.802zm9.9-6.801c-.401 1.2-1.5 4.1-2.1 4-.501-.101-.801-2.301-.1-4.5.4-1.1 1.199-2.4 1.6-2.901.7-.8 1.499-1.1 1.799-.7.2.202-.9 3.4-1.2 4.1zm8.1 3.899c-.202.1-.403.1-.403.1l.1-.1s1-1.1 1.402-1.599c.199-.298.5-.7.8-1v.1c-.1 1.199-1.4 2.1-1.9 2.5zm6.2-1.401c-.1-.099-.1-.4.399-1.5.2-.399.7-1.1 1.4-1.8.1.301.1.503.1.802 0 1.6-1.102 2.2-1.9 2.498zm0 0" transform="matrix(1.7456 0 0 1.77926 .217 0)"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="51" xmlns="http://www.w3.org/2000/svg"><path d="M23.023 63.957c-8.199-.34-15.543-2.875-19.468-6.77-1.196-1.011-2.39-2.535-2.903-3.55L.31 52.96v-7.617c0-7.614 0-7.614.171-6.934.34 1.692 1.368 3.383 2.903 4.735 1.023.847 3.074 2.37 4.781 3.214 2.906 1.524 6.66 2.54 10.59 3.047 2.39.34 3.246.34 6.66.34 3.418 0 4.27 0 6.66-.34 3.93-.508 7.516-1.691 10.59-3.047 1.707-.843 3.758-2.199 4.781-3.214 1.368-1.352 2.563-3.043 2.903-4.735.172-.508.172-.508.172 6.934v7.445l-.34.68c-1.196 2.367-3.246 4.398-5.98 6.09-5.294 3.046-13.321 4.738-21.177 4.398zm0-18.95c-7.171-.339-13.832-2.37-18.101-5.413-1.027-.68-2.39-2.032-2.906-2.707-.512-.68-1.024-1.524-1.364-2.371L.31 33.84v-7.445c0-7.446 0-7.446.171-6.938.34 1.184.852 2.54 1.88 3.555.511.675 1.367 1.523 1.878 1.86.168.171.684.339 1.024.679 3.414 2.367 8.199 4.058 13.664 4.906 2.39.336 3.242.336 6.66.336 3.414 0 4.27 0 6.66-.336 3.93-.508 7.516-1.691 10.59-3.047 1.707-.847 3.758-2.2 4.781-3.215 1.367-1.351 2.39-3.047 2.903-4.738.171-.508.171-.508.171 6.938v7.445l-.511 1.015c-.856 1.524-1.368 2.368-2.39 3.383-1.028 1.016-2.052 1.864-3.419 2.54-5.465 3.046-13.492 4.738-21.348 4.23zm-.511-18.78c-4.782-.34-8.54-1.184-12.125-2.54-4.27-1.69-7.344-3.89-8.883-6.597a5.594 5.594 0 0 1-.852-2.031C.48 14.383.31 12.69.48 11.676 1.504 6.262 8.848 1.859 18.754.34 21.144 0 22 0 25.414 0c3.418 0 4.27 0 6.66.34 3.93.508 7.516 1.691 10.59 3.043 4.441 2.199 7.172 5.078 7.684 8.12.172.849.172 2.708-.168 3.388-.512 1.691-1.196 2.707-2.563 4.058-3.586 3.723-9.906 6.094-17.762 6.938-1.023.34-6.32.34-7.343.34zm0 0" fill="#a03537"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="79" xmlns="http://www.w3.org/2000/svg"><path d="m42.852 35.445 4.695 1.344 2.851-10.418-4.695-1.344c0-1.68-.168-3.359-.672-5.039l4.192-2.52-5.364-9.405-4.359 2.519a18.036 18.036 0 0 0-4.023-3.023l1.34-4.704L26.421 0l-1.34 4.703c-1.676 0-3.352.168-5.027.672l-2.516-4.2-9.387 5.376 2.512 4.199a18.053 18.053 0 0 0-3.016 4.031l-4.695-1.343L.105 23.852l4.692 1.343c0 1.68.168 3.36.672 5.04l-4.192 2.523 5.364 9.406 4.191-2.52a18.126 18.126 0 0 0 4.023 3.024l-1.34 4.703 10.395 2.856 1.34-4.704c1.676 0 3.352-.168 5.031-.671l2.512 4.199 9.39-5.375-2.515-4.2c1.172-1.175 2.348-2.519 3.184-4.03zm-25.985-5.547c-2.68-4.535-1.004-10.414 3.52-13.101 4.527-2.688 10.394-1.008 13.078 3.527 2.683 4.535 1.004 10.414-3.52 13.106-4.527 2.687-10.394 1.175-13.078-3.532zm50.63 33.262 6.034-3.527-1.676-2.856c.84-.84 1.508-1.68 2.012-2.687l3.184.84 1.844-6.887-3.184-.84c0-1.176-.168-2.183-.504-3.36l2.852-1.679-3.52-6.047-2.852 1.68c-.84-.84-1.675-1.512-2.683-2.016l.84-3.191-6.875-1.852-.836 3.196c-1.176 0-2.18.168-3.356.504l-1.675-2.86-5.7 3.7 1.676 2.855c-.836.84-1.508 1.68-2.012 2.687l-3.183-1.007-1.844 6.886 3.184.84c0 1.176.168 2.184.504 3.36l-2.852 1.68 3.523 6.046 2.848-1.68c.84.84 1.676 1.512 2.684 2.016l-.84 3.191L61.965 64l.836-3.191c1.176 0 2.18-.168 3.355-.504-.336 0 1.34 2.855 1.34 2.855zM57.101 50.563c-1.676-3.024-.668-6.887 2.347-8.567 3.02-1.68 6.875-.672 8.551 2.352 1.676 3.023.672 6.886-2.348 8.566-3.015 1.68-6.875.672-8.55-2.352zm0 0" fill="#999"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="69" xmlns="http://www.w3.org/2000/svg"><path d="M13.875 13.874h10.9v2.701h-10.9zm0 5.4h10.9v2.701h-10.9zm0 5.5h10.9v2.702h-10.9zm19-24.399H11.177c-3 0-5.402 2.4-5.402 5.4v24.4h-5.4c0 3 2.402 5.4 5.4 5.4h21.7c3 0 5.402-2.4 5.402-5.4v-21.7h5.4v-2.7c0-3-2.402-5.4-5.4-5.4zm-2.7 29.3c0 1.801-1.4 3.2-3.2 3.2h-19.9c1.3-.9 1.3-2.7 1.3-2.7v-24.4c0-1.5 1.2-2.7 2.7-2.7 1.501 0 2.7 1.2 2.7 2.7v2.7h16.3zm-13.6-23.9v-2.7h16.3c2.501 0 2.7 1.6 2.7 2.7zm0 0" fill="#999" stroke="#999" stroke-miterlimit="10" stroke-width=".75" transform="matrix(1.7717 0 0 1.78025 .262 0)"/></svg> |
| 1 | ||
| 1 | <svg height="63" width="54" xmlns="http://www.w3.org/2000/svg"><path d="M53.344 18.172H44.02V8.965zM28.309 8.965v33.437h25.199V20.434H41.727V8.964zm3.93-8.723H4.417v6.461h10.965l-6.875 5.332v5.652l10.148-7.753V6.867H54V4.281zM18.655 14.297 8.508 22.05v5.652l10.148-7.754zM8.344 37.559l10.148-7.754v-5.657L8.344 31.902zm10.312 2.261v-5.656L8.508 41.918v2.91h-4.09v6.461h6.219v4.523H7.035c-.652-1.132-1.797-1.937-3.273-1.937C1.637 53.875 0 55.488 0 57.59c0 2.097 1.637 3.715 3.762 3.715 1.476 0 2.62-.809 3.273-1.938h3.602v3.39h5.562v-3.39h3.602c.652 1.13 1.8 1.938 3.273 1.938 2.125 0 3.762-1.618 3.762-3.715 0-2.102-1.637-3.715-3.762-3.715-1.472 0-2.62.805-3.273 1.938h-3.602v-4.524h15.875l21.762-3.879v-2.582H11.78zm0 0" fill="#90c"/></svg> |
| 1 | ||
| 1 | <svg height="63" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M56.645 44.492c-.348-.512-.864-.68-1.38-.68H38.728c-.516 1.188-1.204 2.376-1.723 3.567-1.375 2.715-2.926 5.773-4.305 8.32v.168c-.863 1.528-2.41 2.38-4.133 2.38s-3.273-.852-4.136-2.38c-.516-.847-2.239-4.074-4.477-8.32-.691-1.188-1.207-2.379-1.723-3.567H9.27c-.516 0-1.204.34-1.375.852L.14 60.793a2.327 2.327 0 0 0 0 1.527c.343.512.863.68 1.379.68h46.34c.515 0 1.203-.34 1.374-.848l7.754-15.965c0-.68 0-1.187-.343-1.695zm0 0" fill="#039"/><path d="M28.39 0c-9.472 0-17.222 7.64-17.222 16.98 0 5.606 6.2 18.852 11.367 29.04 2.41 4.753 4.309 8.32 4.48 8.32.344.508.86.847 1.376.847.52 0 1.035-.34 1.379-.847 0 0 1.894-3.567 4.48-8.32 5.168-10.188 11.367-23.434 11.367-29.04C45.617 7.64 37.867 0 28.391 0zm0 27.168c-4.304 0-7.921-3.223-8.265-7.469v-.851c0-4.582 3.79-8.32 8.441-8.32 4.305 0 7.922 3.226 8.266 7.472v.848c0 4.586-3.789 8.32-8.441 8.32zm0 0" fill="#efce4a"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M21.344 36.297c-1.871 1.527-3.739 2.887-5.61 4.246L4.52 49.211c-.512.34-.852.508-1.36.168A15.884 15.884 0 0 0 .781 48.19c-.511-.171-.68-.511-.68-1.02V17.267c0-.34.34-.852.508-1.02.852d5006e"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="70" xmlns="http://www.w3.org/2000/svg"><g fill="#c60" stroke="#c60" stroke-miterlimit="10"><path d="M53 47.7H19a3.116 3.116 0 0 0-3.101 3.1v21.8c0 1.7 1.4 3.1 3.101 3.1h14.2L31.8 81h-1.6c-.7 0-1.2.501-1.2 1.2s.5 1.2 1.2 1.2h11.5c.7 0 1.2-.501 1.2-1.2s-.5-1.2-1.2-1.2H40l-1.4-5.4H53c1.7 0 3.101-1.4 3.101-3.1V50.8c0-1.7-1.4-3.1-3.101-3.1zm.3 25.1H18.7V50.6h34.5zm0 0" transform="matrix(1.69903 0 0 1.72133 -26.165 -80.833)"/><path d="M27.6 63.9h2.8v5.6h-2.8zm4.7-1.8h2.801v7.4h-2.8zM36.9 60.2h2.8v9.302h-2.8zm4.6-1.8h2.8v11.102h-2.8zm-.2-4.098L36.4 56.999l-3.6-1.198-6.1 3.3.9.998 5.4-2.798 3.6 1.198 5.6-3.1.9 1.001 2.101-3.5-4.8.3zm0 0" transform="matrix(1.69903 0 0 1.72133 -26.165 -80.833)"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="70" xmlns="http://www.w3.org/2000/svg"><g fill="#c60" stroke="#c60" stroke-miterlimit="10"><path d="M53 47.7H19a3.116 3.116 0 0 0-3.101 3.1v21.8c0 1.7 1.4 3.1 3.101 3.1h14.2L31.8 81h-1.6c-.7 0-1.2.501-1.2 1.2s.5 1.2 1.2 1.2h11.5c.7 0 1.2-.501 1.2-1.2s-.5-1.2-1.2-1.2H40l-1.4-5.4H53c1.7 0 3.101-1.4 3.101-3.1V50.8c0-1.7-1.4-3.1-3.101-3.1zm.3 25.1H18.7V50.6h34.5zm0 0" transform="matrix(1.69903 0 0 1.72133 -26.165 -80.833)"/><path d="M27.6 63.9h2.8v5.6h-2.8zm4.7-1.8h2.801v7.4h-2.8zM36.9 60.2h2.8v9.302h-2.8zm4.6-1.8h2.8v11.102h-2.8zm-.2-4.098L36.4 56.999l-3.6-1.198-6.1 3.3.9.998 5.4-2.798 3.6 1.198 5.6-3.1.9 1.001 2.101-3.5-4.8.3zm0 0" transform="matrix(1.69903 0 0 1.72133 -26.165 -80.833)"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M21.344 36.297c-1.871 1.527-3.739 2.887-5.61 4.246L4.52 49.211c-.512.34-.852.508-1.36.168A15.884 15.884 0 0 0 .781 48.19c-.511-.171-.68-.511-.68-1.02V17.267c0-.34.34-.852.508-1.02.852d5006e"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M30.871 11.793h2.602c.867 0 1.39-.691 1.39-1.387v-9.02C34.863.52 34.168 0 33.473 0H30.87c-.867 0-1.387.695-1.387 1.387v8.847c-.172.868.52 1.559 1.387 1.559zm21.336 18.906v2.602c0 .867.691 1.386 1.387 1.386h9.02c.866 0 1.386-.69 1.386-1.386v-2.602c0-.867-.695-1.387-1.387-1.387h-9.02c-.695-.175-1.386.52-1.386 1.387zM33.301 64c.867 0 1.386-.695 1.386-1.387v-9.02c0-.866-.69-1.386-1.386-1.386h-2.602c-.867 0-1.387.691-1.387 1.387v9.02c0 .866.692 1.386 1.387 1.386zM1.387 34.687h9.02c.866 0 1.386-.69 1.386-1.386v-2.602c0-.867-.691-1.387-1.387-1.387h-9.02C.52 29.313 0 30.005 0 30.7v2.602c0 .695.695 1.386 1.387 1.386zM47.176 18.56c.52.52 1.562.52 2.082 0l6.418-6.418c.52-.52.52-1.563 0-2.082L53.94 8.324c-.52-.52-1.562-.52-2.082 0l-6.418 6.418c-.52.52-.52 1.563 0 2.082zM53.94 55.5l1.735-1.734c.52-.52.52-1.559 0-2.078l-6.418-6.418c-.52-.524-1.563-.524-2.082 0l-1.735 1.734c-.52.52-.52 1.559 0 2.082L51.86 55.5c.52.523 1.387.523 2.082 0zm-41.629 0 6.418-6.414c.524-.523.524-1.563 0-2.082l-1.734-1.734c-.52-.524-1.558-.524-2.082 0L8.5 51.687c-.523.52-.523 1.56 0 2.079l1.734 1.734c.692.523 1.559.523 2.079 0zm2.602-36.941c.523.52 1.563.52 2.082 0l1.734-1.735c.524-.52.524-1.562 0-2.082l-6.418-6.418c-.519-.52-1.558-.52-2.078 0L8.5 10.06c-.523.52-.523 1.562 0 2.082zm0 0" fill="#fea500"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><g fill="#bababa"><path d="M30.906 0h3.746v2.496h-3.746zm31.532 26.066c.156-2.027 0-4.058-.465-5.93h-8.899v-3.745h7.18a15.572 15.572 0 0 0-2.031-2.496l-8.895-8.899-1.406 14.047c-.313 3.59-2.027 6.871-4.527 9.367v6.242h4.996c2.808 0 5.308 1.094 7.18 2.657 2.808-1.72 4.84-4.371 6.09-7.336h-8.587v-3.75h9.364zM34.651 2.652V7.18h-3.746V2.652H19.98l1.563 15.922c.312 2.813 1.559 5.465 3.746 7.34 2.027 1.871 4.836 2.965 7.648 2.965 2.81 0 5.461-1.094 7.649-2.965 2.027-1.875 3.434-4.527 3.746-7.34l1.563-15.922zm5.153 12.176h-4.996v6.09h-3.746v-6.09h-4.997v-3.746h13.739zm0 0"/><path d="M48.234 38.242h-8.742v-7.336c-2.027 1.094-4.37 1.563-6.71 1.563-2.344 0-4.684-.625-6.716-1.563v7.336h-8.738a7.33 7.33 0 0 0-7.336 7.34v4.68c5.774.937 10.145 5.933 10.145 11.863V64h23.57v-1.875c0-6.555 5.309-11.863 11.863-12.02v-4.523a7.33 7.33 0 0 0-7.336-7.34zm0 0"/><path d="M55.727 53.855c-4.528 0-8.274 3.747-8.274 8.27V64h6.402v-4.996h3.747V64H64v-1.875c0-4.68-3.746-8.27-8.273-8.27zm-37.93-34.968L16.39 4.84l-8.899 8.898a15.342 15.342 0 0 0-2.027 2.496h7.18v3.746H3.746c-.625 1.875-.781 3.903-.469 5.934h9.524v3.746H4.215c1.094 2.965 3.277 5.617 6.086 7.336 1.875-1.719 4.527-2.656 7.183-2.656h4.993v-6.242a13.914 13.914 0 0 1-4.68-9.211zM8.273 53.855C3.746 53.855 0 57.602 0 62.125V64h6.398v-4.996h3.747V64h6.402v-1.875c0-4.68-3.746-8.27-8.274-8.27zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="51" xmlns="http://www.w3.org/2000/svg"><path d="M23.023 63.957c-8.199-.34-15.543-2.875-19.468-6.77-1.196-1.011-2.39-2.535-2.903-3.55L.31 52.96v-7.617c0-7.614 0-7.614.171-6.934.34 1.692 1.368 3.383 2.903 4.735 1.023.847 3.074 2.37 4.781 3.214 2.906 1.524 6.66 2.54 10.59 3.047 2.39.34 3.246.34 6.66.34 3.418 0 4.27 0 6.66-.34 3.93-.508 7.516-1.691 10.59-3.047 1.707-.843 3.758-2.199 4.781-3.214 1.368-1.352 2.563-3.043 2.903-4.735.172-.508.172-.508.172 6.934v7.445l-.34.68c-1.196 2.367-3.246 4.398-5.98 6.09-5.294 3.046-13.321 4.738-21.177 4.398zm0-18.95c-7.171-.339-13.832-2.37-18.101-5.413-1.027-.68-2.39-2.032-2.906-2.707-.512-.68-1.024-1.524-1.364-2.371L.31 33.84v-7.445c0-7.446 0-7.446.171-6.938.34 1.184.852 2.54 1.88 3.555.511.675 1.367 1.523 1.878 1.86.168.171.684.339 1.024.679 3.414 2.367 8.199 4.058 13.664 4.906 2.39.336 3.242.336 6.66.336 3.414 0 4.27 0 6.66-.336 3.93-.508 7.516-1.691 10.59-3.047 1.707-.847 3.758-2.2 4.781-3.215 1.367-1.351 2.39-3.047 2.903-4.738.171-.508.171-.508.171 6.938v7.445l-.511 1.015c-.856 1.524-1.368 2.368-2.39 3.383-1.028 1.016-2.052 1.864-3.419 2.54-5.465 3.046-13.492 4.738-21.348 4.23zm-.511-18.78c-4.782-.34-8.54-1.184-12.125-2.54-4.27-1.69-7.344-3.89-8.883-6.597a5.594 5.594 0 0 1-.852-2.031C.48 14.383.31 12.69.48 11.676 1.504 6.262 8.848 1.859 18.754.34 21.144 0 22 0 25.414 0c3.418 0 4.27 0 6.66.34 3.93.508 7.516 1.691 10.59 3.043 4.441 2.199 7.172 5.078 7.684 8.12.172.849.172 2.708-.168 3.388-.512 1.691-1.196 2.707-2.563 4.058-3.586 3.723-9.906 6.094-17.762 6.938-1.023.34-6.32.34-7.343.34zm0 0" fill="#a03537"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="51" xmlns="http://www.w3.org/2000/svg"><path d="M23.023 63.957c-8.199-.34-15.543-2.875-19.468-6.77-1.196-1.011-2.39-2.535-2.903-3.55L.31 52.96v-7.617c0-7.614 0-7.614.171-6.934.34 1.692 1.368 3.383 2.903 4.735 1.023.847 3.074 2.37 4.781 3.214 2.906 1.524 6.66 2.54 10.59 3.047 2.39.34 3.246.34 6.66.34 3.418 0 4.27 0 6.66-.34 3.93-.508 7.516-1.691 10.59-3.047 1.707-.843 3.758-2.199 4.781-3.214 1.368-1.352 2.563-3.043 2.903-4.735.172-.508.172-.508.172 6.934v7.445l-.34.68c-1.196 2.367-3.246 4.398-5.98 6.09-5.294 3.046-13.321 4.738-21.177 4.398zm0-18.95c-7.171-.339-13.832-2.37-18.101-5.413-1.027-.68-2.39-2.032-2.906-2.707-.512-.68-1.024-1.524-1.364-2.371L.31 33.84v-7.445c0-7.446 0-7.446.171-6.938.34 1.184.852 2.54 1.88 3.555.511.675 1.367 1.523 1.878 1.86.168.171.684.339 1.024.679 3.414 2.367 8.199 4.058 13.664 4.906 2.39.336 3.242.336 6.66.336 3.414 0 4.27 0 6.66-.336 3.93-.508 7.516-1.691 10.59-3.047 1.707-.847 3.758-2.2 4.781-3.215 1.367-1.351 2.39-3.047 2.903-4.738.171-.508.171-.508.171 6.938v7.445l-.511 1.015c-.856 1.524-1.368 2.368-2.39 3.383-1.028 1.016-2.052 1.864-3.419 2.54-5.465 3.046-13.492 4.738-21.348 4.23zm-.511-18.78c-4.782-.34-8.54-1.184-12.125-2.54-4.27-1.69-7.344-3.89-8.883-6.597a5.594 5.594 0 0 1-.852-2.031C.48 14.383.31 12.69.48 11.676 1.504 6.262 8.848 1.859 18.754.34 21.144 0 22 0 25.414 0c3.418 0 4.27 0 6.66.34 3.93.508 7.516 1.691 10.59 3.043 4.441 2.199 7.172 5.078 7.684 8.12.172.849.172 2.708-.168 3.388-.512 1.691-1.196 2.707-2.563 4.058-3.586 3.723-9.906 6.094-17.762 6.938-1.023.34-6.32.34-7.343.34zm0 0" fill="#369"/></svg> |
| 1 | ||
| 1 | <svg height="63" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M33.325 19.55c-.498-.2-1.1 0-1.299.5-1.1 2.5-2.901 4.7-5.1 6.4l-6.7-13.601c1-.8 1.6-1.999 1.6-3.4 0-2.099-1.501-3.899-3.501-4.3v-3.4a1 1 0 0 0-2 0v3.4c-2 .401-3.5 2.201-3.5 4.3 0 1.401.6 2.6 1.601 3.4l-6.7 13.602c-2.201-1.7-4-3.801-5.1-6.401-.201-.5-.8-.7-1.301-.5-.499.199-.7.8-.499 1.3 1.299 3 3.4 5.4 6 7.3l-4 8c-.2.5 0 1.1.4 1.3.098 0 .3.1.4.1.3 0 .7-.2.9-.5l3.8-7.8c2.7 1.5 5.6 2.2 8.7 2.2 3.1 0 6-.8 8.699-2.2l3.8 7.8c.1.3.501.5.9.5.1 0 .3 0 .4-.1.5-.2.7-.8.4-1.3l-3.9-8c2.6-1.8 4.701-4.4 6-7.3.6-.5.401-1.101 0-1.3zM17.326 6.95c1.4 0 2.5 1.1 2.5 2.499 0 1.401-1.1 2.502-2.5 2.502s-2.5-1.1-2.5-2.502c0-1.4 1.199-2.5 2.5-2.5zm0 22.6c-2.8 0-5.4-.7-7.801-2l6.8-13.7c.3.1.701.1 1.1.1.402 0 .701 0 1.1-.1l6.8 13.7c-2.5 1.3-5.199 2-7.999 2zm0 0" fill="#369" stroke="#369" stroke-miterlimit="10" stroke-width="1.5" transform="matrix(1.6544 0 0 1.63607 0 .154)"/></svg> |
| 1 | ||
| 1 | <svg height="63" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M33.325 19.55c-.498-.2-1.1 0-1.299.5-1.1 2.5-2.901 4.7-5.1 6.4l-6.7-13.601c1-.8 1.6-1.999 1.6-3.4 0-2.099-1.501-3.899-3.501-4.3v-3.4a1 1 0 0 0-2 0v3.4c-2 .401-3.5 2.201-3.5 4.3 0 1.401.6 2.6 1.601 3.4l-6.7 13.602c-2.201-1.7-4-3.801-5.1-6.401-.201-.5-.8-.7-1.301-.5-.499.199-.7.8-.499 1.3 1.299 3 3.4 5.4 6 7.3l-4 8c-.2.5 0 1.1.4 1.3.098 0 .3.1.4.1.3 0 .7-.2.9-.5l3.8-7.8c2.7 1.5 5.6 2.2 8.7 2.2 3.1 0 6-.8 8.699-2.2l3.8 7.8c.1.3.501.5.9.5.1 0 .3 0 .4-.1.5-.2.7-.8.4-1.3l-3.9-8c2.6-1.8 4.701-4.4 6-7.3.6-.5.401-1.101 0-1.3zM17.326 6.95c1.4 0 2.5 1.1 2.5 2.499 0 1.401-1.1 2.502-2.5 2.502s-2.5-1.1-2.5-2.502c0-1.4 1.199-2.5 2.5-2.5zm0 22.6c-2.8 0-5.4-.7-7.801-2l6.8-13.7c.3.1.701.1 1.1.1.402 0 .701 0 1.1-.1l6.8 13.7c-2.5 1.3-5.199 2-7.999 2zm0 0" fill="#369" stroke="#369" stroke-miterlimit="10" stroke-width="1.5" transform="matrix(1.6544 0 0 1.63607 0 .154)"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M16.223 21.805.09 55.844l3.012 3.015 20.035-20.035c-.711-1.594-.532-3.543.886-4.96 1.774-1.774 4.43-1.774 6.204 0 1.773 1.769 1.773 4.429 0 6.202-1.243 1.243-3.368 1.594-4.965.887L5.23 60.984 8.242 64l34.04-16.133L49.73 27.48 36.61 14.36zm46.625-4.075L46.184 1.062c-1.418-1.417-3.547-1.417-4.965 0L37.32 4.966c-1.422 1.418-1.422 3.543 0 4.965l16.664 16.664c1.418 1.418 3.543 1.418 4.965 0l3.899-3.903c1.418-1.418 1.418-3.543 0-4.96zm0 0" fill="#fea500"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="52" xmlns="http://www.w3.org/2000/svg"><path d="M46.168 13.516c1.793-.711 3.766-.891 5.738-.891V.008c-8.605-.18-16.851 3.554-22.23 10.308-2.153 2.844-4.125 5.864-5.559 9.243l-4.12 10.128c-1.079 3.024-2.333 6.223-3.767 9.067a31.916 999"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="52" xmlns="http://www.w3.org/2000/svg"><path d="M46.168 13.516c1.793-.711 3.766-.891 5.738-.891V.008c-8.605-.18-16.851 3.554-22.23 10.308-2.153 2.844-4.125 5.864-5.559 9.243l-4.12 10.128c-1.079 3.024-2.333 6.223-3.767 9.067a31.916 31.916 0 0 1-3.945 6.754c-1.254 1.777-3.047 3.199-5.02 4.09-2.152 1.066-4.66 1.597-7.171 1.597v12.797c8.605.18 16.851-3.554 22.23-10.308 1.613-2.309 3.227-4.797 4.485-7.286l3.406-8h14.879v-12.62h-9.86c.715-1.954 1.793-3.731 3.047-5.508.895-1.602 2.153-2.844 3.407-3.91 1.613-1.422 3.046-2.313 4.48-2.844zm0 0" fill="#d10407"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="72" xmlns="http://www.w3.org/2000/svg"><path d="M65.75 44.957S76.094 21.352 44.36.051c0 0 12.972 16.152 6.312 34.433 0 0-23.32-16.328-35.067-28.222 0 0 14.727 20.945 19.989 25.207 0 0-8.77-4.438-28.93-21.657 0 0 23.316 30.176 34.188 36.387 0 0-16.657 11.184-40.852-4.613 0 0 12.8 22.363 39.625 22.363 12.098 0 15.605-6.21 21.566-6.21 6.137 0 9.993 6.21 9.993 6.21 3.507-8.875-5.434-18.992-5.434-18.992zm0 0" fill="#fa2a22"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="74" xmlns="http://www.w3.org/2000/svg"><g fill="#bababa"><path d="M73.734 51.555c0-2.844-2.289-5.157-5.109-5.157H5.375c-2.82 0-5.11 2.313-5.11 5.157v7.289c0 2.843 2.29 5.156 5.11 5.156h63.25c2.82 0 5.11-2.313 5.11-5.156zm-27.308 6.757a2.985 2.985 0 0 1-2.996-3.023 2.985 2.985 0 0 1 2.996-3.023 2.985 2.985 0 0 1 2.996 3.023c0 1.777-1.234 3.023-2.996 3.023zm8.984 0a2.984 2.984 0 0 1-2.992-3.023c0-1.777 1.23-3.023 2.992-3.023a2.985 2.985 0 0 1 2.996 3.023 2.985 2.985 0 0 1-2.996 3.023zm8.813 0a2.985 2.985 0 0 1-2.996-3.023c0-1.777 1.234-3.023 2.996-3.023a2.981 2.981 0 0 1 2.992 3.023 2.981 2.981 0 0 1-2.992 3.023zM5.375 43.38h63.25c1.41 0 2.82.355 3.879 1.066l-6.168-12.98c-1.762-3.73-4.582-5.153-7.398-5.153h-6.876L42.2 36.623c-.707.71-1.586 1.245-2.469 1.6-.878.356-1.937.532-2.82.532-1.055 0-1.937-.176-2.816-.531h-.352c-.707-.356-1.41-.891-2.117-1.422l-9.867-10.668h-6.871c-2.817 0-5.461 1.601-7.399 5.156L1.32 44.266c1.235-.532 2.47-.887 4.055-.887zm0 0"/><path d="M51.71 21.332c.352-.355.532-.71.884-1.242.176-.535.351-.89.351-1.602 0-.531-.175-1.066-.351-1.422-.176-.53-.532-.886-.883-1.246a5.273 5.273 0 0 0-1.23-.886c-.356-.18-.883-.356-1.41-.356-.532 0-1.06.176-1.41.356-.528.175-.884.53-1.235.886l-5.637 5.692V3.734c0-.535-.176-1.066-.352-1.421-.18-.536-.53-.891-.882-1.247-.352-.355-.703-.71-1.235-.886C37.97 0 37.441 0 36.91 0c-.527 0-1.055 0-1.406.18-.531.175-.883.53-1.234.886-.352.356-.708.711-.883 1.246-.176.532-.352.887-.352 1.422v17.953L27.398 16c-.351-.355-.707-.71-1.234-.89-.352-.176-.879-.356-1.41-.356-.527 0-1.055.18-1.41.355-.352.18-.88.536-1.23.891-.356.355-.708.71-.884 1.246-.175.531-.351.887-.351 1.422 0 .531.176 1.066.351 1.598.176.535.528.89.883 1.246L34.27 33.957c.351.355.703.711 1.234.887.351.18.879.355 1.406.355.531 0 1.059-.176 1.41-.355.532-.176.883-.532 1.235-.887zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg height="63" width="60" xmlns="http://www.w3.org/2000/svg"><path d="M57.96 53.09 37.532 32.832l-.527-.523 3.7-3.844.526-.524c4.754 1.747 10.391.875 14.266-2.968 2.816-2.793 4.227-6.637 3.875-10.653 0-.523-.355-.875-.707-1.047-.352-.175-.879 0-1.23.348l-6.516 6.461-6.871-1.57-1.758-6.813 6.516-6.46c.351-.348.351-.872.351-1.223-.176-.348-.527-.7-1.058-.7-4.051-.347-7.922 1.051-10.743 3.844-3.87 3.844-4.93 9.43-2.992 14.145l-.527.523-5.285 5.067-9.86-9.782-.355-.347c.176-.176.176-.352.355-.7 2.114.348 5.809-3.668 8.98-6.812L18.337 0c-4.227 4.191-7.219 6.984-6.867 8.906-.88.524-1.762 1.047-2.465 1.57L7.77 11.7c-.88.875-1.407 1.922-1.582 2.969-.176.176-.176.352-.352.523l-.531 1.051v.172l-.528.7c-.351.35-.527.698-.703 1.222a.378.378 0 0 1-.351.352l-.18.171c-.176.524-.527.875-.703 1.399-.176.523-.527 1.222-.703 1.922v.347c0 .176-.176.524-.176.7l-.176.875c-.176.523-.176 1.046-.176 1.57v3.144l.176.696v.351c0 .348.176.524.176.871l.527 1.575c.176.523.703.87 1.235.87.351 0 .527-.171.703-.347s.351-.352.351-.7l.176-1.745c0-.176 0-.348.176-.524 0-.175 0-.351.176-.351l.175-.696s0-.175.176-.175c0 0 0-.176.18-.176 0-.172.176-.348.176-.348.175-.351.175-.523.351-.699 0-.176.176-.176.176-.348.176-.351.352-.527.527-.875l.352-.523c0-.176.176-.176.352-.352l.18-.172c.175-.351.527-.523.878-.875l.176-.171c.176-.176.527-.352.703-.528.176 0 .176-.172.355-.172.176 0 .176-.175.352-.175.176-.176.352-.348.703-.348l.528-.352.53-.175c.177-.172.352-.172.528-.172s.176 0 .352-.176c0 0 .175 0 .175-.176.176 0 .176 0 .352-.172h.176c.176.172.351.524.531.696l9.684 9.605L2.488 51.52c-2.64 2.617-2.992 6.285-.351 8.906 2.64 2.617 6.164 1.918 8.629-.7l18.136-19.035.356.348 20.426 20.258a5.883 5.883 0 0 0 8.277 0 5.763 5.763 0 0 0 0-8.207zM7.95 57.629c-.884.875-2.47.875-3.348 0-.88-.871-.88-2.445 0-3.316.878-.876 2.464-.876 3.347 0a2.134 2.134 0 0 1 0 3.316zm0 0" fill="#999"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="74" xmlns="http://www.w3.org/2000/svg"><path d="m49.332 34.941-12.25-5.714L61.75 17.633 74 23.348l-12.25 5.879zM61.75 6.207 49.5.492 37.25 6.207l24.5 11.594L74 12.086zm-37.082 17.14-12.25-5.714-12.25 5.715L24.836 34.94l12.246-5.714zm0-11.429 12.25-5.711L24.668.492 0 12.086 12.25 17.8zM61.75 32.59l-11.074 5.039-1.344.672-1.34-.672-11.074-5.04-11.078 5.04-1.34.672-1.344-.672-11.074-5.04v17.977L36.75 63.508l25-12.942zm0 0" fill="#4d1b9b"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="67" xmlns="http://www.w3.org/2000/svg"><path d="M12.726.224c-2.801 0-5.202 2.302-5.202 5.2 0 2.8 2.302 5.2 5.202 5.2.9 0 1.698-.199 2.4-.599l2.099 2.101-6 6c-.999.999-.999 2.7 0 3.698l.2.202L23.524 9.925c.702.4 1.602.601 2.4.601 2.801 0 5.202-2.302 5.202-5.2 0-2.8-2.302-5.2-5.202-5.2-2.798 0-5.199 2.3-5.199 5.2 0 .898.2 1.698.601 2.4l-2.101 2.098-2.1-2.098c.399-.702.6-1.6.6-2.4.2-2.8-2.2-5.102-5-5.102zm0 3.001c1.199 0 2.2 1 2.2 2.2 0 1.2-1.001 2.2-2.2 2.2a2.22 2.22 0 0 1-2.2-2.2c0-1.3.998-2.2 2.2-2.2zm13.3 0c1.199 0 2.2 1 2.2 2.2 0 1.2-1.001 2.2-2.2 2.2a2.22 2.22 0 0 1-2.2-2.2c0-1.3.998-2.2 2.2-2.2zm-22.902 10.3c-.198 0-.398 0-.598.1-.2 0-.4.101-.601.2-.2.1-.3.2-.5.301-.1.098-.301.199-.4.3-.099.1-.2.299-.3.4-.1.1-.2.299-.3.5-.1.199-.1.3-.2.498v.1c0 .202-.1.4-.1.602v17.8c0 .198 0 .4.1.598 0 .201.1.4.2.601.1.2.2.3.3.501.1.098.201.3.3.4.099.098.3.199.4.3.1.1.3.198.5.299.2.1.299.1.5.201h.1c.2 0 .401.098.599.098h32.602c.198 0 .398 0 .598-.098.2 0 .4-.1.601-.201.2-.1.3-.199.5-.3.1-.1.301-.2.4-.299.099-.1.2-.302.3-.4.1-.1.2-.302.3-.5.1-.202.1-.3.2-.501v-.1c0-.2.1-.4.1-.6V16.526c0-.201 0-.4-.1-.601 0-.199-.1-.4-.2-.599-.1-.201-.2-.302-.3-.5-.1-.101-.201-.3-.3-.4-.099-.101-.3-.202-.4-.3-.1-.1-.3-.201-.5-.302-.2-.098-.299-.098-.5-.199h-.1c-.2 0-.401-.1-.599-.1h-11.9l-3.002 3.001h11.802c0 1.6 1.298 2.999 2.999 2.999v11.8c-1.6 0-2.999 1.3-2.999 3h-26.6c0-1.6-1.3-3-3.001-3v-11.9c1.6 0 3.001-1.299 3.001-3h3.4l2.998-3zm16.301 5.9c-3.3 0-5.9 3-5.9 6.699 0 2.1.899 4 2.2 5.2h7.3c1.401-1.2 2.2-3.1 2.2-5.2.1-3.698-2.601-6.7-5.8-6.7zm-11.9 4.5c-.8 0-1.499.7-1.499 1.5s.7 1.499 1.498 1.499c.801 0 1.5-.7 1.5-1.5s-.699-1.499-1.5-1.499zm23.7 0c-.8 0-1.501.7-1.501 1.5s.702 1.499 1.5 1.499c.801 0 1.501-.7 1.501-1.5s-.7-1.499-1.5-1.499zm0 0" fill="#83ad51" stroke="#83ad51" stroke-miterlimit="10" stroke-width=".25" transform="matrix(1.6973 0 0 1.70894 .53 0)"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="69" xmlns="http://www.w3.org/2000/svg"><path d="M13.875 13.874h10.9v2.701h-10.9zm0 5.4h10.9v2.701h-10.9zm0 5.5h10.9v2.702h-10.9zm19-24.399H11.177c-3 0-5.402 2.4-5.402 5.4v24.4h-5.4c0 3 2.402 5.4 5.4 5.4h21.7c3 0 5.402-2.4 5.402-5.4v-21.7h5.4v-2.7c0-3-2.402-5.4-5.4-5.4zm-2.7 29.3c0 1.801-1.4 3.2-3.2 3.2h-19.9c1.3-.9 1.3-2.7 1.3-2.7v-24.4c0-1.5 1.2-2.7 2.7-2.7 1.501 0 2.7 1.2 2.7 2.7v2.7h16.3zm-13.6-23.9v-2.7h16.3c2.501 0 2.7 1.6 2.7 2.7zm0 0" fill="#999" stroke="#999" stroke-miterlimit="10" stroke-width=".75" transform="matrix(1.7717 0 0 1.78025 .262 0)"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M54.633 9.367C42.145-3.12 21.855-3.12 9.367 9.367s-12.488 32.778 0 45.266 32.778 12.488 45.266 0 12.488-32.778 0-45.266zM12.176 44.801c-5.934-9.211-4.84-21.543 3.12-29.504s20.294-9.055 29.505-3.121zm7.023 7.023L51.824 19.2c5.934 9.211 4.84 21.543-3.12 29.504s-20.294 9.055-29.505 3.121zm0 0" fill="#bababa"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="82" xmlns="http://www.w3.org/2000/svg"><g fill="#3c3"><path d="M0 .094v63.812h82V.094zM77.34 4.8v27.86L57.773 17.6 36.34 39.247l-15.094-8.469L4.844 43.953V4.801zm0 0"/><path d="M22.55 17.223c0 3.222-2.585 5.836-5.777 5.836-3.191 0-5.777-2.614-5.777-5.836s2.586-5.836 5.777-5.836c3.192 0 5.778 2.613 5.778 5.836zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg height="63" width="54" xmlns="http://www.w3.org/2000/svg"><path d="M53.344 18.172H44.02V8.965zM28.309 8.965v33.437h25.199V20.434H41.727V8.964zm3.93-8.723H4.417v6.461h10.965l-6.875 5.332v5.652l10.148-7.753V6.867H54V4.281zM18.655 14.297 8.508 22.05v5.652l10.148-7.754zM8.344 37.559l10.148-7.754v-5.657L8.344 31.902zm10.312 2.261v-5.656L8.508 41.918v2.91h-4.09v6.461h6.219v4.523H7.035c-.652-1.132-1.797-1.937-3.273-1.937C1.637 53.875 0 55.488 0 57.59c0 2.097 1.637 3.715 3.762 3.715 1.476 0 2.62-.809 3.273-1.938h3.602v3.39h5.562v-3.39h3.602c.652 1.13 1.8 1.938 3.273 1.938 2.125 0 3.762-1.618 3.762-3.715 0-2.102-1.637-3.715-3.762-3.715-1.472 0-2.62.805-3.273 1.938h-3.602v-4.524h15.875l21.762-3.879v-2.582H11.78zm0 0" fill="#90c"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="82" xmlns="http://www.w3.org/2000/svg"><g fill="#3c3"><path d="M0 .094v63.812h82V.094zM77.34 4.8v27.86L57.773 17.6 36.34 39.247l-15.094-8.469L4.844 43.953V4.801zm0 0"/><path d="M22.55 17.223c0 3.222-2.585 5.836-5.777 5.836-3.191 0-5.777-2.614-5.777-5.836s2.586-5.836 5.777-5.836c3.192 0 5.778 2.613 5.778 5.836zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="69" xmlns="http://www.w3.org/2000/svg"><g fill="#bababa"><path d="M51.227 30.453c.687.688 1.89.688 2.574-.172.687-.691.687-1.722.172-2.582l-4.805-5.676a1.33 1.33 0 0 1-.34-.863l-.687-10.664c0-1.035-.86-1.723-1.887-1.723-1.031 0-1.719.688-1.887 1.723v.172l-.687 11.7v.171c0 .688.172 1.375.855 1.89l.344.344zm0 0"/><path d="M46.426 0C36.645 0 28.41 6.367 25.32 15.14c1.887.172 3.774.688 5.664 1.204 2.403-6.192 8.407-10.668 15.442-10.668 9.094 0 16.469 7.398 16.469 16.52 0 8.257-6.004 15.136-13.899 16.343.172 1.031.172 2.234.172 3.266 0 .863 0 1.722-.172 2.582 11.152-1.203 19.734-10.668 19.734-22.02C68.73 10.152 58.777 0 46.426 0zm0 0"/><path d="M42.648 38.71h-2.914c-.515-2.41-1.375-4.644-2.746-6.71l2.059-2.066c.687-.688.687-1.891 0-2.579l-2.059-2.066c-.687-.687-1.886-.687-2.574 0l-2.059 2.066c-2.058-1.378-4.289-2.41-6.69-2.753v-2.926c0-1.031-.86-1.89-1.888-1.89H20.86c-1.027 0-1.886.859-1.886 1.89v2.926c-2.403.515-4.633 1.375-6.692 2.753l-1.886-2.238c-.688-.687-1.887-.687-2.575 0l-2.058 2.067c-.688.687-.688 1.89 0 2.578l1.886 2.066c-1.37 2.063-2.402 4.3-2.746 6.711H2.16c-1.031 0-1.89.86-1.89 1.89v2.926c0 1.032.859 1.891 1.89 1.891h2.742c.516 2.41 1.375 4.645 2.746 6.711l-1.886 1.89c-.688.692-.688 1.895 0 2.583l2.058 2.066c.688.688 1.887.688 2.575 0l2.058-1.894c2.059 1.375 4.29 2.41 6.692 2.753v2.754c0 1.032.859 1.891 1.886 1.891h2.918c1.028 0 1.887-.86 1.887-1.89v-2.755c2.402-.515 4.633-1.378 6.691-2.753l1.887 2.066c.688.687 1.887.687 2.574 0l2.059-2.066c.687-.688.687-1.891 0-2.579l-2.059-2.066c1.371-2.066 2.403-4.3 2.746-6.71h2.914c1.032 0 1.887-.86 1.887-1.892V40.43c0-.86-.855-1.72-1.887-1.72zM29.094 48.86c-3.774 3.785-9.95 3.785-13.723 0-3.777-3.786-3.777-9.977 0-13.762 3.774-3.785 9.95-3.785 13.723 0 3.949 3.785 3.777 9.976 0 13.761zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="80" xmlns="http://www.w3.org/2000/svg"><path d="M38.027 37.414c-5.011-4.812-9.425-9.223-12.03-19.25H43.64v-7.219H26.195V1.121h-7.617v10.024H.93v7.421h18.047s-.2 1.403-.399 2.606C15.968 30.996 13.164 37.215.93 43.23l2.61 7.418c11.429-6.015 17.444-13.835 20.05-22.257 2.605 6.418 6.816 11.629 11.629 16.441zM61.29 13.352H51.262L33.617 62.879h7.617l5.016-14.836H66.3l5.013 14.836h7.62zm-12.434 27.27 7.622-19.65 7.617 19.852zm0 0" fill="#999" stroke="#999" stroke-miterlimit="10" stroke-width="1.5039150000000001"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="58" xmlns="http://www.w3.org/2000/svg"><path d="M57.938 50.598c-.325 1.437-1.29 2.394-2.415 3.511-14.785 15.325-40.34 12.45-51.109-5.906-2.89-4.95-4.5-10.055-4.34-15.8.324-7.184 2.735-13.407 7.235-18.997C12.613 6.703 19.363 2.234 28.043.796 30.129.48 32.219.32 34.309 0v5.906l-4.34.477C17.754 8.14 7.469 18.355 6.664 30.168c-.48 7.34 1.45 14.047 6.43 19.633 1.93 2.394 4.18 4.469 6.91 5.746.805.32 1.77.476 2.574.637-7.715-4.47-12.215-11.172-13.664-19.793-.965-5.746.16-11.332 3.375-16.278C20.49 7.5 34.793 5.426 44.594 9.578c-.801 1.754-1.606 3.512-2.41 5.106-1.926-.317-3.856-.957-5.786-.957-5.625-.32-10.605.957-14.785 4.949-10.61 9.734-7.875 24.738 2.41 31.445 3.215 2.234 6.75 3.828 10.606 4.625.965.32 1.93 0 3.055-.156-.16-.16-.32-.16-.48-.16-4.825-.957-9.325-2.555-13.18-5.907-3.86-3.351-6.75-7.503-7.235-12.77-.48-7.503 2.414-13.566 8.84-17.398 5.625-3.511 11.574-3.511 17.52-.636 3.374 1.593 5.785 4.148 7.714 7.34-1.765.957-3.375 1.757-4.98 2.554-1.45-1.437-2.735-3.031-4.34-3.992-7.555-5.105-18.164-.316-18.965 9.102-.324 4.629 1.606 8.14 4.82 11.332 3.856 3.511 8.52 4.789 13.66 5.425 4.985.641 9.965.48 14.95-.16.965-.16 1.445.48 1.93 1.278 0-.16 0 0 0 0zm0 0" fill="#bababa"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><g fill="#999"><path d="M60.89 0H10.974C10.238 0 9.69.547 9.69 1.281v3.84c0 .73.73 1.277 1.282 1.277h46.629v46.813c0 .55.73 1.281 1.277 1.281h3.84A1.25 1.25 0 0 0 64 53.211V3.109C64 1.281 62.719 0 60.89 0zm0 0"/><path d="M49.922 12.8H1.282C.546 12.8 0 13.349 0 14.079v48.64C0 63.27.73 64 1.281 64h48.64c.548 0 1.278-.547 1.278-1.281v-48.64c0-.731-.547-1.278-1.277-1.278zm-27.43 43.52c0 .547-.73 1.282-1.281 1.282H7.863c-.73 0-1.281-.551-1.281-1.282v-3.84c0-.55.73-1.28 1.281-1.28h13.164c.735 0 1.282.55 1.282 1.28v3.84zm0-12.8c0 .55-.73 1.28-1.281 1.28H7.863c-.73 0-1.281-.55-1.281-1.28v-3.84c0-.73.73-1.282 1.281-1.282h13.164c.735 0 1.282.551 1.282 1.282v3.84zm22.309 12.8c0 .547-.551 1.282-1.281 1.282H30.172c-.73 0-1.281-.551-1.281-1.282v-3.84c0-.55.55-1.28 1.28-1.28H43.52c.55 0 1.28.55 1.28 1.28zm0-12.8c0 .55-.551 1.28-1.281 1.28H30.172c-.73 0-1.281-.55-1.281-1.28v-3.84c0-.73.55-1.282 1.28-1.282H43.52c.55 0 1.28.551 1.28 1.282zm0-12.801c0 .55-.551 1.281-1.281 1.281H7.68a1.25 1.25 0 0 1-1.282-1.281V20.48c0-.73.735-1.28 1.282-1.28h35.84c.73 0 1.28.55 1.28 1.28zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="37" xmlns="http://www.w3.org/2000/svg"><path d="M21.914 13.86V0h-9.039c-.187.547-.371 1.094-.371 1.824-.184.363-.184.547-.184.91-.922 5.106-3.691 8.754-8.3 10.758-1.293.547-2.582.73-3.875.547v11.125h6.64c.184 15.68.184 23.883.184 24.25v.91c.926 6.93 4.43 10.942 10.886 12.582 2.583.73 5.348 1.094 8.301 1.094 3.688-.184 7.196-.73 10.7-1.824v-13.13a101.367 101.367 0 0 0-5.536 1.645c-3.136.91-5.902.364-8.117-1.824-.183-.367-.55-.73-.55-1.094a23.898 23.898 0 0 1-.555-5.105V25.164h14.386V14.04h-14.57zm0 0" fill="#4065aa"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="84" height="52"><path style="fill:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke:#1f7244;stroke-opacity:1;stroke-miterlimit:10" d="M0 1.5h8.5m3.3 0h8.5m3.4 0h8.5m3.3 0H44M0 7.4h8.5m3.3 0h8.5m3.4 0h8.5m3.3 0H44M0 13.3h8.5m3.3 0h8.5m3.4 0h8.5m3.3 0H44M0 19.2h8.5m3.3 0h8.5m3.4 0h8.5m3.3 0H44M0 25.1h8.5m3.3 0h8.5m3.4 0h8.5m3.3 0H44" transform="matrix(1.9091 0 0 1.92593 0 .385)"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="65" xmlns="http://www.w3.org/2000/svg"><path d="M43.223.492V13.66h-1.32c-.825-3-1.65-5.168-2.473-6.5-.825-1.332-2.145-2.336-3.797-3.168-.824-.5-2.473-.668-4.781-.668h-3.63v37.512c0 2.5.165 4 .329 4.668.328.668.824 1.168 1.648 1.668s1.817.664 3.301.664h1.648v1.336H9.074v-1.336h1.649c1.32 0 2.476-.332 3.3-.832.66-.332 1.153-.832 1.485-1.668.328-.5.328-2 .328-4.5V3.324h-3.461c-3.3 0-5.61.668-7.098 2.004-1.976 2-3.297 4.664-3.957 8.332H0V.492zm0 0" fill="#7291a1"/><path d="M65 14.828V28h-1.32c-.825-3-1.649-5.168-2.473-6.504-.828-1.332-2.145-2.332-3.797-3.168-.824-.5-2.472-.664-4.785-.664h-3.629v37.508c0 2.5.168 4.004.332 4.668.328.668.824 1.168 1.649 1.668.824.5 1.816.668 3.3.668h1.649v1.332H30.684v-1.332h1.652c1.32 0 2.473-.336 3.297-.836.66-.332 1.156-.832 1.488-1.664.328-.5.328-2.004.328-4.504V17.664h-3.465c-3.3 0-5.609.664-7.093 2-1.98 2-3.301 4.668-3.961 8.336h-1.317V14.828zm0 0" fill="#36454d"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="72" xmlns="http://www.w3.org/2000/svg"><path d="M66.387 64c-4.18-36.844 4.875-26.973 4.875-26.973-9.926-11.988-14.973.528-17.414 12.164C52.628 30.504 46.883-.523 23.898.008c12.364 0 13.059 25.383 11.84 43.719-10.797-19.391-35-17.98-35-17.98s18.11-.708 18.11 38.077h47.539zm0 0" fill="#7faf4a"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="76" xmlns="http://www.w3.org/2000/svg"><path d="M.176 52.977h75.648V64H.176zm0-26.309h75.648v11.02H.176zM.176 0h75.648v11.023H.176zm0 0" fill="#666"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><g fill="#eab41b"><path d="M28.023 32c0 1.04.344 2.074 1.211 2.766 1.555 1.558 4.149 1.558 5.707 0 .692-.692 1.211-1.727 1.211-2.766s-.347-2.074-1.21-2.766c-.692-.695-1.731-1.21-2.77-1.21-1.035 0-2.074.343-2.766 1.21-1.039.692-1.383 1.727-1.383 2.766zm0 0"/><path d="M9.34 9.34c-12.453 12.453-12.453 32.691 0 45.32 12.453 12.453 32.691 12.453 45.32 0 12.453-12.453 12.453-32.691 0-45.32-12.453-12.453-32.867-12.453-45.32 0zm47.394 36.152c-1.21 2.074-2.765 4.153-4.496 5.88-1.73 1.73-3.804 3.288-5.883 4.5l-7.437-14.184s.691-.176 2.078-1.56c1.383-1.382 1.727-2.073 1.727-2.073zM37.707 26.293c1.559 1.555 2.422 3.633 2.422 5.707s-.863 4.152-2.422 5.707a7.933 7.933 0 0 1-11.242 0c-1.559-1.555-2.422-3.633-2.422-5.707s.691-4.152 2.422-5.707c2.941-3.113 8.129-3.113 11.242 0zm-10.895-5.535s-1.558.863-2.769 2.246c-1.211 1.387-1.211 1.558-1.73 2.25l-14.184-7.61c1.21-2.078 2.77-4.152 4.5-5.882 1.902-1.73 3.805-3.285 5.879-4.496zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M21.344 36.297c-1.871 1.527-3.739 2.887-5.61 4.246L4.52 49.211c-.512.34-.852.508-1.36.168A15.884 15.884 0 0 0 .781 48.19c-.511-.171-.68-.511-.68-1.02V17.267c0-.34.34-.852.508-1.02.852d5006e"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="80" xmlns="http://www.w3.org/2000/svg"><path d="M3.121 5.453v2.363L.227 8.91V6.547zm0 23.637v2.363L.227 32.727v-2.364zm0 24v2.547l-2.894 1.09v-2.364zm-.363-39.817v2.18L.406 16.547v-2.184zm0 8v2.18L.406 24.547v-2.184zm0 16v2.18L.406 40.547v-2.184zm0 8v2.18L.406 48.547v-2.184zm7.414-38.546v2.91L6.375 11.09V8.363zm0 24v2.726L6.375 34.91v-2.726zm0 24.183v2.727l-3.797 1.636v-2.726zm-.184-39.82v2.547l-3.07 1.273v-2.547zm0 8v2.547l-3.07 1.273v-2.726zm0 16v2.547l-3.07 1.273v-2.726zm0 8v2.547l-3.07 1.273v-2.547zm7.414-38.543V12l-5.062 2v-3.273zm0 24V36l-5.062 2v-3.273zm0 23.816v3.453l-5.062 2v-3.453zm-.18-39.453V20l-4.16 1.637v-2.91zm0 8v2.906l-4.16 1.637v-2.906zm0 16v2.906l-4.16 1.637v-2.906zm0 7.637v3.09l-4.16 1.636v-2.91zm8.133-40.184v4.547l-6.144 2.543V11.09zm0 24v4.547l-6.144 2.363v-4.546zm0 23.82v4.544l-6.144 2.546V58.91zm-.359-39.456v4.183l-5.242 2.18v-4.18zm0 8v4l-5.242 2.183v-4.183zm0 16v4.183l-5.242 2v-4.183zm0 7.636v4.184l-5.242 2v-4zm8.496-40.726v5.816l-6.87 2.73v-5.82zm0 24v5.816l-6.87 2.73v-5.82zm0 23.816v5.82L26.622 64v-5.816zm-.363-39.09v4.91l-5.785 2.364v-4.91zm0 7.637v4.91l-5.785 2.363v-4.91zm0 16.363v4.91l-5.965 2.18v-4.906zm0 7.637v4.91l-5.785 2.363v-4.91zm8.68-43.273v8l-7.414 3.09V8.362c2.53-1.636 5.062-2.726 7.414-3.636zm0 8.726v6.91l-7.414 3.09v-6.906zm0 7.82v6.91l-7.414 3.09v-6.91zm0 7.817V36l-7.414 3.09v-6.906zm0 7.82V44l-7.414 3.09V40zm0 8v6.906l-7.414 3.274V48zm0 7.817v7.457c-2.895 1.09-5.426 2.18-7.414 3.27V56zM79.773 4.91v56c-4.699-3.094-10.668-4.726-17.535-4.726-5.785 0-12.297 1.27-19.527 3.632v-7.632c3.797-1.457 7.957-2.547 12.656-3.274V30.727c-3.797.546-8.137 1.82-12.656 4v-5.274a48.751 48.751 0 0 1 12.656-3.816V7.817C51.391 8.546 47.051 10 42.711 12V4.184C49.039 1.454 55.367 0 61.51 0c6.512.184 12.657 1.816 18.262 4.91zM72.36 9.816c-3.07-1.632-6.687-2.363-10.847-2.363h-1.446v18.184h1.63c3.613 0 7.23.547 10.663 1.816zm0 22.73c-3.254-1.456-6.867-2.183-10.664-2.183h-1.629v18.184h1.63c3.976 0 7.41.543 10.663 1.453zm4.883 30.727V62H76.7v-.184h1.266V62h-.543v1.273zm.903 0v-1.457h.363l.543 1.094.543-1.094h.18v1.457h-.18V62l-.543 1.09h-.184L78.328 62v1.273zm0 0" fill="#999"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><g fill="#eab41b"><path d="M28.023 32c0 1.04.344 2.074 1.211 2.766 1.555 1.558 4.149 1.558 5.707 0 .692-.692 1.211-1.727 1.211-2.766s-.347-2.074-1.21-2.766c-.692-.695-1.731-1.21-2.77-1.21-1.035 0-2.074.343-2.766 1.21-1.039.692-1.383 1.727-1.383 2.766zm0 0"/><path d="M9.34 9.34c-12.453 12.453-12.453 32.691 0 45.32 12.453 12.453 32.691 12.453 45.32 0 12.453-12.453 12.453-32.691 0-45.32-12.453-12.453-32.867-12.453-45.32 0zm47.394 36.152c-1.21 2.074-2.765 4.153-4.496 5.88-1.73 1.73-3.804 3.288-5.883 4.5l-7.437-14.184s.691-.176 2.078-1.56c1.383-1.382 1.727-2.073 1.727-2.073zM37.707 26.293c1.559 1.555 2.422 3.633 2.422 5.707s-.863 4.152-2.422 5.707a7.933 7.933 0 0 1-11.242 0c-1.559-1.555-2.422-3.633-2.422-5.707s.691-4.152 2.422-5.707c2.941-3.113 8.129-3.113 11.242 0zm-10.895-5.535s-1.558.863-2.769 2.246c-1.211 1.387-1.211 1.558-1.73 2.25l-14.184-7.61c1.21-2.078 2.77-4.152 4.5-5.882 1.902-1.73 3.805-3.285 5.879-4.496zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="71" xmlns="http://www.w3.org/2000/svg"><path d="M42.602 10.79V7.132C42.602 3.293 39.324 0 35.5 0s-7.102 3.293-7.102 7.133v3.656H.184V64h70.632V10.79zm21.117 46.077H7.28V17.738h21.117v3.473h14.204v-3.473h21.117zm0 0"/><path d="M24.941 32c0 2.02-1.628 3.656-3.64 3.656S17.66 34.02 17.66 32s1.628-3.656 3.64-3.656S24.94 29.98 24.94 32zM21.3 39.133c-3.823 0-7.1 3.289-7.1 7.129v3.66h14.198v-3.66c0-4.024-3.093-7.13-7.097-7.13zm17.84-10.79H56.8v7.13H39.14zm0 14.446H56.8v7.133H39.14zm0 0"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="71" xmlns="http://www.w3.org/2000/svg"><path d="M42.602 10.79V7.132C42.602 3.293 39.324 0 35.5 0s-7.102 3.293-7.102 7.133v3.656H.184V64h70.632V10.79zm21.117 46.077H7.28V17.738h21.117v3.473h14.204v-3.473h21.117zm0 0"/><path d="M24.941 32c0 2.02-1.628 3.656-3.64 3.656S17.66 34.02 17.66 32s1.628-3.656 3.64-3.656S24.94 29.98 24.94 32zM21.3 39.133c-3.823 0-7.1 3.289-7.1 7.129v3.66h14.198v-3.66c0-4.024-3.093-7.13-7.097-7.13zm17.84-10.79H56.8v7.13H39.14zm0 14.446H56.8v7.133H39.14zm0 0"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="74" xmlns="http://www.w3.org/2000/svg"><g fill="#4d1b9b"><path d="M73.734 51.555c0-2.844-2.289-5.157-5.109-5.157H5.375c-2.82 0-5.11 2.313-5.11 5.157v7.289c0 2.843 2.29 5.156 5.11 5.156h63.25c2.82 0 5.11-2.313 5.11-5.156zm-27.308 6.757a2.985 2.985 0 0 1-2.996-3.023 2.985 2.985 0 0 1 2.996-3.023 2.985 2.985 0 0 1 2.996 3.023c0 1.777-1.234 3.023-2.996 3.023zm8.984 0a2.984 2.984 0 0 1-2.992-3.023c0-1.777 1.23-3.023 2.992-3.023a2.985 2.985 0 0 1 2.996 3.023 2.985 2.985 0 0 1-2.996 3.023zm8.813 0a2.985 2.985 0 0 1-2.996-3.023c0-1.777 1.234-3.023 2.996-3.023a2.981 2.981 0 0 1 2.992 3.023 2.981 2.981 0 0 1-2.992 3.023zM5.375 43.38h63.25c1.41 0 2.82.355 3.879 1.066l-6.168-12.98c-1.762-3.73-4.582-5.153-7.398-5.153h-6.876L42.2 36.623c-.707.71-1.586 1.245-2.469 1.6-.878.356-1.937.532-2.82.532-1.055 0-1.937-.176-2.816-.531h-.352c-.707-.356-1.41-.891-2.117-1.422l-9.867-10.668h-6.871c-2.817 0-5.461 1.601-7.399 5.156L1.32 44.266c1.235-.532 2.47-.887 4.055-.887zm0 0"/><path d="M51.71 21.332c.352-.355.532-.71.884-1.242.176-.535.351-.89.351-1.602 0-.531-.175-1.066-.351-1.422-.176-.53-.532-.886-.883-1.246a5.273 5.273 0 0 0-1.23-.886c-.356-.18-.883-.356-1.41-.356-.532 0-1.06.176-1.41.356-.528.175-.884.53-1.235.886l-5.637 5.692V3.734c0-.535-.176-1.066-.352-1.421-.18-.536-.53-.891-.882-1.247-.352-.355-.703-.71-1.235-.886C37.97 0 37.441 0 36.91 0c-.527 0-1.055 0-1.406.18-.531.175-.883.53-1.234.886-.352.356-.708.711-.883 1.246-.176.532-.352.887-.352 1.422v17.953L27.398 16c-.351-.355-.707-.71-1.234-.89-.352-.176-.879-.356-1.41-.356-.527 0-1.055.18-1.41.355-.352.18-.88.536-1.23.891-.356.355-.708.71-.884 1.246-.175.531-.351.887-.351 1.422 0 .531.176 1.066.351 1.598.176.535.528.89.883 1.246L34.27 33.957c.351.355.703.711 1.234.887.351.18.879.355 1.406.355.531 0 1.059-.176 1.41-.355.532-.176.883-.532 1.235-.887zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="74" xmlns="http://www.w3.org/2000/svg"><g fill="#4d1b9b"><path d="M73.734 51.555c0-2.844-2.289-5.157-5.109-5.157H5.375c-2.82 0-5.11 2.313-5.11 5.157v7.289c0 2.843 2.29 5.156 5.11 5.156h63.25c2.82 0 5.11-2.313 5.11-5.156zm-27.308 6.757a2.985 2.985 0 0 1-2.996-3.023 2.985 2.985 0 0 1 2.996-3.023 2.985 2.985 0 0 1 2.996 3.023c0 1.777-1.234 3.023-2.996 3.023zm8.984 0a2.984 2.984 0 0 1-2.992-3.023c0-1.777 1.23-3.023 2.992-3.023a2.985 2.985 0 0 1 2.996 3.023 2.985 2.985 0 0 1-2.996 3.023zm8.813 0a2.985 2.985 0 0 1-2.996-3.023c0-1.777 1.234-3.023 2.996-3.023a2.981 2.981 0 0 1 2.992 3.023 2.981 2.981 0 0 1-2.992 3.023zM5.375 43.38h63.25c1.41 0 2.82.355 3.879 1.066l-6.168-12.98c-1.762-3.73-4.582-5.153-7.398-5.153h-6.876L42.2 36.623c-.707.71-1.586 1.245-2.469 1.6-.878.356-1.937.532-2.82.532-1.055 0-1.937-.176-2.816-.531h-.352c-.707-.356-1.41-.891-2.117-1.422l-9.867-10.668h-6.871c-2.817 0-5.461 1.601-7.399 5.156L1.32 44.266c1.235-.532 2.47-.887 4.055-.887zm0 0"/><path d="M51.71 21.332c.352-.355.532-.71.884-1.242.176-.535.351-.89.351-1.602 0-.531-.175-1.066-.351-1.422-.176-.53-.532-.886-.883-1.246a5.273 5.273 0 0 0-1.23-.886c-.356-.18-.883-.356-1.41-.356-.532 0-1.06.176-1.41.356-.528.175-.884.53-1.235.886l-5.637 5.692V3.734c0-.535-.176-1.066-.352-1.421-.18-.536-.53-.891-.882-1.247-.352-.355-.703-.71-1.235-.886C37.97 0 37.441 0 36.91 0c-.527 0-1.055 0-1.406.18-.531.175-.883.53-1.234.886-.352.356-.708.711-.883 1.246-.176.532-.352.887-.352 1.422v17.953L27.398 16c-.351-.355-.707-.71-1.234-.89-.352-.176-.879-.356-1.41-.356-.527 0-1.055.18-1.41.355-.352.18-.88.536-1.23.891-.356.355-.708.71-.884 1.246-.175.531-.351.887-.351 1.422 0 .531.176 1.066.351 1.598.176.535.528.89.883 1.246L34.27 33.957c.351.355.703.711 1.234.887.351.18.879.355 1.406.355.531 0 1.059-.176 1.41-.355.532-.176.883-.532 1.235-.887zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M.238 64h83.524V0H.238zm16.16-4.91H6.41V52h9.988zm30.688 0h-9.988V52h9.988zM67.602 4.363h9.988v7.274h-9.988zm0 47.453h9.988v7.094h-9.988zM52.168 4.363h9.805v7.09h-9.985v-7.09zm0 47.453h9.805v7.094h-9.985zM36.914 4.363h9.988v7.09h-9.988zM35.464 22l13.071 7.453c2.363 1.457 2.363 3.637 0 5.094L35.465 42c-2.363 1.453-4.36.184-4.36-2.547v-15.09c0-2.547 1.997-3.816 4.36-2.363zM21.485 4.363h9.805v7.09h-9.805zm0 47.453h9.805v7.094h-9.805zM6.41 4.363h9.988v7.274H6.41zm0 0" fill="#f60"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="74" xmlns="http://www.w3.org/2000/svg"><g fill="#039"><path d="m31.793 20.445 11.852 8.008V.246L31.793 8.254V4.25c0-2.184-1.797-4.004-3.953-4.004H3.953C1.797.246 0 2.066 0 4.25v20.2c0 2.183 1.797 4.003 3.953 4.003H27.84c2.156 0 3.953-1.82 3.953-4.004zm18.32 7.278v12.011c0 4.368 3.59 8.008 7.903 8.008 4.308 0 7.902-3.64 7.902-8.008V27.723c0-4.368-3.594-8.004-7.902-8.004-4.313 0-7.903 3.636-7.903 8.004zm0 0"/><path d="M70.047 39.734c0 6.73-5.387 12.008-11.852 12.008-6.648 0-11.855-5.457-11.855-12.008h-3.953A15.96 15.96 0 0 0 54.242 55.2v8.555h7.903v-8.555A15.955 15.955 0 0 0 74 39.734zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M54.633 9.367C42.145-3.12 21.855-3.12 9.367 9.367s-12.488 32.778 0 45.266 32.778 12.488 45.266 0 12.488-32.778 0-45.266zM12.176 44.801c-5.934-9.211-4.84-21.543 3.12-29.504s20.294-9.055 29.505-3.121zm7.023 7.023L51.824 19.2c5.934 9.211 4.84 21.543-3.12 29.504s-20.294 9.055-29.505 3.121zm0 0" fill="#bababa"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="48" xmlns="http://www.w3.org/2000/svg"><g stroke-miterlimit="10" stroke-width=".5"><path d="M44.2 75.3c7.2-3.701 3.9-7.3 1.5-6.799-.6.099-.801.2-.801.2s.2-.3.601-.5C50.1 66.6 53.6 73 44 75.5zm0 0" fill="#265db4" stroke="#265db4" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/><path d="M37.8 64.8c1.801 2.1-.5 4-.5 4s4.7-2.4 2.5-5.5c-2-2.8-3.6-4.2 4.8-9.101 0 .101-13.1 3.401-6.8 10.6" fill="#c00" stroke="#c00" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/><path d="M39.8 46.499s3.999 4-3.8 10.102c-6.2 4.898-1.4 7.7 0 10.899-3.601-3.3-6.3-6.2-4.5-8.8 2.7-4 9.9-5.9 8.3-12.201" fill="#c00" stroke="#c00" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/><g fill="#265db4" stroke="#265db4"><path d="M31 76.8s-1.5.9 1 1.1c3 .299 4.6.299 7.9-.3 0 0 .9.599 2.1 1-7.4 3.3-16.901-.1-11-1.8m-.9-4.2s-1.6 1.199.9 1.5c3.2.3 5.8.4 10.2-.5 0 0 .6.6 1.599 1-9.1 2.6-19.199.2-12.698-2" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/><path d="M47.7 79.9s1.1.9-1.2 1.599c-4.3 1.302-18 1.702-21.8.101-1.4-.6 1.2-1.4 2-1.6.8-.2 1.3-.1 1.3-.1-1.5-1.1-9.8 2.1-4.2 3 15.3 2.4 27.9-1.199 23.9-3M31.7 68.3s-7 1.702-2.499 2.301c1.9.301 5.699.2 9.2-.101 2.9-.2 5.799-.8 5.799-.8s-1 .4-1.8.901c-7.1 1.9-20.7.999-16.8-.9 3.4-1.6 6.1-1.401 6.1-1.401" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/><path d="M32.399 85.4c6.901.4 17.502-.2 17.7-3.5 0 0-.499 1.2-5.699 2.2-5.899 1.1-13.101 1-17.5.3.1 0 1 .7 5.499 1" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/></g></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="84" height="60"><path style="stroke:none;fill-rule:nonzero;fill:#999;fill-opacity:1" d="m12.762 33.262-8.39-26.09c-.349-1.059-.524-1.41-.7-1.41-.176-.176-.352-.176-.527-.352l-2.97-.883L0 .824h15.734l.348 3.703-2.973.883v.352c0 .351.176 1.058.528 1.761L16.78 17.57 22.38.824 26.57.648l5.07 16.747 3.497-10.051c.175-.703.527-1.41.527-1.762V5.41l-2.621-.707-.176-3.879h12.235l.351 3.703-3.32 1.059c-.176 0-.352.176-.528.176 0 .176-.347.351-.523 1.234l-9.266 25.91-4.37.356-4.716-16.043-5.597 15.687zm0 0"/><path style="fill-rule:nonzero;fill:#999;fill-opacity:1;stroke-width:.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#999;stroke-opacity:1;stroke-miterlimit:10" d="M42.4 48.6H60v2.8H42.4zm0 7.401H60V58.8H42.4zm0 7.7H60V66.5H42.4zm-29.4 7.8h47v2.798H13zm0 7.598h47v2.8H13zm0 0" transform="matrix(1.74818 0 0 1.76287 -21.328 -85.027)"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M18.785 46.805c3.504-1.43 7.164-2.387 10.985-2.547V34.07H16.398c.16 4.297.954 8.754 2.387 12.735zM11.461 7.64c1.594 1.593 3.504 2.867 5.254 3.98 1.594-3.66 3.664-7.164 6.21-10.348-4.3 1.274-8.12 3.344-11.464 6.368zm33.434 9.554c-3.5 1.43-7.165 2.387-10.985 2.547V29.93h13.375c-.16-4.297-.957-8.754-2.39-12.735zM29.93 19.582c-3.82-.316-7.64-1.113-10.985-2.547A43.883 43.883 0 0 0 16.56 29.93h13.37zm-9.551-6.207c3.023 1.273 6.207 1.91 9.55 2.227V0h-.316L27.86 1.91c-3.343 3.344-5.73 7.324-7.48 11.465zM47.285 33.91H33.91v10.188c3.82.32 7.64 1.117 10.985 2.55 1.433-3.824 2.23-8.28 2.39-12.738zM33.75 15.762c3.344-.32 6.527-.957 9.555-2.23-1.91-4.298-4.457-8.118-7.485-11.622L34.547.16h-.637zm18.629-8.278c-3.344-2.867-7.324-5.097-11.621-6.21a45.734 45.734 0 0 1 6.207 10.347c1.91-1.113 3.66-2.387 5.414-4.137zm-22.45 40.754c-3.343.32-6.527.957-9.55 2.23 1.91 4.137 4.297 8.118 7.324 11.462l1.59 1.75h.477zM12.419 30.09c.16-5.094 1.273-9.871 2.707-14.649-2.39-1.273-4.457-2.863-6.687-4.933l-.16-.16C3.503 15.602.32 22.449 0 30.09zm38.848 3.82c-.16 5.094-1.278 9.871-2.707 14.649 2.386 1.273 4.457 2.863 6.683 4.933l.32.32C60.34 48.56 63.523 41.712 64 34.07c-.32-.16-12.734-.16-12.734-.16zm3.82-23.402c-1.91 1.91-4.3 3.504-6.688 4.933 1.75 4.618 2.707 9.555 2.707 14.649H63.68c-.477-7.64-3.5-14.488-8.438-19.742zm-2.867 45.851c-1.594-1.593-3.504-2.867-5.254-3.98a45.734 45.734 0 0 1-6.207 10.348c4.297-1.274 8.277-3.344 11.46-6.368zM8.598 53.492c1.91-1.91 4.297-3.504 6.527-4.933-1.75-4.618-2.707-9.555-2.867-14.649H0c.477 7.64 3.504 14.488 8.277 19.742zm8.117-1.113c-1.91 1.113-3.66 2.547-5.254 3.98 3.344 2.864 7.324 5.094 11.625 6.207-2.707-3.023-4.777-6.367-6.371-10.187zm26.59-1.754c-3.028-1.273-6.211-1.91-9.555-2.227V64h.48l1.75-1.91c3.184-3.344 5.57-7.485 7.325-11.465zm0 0" fill="#bababa"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M.238 64h83.524V0H.238zm16.16-4.91H6.41V52h9.988zm30.688 0h-9.988V52h9.988zM67.602 4.363h9.988v7.274h-9.988zm0 47.453h9.988v7.094h-9.988zM52.168 4.363h9.805v7.09h-9.985v-7.09zm0 47.453h9.805v7.094h-9.985zM36.914 4.363h9.988v7.09h-9.988zM35.464 22l13.071 7.453c2.363 1.457 2.363 3.637 0 5.094L35.465 42c-2.363 1.453-4.36.184-4.36-2.547v-15.09c0-2.547 1.997-3.816 4.36-2.363zM21.485 4.363h9.805v7.09h-9.805zm0 47.453h9.805v7.094h-9.805zM6.41 4.363h9.988v7.274H6.41zm0 0" fill="#f60"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="82" xmlns="http://www.w3.org/2000/svg"><g fill="#3c3"><path d="M0 .094v63.812h82V.094zM77.34 4.8v27.86L57.773 17.6 36.34 39.247l-15.094-8.469L4.844 43.953V4.801zm0 0"/><path d="M22.55 17.223c0 3.222-2.585 5.836-5.777 5.836-3.191 0-5.777-2.614-5.777-5.836s2.586-5.836 5.777-5.836c3.192 0 5.778 2.613 5.778 5.836zm0 0"/></g></svg> |
| 1 | ||
| 1 | <svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M16.223 21.805.09 55.844l3.012 3.015 20.035-20.035c-.711-1.594-.532-3.543.886-4.96 1.774-1.774 4.43-1.774 6.204 0 1.773 1.769 1.773 4.429 0 6.202-1.243 1.243-3.368 1.594-4.965.887L5.23 60.984 8.242 64l34.04-16.133L49.73 27.48 36.61 14.36zm46.625-4.075L46.184 1.062c-1.418-1.417-3.547-1.417-4.965 0L37.32 4.966c-1.422 1.418-1.422 3.543 0 4.965l16.664 16.664c1.418 1.418 3.543 1.418 4.965 0l3.899-3.903c1.418-1.418 1.418-3.543 0-4.96zm0 0" fill="#fea500"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M.238 64h83.524V0H.238zm16.16-4.91H6.41V52h9.988zm30.688 0h-9.988V52h9.988zM67.602 4.363h9.988v7.274h-9.988zm0 47.453h9.988v7.094h-9.988zM52.168 4.363h9.805v7.09h-9.985v-7.09zm0 47.453h9.805v7.094h-9.985zM36.914 4.363h9.988v7.09h-9.988zM35.464 22l13.071 7.453c2.363 1.457 2.363 3.637 0 5.094L35.465 42c-2.363 1.453-4.36.184-4.36-2.547v-15.09c0-2.547 1.997-3.816 4.36-2.363zM21.485 4.363h9.805v7.09h-9.805zm0 47.453h9.805v7.094h-9.805zM6.41 4.363h9.988v7.274H6.41zm0 0" fill="#f60"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="84" height="48"><path style="stroke:none;fill-rule:nonzero;fill:#7291a1;fill-opacity:1" d="M28.621 33.172h-16.32l-2.012 4.45c-.55 1.483-.918 2.593-.918 3.706 0 1.297.547 2.223 1.649 2.781.55.371 2.203.555 4.582.743v1.293H.203v-1.293c1.652-.188 2.934-.93 4.035-2.04 1.098-1.113 2.383-3.34 3.848-6.859L24.586 0h.73L42 36.879c1.648 3.52 2.934 5.746 3.852 6.672.73.742 1.832 1.113 3.296 1.113v1.297h-22.18v-1.297h.919c1.832 0 3.113-.184 3.847-.742.551-.371.735-.926.735-1.48 0-.372 0-.743-.184-1.301 0-.184-.367-1.11-1.101-2.407zm-1.101-2.406-6.786-15.57-7.148 15.57zm0 0"/><path style="stroke:none;fill-rule:nonzero;fill:#36454d;fill-opacity:1" d="m83.797 16.309-6.602 22.054-.734 2.778c0 .375-.184.558-.184.742 0 .187.184.558.371.742.184.188.368.371.547.371.551 0 1.102-.371 2.016-1.113.371-.367 1.102-1.297 2.387-2.965l1.097.559c-1.648 2.964-3.3 5.003-5.132 6.3-1.833 1.297-3.852 2.04-5.864 2.04-1.285 0-2.203-.372-2.933-.93-.735-.742-1.102-1.485-1.102-2.407 0-.93.367-2.41 1.102-4.82l.73-2.781c-2.562 4.45-5.133 7.601-7.516 9.453C60.516 47.442 59.05 48 57.582 48c-2.016 0-3.668-.926-4.582-2.594-.918-1.668-1.465-3.523-1.465-5.746 0-3.152.914-6.672 2.934-10.75 2.011-4.074 4.582-7.226 7.695-9.82 2.566-2.04 5.133-2.965 7.332-2.965 1.285 0 2.203.367 3.121 1.11.73.742 1.281 2.038 1.649 3.89l1.28-4.074zM72.98 22.797c0-1.856-.367-3.152-.918-3.895-.367-.554-.914-.742-1.648-.742-.734 0-1.469.375-2.2.93-1.464 1.297-3.116 4.074-4.948 8.336-1.832 4.265-2.57 7.785-2.57 10.937 0 1.11.183 2.035.554 2.594.363.559.914.742 1.281.742 1.098 0 2.016-.558 3.117-1.668 1.465-1.668 2.934-3.707 4.032-5.93 2.199-4.449 3.3-8.156 3.3-11.304zm0 0"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="84" height="48"><path style="stroke:none;fill-rule:nonzero;fill:#7291a1;fill-opacity:1" d="M28.621 33.172h-16.32l-2.012 4.45c-.55 1.483-.918 2.593-.918 3.706 0 1.297.547 2.223 1.649 2.781.55.371 2.203.555 4.582.743v1.293H.203v-1.293c1.652-.188 2.934-.93 4.035-2.04 1.098-1.113 2.383-3.34 3.848-6.859L24.586 0h.73L42 36.879c1.648 3.52 2.934 5.746 3.852 6.672.73.742 1.832 1.113 3.296 1.113v1.297h-22.18v-1.297h.919c1.832 0 3.113-.184 3.847-.742.551-.371.735-.926.735-1.48 0-.372 0-.743-.184-1.301 0-.184-.367-1.11-1.101-2.407zm-1.101-2.406-6.786-15.57-7.148 15.57zm0 0"/><path style="stroke:none;fill-rule:nonzero;fill:#36454d;fill-opacity:1" d="m83.797 16.309-6.602 22.054-.734 2.778c0 .375-.184.558-.184.742 0 .187.184.558.371.742.184.188.368.371.547.371.551 0 1.102-.371 2.016-1.113.371-.367 1.102-1.297 2.387-2.965l1.097.559c-1.648 2.964-3.3 5.003-5.132 6.3-1.833 1.297-3.852 2.04-5.864 2.04-1.285 0-2.203-.372-2.933-.93-.735-.742-1.102-1.485-1.102-2.407 0-.93.367-2.41 1.102-4.82l.73-2.781c-2.562 4.45-5.133 7.601-7.516 9.453C60.516 47.442 59.05 48 57.582 48c-2.016 0-3.668-.926-4.582-2.594-.918-1.668-1.465-3.523-1.465-5.746 0-3.152.914-6.672 2.934-10.75 2.011-4.074 4.582-7.226 7.695-9.82 2.566-2.04 5.133-2.965 7.332-2.965 1.285 0 2.203.367 3.121 1.11.73.742 1.281 2.038 1.649 3.89l1.28-4.074zM72.98 22.797c0-1.856-.367-3.152-.918-3.895-.367-.554-.914-.742-1.648-.742-.734 0-1.469.375-2.2.93-1.464 1.297-3.116 4.074-4.948 8.336-1.832 4.265-2.57 7.785-2.57 10.937 0 1.11.183 2.035.554 2.594.363.559.914.742 1.281.742 1.098 0 2.016-.558 3.117-1.668 1.465-1.668 2.934-3.707 4.032-5.93 2.199-4.449 3.3-8.156 3.3-11.304zm0 0"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="84" height="60"><path style="stroke:none;fill-rule:nonzero;fill:#6190aa;fill-opacity:1" d="m12.762 33.262-8.39-26.09c-.349-1.059-.524-1.41-.7-1.41-.176-.176-.352-.176-.527-.352l-2.97-.883L0 .824h15.734l.348 3.703-2.973.883v.352c0 .351.176 1.058.528 1.761L16.78 17.57 22.38.824 26.57.648l5.07 16.747 3.497-10.051c.175-.703.527-1.41.527-1.762V5.41l-2.621-.707-.176-3.879h12.235l.351 3.703-3.32 1.059c-.176 0-.352.176-.528.176 0 .176-.347.351-.523 1.234l-9.266 25.91-4.37.356-4.716-16.043-5.597 15.687zm0 0"/><path style="fill-rule:nonzero;fill:#6190aa;fill-opacity:1;stroke-width:.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#6190aa;stroke-opacity:1;stroke-miterlimit:10" d="M42.4 48.6H60v2.8H42.4zm0 7.401H60V58.8H42.4zm0 7.7H60V66.5H42.4zm-29.4 7.8h47v2.798H13zm0 7.598h47v2.8H13zm0 0" transform="matrix(1.74818 0 0 1.76287 -21.328 -85.027)"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="69" xmlns="http://www.w3.org/2000/svg"><path d="M13.875 13.874h10.9v2.701h-10.9zm0 5.4h10.9v2.701h-10.9zm0 5.5h10.9v2.702h-10.9zm19-24.399H11.177c-3 0-5.402 2.4-5.402 5.4v24.4h-5.4c0 3 2.402 5.4 5.4 5.4h21.7c3 0 5.402-2.4 5.402-5.4v-21.7h5.4v-2.7c0-3-2.402-5.4-5.4-5.4zm-2.7 29.3c0 1.801-1.4 3.2-3.2 3.2h-19.9c1.3-.9 1.3-2.7 1.3-2.7v-24.4c0-1.5 1.2-2.7 2.7-2.7 1.501 0 2.7 1.2 2.7 2.7v2.7h16.3zm-13.6-23.9v-2.7h16.3c2.501 0 2.7 1.6 2.7 2.7zm0 0" fill="#999" stroke="#999" stroke-miterlimit="10" stroke-width=".75" transform="matrix(1.7717 0 0 1.78025 .262 0)"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="83" height="55"><path style="fill-rule:nonzero;fill:#999;fill-opacity:1;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#999;stroke-opacity:1;stroke-miterlimit:10" d="M11.143 25.867c-.5 0-1.1-.2-1.502-.6l-8.21.1.6-1.6.6zm25.101 0c-.503 0-1.102-.2-1.502999.6-1.5.6zm-16.7 4.1c-.202 0-.403 0-.7-.1-1.1028. |
| 1 | ||
| 1 | <svg height="64" width="78" xmlns="http://www.w3.org/2000/svg"><path d="M60.387 42.926c.734.367 1.648.738 2.383 1.293 2.382 1.48 4.585 2.957 6.785 4.437.367.184.734.371 1.101.184 2.567-.555 5.317.926 6.051 3.512.55 1.664.734 3.328.918 5.18.184 2.03.184 4.25.367 6.468-3.668-.926-7.152-2.035-9.719-4.805-.734-.742-.918-1.851-1.468-2.773-.184-.188-.368-.555-.551-.555A61.383 61.383 0 0 1 52.5 50.875c-.184-.188-.734-.188-.918 0-4.398 2.219-9.168 3.14-14.121 2.773-6.602-.37-12.652-2.59-18.52-5.363-.918-.555-2.02-1.11-2.937-1.664 4.586-2.219 6.605-5.914 6.605-10.906-1.101-.184-2.203-.184-3.12-.371-.184.926-.184 2.035-.368 3.144-1.098 4.067-4.95 6.285-9.168 5.176C4.453 42.184-.5 35.714.051 29.43c.367-4.621 4.402-7.578 8.8-6.47.735.185 1.47.368 2.204.74.734.366 1.28.738 2.015 1.109.551-.926.918-2.036 1.47-2.957.183-.188 0-.555 0-.743V6.32h.183c.183.184.367.371.55.739 1.649 2.406 3.118 4.808 5.133 6.843 2.383 2.215 4.77 4.067 7.887 4.805.918.184 1.648.184 2.566-.371 3.485-2.219 6.97-2.402 10.637-.555.184.188.55.188.918.188 5.133-1.297 9.902-3.512 13.754-7.395 1.652-1.664 2.934-3.699 3.852-6.101.367-1.11.917-2.035 1.468-3.145.547-.922 1.282-1.476 2.2-1.293 1.101.184 1.648.926 1.832 1.848.367 1.851.734 3.699.917 5.547.184 3.328.184 6.656.184 9.984-.184 6.84-.918 13.68-3.3 20.149-1.102 1.296-2.016 3.328-2.934 5.363zm-9.172-.371c.734-1.11.734-2.22.183-3.328-.914-1.664-2.382-2.957-4.214-3.696H47l.547 1.11c.183.367.367.738.367 1.293.367 1.48.184 2.218-1.281 2.773-.918.371-1.836.555-2.57.738-4.399.739-8.985.739-13.387.555h-1.281c0 .184.183.184.183.184 4.399 1.48 8.8 2.59 13.387 2.96 1.648.184 3.484.184 5.133-.37.55-.184.918 0 1.285.183 4.953 3.328 10.27 5.73 16.137 7.211 1.101.371 1.101.371 1.652-.738.183-.188.183-.371.367-.555-4.953-3.7-10.453-6.285-16.324-8.32zm-15.586-17.38c-.184 2.22.184 3.145 1.465 3.516 1.101.368 2.386 0 2.754-.925.367-.555.367-1.293.367-2.036-.184-.554-.735-1.109-1.102-1.664 2.2.188 3.485 1.48 4.219 3.516.547-1.852-.367-5.547-3.117-7.395-2.938-1.851-6.973-1.48-9.356 1.11-2.382 2.586-2.566 6.469-.734 9.426 1.836 2.773 5.504 3.699 7.152 2.957-2.015-.739-3.3-2.215-3.484-4.434 0-1.664.55-2.96 1.836-4.07zm-13.387 7.028c-3.3-1.848-4.035-5.363-1.652-7.027-.367 1.48 0 2.406 1.101 2.96.735.368 2.016.184 2.383-.741.367-.555.551-1.293.367-1.848s-.734-.926-1.101-1.664c.918.37 1.652.555 2.387.926.546-1.664.546-1.664 0-2.403-1.653-1.48-3.485-2.035-5.504-1.48-2.2.554-3.485 2.035-4.035 4.25-.184.926-.368 1.851.183 2.773l1.652 2.774c.184.187.184.554.551.554.914.743 2.2.926 3.668.926zM2.984 29.984c0 .926.368 2.036 1.102 2.957 1.098 1.293 2.934 1.293 4.219 0 1.832-1.847 1.648-4.992-.367-6.656-.551-.555-1.286-.738-2.02-.555-1.832.188-3.117 1.852-2.934 4.254zm0 0" fill="#3c3"/></svg> |
| 1 | ||
| 1 | <svg height="63" width="49" xmlns="http://www.w3.org/2000/svg"><path d="M4.524 3.224v10.102h8.5v2.598h-8.5v13.7h-3.9V.626h13.301v2.598zm14.402 26.3V.826h3.7v28.7zm0 0" fill="#d10407" stroke="#d10407" stroke-miterlimit="10" stroke-width="1.25" transform="matrix(2.10753 0 0 2.07742 0 .079)"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="84" height="62"><path style="stroke:none;fill-rule:nonzero;fill:#1f7244;fill-opacity:1" d="M61.328.137H84v15.152H61.328zm0 23.383H84v15.152H61.328zm0 23.19H84v15.153H61.328zm-30.664 0h22.672v15.153H30.664zM0 46.71h22.672v15.153H0zm50.363-8.98L35.496 18.84 49.06 1.633H35.684l-7.067 9.351-6.5-9.347H8.18l13.746 17.578L7.434 37.73H21l7.617-10.285 7.621 10.285zm0 0"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="84" height="62"><path style="stroke:none;fill-rule:nonzero;fill:#1f7244;fill-opacity:1" d="M61.328.137H84v15.152H61.328zm0 23.383H84v15.152H61.328zm0 23.19H84v15.153H61.328zm-30.664 0h22.672v15.153H30.664zM0 46.71h22.672v15.153H0zm50.363-8.98L35.496 18.84 49.06 1.633H35.684l-7.067 9.351-6.5-9.347H8.18l13.746 17.578L7.434 37.73H21l7.617-10.285 7.621 10.285zm0 0"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="84" height="62"><path style="stroke:none;fill-rule:nonzero;fill:#1f7244;fill-opacity:1" d="M61.328.137H84v15.152H61.328zm0 23.383H84v15.152H61.328zm0 23.19H84v15.153H61.328zm-30.664 0h22.672v15.153H30.664zM0 46.71h22.672v15.153H0zm50.363-8.98L35.496 18.84 49.06 1.633H35.684l-7.067 9.351-6.5-9.347H8.18l13.746 17.578L7.434 37.73H21l7.617-10.285 7.621 10.285zm0 0"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="84" height="62"><path style="stroke:none;fill-rule:nonzero;fill:#1f7244;fill-opacity:1" d="M61.328.137H84v15.152H61.328zm0 23.383H84v15.152H61.328zm0 23.19H84v15.153H61.328zm-30.664 0h22.672v15.153H30.664zM0 46.71h22.672v15.153H0zm50.363-8.98L35.496 18.84 49.06 1.633H35.684l-7.067 9.351-6.5-9.347H8.18l13.746 17.578L7.434 37.73H21l7.617-10.285 7.621 10.285zm0 0"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="84" height="62"><path style="stroke:none;fill-rule:nonzero;fill:#1f7244;fill-opacity:1" d="M61.328.137H84v15.152H61.328zm0 23.383H84v15.152H61.328zm0 23.19H84v15.153H61.328zm-30.664 0h22.672v15.153H30.664zM0 46.71h22.672v15.153H0zm50.363-8.98L35.496 18.84 49.06 1.633H35.684l-7.067 9.351-6.5-9.347H8.18l13.746 17.578L7.434 37.73H21l7.617-10.285 7.621 10.285zm0 0"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="84" height="62"><path style="stroke:none;fill-rule:nonzero;fill:#1f7244;fill-opacity:1" d="M61.328.137H84v15.152H61.328zm0 23.383H84v15.152H61.328zm0 23.19H84v15.153H61.328zm-30.664 0h22.672v15.153H30.664zM0 46.71h22.672v15.153H0zm50.363-8.98L35.496 18.84 49.06 1.633H35.684l-7.067 9.351-6.5-9.347H8.18l13.746 17.578L7.434 37.73H21l7.617-10.285 7.621 10.285zm0 0"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="84" height="62"><path style="stroke:none;fill-rule:nonzero;fill:#1f7244;fill-opacity:1" d="M61.328.137H84v15.152H61.328zm0 23.383H84v15.152H61.328zm0 23.19H84v15.153H61.328zm-30.664 0h22.672v15.153H30.664zM0 46.71h22.672v15.153H0zm50.363-8.98L35.496 18.84 49.06 1.633H35.684l-7.067 9.351-6.5-9.347H8.18l13.746 17.578L7.434 37.73H21l7.617-10.285 7.621 10.285zm0 0"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="83" height="55"><path style="fill-rule:nonzero;fill:#666;fill-opacity:1;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#666;stroke-opacity:1;stroke-miterlimit:10" d="M11.241 25.867c-.498 0-1.1-.2-1.5-.6l-8.398-8.4c-.8-.799-.8-2.1 0-3.001l8.398-8.4c.8-.798 2.101-.798 3.002 0 .8.801.8 2.1 0 3.001l-6.901 6.9 6.9 6.9c.8.8.8 2.098 0 3-.5.4-.998.6-1.499.6zm25 0c-.5 0-1.099-.2-1.499-.6-.8-.8-.8-2.1 0-3l6.901-6.9-6.9-6.9c-.8-.8-.8-2.1 0-3 .8-.8 2.1-.8 2.998 0l8.4 8.399c.801.8.801 2.102 0 3l-8.4 8.4c-.4.4-.898.6-1.5.6zm-16.698 4.1c-.2 0-.402 0-.7-.1-1.1-.399-1.7-1.5-1.3-2.599l8.399-25.1c.402-1.101 1.5-1.702 2.6-1.302 1.1.4 1.7 1.502 1.3 2.6l-8.4 25.101c-.198.901-1 1.4-1.899 1.4zm0 0" transform="matrix(1.74792 0 0 1.75607 0 .53)"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="67" xmlns="http://www.w3.org/2000/svg"><path d="M46.406 0c6.367 4.457 10.078 16.043 10.078 24.781 0 2.317-.351 4.457-.882 6.418-.532-5.172-3.008-9.629-6.895-12.48 2.121 2.851 3.36 6.418 3.36 10.34 0 9.625-7.782 17.468-17.329 17.468-3.89 0-5.836-.71-8.664-2.851 5.836 0 9.547-5.883 14.5-5.883 0 0-.71-2.852-4.422-2.852-3.715 0-1.945 2.852-8.664 2.852S17.41 33.695 17.41 30.484c0-3.207 4.774-5.527 5.836-4.457 1.059-1.07 0-2.851 0-2.851l8.664-5.883h-2.832c-12.906 0-5.48-9.094-2.828-11.59-4.598 0-7.426 4.281-8.664 5.883-.707-.356-5.832-.356-7.246 0-.707.18-1.594-1.066-2.3-2.492-1.06-1.961-1.946-4.637-1.946-6.242-3.711 3.746-3.004 9.27-1.59 11.41l-.176.18C1.676 19.253.262 24.601.262 30.483.262 49.024 15.113 64 33.5 64s33.238-13.547 33.238-32.09V29.06C66.563 11.766 55.602 2.852 46.406 0zm0 0" fill="#999"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="83" height="55"><path style="fill-rule:nonzero;fill:#999;fill-opacity:1;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#999;stroke-opacity:1;stroke-miterlimit:10" d="M11.143 25.867c-.5 0-1.1-.2-1.502-.6l-8.21.1.6-1.6.6zm25.101 0c-.503 0-1.102-.2-1.502999.6-1.5.6zm-16.7 4.1c-.202 0-.403 0-.7-.1-1.1028. |
| 1 | ||
| 1 | <svg height="64" width="74" xmlns="http://www.w3.org/2000/svg"><path d="m49.332 34.941-12.25-5.714L61.75 17.633 74 23.348l-12.25 5.879zM61.75 6.207 49.5.492 37.25 6.207l24.5 11.594L74 12.086zm-37.082 17.14-12.25-5.714-12.25 5.715L24.836 34.94l12.246-5.714zm0-11.429 12.25-5.711L24.668.492 0 12.086 12.25 17.8zM61.75 32.59l-11.074 5.039-1.344.672-1.34-.672-11.074-5.04-11.078 5.04-1.34.672-1.344-.672-11.074-5.04v17.977L36.75 63.508l25-12.942zm0 0" fill="#55486d"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="69" xmlns="http://www.w3.org/2000/svg"><path d="M26.555 0h15.89v16h-15.89zm0 48h15.89v16h-15.89zM.015 48h15.887v16H.016zm53.083 0h15.886v16H53.098zM37.207 29.273V18.727h-5.414v10.546H5.25v16h5.418V34.727h21.125v10.546h5.414V34.727h21.125v10.546h5.418v-16zm0 0" fill="#999"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="83" height="55"><path style="fill-rule:nonzero;fill:#999;fill-opacity:1;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#999;stroke-opacity:1;stroke-miterlimit:10" d="M11.143 25.867c-.5 0-1.1-.2-1.502-.6l-8.21.1.6-1.6.6zm25.101 0c-.503 0-1.102-.2-1.502999.6-1.5.6zm-16.7 4.1c-.202 0-.403 0-.7-.1-1.1028. |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="83" height="63"><path style="stroke:none;fill-rule:nonzero;fill:#039;fill-opacity:1" d="M4.059 10.39h40.254c2.109 0 3.69-1.613 3.69-3.761 0-2.149-1.581-3.758-3.69-3.758H4.059c-2.11 0-3.692 1.61-3.692 3.758 0 2.152 1.582 3.762 3.692 3.762zm0 19.891h40.254c2.109 0 3.69-1.613 3.69-3.765 0-2.149-1.581-3.762-3.69-3.762H4.059c-2.11 0-3.692 1.613-3.692 3.762 0 2.148 1.582 3.765 3.692 3.765zm19.336 10.57H4.059c-2.11 0-3.692 1.614-3.692 3.762 0 2.149 1.582 3.766 3.692 3.766h19.336c2.109 0 3.69-1.617 3.69-3.766 0-2.148-1.581-3.761-3.69-3.761zm0 0"/><path style="stroke:none;fill-rule:nonzero;fill:#039;fill-opacity:1" d="M70.68 9.496c-2.813-1.434-6.504-3.582-7.91-6.629C62.77 1.254 61.54 0 59.957 0c-1.582 0-2.812 1.254-2.812 2.867v38.52c-2.989-1.614-8.614-1.075-12.833 1.433-6.68 3.766-9.492 10.93-6.68 15.766 2.813 4.84 10.723 5.914 17.4 2.152 4.573-2.687 7.738-6.988 7.913-11.289V16.305c9.492 0 15.29 3.941 13.18 13.437-.352 1.793-1.05 3.403-1.754 5.195-.355.54-.355 1.254.176 1.793.527.536 1.402.356 2.11-.359 3.515-3.582 5.796-8.242 5.976-13.437-.18-6.805-6.508-10.75-11.953-13.438zm0 0"/></svg> |
| 1 | ||
| 1 | <svg height="63" width="54" xmlns="http://www.w3.org/2000/svg"><path d="M53.344 18.172H44.02V8.965zM28.309 8.965v33.437h25.199V20.434H41.727V8.964zm3.93-8.723H4.417v6.461h10.965l-6.875 5.332v5.652l10.148-7.753V6.867H54V4.281zM18.655 14.297 8.508 22.05v5.652l10.148-7.754zM8.344 37.559l10.148-7.754v-5.657L8.344 31.902zm10.312 2.261v-5.656L8.508 41.918v2.91h-4.09v6.461h6.219v4.523H7.035c-.652-1.132-1.797-1.937-3.273-1.937C1.637 53.875 0 55.488 0 57.59c0 2.097 1.637 3.715 3.762 3.715 1.476 0 2.62-.809 3.273-1.938h3.602v3.39h5.562v-3.39h3.602c.652 1.13 1.8 1.938 3.273 1.938 2.125 0 3.762-1.618 3.762-3.715 0-2.102-1.637-3.715-3.762-3.715-1.472 0-2.62.805-3.273 1.938h-3.602v-4.524h15.875l21.762-3.879v-2.582H11.78zm0 0" fill="#90c"/></svg> |
| 1 | ||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="83" height="63"><path style="stroke:none;fill-rule:nonzero;fill:#999;fill-opacity:1" d="M.125 0h69.586v8.184H.125zm13.164 18.273h69.586v8.18H13.289zM.125 36.543h69.586v8.184H.125zm13.164 18.273h69.586V63H13.289zm0 0"/></svg> |
| 1 | <svg height="63" width="54" xmlns="http://www.w3.org/2000/svg"><path d="M53.344 18.172H44.02V8.965zM28.309 8.965v33.437h25.199V20.434H41.727V8.964zm3.93-8.723H4.417v6.461h10.965l-6.875 5.332v5.652l10.148-7.753V6.867H54V4.281zM18.655 14.297 8.508 22.05v5.652l10.148-7.754zM8.344 37.559l10.148-7.754v-5.657L8.344 31.902zm10.312 2.261v-5.656L8.508 41.918v2.91h-4.09v6.461h6.219v4.523H7.035c-.652-1.132-1.797-1.937-3.273-1.937C1.637 53.875 0 55.488 0 57.59c0 2.097 1.637 3.715 3.762 3.715 1.476 0 2.62-.809 3.273-1.938h3.602v3.39h5.562v-3.39h3.602c.652 1.13 1.8 1.938 3.273 1.938 2.125 0 3.762-1.618 3.762-3.715 0-2.102-1.637-3.715-3.762-3.715-1.472 0-2.62.805-3.273 1.938h-3.602v-4.524h15.875l21.762-3.879v-2.582H11.78zm0 0" fill="#90c"/></svg> | |
| 1 | 2 |
| 1 | ||
| 1 | <svg height="63" width="54" xmlns="http://www.w3.org/2000/svg"><path d="M53.344 18.172H44.02V8.965zM28.309 8.965v33.437h25.199V20.434H41.727V8.964zm3.93-8.723H4.417v6.461h10.965l-6.875 5.332v5.652l10.148-7.753V6.867H54V4.281zM18.655 14.297 8.508 22.05v5.652l10.148-7.754zM8.344 37.559l10.148-7.754v-5.657L8.344 31.902zm10.312 2.261v-5.656L8.508 41.918v2.91h-4.09v6.461h6.219v4.523H7.035c-.652-1.132-1.797-1.937-3.273-1.937C1.637 53.875 0 55.488 0 57.59c0 2.097 1.637 3.715 3.762 3.715 1.476 0 2.62-.809 3.273-1.938h3.602v3.39h5.562v-3.39h3.602c.652 1.13 1.8 1.938 3.273 1.938 2.125 0 3.762-1.618 3.762-3.715 0-2.102-1.637-3.715-3.762-3.715-1.472 0-2.62.805-3.273 1.938h-3.602v-4.524h15.875l21.762-3.879v-2.582H11.78zm0 0" fill="#90c"/></svg> |
| 1 | ||
| 1 | <svg height="64" width="69" xmlns="http://www.w3.org/2000/svg"><path d="M13.875 13.874h10.9v2.701h-10.9zm0 5.4h10.9v2.701h-10.9zm0 5.5h10.9v2.702h-10.9zm19-24.399H11.177c-3 0-5.402 2.4-5.402 5.4v24.4h-5.4c0 3 2.402 5.4 5.4 5.4h21.7c3 0 5.402-2.4 5.402-5.4v-21.7h5.4v-2.7c0-3-2.402-5.4-5.4-5.4zm-2.7 29.3c0 1.801-1.4 3.2-3.2 3.2h-19.9c1.3-.9 1.3-2.7 1.3-2.7v-24.4c0-1.5 1.2-2.7 2.7-2.7 1.501 0 2.7 1.2 2.7 2.7v2.7h16.3zm-13.6-23.9v-2.7h16.3c2.501 0 2.7 1.6 2.7 2.7zm0 0" fill="#999" stroke="#999" stroke-miterlimit="10" stroke-width=".75" transform="matrix(1.7717 0 0 1.78025 .262 0)"/></svg> |
| 1 | .tagmark { | |
| 2 | -fx-fill: gray; | |
| 3 | } | |
| 4 | .anytag { | |
| 5 | -fx-fill: crimson; | |
| 6 | } | |
| 7 | .paren { | |
| 8 | -fx-fill: firebrick; | |
| 9 | -fx-font-weight: bold; | |
| 10 | } | |
| 11 | .attribute { | |
| 12 | -fx-fill: darkviolet; | |
| 13 | } | |
| 14 | .avalue { | |
| 15 | -fx-fill: black; | |
| 16 | } | |
| 1 | 17 | |
| 18 | .comment { | |
| 19 | -fx-fill: teal; | |
| 20 | } |
| 1 | # Lexicons | |
| 2 | ||
| 3 | This directory contains lexicons used for spell checking. Each lexicon | |
| 4 | file contains tab-delimited word-frequency pairs. | |
| 5 | ||
| 6 | Compiling a high-quality list of correctly spelled words requires the | |
| 7 | following steps: | |
| 1 | 8 | |
| 9 | 1. Download a unigram frequency lResource |
| 1 | # Overview | |
| 2 | ||
| 3 | Lexicons in this directory are meant to relate to a particular subject | |
| 4 | (medicine, chemistry, math, sports, and such), extend the main lexicon, | |
| 5 | or not be in common use. | |
| 6 | ||
| 1 | 7 |
| 1 | ||
| 1 | 'aight | |
| 2 | ain't | |
| 3 | amn't | |
| 4 | aren't | |
| 5 | can't | |
| 6 | 'cause | |
| 7 | couldn't | |
| 8 | couldn't've | |
| 9 | could've | |
| 10 | daren't | |
| 11 | daresn't | |
| 12 | dasn't | |
| 13 | didn't | |
| 14 | doesn't | |
| 15 | don't | |
| 16 | dunno | |
| 17 | d'ye | |
| 18 | e'er | |
| 19 | everybody's | |
| 20 | everyone's | |
| 21 | g'day | |
| 22 | gimme | |
| 23 | giv'n | |
| 24 | gonna | |
| 25 | gon't | |
| 26 | gotta | |
| 27 | hadn't | |
| 28 | had've | |
| 29 | hasn't | |
| 30 | haven't | |
| 31 | he'd | |
| 32 | he'll | |
| 33 | he's | |
| 34 | he've | |
| 35 | how'd | |
| 36 | howdy | |
| 37 | ho |
| 1 | analytics 130337 | |
| 2 | hotspot 130022 | |
| 3 | instantiation 130000 | |
| 4 | onboarding 129953 | |
| 5 | biometric 129795 | |
| 6 | anamorphic 129777 | |
| 7 | benchmarking 129772 | |
| 8 | cybersecurity 129769 | |
| 9 | barcode 129757 | |
| 10 | splitter 129755 | |
| 11 | keychain 129719 | |
| 12 | crowdfunding 129696 | |
| 13 | polymorphism 129688 | |
| 14 | automata 129666 | |
| 15 | shockwave 129658 | |
| 16 | profiler 129648 | |
| 17 | kerning 129646 | |
| 18 | nanometer 129630 | |
| 19 | meridiem 129624 | |
| 20 | influencer 129618 | |
| 21 | passcode 129617 | |
| 22 | sexting 129607 | |
| 23 | cryptology 129606 | |
| 24 | biometrics 129606 | |
| 25 | bitcoin 129599 | |
| 26 | specular 129598 | |
| 27 | accelerometer 129588 | |
| 28 | googolplex 129583 | |
| 29 | grayscale 129576 | |
| 30 | ascender 129571 | |
| 31 | pixelated 129569 | |
| 32 | rockstar 129565 | |
| 33 | ragdoll 129564 | |
| 34 | cyberattack 129564 | |
| 35 | cryptanalysis 129562 | |
| 36 | ransomware 129553 | |
| 37 | crowdsourcing 129552 | |
| 38 | hackathon 129551 | |
| 39 | audiobook 129544 | |
| 40 | degauss 129543 | |
| 41 | attenuator 129540 | |
| 42 | jetpack 129538 | |
| 43 | packrat 129536 | |
| 44 | backlight 129535 | |
| 45 | bootable 129530 | |
| 46 | octothorpe 129529 | |
| 47 | newsfeed 129525 | |
| 48 | extranet 129523 | |
| 49 | failover 129516 | |
| 50 | cyberbullying 129516 | |
| 51 | neumann 129515 | |
| 52 | capacitive 129514 | |
| 53 | backlit 129511 | |
| 54 | millimicron 129507 | |
| 55 | inductor 129505 | |
| 56 | workgroup 129502 | |
| 57 | journaling 129500 | |
| 58 | middleware 129499 | |
| 59 | spooler 129497 | |
| 60 | clamshell 129495 | |
| 61 | wireframe 129494 | |
| 62 | modularity 129493 | |
| 63 | strikethrough 129489 | |
| 64 | petabyte 129487 | |
| 65 | jughead 129482 | |
| 66 | acyclic 129482 | |
| 67 | gearhead 129478 | |
| 68 | stateful 129473 | |
| 69 | submenu 129467 | |
| 70 | pseudorandom 129463 | |
| 71 | earbuds 129461 | |
| 72 | narrowband 129460 | |
| 73 | recordable 129457 | |
| 74 | unallocated 129455 | |
| 75 | mappable 129455 | |
| 76 | chipset 129454 | |
| 77 | multicast 129447 | |
| 78 | loopback 129444 | |
| 79 | pixelate 129441 | |
| 80 | cryptographic 129441 | |
| 81 | pixelation 129438 | |
| 82 | autocorrect 129438 | |
| 83 | teraflop 129437 | |
| 84 | digitizer 129436 | |
| 85 | tunnelling 129434 | |
| 86 | deduplication 129434 | |
| 87 | subwoofer 129433 | |
| 88 | touchpad 129429 | |
| 89 | namespace 129428 | |
| 90 | microcontroller 129428 | |
| 91 | geolocation 129428 | |
| 92 | telepresence 129427 | |
| 93 | driverless 129426 | |
| 94 | photolithography 129425 | |
| 95 | multiphase 129425 | |
| 96 | verifier 129424 | |
| 97 | robocall 129424 | |
| 98 | autofocus 129424 | |
| 99 | kilobit 129422 | |
| 100 | hacktivist 129419 | |
| 101 | geocache 129415 | |
| 102 | rasterize 129412 | |
| 103 | plaintext 129411 | |
| 104 | pipelining 129411 | |
| 105 | technobabble 129409 | |
| 106 | defragment 129409 | |
| 107 | connectionless 129409 | |
| 108 | homomorphic 129407 | |
| 109 | demodulator 129406 | |
| 110 | datagram 129406 | |
| 111 | activex 129406 | |
| 112 | normalisation 129404 | |
| 113 | blackhole 129402 | |
| 114 | cyberstalker 129401 | |
| 115 | multifunction 129400 | |
| 116 | undirected 129397 | |
| 117 | ciphertext 129397 | |
| 118 | superspeed 129396 | |
| 119 | spacebar 129395 | |
| 120 | cyberwar 129395 | |
| 121 | borderless 129395 | |
| 122 | transcode 129393 | |
| 123 | cyberbully 129393 | |
| 124 | multimeter 129392 | |
| 125 | dropship 129391 | |
| 126 | yottabyte 129390 | |
| 127 | infector 129390 | |
| 128 | superclass 129389 | |
| 129 | tooltip 129388 | |
| 130 | dereference 129387 | |
| 131 | combinator 129386 | |
| 132 | milliwatt 129385 | |
| 133 | cyberstalking 129384 | |
| 134 | subfolder 129383 | |
| 135 | wideband 129382 | |
| 136 | noncontiguous 129382 | |
| 137 | ferroelectric 129382 | |
| 138 | cybersquatting 129378 | |
| 139 | autofill 129378 | |
| 140 | trackpad 129376 | |
| 141 | associatively 129376 | |
| 142 | luggable 129374 | |
| 143 | seamonkey 129373 | |
| 144 | defragmentation 129373 | |
| 145 | starcraft 129371 | |
| 146 | obliquing 129371 | |
| 147 | leadless 129371 | |
| 148 | greeking 129371 | |
| 149 | upgradeable 129370 | |
| 150 | radiosity 129370 | |
| 151 | transcoding 129369 | |
| 152 | quintillionth 129369 | |
| 153 | bitmapped 129369 | |
| 154 | subdirectory 129368 | |
| 155 | degausser 129368 | |
| 156 | curtiss 129368 | |
| 157 | scunthorpe 129367 | |
| 158 | undelete 129365 | |
| 159 | gigaflops 129365 | |
| 160 | darknet 129365 | |
| 161 | zettabyte 129364 | |
| 162 | topologies 129363 | |
| 163 | spidering 129363 | |
| 164 | photorealism 129363 | |
| 165 | multithreading 129363 | |
| 166 | deallocate 129363 | |
| 167 | mersenne 129362 | |
| 168 | machinima 129361 | |
| 169 | satisfiable 129360 | |
| 170 | laserjet 129360 | |
| 171 | multicore 129359 | |
| 172 | microblog 129359 | |
| 173 | megaflops 129359 | |
| 174 | homeomorphic 129359 | |
| 175 | microblogging 129358 | |
| 176 | kilobaud 129358 | |
| 177 | cyberwarfare 129358 | |
| 178 | microarchitecture 129357 | |
| 179 | autosave 129357 | |
| 180 | wirelessly 129356 | |
| 181 | sneakernet 129355 | |
| 182 | textbox 129354 | |
| 183 | obfuscator 129354 | |
| 184 | microkernel 129353 | |
| 185 | substring 129352 | |
| 186 | macroinstruction 129352 | |
| 187 | endianness 129352 | |
| 188 | indexable 129351 | |
| 189 | backtick 129351 | |
| 190 | unshielded 129350 | |
| 191 | cleartext 129350 | |
| 192 | autocomplete 129349 | |
| 193 | abandonware 129349 | |
| 194 | hacktivism 129348 | |
| 195 | antikythera 129348 | |
| 196 | stereolithography 129347 | |
| 197 | photorealistic 129347 | |
| 198 | macrovision 129347 | |
| 199 | greasemonkey 129347 | |
| 200 | geotagging 129347 | |
| 201 | disassembler 129346 | |
| 202 | spacewar 129345 | |
| 203 | pluggable 129345 | |
| 204 | kilobits 129345 | |
| 205 | webcomic 129344 | |
| 206 | unfollow 129344 | |
| 207 | photosensor 129344 | |
| 208 | petaflop 129344 | |
| 209 | garageband 129344 | |
| 210 | truetype 129343 | |
| 211 | subnetwork 129342 | |
| 212 | backpropagation 129342 | |
| 213 | supercomputing 129340 | |
| 214 | smartwatch 129340 | |
| 215 | unbundled 129339 | |
| 216 | smilies 129339 | |
| 217 | milliamp 129339 | |
| 218 | bytecode 129339 | |
| 219 | trackpoint 129337 | |
| 220 | slipstreaming 129337 | |
| 221 | monospace 129337 | |
| 222 | memoization 129337 | |
| 223 | scaleable 129336 | |
| 224 | respawn 129335 | |
| 225 | multicasting 129335 | |
| 226 | geocacher 129335 | |
| 227 | workgroups 129334 | |
| 228 | ferrofluid 129334 | |
| 229 | smartdrive 129333 | |
| 230 | subsampling 129332 | |
| 231 | rasterization 129332 | |
| 232 | guiltware 129332 | |
| 233 | defragger 129332 | |
| 234 | satisfiability 129331 | |
| 235 | activision 129331 | |
| 236 | subdirectories 129330 | |
| 237 | segfault 129330 | |
| 238 | flamebait 129330 | |
| 239 | framebuffer 129329 | |
| 240 | defragging 129329 | |
| 241 | decompiler 129329 | |
| 242 | unshift 129328 | |
| 243 | memristor 129328 | |
| 244 | zebibyte 129327 | |
| 245 | semiprime 129327 | |
| 246 | rotoscoping 129327 | |
| 247 | hypertransport 129327 | |
| 248 | smartmedia 129326 | |
| 249 | grayware 129326 | |
| 250 | defragmenting 129326 | |
| 251 | defragmenter 129326 | |
| 252 | repagination 129325 | |
| 253 | subnetting 129324 | |
| 254 | skeuomorphism 129324 | |
| 255 | screencast 129324 | |
| 256 | stylesheet 129323 | |
| 257 | superintelligence 129322 | |
| 258 | multitenancy 129322 | |
| 259 | datastore 129322 | |
| 260 | autoplay 129322 | |
| 261 | repaginate 129321 | |
| 262 | macbook 129321 | |
| 263 | geotagged 129321 | |
| 264 | baudrate 129321 | |
| 265 | transmeta 129320 | |
| 266 | screwless 129320 | |
| 267 | nameserver 129320 | |
| 268 | interexchange 129320 | |
| 269 | geocoding 129319 | |
| 270 | downloader 129319 | |
| 271 | autodiscovery 129319 | |
| 272 | extortion 65752 | |
| 273 | emoji 65684 | |
| 274 | googol 65618 | |
| 275 | backside 65388 | |
| 276 | fibre 65387 | |
| 277 | metre 65333 | |
| 278 | royale 65173 | |
| 279 | radix 65093 | |
| 280 | hotdog 65091 | |
| 281 | lecher 65062 | |
| 282 | uptime 65009 | |
| 283 | unbound 64979 | |
| 284 | eniac 64975 | |
| 285 | synaptic 64966 | |
| 286 | voxel 64926 | |
| 287 | selfie 64917 | |
| 288 | uplink 64887 | |
| 289 | fanboy 64857 | |
| 290 | defrag 64849 | |
| 291 | nondisclosure 64839 | |
| 292 | qubit 64828 | |
| 293 | yippie 64821 | |
| 294 | gearhead 64819 | |
| 295 | subnet 64818 | |
| 296 | endian 64798 | |
| 297 | bezier 64797 | |
| 298 | reallocation 64796 | |
| 299 | telephonic 64789 | |
| 300 | mosfet 64777 | |
| 301 | mutex 64775 | |
| 302 | inkjet 64772 | |
| 303 | gobbing 64768 | |
| 304 | shader 64766 | |
| 305 | ultralight 64755 | |
| 306 | hackers 64746 | |
| 307 | pacman 64742 | |
| 308 | unlink 64741 | |
| 309 | undock 64740 | |
| 310 | understroke 64738 | |
| 311 | beginners 64736 | |
| 312 | photoscope 64731 | |
| 313 | gantt 64725 | |
| 314 | programmers 64722 | |
| 315 | todays 64720 | |
| 316 | moores 64716 | |
| 317 | fullscreen 64715 | |
| 318 | moveless 64708 | |
| 319 | reformatted 64704 | |
| 320 | deallocate 64704 | |
| 321 | laserdisc 64702 | |
| 322 | macos 64700 | |
| 323 | nonactive 64697 | |
| 324 | nonadjacent 64696 | |
| 325 | hotfix 64695 | |
| 326 | keylogger 64694 | |
| 327 | geotag 64691 | |
| 328 | oreilly 64681 | |
| 329 | exabit 64678 | |
| 330 | jailbroken 64677 | |
| 331 | fuzzer 64676 | |
| 332 | noninteractive 64673 | |
| 333 | multifactor 64672 | |
| 334 | letterspacing 64671 | |
| 335 | preinstall 64669 | |
| 336 | multiboot 64666 | |
| 337 | runescape 64665 | |
| 338 | micropayment 64664 | |
| 339 | numpad 64663 | |
| 340 | preinstalled 64661 | |
| 341 | jailbreaking 64660 | |
| 342 | attend 2158 | |
| 343 | withstand 1809 | |
| 344 | transpire 1116 | |
| 345 | reading 1110 | |
| 346 | texture 1065 | |
| 347 | capitalize 832 | |
| 348 | calling 779 | |
| 349 | unfold 767 | |
| 350 | starboard 679 | |
| 351 | commode 625 | |
| 352 | doing 594 | |
| 353 | textbook 499 | |
| 354 | unease 378 | |
| 355 | unpack 358 | |
| 356 | keycard 231 | |
| 357 | mainspring 207 | |
| 358 | grr 180 | |
| 359 | geocaching 167 | |
| 360 | microbus 160 | |
| 361 | mp3 147 | |
| 362 | svg 139 | |
| 363 | shifted 128 | |
| 364 | texted 127 | |
| 365 | towheaded 118 | |
| 366 | mineshaft 115 | |
| 367 | nonparty 95 | |
| 368 | crossbite 80 | |
| 369 | resignedness 69 | |
| 370 | msrp 61 | |
| 371 | inbreak 53 | |
| 372 | nanocomposite 44 | |
| 373 | md5 44 | |
| 374 | neomorphic 41 | |
| 375 | superstrain 28 | |
| 376 | lifers 27 | |
| 377 | multination 26 | |
| 378 | smartwatch 22 | |
| 379 | antilibration 22 | |
| 380 | zapf 20 | |
| 381 | mp4 20 | |
| 1 | 382 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite; | |
| 3 | ||
| 4 | import javafx.embed.swing.JFXPanel; | |
| 5 | import org.junit.jupiter.api.extension.BeforeAllCallback; | |
| 6 | import org.junit.jupiter.api.extension.ExtensionContext; | |
| 7 | import org.testfx.osgi.service.TestFx; | |
| 8 | ||
| 9 | import java.util.concurrent.Semaphore; | |
| 10 | ||
| 11 | import static javafx.application.Platform.runLater; | |
| 12 | import static javax.swing.SwingUtilities.invokeLater; | |
| 13 | ||
| 14 | /** | |
| 15 | * Blocks all unit tests until JavaFX is ready. | |
| 16 | */ | |
| 17 | public class AwaitFxExtension implements BeforeAllCallback { | |
| 18 | /** | |
| 19 | * Prevent {@link RuntimeException} for internal graphics not initialized yet. | |
| 20 | * | |
| 21 | * @param context Provided by the {@link TestFx} framework. | |
| 22 | * @throws InterruptedException Could not acquire semaphore. | |
| 23 | */ | |
| 24 | @Override | |
| 25 | public void beforeAll( final ExtensionContext context ) | |
| 26 | throws InterruptedException { | |
| 27 | final var semaphore = new Semaphore( 0 ); | |
| 28 | ||
| 29 | invokeLater( () -> { | |
| 30 | // Prepare JavaFX toolkit and environment. | |
| 31 | new JFXPanel(); | |
| 32 | runLater( semaphore::release ); | |
| 33 | } ); | |
| 34 | ||
| 35 | semaphore.acquire(); | |
| 36 | } | |
| 37 | } | |
| 1 | 38 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.definition; | |
| 3 | ||
| 4 | import com.keenwrite.editors.definition.DefinitionEditor; | |
| 5 | import com.keenwrite.editors.definition.yaml.YamlTreeTransformer; | |
| 6 | import com.keenwrite.editors.markdown.MarkdownEditor; | |
| 7 | import com.keenwrite.preferences.Workspace; | |
| 8 | import com.keenwrite.preview.HtmlPreview; | |
| 9 | import com.panemu.tiwulfx.control.dock.DetachableTabPane; | |
| 10 | import javafx.application.Application; | |
| 11 | import javafx.beans.property.SimpleObjectProperty; | |
| 12 | import javafx.event.Event; | |
| 13 | import javafx.event.EventHandler; | |
| 14 | import javafx.scene.Node; | |
| 15 | import javafx.scene.Scene; | |
| 16 | import javafx.scene.control.ColorPicker; | |
| 17 | import javafx.scene.control.SplitPane; | |
| 18 | import javafx.scene.control.Tooltip; | |
| 19 | import javafx.scene.control.TreeItem; | |
| 20 | import javafx.stage.Stage; | |
| 21 | import org.assertj.core.util.Files; | |
| 22 | import org.testfx.framework.junit5.Start; | |
| 23 | ||
| 24 | import static com.keenwrite.util.FontLoader.initFonts; | |
| 25 | ||
| 26 | public class TreeViewTest extends Application { | |
| 27 | private final SimpleObjectProperty<Node> mTextEditor = | |
| 28 | new SimpleObjectProperty<>(); | |
| 29 | ||
| 30 | private final EventHandler<TreeItem.TreeModificationEvent<Event>> mTreeHandler = | |
| 31 | event -> refresh( mTextEditor.get() ); | |
| 32 | ||
| 33 | private void refresh( final Node node ) { | |
| 34 | throw new RuntimeException( "Derp: " + node ); | |
| 35 | } | |
| 36 | ||
| 37 | public static void main( final String[] args ) { | |
| 38 | initFonts(); | |
| 39 | launch( args ); | |
| 40 | } | |
| 41 | ||
| 42 | public void start( final Stage stage ) { | |
| 43 | onStart( stage ); | |
| 44 | } | |
| 45 | ||
| 46 | @Start | |
| 47 | private void onStart( final Stage stage ) { | |
| 48 | final var workspace = new Workspace(); | |
| 49 | final var mainPane = new SplitPane(); | |
| 50 | final var transformer = new YamlTreeTransformer(); | |
| 51 | final var editor = new DefinitionEditor( transformer ); | |
| 52 | final var file = Files.newTemporaryFile(); | |
| 53 | ||
| 54 | final var tabPane1 = new DetachableTabPane(); | |
| 55 | tabPane1.addTab( "Editor", editor ); | |
| 56 | ||
| 57 | final var tabPane2 = new DetachableTabPane(); | |
| 58 | final var tab21 = | |
| 59 | tabPane2.addTab( "Picker", new ColorPicker() ); | |
| 60 | final var tab22 = | |
| 61 | tabPane2.addTab( "Editor", new MarkdownEditor( file, workspace ) ); | |
| 62 | tab21.setTooltip( new Tooltip( "Colour Picker" ) ); | |
| 63 | tab22.setTooltip( new Tooltip( "Text Editor" ) ); | |
| 64 | ||
| 65 | final var tabPane3 = new DetachableTabPane(); | |
| 66 | tabPane3.addTab( "Preview", new HtmlPreview( workspace ) ); | |
| 67 | ||
| 68 | editor.addTreeChangeHandler( mTreeHandler ); | |
| 69 | ||
| 70 | mainPane.getItems().addAll( tabPane1, tabPane2, tabPane3 ); | |
| 71 | ||
| 72 | stage.setScene( new Scene( mainPane ) ); | |
| 73 | stage.show(); | |
| 74 | } | |
| 75 | } | |
| 1 | 76 |
| 1 | package com.keenwrite.editors.markdown; | |
| 2 | ||
| 3 | import com.keenwrite.AwaitFxExtension; | |
| 4 | import com.keenwrite.preferences.Workspace; | |
| 5 | import org.assertj.core.util.Files; | |
| 6 | import org.junit.jupiter.api.Test; | |
| 7 | import org.junit.jupiter.api.extension.ExtendWith; | |
| 8 | import org.testfx.framework.junit5.ApplicationExtension; | |
| 9 | ||
| 10 | import java.io.File; | |
| 11 | import java.util.regex.Pattern; | |
| 12 | ||
| 13 | import static java.util.regex.Pattern.compile; | |
| 14 | import static javafx.application.Platform.runLater; | |
| 15 | import static org.junit.jupiter.api.Assertions.assertEquals; | |
| 16 | import static org.junit.jupiter.api.Assertions.assertTrue; | |
| 17 | ||
| 18 | @ExtendWith( {ApplicationExtension.class, AwaitFxExtension.class} ) | |
| 19 | public class MarkdownEditorTest { | |
| 20 | private static final File TEMP_FILE = Files.newTemporaryFile(); | |
| 21 | ||
| 22 | private static final String[] WORDS = new String[]{ | |
| 23 | "Italicize", | |
| 24 | "English's", | |
| 25 | "foreign", | |
| 26 | "words", | |
| 27 | "based", | |
| 28 | "on", | |
| 29 | "popularity,", | |
| 30 | "like", | |
| 31 | "_bête_", | |
| 32 | "_noire_", | |
| 33 | "and", | |
| 34 | "_Weltanschauung_", | |
| 35 | "but", | |
| 36 | "not", | |
| 37 | "résumé.", | |
| 38 | "Don't", | |
| 39 | "omit", | |
| 40 | "accented", | |
| 41 | "characters!", | |
| 42 | "Cœlacanthe", | |
| 43 | "L'Haÿ-les-Roses", | |
| 44 | "Mühlfeldstraße", | |
| 45 | "Da̱nx̱a̱laga̱litła̱n", | |
| 46 | }; | |
| 47 | ||
| 48 | private static final String TEXT = String.join( " ", WORDS ); | |
| 49 | ||
| 50 | private static final Pattern REGEX = compile( | |
| 51 | "[^\\p{Mn}\\p{Me}\\p{L}\\p{N}'-]+" ); | |
| 52 | ||
| 53 | /** | |
| 54 | * Test that the {@link MarkdownEditor} can retrieve a word at the caret | |
| 55 | * position, regardless of whether the caret is at the beginning, middle, or | |
| 56 | * end of the word. | |
| 57 | */ | |
| 58 | @Test | |
| 59 | public void test_CaretWord_GetISO88591Word_WordSelected() { | |
| 60 | runLater( () -> { | |
| 61 | final var editor = createMarkdownEditor(); | |
| 62 | ||
| 63 | for( int i = 0; i < WORDS.length; i++ ) { | |
| 64 | final var word = WORDS[ i ]; | |
| 65 | final var len = word.length(); | |
| 66 | final var expected = REGEX.matcher( word ).replaceAll( "" ); | |
| 67 | ||
| 68 | for( int j = 0; j < len; j++ ) { | |
| 69 | editor.moveTo( offset( i ) + j ); | |
| 70 | final var actual = editor.getCaretWordText(); | |
| 71 | assertEquals( expected, actual ); | |
| 72 | } | |
| 73 | } | |
| 74 | } ); | |
| 75 | } | |
| 76 | ||
| 77 | /** | |
| 78 | * Test that the {@link MarkdownEditor} can make a word bold. | |
| 79 | */ | |
| 80 | @Test | |
| 81 | public void test_CaretWord_SetWordBold_WordIsBold() { | |
| 82 | final var index = 20; | |
| 83 | final var editor = createMarkdownEditor(); | |
| 84 | ||
| 85 | editor.moveTo( offset( index ) ); | |
| 86 | editor.bold(); | |
| 87 | assertTrue( editor.getText().contains( "**" + WORDS[ index ] + "**" ) ); | |
| 88 | } | |
| 89 | ||
| 90 | /** | |
| 91 | * Returns the document offset for a string at the given index. | |
| 92 | */ | |
| 93 | private static int offset( final int index ) { | |
| 94 | assert 0 <= index && index < WORDS.length; | |
| 95 | int offset = 0; | |
| 96 | ||
| 97 | for( int i = 0; i < index; i++ ) { | |
| 98 | offset += WORDS[ i ].length(); | |
| 99 | } | |
| 100 | ||
| 101 | // Add the index to compensate for one space between words. | |
| 102 | return offset + index; | |
| 103 | } | |
| 104 | ||
| 105 | /** | |
| 106 | * Returns an instance of {@link MarkdownEditor} pre-populated with | |
| 107 | * {@link #TEXT}. | |
| 108 | * | |
| 109 | * @return A new {@link MarkdownEditor} instance, ready for unit tests. | |
| 110 | */ | |
| 111 | private MarkdownEditor createMarkdownEditor() { | |
| 112 | final var workspace = new Workspace(); | |
| 113 | final var editor = new MarkdownEditor( TEMP_FILE, workspace ); | |
| 114 | editor.setText( TEXT ); | |
| 115 | return editor; | |
| 116 | } | |
| 117 | } | |
| 1 | 118 |
| 1 | package com.keenwrite.encoding; | |
| 2 | ||
| 3 | import com.keenwrite.util.EncodingDetector; | |
| 4 | import org.junit.jupiter.api.Test; | |
| 5 | ||
| 6 | import java.nio.charset.Charset; | |
| 7 | import java.nio.charset.StandardCharsets; | |
| 8 | ||
| 9 | import static java.nio.charset.StandardCharsets.*; | |
| 10 | import static org.junit.jupiter.api.Assertions.assertEq@SuppressWarnings( "UnnecessaryLocalVariable" )or = new EncodingDetector();UTF_8;detector.detect( bytes UTF_8 ); | |
| 11 | } | |
| 12 | } | |
| 1 | 13 |
| 1 | /* Copyright 2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.flexmark; | |
| 3 | ||
| 4 | import com.keenwrite.processors.markdown.extensions.fences.FencedDivExtension; | |
| 5 | import com.keenwrite.processors.markdown.extensions.references.CrossReferenceExtension; | |
| 6 | import com.vladsch.flexmark.ext.definition.DefinitionExtension; | |
| 7 | import com.vladsch.flexmark.ext.gfm.strikethrough.StrikethroughSubscriptExtension; | |
| 8 | import com.vladsch.flexmark.ext.superscript.SuperscriptExtension; | |
| 9 | import com.vladsch.flexmark.ext.tables.TablesExtension; | |
| 10 | import com.vladsch.flexmark.html.HtmlRenderer; | |
| 11 | import com.vladsch.flexmark.parser.Parser; | |
| 12 | import com.vladsch.flexmark.util.data.MutableDataSet; | |
| 13 | import com.vladsch.flexmark.util.misc.Extension; | |
| 14 | import org.junit.jupiter.params.ParameterizedTest; | |
| 15 | import org.junit.jupiter.params.provider.Arguments; | |
| 16 | import org.junit.jupiter.params.provider.MethodSource; | |
| 17 | ||
| 18 | import java.util.ArrayList; | |
| 19 | import java.util.List; | |
| 20 | import java.util.stream.Stream; | |
| 21 | ||
| 22 | import static org.junit.jupiter.api.Assertions.assertEquals; | |
| 23 | ||
| 24 | /** | |
| 25 | * Test that basic styles for conversion exports as expected. | |
| 26 | */ | |
| 27 | public class ParserTest { | |
| 28 | ||
| 29 | @ParameterizedTest | |
| 30 | @MethodSource( "markdownParameters" ) | |
| 31 | void test_Conversion_Markdown_Html( final String md, final String expected ) { | |
| 32 | final var extensions = createExtensions(); | |
| 33 | final var options = new MutableDataSet(); | |
| 34 | final var parser = Parser | |
| 35 | .builder( options ) | |
| 36 | .extensions( extensions ) | |
| 37 | .build(); | |
| 38 | final var renderer = HtmlRenderer | |
| 39 | .builder( options ) | |
| 40 | .extensions( extensions ) | |
| 41 | .build(); | |
| 42 | ||
| 43 | final var document = parser.parse( md ); | |
| 44 | final var actual = renderer.render( document ); | |
| 45 | ||
| 46 | assertEquals( expected, actual ); | |
| 47 | } | |
| 48 | ||
| 49 | private List<Extension> createExtensions() { | |
| 50 | final var extensions = new ArrayList<Extension>(); | |
| 51 | ||
| 52 | extensions.add( DefinitionExtension.create() ); | |
| 53 | extensions.add( StrikethroughSubscriptExtension.create() ); | |
| 54 | extensions.add( SuperscriptExtension.create() ); | |
| 55 | extensions.add( TablesExtension.create() ); | |
| 56 | extensions.add( FencedDivExtension.create() ); | |
| 57 | extensions.add( CrossReferenceExtension.create() ); | |
| 58 | ||
| 59 | return extensions; | |
| 60 | } | |
| 61 | ||
| 62 | private static Stream<Arguments> markdownParameters() { | |
| 63 | return Stream.of( | |
| 64 | Arguments.of( | |
| 65 | "*emphasis* _emphasis_ **strong**", | |
| 66 | "<p><em>emphasis</em> <em>emphasis</em> <strong>strong</strong></p>\n" | |
| 67 | ), | |
| 68 | Arguments.of( | |
| 69 | "the \uD83D\uDC4D emoji", | |
| 70 | "<p>the \uD83D\uDC4D emoji</p>\n" | |
| 71 | ) | |
| 72 | ); | |
| 73 | } | |
| 74 | } | |
| 1 | 75 |
| 1 | package com.keenwrite.io; | |
| 2 | ||
| 3 | import org.apache.commons.vfs2.FileSystemException; | |
| 4 | import org.junit.jupiter.api.Disabled; | |
| 5 | import org.renjin.eval.SessionBuilder; | |
| 6 | ||
| 7 | import java.io.IOException; | |
| 8 | import java.io.OutputStreamWriter; | |
| 9 | ||
| 10 | import static com.keenwrite.constants.Constants.TEMPORARY_DIRECTORY; | |
| 11 | import static java.io.File.separator; | |
| 12 | import static java.lang.String.format; | |
| 13 | import static java.nio.charset.StandardCharsets.UTF_8; | |
| 14 | ||
| 15 | /** | |
| 16 | * Tests file resource allocation. | |
| 17 | */ | |
| 18 | public class FileObjectTest { | |
| 19 | /** | |
| 20 | * Test that resources are not exhausted. | |
| 21 | * <p> | |
| 22 | * Disabled because no issue was found and this test thrashes the I/O. | |
| 23 | * </p> | |
| 24 | */ | |
| 25 | @Disabled | |
| 26 | void test_Open_MultipleFiles_NoResourcesExpire() throws FileSystemException { | |
| 27 | final var builder = new SessionBuilder(); | |
| 28 | final var session = builder.build(); | |
| 29 | ||
| 30 | for( int i = 0; i < 10000; i++ ) { | |
| 31 | final var filename = format( | |
| 32 | "%s%s%d.txt", TEMPORARY_DIRECTORY, separator, i | |
| 33 | ); | |
| 34 | final var fileObject = session | |
| 35 | .getFileSystemManager() | |
| 36 | .resolveFile( filename ); | |
| 37 | ||
| 38 | try( | |
| 39 | final var stream = fileObject.getContent().getOutputStream(); | |
| 40 | final var writer = new OutputStreamWriter( stream, UTF_8 ) ) { | |
| 41 | writer.write( "contents" ); | |
| 42 | } catch( final IOException e ) { | |
| 43 | throw new FileSystemException( e ); | |
| 44 | } | |
| 45 | ||
| 46 | fileObject.delete(); | |
| 47 | } | |
| 48 | } | |
| 49 | } | |
| 1 | 50 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.io; | |
| 3 | ||
| 4 | import org.junit.jupiter.api.Test; | |
| 5 | import org.junit.jupiter.api.Timeout; | |
| 6 | ||
| 7 | import java.io.File; | |
| 8 | import java.io.IOException; | |
| 9 | import java.nio.file.Files; | |
| 10 | import java.util.concurrent.Semaphore; | |
| 11 | import java.util.function.Consumer; | |
| 12 | ||
| 13 | import static java.io.File.createTempFile; | |
| 14 | import static java.nio.charset.StandardCharsets.UTF_8; | |
| 15 | import static java.nio.file.StandardOpenOption.APPEND; | |
| 16 | import static java.nio.file.StandardOpenOption.CREATE; | |
| 17 | import static java.util.concurrent.TimeUnit.SECONDS; | |
| 18 | import static org.junit.jupiter.api.Assertions.assertEquals; | |
| 19 | ||
| 20 | /** | |
| 21 | * Responsible for testing that the {@link FileWatchService} fires the | |
| 22 | * expected {@link FileEvent} when the system raises state changes. | |
| 23 | */ | |
| 24 | class FileWatchServiceTest { | |
| 25 | /** | |
| 26 | * Test that modifying a file produces a {@link FileEvent}. | |
| 27 | * | |
| 28 | * @throws IOException Could not create watcher service. | |
| 29 | * @throws InterruptedException Could not join on watcher service thread. | |
| 30 | */ | |
| 31 | @Test | |
| 32 | @Timeout( value = 5, unit = SECONDS ) | |
| 33 | void test_SingleFile_Write_Notified() throws | |
| 34 | IOException, InterruptedException { | |
| 35 | final var text = "arbitrary text to write"; | |
| 36 | final var file = createTemporaryFile(); | |
| 37 | final var service = new FileWatchService( file ); | |
| 38 | final var thread = new Thread( service ); | |
| 39 | final var semaphor = new Semaphore( 0 ); | |
| 40 | final var listener = createListener( f -> { | |
| 41 | semaphor.release(); | |
| 42 | assertEquals( file, f ); | |
| 43 | } ); | |
| 44 | ||
| 45 | thread.start(); | |
| 46 | service.addListener( listener ); | |
| 47 | Files.writeString( file.toPath(), text, UTF_8, CREATE, APPEND ); | |
| 48 | semaphor.acquire(); | |
| 49 | service.stop(); | |
| 50 | thread.join(); | |
| 51 | } | |
| 52 | ||
| 53 | private FileModifiedListener createListener( final Consumer<File> action ) { | |
| 54 | return fileEvent -> action.accept( fileEvent.getFile() ); | |
| 55 | } | |
| 56 | ||
| 57 | private File createTemporaryFile() throws IOException { | |
| 58 | final var prefix = getClass().getPackageName(); | |
| 59 | final var file = createTempFile( prefix, null, null ); | |
| 60 | file.deleteOnExit(); | |
| 61 | return file; | |
| 62 | } | |
| 63 | } | |
| 1 | 64 |
| 1 | package com.keenwrite.io; | |
| 2 | ||
| 3 | import org.junit.jupiter.api.Test; | |
| 4 | ||
| 5 | import java.io.File; | |
| 1 | 6 | |
| 7 | import static com.keenwrite.io.MediaTypeExtension.valueFrom; | |
| 8 | import static org.apache.commons.io.FilenameUtils.getExtension; | |
| 9 | import static org.junit.jupiter.api.AssertionTR."\{dir}/images"TR."\{image} -> \{media}" |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.io; | |
| 3 | ||
| 4 | import org.junit.jupiter.api.Test; | |
| 5 | ||
| 6 | import java.util.Map; | |
| 7 | ||
| 8 | import static com.keenwrite.io.MediaType.*; | |
| 9 | import static com.keenwrite.io.downloads.DownloadManager.open; | |
| 10 | import static org.junit.jupiter.api.Assertions.*; | |
| 11 | ||
| 12 | /** | |
| 13 | * Test that {@link MediaType} instances can be queried and return reliable | |
| 14 | * results. | |
| 15 | */ | |
| 16 | public class MediaTypeTest { | |
| 17 | /** | |
| 18 | * Test that {@link MediaType#equals(String, String)} is case-insensitive. | |
| 19 | */ | |
| 20 | @Test | |
| 21 | public void test_Equality_IgnoreCase_Success() { | |
| 22 | final var mediaType = TEXT_PLAIN; | |
| 23 | assertTrue( mediaType.equals( "TeXt", "Plain" ) ); | |
| 24 | assertEquals( "text/plain", mediaType.toString() ); | |
| 25 | } | |
| 26 | ||
| 27 | /** | |
| 28 | * Test that {@link MediaType#fromFilename(String)} can lookup by file name. | |
| 29 | */ | |
| 30 | @Test | |
| 31 | public void test_FilenameExtensions_Supported_Success() { | |
| 32 | final var map = Map.of( | |
| 33 | "jpeg", IMAGE_JPEG, | |
| 34 | "png", IMAGE_PNG, | |
| 35 | "svg", IMAGE_SVG_XML, | |
| 36 | "md", TEXT_MARKDOWN, | |
| 37 | "Rmd", TEXT_R_MARKDOWN, | |
| 38 | "txt", TEXT_PLAIN, | |
| 39 | "yml", TEXT_YAML | |
| 40 | ); | |
| 41 | ||
| 42 | map.forEach( ( k, v ) -> assertEquals( v, fromFilename( "f." + k ) ) ); | |
| 43 | } | |
| 44 | ||
| 45 | /** | |
| 46 | * Test that remote fetches will pull and identify the type of resource | |
| 47 | * based on the HTTP Content-Type header (or shallow decoding). | |
| 48 | */ | |
| 49 | @Test | |
| 50 | public void test_HttpRequest_Supported_Success() { | |
| 51 | //@formatter:off | |
| 52 | final var map = Map.of( | |
| 53 | "https://kroki.io/robots.txt", TEXT_PLAIN, | |
| 54 | "https://place-hold.it/300x500", IMAGE_GIF, | |
| 55 | "https://loremflickr.com/200/300", IMAGE_JPEG, | |
| 56 | "https://upload.wikimedia.org/wikipedia/commons/9/9f/Vimlogo.svg", IMAGE_SVG_XML, | |
| 57 | "https://kroki.io//graphviz/svg/eNpLyUwvSizIUHBXqPZIzcnJ17ULzy_KSanlAgB1EAjQ", IMAGE_SVG_XML | |
| 58 | ); | |
| 59 | //@formatter:on | |
| 60 | ||
| 61 | map.forEach( ( k, v ) -> { | |
| 62 | try( var response = open( k ) ) { | |
| 63 | System.out.printf( "%s => %s%n", k, v ); | |
| 64 | assertEquals( v, response.getMediaType() ); | |
| 65 | } catch( final Exception e ) { | |
| 66 | throw new RuntimeException( e ); | |
| 67 | } | |
| 68 | } ); | |
| 69 | } | |
| 70 | } | |
| 1 | 71 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.io; | |
| 3 | ||
| 4 | import org.junit.jupiter.api.Test; | |
| 5 | ||
| 6 | import java.io.IOException; | |
| 7 | import java.nio.file.Path; | |
| 8 | import java.util.Optional; | |
| 9 | import java.util.concurrent.atomic.AtomicBoolean; | |
| 10 | import java.util.function.Function; | |
| 11 | ||
| 12 | import static org.junit.jupiter.api.Assertions.*; | |
| 13 | ||
| 14 | class SysFileTest { | |
| 15 | ||
| 16 | @Test | |
| 17 | void test_Locate_ExistingExecutable_PathFound() { | |
| 18 | testFunction( SysFile::locate, "env", "/usr/bin/env" ); | |
| 19 | } | |
| 20 | ||
| 21 | @Test | |
| 22 | void test_Where_ExistingExecutable_PathFound() { | |
| 23 | testFunction( sysFile -> { | |
| 24 | try { | |
| 25 | return sysFile.where(); | |
| 26 | } catch( final IOException e ) { | |
| 27 | throw new RuntimeException( e ); | |
| 28 | } | |
| 29 | }, "which", "/usr/bin/which" ); | |
| 30 | } | |
| 31 | ||
| 32 | void testFunction( final Function<SysFile, Optional<Path>> consumer, | |
| 33 | final String command, | |
| 34 | final String expected ) { | |
| 35 | final var file = new SysFile( command ); | |
| 36 | final var path = consumer.apply( file ); | |
| 37 | final var failed = new AtomicBoolean( false ); | |
| 38 | ||
| 39 | assertTrue( file.canRun() ); | |
| 40 | ||
| 41 | path.ifPresentOrElse( | |
| 42 | location -> { | |
| 43 | final var actual = location.toAbsolutePath().toString(); | |
| 44 | ||
| 45 | assertEquals( expected, actual ); | |
| 46 | }, | |
| 47 | () -> failed.set( true ) | |
| 48 | ); | |
| 49 | ||
| 50 | assertFalse( failed.get() ); | |
| 51 | } | |
| 52 | } | |
| 1 | 53 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.io; | |
| 6 | ||
| 7 | import org.junit.jupiter.api.Test; | |
| 8 | ||
| 9 | import static org.junit.jupiter.api.Assertions.assertFalse; | |
| 10 | import static org.junit.jupiter.api.Assertions.assertTrue; | |
| 11 | ||
| 1 | 12 |
| 1 | package com.keenwrite.io; | |
| 2 | ||
| 3 | import org.junit.jupiter.api.Test; | |
| 4 | ||
| 5 | import static com.keenwrite.io.WindowsRegistry.*; | |
| 6 | import static org.junit.jupiter.api.Assertions.*; | |
| 7 | ||
| 8 | class WindowsRegistryTest { | |
| 9 | private static final String REG_PATH_PREFIX = | |
| 10 | "%USERPROFILE%"; | |
| 11 | private static final String REG_PATH_SUFFIX = | |
| 12 | "\\AppData\\Local\\Microsoft\\WindowsApps;"; | |
| 13 | private static final String REG_PATH = REG_PATH_PREFIX + REG_PATH_SUFFIX; | |
| 14 | ||
| 15 | @Test | |
| 16 | void test_Parse_RegistryEntry_ValueObtained() { | |
| 17 | final var expected = REG_PATH; | |
| 18 | final var actual = parseRegEntry( | |
| 19 | " path REG_EXPAND_SZ " + expected | |
| 20 | ); | |
| 21 | ||
| 22 | assertEquals( expected, actual ); | |
| 23 | } | |
| 24 | ||
| 25 | @Test | |
| 26 | void test_Expand_RegistryEntry_VariablesExpanded() { | |
| 27 | final var value = "UserProfile"; | |
| 28 | final var expected = value + REG_PATH_SUFFIX; | |
| 29 | final var actual = expand( REG_PATH, s -> value ); | |
| 30 | ||
| 31 | assertEquals( expected, actual ); | |
| 32 | } | |
| 33 | } | |
| 1 | 34 |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.io.downloads; | |
| 6 | ||
| 7 | import org.junit.jupiter.api.Test; | |
| 1 | 8 | |
| 9 | import java.io.File; | |
| 10 | import java.io.IOException; | |
| 11 | import java.net.URISyntaxException; | |
| 12 | import java.util.URL_BINARY = | |
| 13 | "https://keenwrite.com/downloads/KeenWfile = File.createTempFile( "kw-", "test" ); | |
| 14 | file.deleteOnExit()_BINARYfileassertNull( future |
| 1 | package com.keenwrite.preferences; | |
| 2 | ||
| 3 | import org.junit.jupiter.api.Test; | |
| 4 | ||
| 5 | import static com.keenwrite.preferences.Key.key; | |
| 6 | import static org.junit.jupiter.api.Assertions.assertEquals; | |
| 7 | ||
| 8 | /** | |
| 9 | * Test that {@link Key} hierarchies can be transformed into alternate data | |
| 10 | * models. | |
| 11 | */ | |
| 12 | class KeyTest { | |
| 13 | @Test | |
| 14 | public void test_String_ParentHierarchy_DotNotation() { | |
| 15 | final var keyRoot = key( "root" ); | |
| 16 | final var keyMeta = key( keyRoot, "meta" ); | |
| 17 | final var keyDate = key( keyMeta, "date" ); | |
| 18 | ||
| 19 | final var expected = "root.meta.date"; | |
| 20 | final var actual = keyDate.toString(); | |
| 21 | ||
| 22 | assertEquals( expected, actual ); | |
| 23 | } | |
| 24 | } | |
| 1 | 25 |
| 1 | package com.keenwrite.preview; | |
| 2 | ||
| 3 | import org.junit.jupiter.api.Test; | |
| 4 | ||
| 5 | import static com.keenwrite.constants.Constants.DIAGRAM_SERVER_NAME; | |
| 6 | import static com.keenwrite.preview.DiagramUrlGenerator.toUrl; | |
| 7 | import static org.junit.jupiter.api.Assertions.assertEquals; | |
| 8 | ||
| 9 | /** | |
| 10 | * Responsible for testing that images sent to the diagram server will render. | |
| 11 | */ | |
| 12 | class DiagramUrlGeneratorTest { | |
| 13 | // @formatter:off | |
| 14 | private static final String[] DIAGRAMS = new String[]{ | |
| 15 | "graphviz", | |
| 16 | "digraph G {Hello->World; World->Hello;}", | |
| 17 | "https://kroki.io/graphviz/svg/eJxLyUwvSizIUHBXqPZIzcnJ17ULzy_KSbFWAFO6dmBB61oAE9kNww==", | |
| 18 | ||
| 19 | "blockdiag", | |
| 20 | """ | |
| 21 | blockdiag { | |
| 22 | Kroki -> generates -> "Block diagrams"; | |
| 23 | Kroki -> is -> "very easy!"; | |
| 24 | ||
| 25 | Kroki [color = "greenyellow"]; | |
| 26 | "Block diagrams" [color = "pink"]; | |
| 27 | "very easy!" [color = "orange"]; | |
| 28 | } | |
| 29 | """, | |
| 30 | "https://kroki.io/blockdiag/svg/eJxdzDEKQjEQhOHeU4zpPYFoYesRxGJ9bwghMSsbUYJ4d10UCZbDfPynolOek0Q8FsDeNCestoisNLmy-Qg7R3Blcm5hPcr0ITdaB6X15fv-_YdJixo2CNHI2lmK3sPRA__RwV5SzV80ZAegJjXSyfMFptc71w==" | |
| 31 | }; | |
| 32 | // @formatter:on | |
| 33 | ||
| 34 | /** | |
| 35 | * Test that URL encoding works with Kroki's server. | |
| 36 | */ | |
| 37 | @Test | |
| 38 | public void test_Generation_TextDiagram_UrlEncoded() { | |
| 39 | // Use a map of pairs if this test needs more complexity. | |
| 40 | for( int i = 0; i < DIAGRAMS.length / 3; i += 3 ) { | |
| 41 | final var name = DIAGRAMS[ i ]; | |
| 42 | final var text = DIAGRAMS[ i + 1 ]; | |
| 43 | final var expected = DIAGRAMS[ i + 2 ]; | |
| 44 | final var actual = toUrl( DIAGRAM_SERVER_NAME, name, text ); | |
| 45 | ||
| 46 | assertEquals( expected, actual ); | |
| 47 | } | |
| 48 | } | |
| 49 | } | |
| 1 | 50 |
| 1 | package com.keenwrite.processors.html; | |
| 2 | ||
| 3 | import com.keenwrite.ExportFormat; | |
| 4 | import com.keenwrite.editors.common.Caret; | |
| 5 | import com.keenwrite.processors.ProcessorContext; | |
| 6 | import org.junit.jupiter.params.ParameterizedTest; | |
| 7 | import org.junit.jupiter.params.provider.Arguments; | |
| 8 | import org.junit.jupiter.params.provider.MethodSource; | |
| 9 | ||
| 10 | import java.io.File; | |
| 11 | import java.nio.file.Path; | |
| 12 | import java.util.HashMap; | |
| 13 | import java.util.stream.Stream; | |
| 14 | ||
| 15 | import static com.keenwrite.ExportFormat.HTML_TEX_DELIMITED; | |
| 16 | import static com.keenwrite.ExportFormat.XHTML_TEX; | |
| 17 | import static com.keenwrite.processors.ProcessorContext.builder; | |
| 18 | import static com.keenwrite.processors.ProcessorFactory.createProcessors; | |
| 19 | import static java.util.Locale.ENGLISH; | |
| 20 | import static org.junit.jupiter.api.Assertions.assertEquals; | |
| 21 | ||
| 22 | public class XhtmlProcessorTest { | |
| 23 | ||
| 24 | /** | |
| 25 | * Contains the thumbs up emoji. | |
| 26 | */ | |
| 27 | private static final String EMOJI_MARKDOWN = "the \uD83D\uDC4D emoji"; | |
| 28 | ||
| 29 | @ParameterizedTest | |
| 30 | @MethodSource( "formatParameters" ) | |
| 31 | void test_Conversion_EmojiInput_EncodedEmoji( | |
| 32 | final ExportFormat format, final String expected ) { | |
| 33 | final var context = createProcessorContext( format ); | |
| 34 | final var processor = createProcessors( context ); | |
| 35 | final var actual = processor.apply( EMOJI_MARKDOWN ); | |
| 36 | ||
| 37 | assertEquals( expected, actual ); | |
| 38 | } | |
| 39 | ||
| 40 | private static ProcessorContext createProcessorContext( | |
| 41 | final ExportFormat format ) { | |
| 42 | final var caret = Caret.builder().build(); | |
| 43 | return builder() | |
| 44 | .with( ProcessorContext.Mutator::setExportFormat, format ) | |
| 45 | .with( ProcessorContext.Mutator::setSourcePath, Path.of( "f.md" ) ) | |
| 46 | .with( ProcessorContext.Mutator::setDefinitions, HashMap::new ) | |
| 47 | .with( ProcessorContext.Mutator::setLocale, () -> ENGLISH ) | |
| 48 | .with( ProcessorContext.Mutator::setMetadata, HashMap::new ) | |
| 49 | .with( ProcessorContext.Mutator::setThemeDir, () -> Path.of( "b" ) ) | |
| 50 | .with( ProcessorContext.Mutator::setCaret, () -> caret ) | |
| 51 | .with( ProcessorContext.Mutator::setImageDir, () -> new File( "i" ) ) | |
| 52 | .with( ProcessorContext.Mutator::setImageOrder, () -> "" ) | |
| 53 | .with( ProcessorContext.Mutator::setImageServer, () -> "" ) | |
| 54 | .with( ProcessorContext.Mutator::setSigilBegan, () -> "" ) | |
| 55 | .with( ProcessorContext.Mutator::setSigilEnded, () -> "" ) | |
| 56 | .with( ProcessorContext.Mutator::setRScript, () -> "" ) | |
| 57 | .with( ProcessorContext.Mutator::setRWorkingDir, () -> Path.of( "r" ) ) | |
| 58 | .with( ProcessorContext.Mutator::setCurlQuotes, () -> true ) | |
| 59 | .with( ProcessorContext.Mutator::setAutoRemove, () -> true ) | |
| 60 | .build(); | |
| 61 | } | |
| 62 | ||
| 63 | private static Stream<Arguments> formatParameters() { | |
| 64 | return Stream.of( | |
| 65 | Arguments.of( | |
| 66 | HTML_TEX_DELIMITED, | |
| 67 | """ | |
| 68 | <html><head></head><body><p>the 👍 emoji</p> | |
| 69 | </body></html>""" | |
| 70 | ), | |
| 71 | Arguments.of( | |
| 72 | XHTML_TEX, | |
| 73 | """ | |
| 74 | <html><head><title/><meta charset="UTF-8"/><meta content="2" name="count"/></head><body><p>the 👍 emoji</p> | |
| 75 | </body></html>""" | |
| 76 | ) | |
| 77 | ); | |
| 78 | } | |
| 79 | } | |
| 1 | 80 |
| 1 | package com.keenwrite.processors.markdown.extensions; | |
| 2 | api.TestInstanceTestInstance( TestInstance.Lifecycle.PER_CLASS ) | |
| 3 | public abstract class ExtensionTest { | |
| 4 | private final List<ParserExtension> mE>(); | |
| 5 | geExtensions_MarkdownmEmEotected void addExtension( final ParserExtension extension ) { | |
| 6 | mExtensions.add( extension ); | |
| 7 | } | |
| 8 | ||
| 9 | protected Arguments argotected abstract Stream<Arguments> getDocuments(); | |
| 10 | } | |
| 1 | 11 |
| 1 | /* Copyright 2024 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.processors.markdown.extensions.fences; | |
| 6 | ||
| 7 | import com.keeExtensionTest; | |
| 8 | import public class FencedDiv} | |
| 9 | ||
| 10 | @Override::: {.concurrent title="3:58"} | |
| 11 | > Line 1 | |
| 12 | > :::::: {.concurrent title="3:59"} | |
| 13 | > Line 2 | |
| 14 | > :::::: {.concurrent title="4:00"} | |
| 15 | > Line 3 | |
| 16 | > :::div class="concurrent" data-title="3:58"> | |
| 17 | <p>Line 1</p> | |
| 18 | </div><div class="concurrent" data-title="3:59"> | |
| 19 | <p>Line 2</p> | |
| 20 | </div><div class="concurrent" data-title="4:00"> | |
| 21 | <p>Line 3> Hello::: world | |
| 22 | > Adventuresin **absolute**nesting. | |
| 23 | > :::GoodbyeHello</p> | |
| 24 | <div class="world"> | |
| 25 | <p>Adventures</p> | |
| 26 | <p>in <strong>absolute</strong></p> | |
| 27 | <p>nesting<p>Goodbye | |
| 28 | ); | |
| 29 | } | |
| 30 | } | |
| 1 | 31 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.processors.markdown.extensions.images; | |
| 3 | ||
| 4 | import com.keenwrite.editors.common.Caret; | |
| 5 | import com.keenwrite.processors.Processor; | |
| 6 | import com.keenwrite.processorTR."\{URI_PATH}.png"JPG = STR."\{URI_PATH}.jpg"; | |
| 1 | 7 | |
| 8 | /*STR."//\{PLACEHOLDER}/200/200", STR."//\{PLACEHOLDER}/200/200" ); | |
| 9 | add( STR."ftp://\{PLACEHOLDER}/200/200", STR."ftp://\{PLACEHOLDER}/200/200" ); | |
| 10 | add( STR."http://\{PLACEHOLDER}/200/200", STR."http://\{PLACEHOLDER}/200/200" ); | |
| 11 | add( STR."https://\{PLACEHOLDER}/200/200", STR."https://\{PLACEHOLDER}/200/200" |
| 1 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 2 | * | |
| 3 | * SPDX-License-Identifier: MIT | |
| 4 | */ | |
| 5 | package com.keenwrite.processors.markdown.extensions.references; | |
| 6 | ||
| 7 | import com.keenwrite.processors.markdown.extensions.ExtensionTest; | |
| 8 | import com.keenwrite.processors.markdown.extensions.captions.CaptionExtension; | |
| 9 | imapi.BeforeAllextends ExtensionTest { | |
| 10 | protected Stream<Arguments> ge @BeforeAll | |
| 11 | protected void setup() {addExtensionaddExtension( Defini addExtensionaddExtension( addExtensionaddExtensionaddExtensionaddExtension } | |
| 12 | } | |
| 1 | 13 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.r; | |
| 3 | ||
| 4 | import org.junit.jupiter.api.BeforeAll; | |
| 5 | import org.junit.jupiter.api.Test; | |
| 1 | 6 | |
| 7 | import javax.script.ScriptEngine; | |
| 8 | import javax.script.ScriptEngineManager; | |
| 9 | iod |
| 1 | package com.keenwrite.richtext; | |
| 1 | 2 | |
| 3 | import javafx.application.Application; | |
| 4 | import javafx.scene.Scene; | |
| 5 | import javafx.scene.layout.StackPane; | |
| 6 | import javafx.stage.Stage; | |
| 7 | import org.fxmisc.flowless.VirtualizedScrollPane; | |
| 8 | import org.fxmisc.richtext.StyleClassedTestatic final |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.sigils; | |
| 3 | ||
| 4 | import org.junit.jupiter.api.Test; | |
| 5 | ||
| 6 | import static oKeyOperatorTest {Process_KeyName_ProcessmOperator = new RKeyOperator();apply( "a.b.c.d" ); | |
| 7 | } | |
| 1 | 8 |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.util; | |
| 3 | ||
| 4 | import org.junit.jupiter.api.Test; | |
| 5 | ||
| 6 | import java.util.ArrayList; | |
| 7 | import java.util.Arrays; | |
| 8 | import java.util.Collections; | |
| 9 | ||
| 10 | import static org.junit.jupiter.api.Assertions.assertEquals; | |
| 11 | ||
| 12 | /** | |
| 13 | * Responsible for testing the http://www.davekoelle.com/alphanum.html | |
| 14 | * implementation. | |
| 15 | */ | |
| 16 | class AlphanumComparatorTest { | |
| 17 | ||
| 18 | /** | |
| 19 | * Test that a randomly sorted list containing a mix of alphanumeric | |
| 20 | * characters ("chunks") will be sorted according to numeric and alphabetic | |
| 21 | * order. | |
| 22 | */ | |
| 23 | @Test | |
| 24 | public void test_Sort_UnsortedList_SortedAlphanumerically() { | |
| 25 | final var expected = Arrays.asList( | |
| 26 | "10X Radonius", | |
| 27 | "20X Radonius", | |
| 28 | "20X Radonius Prime", | |
| 29 | "30X Radonius", | |
| 30 | "40X Radonius", | |
| 31 | "200X Radonius", | |
| 32 | "1000X Radonius Maximus", | |
| 33 | "Allegia 6R Clasteron", | |
| 34 | "Allegia 50 Clasteron", | |
| 35 | "Allegia 50B Clasteron", | |
| 36 | "Allegia 51 Clasteron", | |
| 37 | "Allegia 500 Clasteron", | |
| 38 | "Alpha 2", | |
| 39 | "Alpha 2A", | |
| 40 | "Alpha 2A-900", | |
| 41 | "Alpha 2A-8000", | |
| 42 | "Alpha 100", | |
| 43 | "Alpha 200", | |
| 44 | "Callisto Morphamax", | |
| 45 | "Callisto Morphamax 500", | |
| 46 | "Callisto Morphamax 600", | |
| 47 | "Callisto Morphamax 700", | |
| 48 | "Callisto Morphamax 5000", | |
| 49 | "Callisto Morphamax 6000 SE", | |
| 50 | "Callisto Morphamax 6000 SE2", | |
| 51 | "Callisto Morphamax 7000", | |
| 52 | "Xiph Xlater 5", | |
| 53 | "Xiph Xlater 40", | |
| 54 | "Xiph Xlater 50", | |
| 55 | "Xiph Xlater 58", | |
| 56 | "Xiph Xlater 300", | |
| 57 | "Xiph Xlater 500", | |
| 58 | "Xiph Xlater 2000", | |
| 59 | "Xiph Xlater 5000", | |
| 60 | "Xiph Xlater 10000" | |
| 61 | ); | |
| 62 | final var actual = new ArrayList<>( expected ); | |
| 63 | ||
| 64 | Collections.shuffle( actual ); | |
| 65 | actual.sort( new AlphanumComparator<>() ); | |
| 66 | assertEquals( expected, actual ); | |
| 67 | } | |
| 68 | } | |
| 1 | 69 |
| 1 | package com.keenwrite.util; | |
| 2 | ||
| 3 | import com.keenwrite.collections.CircularQueue; | |
| 4 | import org.junit.jupiter.api.Test; | |
| 5 | ||
| 6 | import static org.junit.jupiter.api.Assertions.assertEquals; | |
| 7 | ||
| 8 | /** | |
| 9 | * Tests the {@link CircularQueue} class. | |
| 10 | */ | |
| 11 | public class CircularQueueTest { | |
| 1 | 12 | |
| 13 | /** | |
| 14 | * Exercises the circularity aspect |
| 1 | /* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */ | |
| 2 | package com.keenwrite.util; | |
| 3 | ||
| 4 | import org.junit.jupiter.api.Test; | |
| 5 | ||
| 6 | import java.util.List; | |
| 7 | import java.util.ListIterator; | |
| 8 | import java.util.NoSuchElementException; | |
| 1 | 9 | |
| 10 | import static org.juni |
| 1 | package com.keenwrite.util; | |
| 2 | ||
| 3 | import org.junit.jupiter.api.Test; | |
| 4 | ||
| 5 | import static org.junit.jupiter.api.Assertions.*; | |
| 6 | ||
| 7 | /** | |
| 8 | * Tests that the range format specifiers correctly identify integer values | |
| 9 | * inside and outside the range. | |
| 10 | */ | |
| 11 | class RangeValidatorTeEmptyRange_AllValid() {"2Integer.MAX_VALUE ) ); | |
| 12 | } | |
| 13 | } | |
| 1 | 14 |
| 1 | <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 68 34" width="68px" height="34px" fill="#005a9c"> | |
| 2 | <desc>W3C</desc> | |
| 3 | <path d="m16.117 1.006 5.759 19.58 5.759-19.58h4.17 11.444v1.946l-5.879 10.128c2.065.663 3.627 1.868 4.686 3.615 1.059 1.748 1.589 3.799 1.589 6.155 0 2.914-.775 5.363-2.324 7.348s-3.555 2.978-6.017 2.978c-1.854 0-3.469-.589-4.845-1.767-1.377-1.178-2.396-2.773-3.058-4.786l3.256-1.35c.477 1.218 1.106 2.178 1.887 2.879.781.702 1.701 1.052 2.76 1.052 1.112 0 2.052-.622 2.82-1.866.768-1.245 1.152-2.74 1.152-4.489 0-1.933-.411-3.429-1.231-4.488-.954-1.244-2.45-1.867-4.489-1.867h-1.588v-1.906l5.56-9.612h-6.712l-.382.65-8.163 27.548h-.397l-5.958-19.937-5.957 19.937h-.397l-9.53-32.168h4.17l5.759 19.58 3.892-13.185-1.906-6.395z"/> | |
| 4 | <path d="m64.92 1.006c-.819 0-1.554.295-2.111.861-.591.6-.92 1.376-.92 2.178s.313 1.545.887 2.128c.583.591 1.334.912 2.145.912.793 0 1.562-.321 2.161-.903.574-.557.887-1.3.887-2.136 0-.811-.321-1.57-.878-2.136-.584-.592-1.344-.904-2.171-.904zm2.643 3.065c0 .701-.271 1.351-.768 1.832-.524.507-1.174.777-1.892.777-.675 0-1.342-.278-1.84-.785s-.777-1.157-.777-1.849.287-1.368.802-1.891c.481-.49 1.131-.751 1.84-.751.726 0 1.376.271 1.883.785.49.489.752 1.147.752 1.882zm-2.559-1.807h-1.3v3.445h.65v-1.469h.642l.701 1.469h.726l-.769-1.57c.498-.102.785-.439.785-.929 0-.625-.472-.946-1.435-.946zm-.118.422c.608 0 .886.169.886.591 0 .405-.278.549-.87.549h-.549v-1.14z"/> | |
| 5 | <path d="m59.807.825.676 4.107-2.391 4.575s-.918-1.941-2.443-3.015c-1.285-.905-2.122-1.102-3.431-.832-1.681.347-3.587 2.357-4.419 4.835-.995 2.965-1.005 4.4-1.04 5.718-.056 2.113.277 3.362.277 3.362s-1.452-2.686-1.438-6.62c.009-2.808.451-5.354 1.75-7.867 1.143-2.209 2.842-3.535 4.35-3.691 1.559-.161 2.791.59 3.743 1.403 1 .854 2.01 2.721 2.01 2.721z"/> | |
| 6 | <path d="m60.102 24.063s-1.057 1.889-1.715 2.617c-.659.728-1.837 2.01-3.292 2.651s-2.218.762-3.656.624c-1.437-.138-2.772-.97-3.24-1.317s-1.664-1.369-2.34-2.322-1.733-2.859-1.733-2.859.589 1.91.958 2.721c.212.467.864 1.894 1.789 3.136.863 1.159 2.539 3.154 5.086 3.604 2.547.451 4.297-.693 4.73-.97s1.346-1.042 1.924-1.66c.603-.645 1.174-1.468 1.49-1.962.231-.36.607-1.092.607-1.092z"/> | |
| 7 | </svg> | |
| 1 | 8 |
| 1 | #define 1617524430813_width 72 | |
| 2 | #define 1617524430813_height 48 | |
| 3 | static char 1617524430813_bits[] = { | |
| 4 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, | |
| 5 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 6 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 7 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, | |
| 8 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 9 | 0x00, 0x00, 0xA8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, | |
| 10 | 0x10, 0x00, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0xAA, 0x78, 0x80, 0x07, | |
| 11 | 0xC0, 0xFF, 0x3F, 0xE0, 0x41, 0x44, 0x78, 0x80, 0x0F, 0xC0, 0xFF, 0x3F, | |
| 12 | 0xF8, 0x67, 0x18, 0xF0, 0x80, 0x07, 0xE0, 0xFF, 0x3F, 0xF8, 0xE7, 0x00, | |
| 13 | 0xE0, 0x00, 0x0F, 0xE0, 0xFF, 0x1F, 0xFC, 0xFF, 0x00, 0xF0, 0x01, 0x0F, | |
| 14 | 0xE0, 0x01, 0x1D, 0xFC, 0x7F, 0x00, 0xF0, 0x01, 0x1F, 0xE0, 0x81, 0x0F, | |
| 15 | 0x3E, 0x7C, 0x00, 0xE0, 0x01, 0x1E, 0xE0, 0x81, 0x07, 0x0E, 0x38, 0x00, | |
| 16 | 0xE0, 0x01, 0x17, 0xF0, 0xC0, 0x07, 0x0F, 0x30, 0x00, 0xE0, 0x03, 0x3F, | |
| 17 | 0xF0, 0xC0, 0x03, 0x07, 0x00, 0x00, 0xC0, 0x03, 0x3F, 0xF8, 0xE0, 0x03, | |
| 18 | 0x07, 0x00, 0x00, 0xC0, 0x83, 0x3F, 0x78, 0xF0, 0x01, 0x07, 0x00, 0x00, | |
| 19 | 0xC0, 0x83, 0x3F, 0x78, 0xB0, 0x00, 0x03, 0x00, 0x00, 0x80, 0x87, 0x7F, | |
| 20 | 0x78, 0xF8, 0x03, 0x03, 0x00, 0x00, 0x80, 0x87, 0x7B, 0x78, 0xFC, 0x07, | |
| 21 | 0x03, 0x00, 0x00, 0x80, 0xCF, 0x7B, 0x3C, 0xF8, 0x0F, 0x03, 0x00, 0x00, | |
| 22 | 0x80, 0xC7, 0xE3, 0x3E, 0xC8, 0x1F, 0x02, 0x00, 0x00, 0x00, 0xEF, 0xF2, | |
| 23 | 0x3C, 0x00, 0x1F, 0x02, 0x00, 0x00, 0x00, 0xEF, 0xF1, 0x1C, 0x00, 0x3E, | |
| 24 | 0x02, 0x00, 0x00, 0x00, 0xEF, 0xB1, 0x1F, 0x00, 0x3C, 0x00, 0x00, 0x00, | |
| 25 | 0x00, 0xFE, 0xE1, 0x1F, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0xF6, 0xE0, | |
| 26 | 0x17, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xE0, 0x0F, 0x00, 0x3C, | |
| 27 | 0x00, 0x00, 0x00, 0x00, 0x7E, 0xC0, 0x0F, 0x00, 0x7C, 0x00, 0x00, 0x00, | |
| 28 | 0x00, 0xFC, 0xC0, 0x0F, 0x00, 0xFC, 0x00, 0x40, 0x00, 0x00, 0x7C, 0x80, | |
| 29 | 0x07, 0x03, 0xBC, 0x00, 0x60, 0x00, 0x00, 0x7C, 0xC0, 0xC7, 0x01, 0x3E, | |
| 30 | 0x03, 0xE0, 0x00, 0x00, 0x18, 0x80, 0xC7, 0x07, 0x1E, 0x03, 0x70, 0x00, | |
| 31 | 0x00, 0x38, 0x80, 0x82, 0x87, 0x1F, 0x0E, 0x7C, 0x00, 0x00, 0x38, 0x00, | |
| 32 | 0x03, 0xFF, 0x1D, 0xBC, 0x3F, 0x00, 0x00, 0x30, 0x00, 0x03, 0xFF, 0x0F, | |
| 33 | 0xFC, 0x1F, 0x00, 0x00, 0x10, 0x00, 0x03, 0xFC, 0x07, 0xF0, 0x1F, 0x00, | |
| 34 | 0x00, 0x10, 0x00, 0x01, 0xF8, 0x01, 0xE0, 0x07, 0x00, 0x00, 0x00, 0x00, | |
| 35 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 36 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 37 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 38 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 39 | 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | |
| 40 | }; | |
| 1 | 41 |
| 1 | <?xml version="1.0" encoding="UTF-8"?> | |
| 2 | <keenwrite> | |
| 3 | <workspace> | |
| 4 | <images> | |
| 5 | <order>svg pdf png jpg tiff</order> | |
| 6 | <dir></dir> | |
| 7 | </images> | |
| 8 | </workspace> | |
| 9 | </keenwrite> | |
| 1 | 10 |
| 1 | *.class | |
| 1 | 2 |
| 1 | Sikuli is used for the following purposes: | |
| 2 | ||
| 3 | * Create application videos. | |
| 4 | * Create integration tests. | |
| 5 | ||
| 1 | 6 |
| 1 | # ----------------------------------------------------------------------------- | |
| 2 | # Copyright 2020 White Magic Software, Ltd. | |
| 3 | # | |
| 4 | # Permission is hereby granted, free of charge, to any person obtaining a | |
| 5 | # copy of this software and associated documentation fiRuns all scripts | |
| 6 | import s01 | |
| 7 | import s02 | |
| 8 | import s03 | |
| 9 | import s04 | |
| 1 | 10 |
| 1 | # ----------------------------------------------------------------------------- | |
| 2 | # Copyright 2020 White Magic Software, Ltd. | |
| 3 | # | |
| 4 | # Permission is hereby granted, free of charge, to any person obtaining a | |
| 5 | # copy of this software and associated documentation fiintroduces the editor and its purpose. | |
| 6 | # Fresh start | |
| 7 | rm( app_home + "/variables.yaml" ) | |
| 8 | rm( app_home + "/untitled.md" ) | |
| 9 | rm( dir_home + "/.scrivenvar | |
| 10 | # Wait for application to launch | |
| 11 | openApp( "java -jar " + app_bin ) | |
| 12 | ||
| 13 | wait("1594187265140.png", 30) | |
| 14 | ||
| 15 | # Breathing room for video recording. | |
| 16 | wait( 4 ) | |
| 17 | ||
| 18 | # --------- | |
| 19 | # Introduc240 ) | |
| 20 | ||
| 21 | heading( "What is this application?" ) | |
| 22 | typer( "Well, this application is a text editor that supports interpolated definitions, ") | |
| 23 | typer( "a few different text formats, real-time preview, spell check ") | |
| 24 | typer( "as you tipe" ) | |
| 25 | wait( 0.5 ) | |
| 26 | recur( 3ype, and R statements." ) | |
| 27 | paragraph() | |
| 28 | wait( 1finition demo | |
| 29 | heading( "What are definitions?" ) | |
| 30 | typer( "Watch. " ) | |
| 31 | wait( .5 ) | |
| 32 | ||
| 33 | # Focus the definition editor. | |
| 34 | click_create() | |
| 35 | recur( 4, tab ) | |
| 36 | ||
| 37 | wait( .5application" ) | |
| 38 | title" ) | |
| 39 | Scrivenvar" ) | |
| 40 | ||
| 41 | # Set focus to the text editor. | |
| 42 | tab() | |
| 43 | ||
| 44 | typer( "The left-hand pane contains a nested, folder-like structure of names " ) | |
| 45 | typer( "and values that are called *definitions*. " ) | |
| 46 | wait( .5 ) | |
| 47 | typer( "Such definitions can simplify updating documents. " ) | |
| 48 | wait( 1 ) | |
| 49 | ||
| 50 | edit_find( "this application" ) | |
| 51 | typer( "$application.title$" ) | |
| 52 | ||
| 53 | edit_find_next() | |
| 54 | typer( "$application.title$" ) | |
| 55 | typer( "Tresult after having substituted definition " ) | |
| 56 | typer( "values into the document." ) | |
| 57 | Now nobody wants to type definition names all the time. Instead, type any " ) | |
| 58 | typer( "partial definition value followed by `Ctrl+Space`, such as: scr" ) | |
| 59 | wait( 0.5 ) | |
| 60 | autoinsert() | |
| 61 | wait( 1 ) | |
| 62 | typer( ". *Much* better!" ) | |
| 63 | paragraph() | |
| 64 | ||
| 65 | heading( "What is interpolation?" ) | |
| 66 | typer( "Definition values can reference definition names. " ) | |
| 67 | wait( .5 ) | |
| 68 | typer( "The definition names act as placeholders. Substituting placeholders with " ) | |
| 69 | typer( "their definition value is called *interpolation*. Let's see how it works." ) | |
| 70 | wait( 2 ) | |
| 1 | 71 |
| 1 | # ----------------------------------------------------------------------------- | |
| 2 | # Copyright 2020 White Magic Software, Ltd. | |
| 3 | # | |
| 4 | # Permission is hereby granted, free of charge, to any person obtaining a | |
| 5 | # copy of this software and associated documentation fihow to use interpolated strings.Open sample chapter.1 ) | |
| 6 | typer( Key.END1O1Edit the sample document.80 ) | |
| 7 | 2, down ) | |
| 8 | ||
| 9 | # Grey | |
| 10 | recur( 3, skip_right ) | |
| 11 | autoinsert() | |
| 12 | ||
| 13 | # 34 | |
| 14 | recur( 4, skip_right ) | |
| 15 | autoinsert() | |
| 16 | ||
| 17 | # Central | |
| 18 | recur( 10, skip_right ) | |
| 19 | autoinsert() | |
| 20 | ||
| 21 | # London | |
| 22 | skip_right() | |
| 23 | autoinsert() | |
| 24 | ||
| 25 | # Hatchery | |
| 26 | skip_right() | |
| 27 | autoinsert() | |
| 28 | ||
| 29 | # and Conditioning | |
| 30 | recur( 2, select_word_right ) | |
| 31 | delete() | |
| 32 | ||
| 33 | # Centre | |
| 34 | skip_right() | |
| 35 | autoinsert( | |
| 36 | typer( " Let's interpolate those four definitions instead!" ) | |
| 37 | wait( 4 ) | |
| 38 | recur( 13, type, Key.BACKSPACE9, backspace60 ) | |
| 39 | ||
| 40 | typer( "name$" ) | |
| 41 | wait( 2 ) | |
| 42 | ||
| 43 | # Collapse all definitions | |
| 44 | tab() | |
| 45 | recur( 8, typer, Key.LEFT ) | |
| 46 | ||
| 47 | # Expand to city | |
| 48 | recur( 4, typer, Key.RIGHT ) | |
| 49 | ||
| 50 | # Jump to name | |
| 51 | recur( 2, down ) | |
| 52 | recur( 2, typer, Key.RIGHT ) | |
| 53 | ||
| 54 | # Open the text field to show the full value | |
| 55 | typer( Key.F2 ) | |
| 56 | ||
| 57 | # Traverse the text field | |
| 58 | home() | |
| 59 | recur( 16, type, Key.RIGHT, Key.CTRL ) | |
| 60 | esc() | |
| 61 | ||
| 62 | restore_typing_speed() | |
| 63 | ||
| 64 | tab() | |
| 65 | type(_next() | |
| 66 | typertyper( "'s" ) | |
| 67 | ||
| 68 | edit_find( "Hatcheries" ) | |
| 69 | autoinsert() | |
| 70 | ||
| 71 | # and Conditioning | |
| 72 | recur( 2, select_word_right ) | |
| 73 | delete() | |
| 74 | ||
| 75 | edit_find( "Central" ) | |
| 76 | autoinsert() | |
| 77 | ||
| 78 | skip_right() | |
| 79 | autoinsert() | |
| 80 | ||
| 81 | typer( " How about a different city?" ) | |
| 82 | wait( 2 ) | |
| 83 | recur( 5, type, Key.BACKSPACE, Key.CTRL ) | |
| 84 | wait( 1 ) | |
| 85 | tab() | |
| 86 | typer( Key.F2 ) | |
| 87 | typer( "Seattle" ) | |
| 88 | enter() | |
| 89 | tab() | |
| 90 | wait( 2 ) | |
| 91 | No?" ) | |
| 92 | paragraph() | |
| 93 | ||
| 94 | tab() | |
| 95 | typer( Key.F2 ) | |
| 96 | typer( "London" ) | |
| 97 | enter() | |
| 98 | ||
| 99 | tab() | |
| 100 | typer( "Organizing definitions is left to your ") | |
| 101 | typer( "doub" ) | |
| 102 | autoinsert() | |
| 103 | typer( " Good imagination." ) | |
| 104 | tab() | |
| 105 | ||
| 106 | # Jump to "char" definition | |
| 107 | home() | |
| 108 | ||
| 109 | # Jump to "char.a.primary.name" definition | |
| 110 | recur( 6, typer, Key.RIGHT ) | |
| 111 | ||
| 112 | # Jump to "char.a.primary.caste" definition | |
| 113 | down() | |
| 114 | typer( Key.RIGHT ) | |
| 115 | ||
| 116 | # Jump to root-level "caste" definition | |
| 117 | recur( 7, down ) | |
| 118 | ||
| 119 | # Reselect "super" | |
| 120 | recur( 5, typer, Key.RIGHT ) | |
| 121 | wait( 2 ) | |
| 122 | ||
| 123 | # Close the window, no save | |
| 124 | type( "w0.5 ) | |
| 125 | tab() | |
| 126 | wait( 0.5 ) | |
| 127 | typer( Key.SPACE ) | |
| 128 | wait( 1 ) | |
| 1 | 129 |
| 1 | # ----------------------------------------------------------------------------- | |
| 2 | # Copyright 2020 White Magic Software, Ltd. | |
| 3 | # | |
| 4 | # Permission is hereby granted, free of charge, to any person obtaining a | |
| 5 | # copy of this software and associated documentation files (the | |
| 6 | # "Software"), to deal in the Software without restriction, including | |
| 7 | # without limitation the rights to use, copy, modify, merge, publish, | |
| 8 | # distribute, sublicense, and/or sell copies of the Software, and to | |
| 9 | # permit persons to whom the Software is furnished to do so, subject to | |
| 10 | # the following conditions: | |
| 11 | # | |
| 12 | # The above copyright notice and this permission notice shall be included | |
| 13 | # in all copies or substantial portions of the Software. | |
| 14 | # | |
| 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
| 16 | # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
| 17 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
| 18 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | |
| 19 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | |
| 20 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | |
| 21 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
| 22 | # ----------------------------------------------------------------------------- | |
| 23 | ||
| 24 | # ----------------------------------------------------------------------------- | |
| 25 | # This script introduces images and R. | |
| 26 | # ----------------------------------------------------------------------------- | |
| 27 | from sikuli import * | |
| 28 | import sys | |
| 29 | ||
| 30 | if not "../editor.sikuli" in sys.path: | |
| 31 | sys.path.append( "../editor.sikuli" ) | |
| 32 | ||
| 33 | from editor import * | |
| 34 | ||
| 35 | set_typing_speed( 80 ) | |
| 36 | ||
| 37 | file_open() | |
| 38 | type( Key.UP, Key.ALT ) | |
| 39 | wait( 0.5 ) | |
| 40 | home() | |
| 41 | wait( 0.25 ) | |
| 42 | enter() | |
| 43 | wait( 1 ) | |
| 44 | end() | |
| 45 | wait( 0.25 ) | |
| 46 | enter() | |
| 47 | wait( 1 ) | |
| 48 | ||
| 49 | set_typing_speed( 200 ) | |
| 50 | ||
| 51 | paragraph() | |
| 52 | heading( "What text formats are supported?" ) | |
| 53 | ||
| 54 | typer( "Scr" ) | |
| 55 | autoinsert() | |
| 56 | typer( " supports Markdown, R Markdown, XML, and R XML; however, the software " ) | |
| 57 | typer( "architecture enables it to easily add new formats. The following figure " ) | |
| 58 | typer( "depicts the overall architecture: " ) | |
| 59 | paragraph() | |
| 60 | typer( "" ) | |
| 61 | paragraph() | |
| 62 | typer( "Many text editors can only open one type of plain text markup format that is " ) | |
| 63 | typer( "only output as HTML. With a little more effort, text editors could support " ) | |
| 64 | typer( "multiple input and output formats. Scr" ) | |
| 65 | autoinsert() | |
| 66 | typer( " does so and goes one step further by introducing interpolated definitions." ) | |
| 67 | paragraph() | |
| 68 | typer( "Kitten interlude:" ) | |
| 69 | paragraph() | |
| 70 | typer( "" ) | |
| 71 | paragraph() | |
| 72 | ||
| 73 | heading( "What is R?" ) | |
| 74 | typer( "R is a programming language. You might have noticed a few potential grammar " ) | |
| 75 | typer( "problems with direct substitution. Rules for possessive forms, numbers, and " ) | |
| 76 | typer( "other quirks can be tackled using R." ) | |
| 77 | ||
| 78 | # ----------------------------------------------------------------------------- | |
| 79 | # Demo bootstrapping | |
| 80 | # ----------------------------------------------------------------------------- | |
| 81 | ||
| 82 | # Jump to the end | |
| 83 | type( Key.END, Key.CTRL ) | |
| 84 | paragraph() | |
| 85 | ||
| 86 | set_typing_speed( 300 ) | |
| 87 | heading( "How is R used?" ) | |
| 88 | typer( "R must be instructed where to find script files and what ones to load. The " ) | |
| 89 | typer( "*working directory* is the full path to those R files; the *startup script* " ) | |
| 90 | typer( "defines what R files to load. Both preferences must be changed before prose " ) | |
| 91 | typer( "may be processed. Preferences can be opened using either the " ) | |
| 92 | typeln( "**Edit > Preferences** menu or by pressing `Ctrl+Alt+s`. Here goes!" ) | |
| 93 | wait( 2 ) | |
| 94 | ||
| 95 | # ----------------------------------------------------------------------------- | |
| 96 | # Select the R script directory | |
| 97 | # ----------------------------------------------------------------------------- | |
| 98 | ||
| 99 | # Change the working directory by clicking "Browse" | |
| 100 | type( "s", Key.CTRL + Key.ALT ) | |
| 101 | wait("1594592396134.png", 1) | |
| 102 | click("1594592396134.png") | |
| 103 | wait( 0.5 ) | |
| 104 | ||
| 105 | # Navigate to and select the "r" directory | |
| 106 | type( Key.UP, Key.ALT ) | |
| 107 | wait( 0.5 ) | |
| 108 | end() | |
| 109 | wait( 0.5 ) | |
| 110 | enter() | |
| 111 | wait( 0.5 ) | |
| 112 | end() | |
| 113 | wait( 0.5 ) | |
| 114 | type( Key.UP ) | |
| 115 | wait( 0.5 ) | |
| 116 | recur( 2, tab ) | |
| 117 | wait( 0.5 ) | |
| 118 | enter() | |
| 119 | wait( 1 ) | |
| 120 | ||
| 121 | # ----------------------------------------------------------------------------- | |
| 122 | # Set the R startup script instructions | |
| 123 | # ----------------------------------------------------------------------------- | |
| 124 | ||
| 125 | wait("1594593710440.png", 5) | |
| 126 | click("1594593710440.png") | |
| 127 | ||
| 128 | set_typing_speed( 440 ) | |
| 129 | ||
| 130 | typeln( "setwd( '$application.r.working.directory$' )" ) | |
| 131 | typeln( "assign( 'anchor', '$date.anchor$', envir = .GlobalEnv )" ) | |
| 132 | typeln( "source( 'pluralize.R' )" ) | |
| 133 | typeln( "source( 'possessive.R' )" ) | |
| 134 | typeln( "source( 'conversion.R' )" ) | |
| 135 | typeln( "source( 'csv.R' )" ) | |
| 136 | ||
| 137 | wait("1594593794335.png", 3) | |
| 138 | click("1594593794335.png") | |
| 139 | ||
| 140 | paragraph() | |
| 141 | set_typing_speed( 220 ) | |
| 142 | ||
| 143 | typer( "R is now configured. The startup script and other R " ) | |
| 144 | typer( "files can be found in the " ) | |
| 145 | typer( "[repository](https://github.com/DaveJarvis/scrivenvar/tree/master/R). " ) | |
| 146 | wait( 1.5 ) | |
| 147 | ||
| 148 | # Wait for the browser to appear. | |
| 149 | wait("1594594984108.png", 5) | |
| 150 | click("1594594984108.png") | |
| 151 | ||
| 152 | wait( 5 ) | |
| 153 | click("1594689573764.png") | |
| 154 | ||
| 155 | paragraph() | |
| 156 | typer( "Next, we'll see how definitions and R can work together." ) | |
| 157 | wait( 2 ) | |
| 1 | 158 |
| 1 | # ----------------------------------------------------------------------------- | |
| 2 | # Copyright 2020 White Magic Software, Ltd. | |
| 3 | # | |
| 4 | # Permission is hereby granted, free of charge, to any person obtaining a | |
| 5 | # copy of this software and associated documentation files (the | |
| 6 | # "Software"), to deal in the Software without restriction, including | |
| 7 | # without limitation the rights to use, copy, modify, merge, publish, | |
| 8 | # distribute, sublicense, and/or sell copies of the Software, and to | |
| 9 | # permit persons to whom the Software is furnished to do so, subject to | |
| 10 | # the following conditions: | |
| 11 | # | |
| 12 | # The above copyright notice and this permission notice shall be included | |
| 13 | # in all copies or substantial portions of the Software. | |
| 14 | # | |
| 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
| 16 | # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
| 17 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
| 18 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | |
| 19 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | |
| 20 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | |
| 21 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
| 22 | # ----------------------------------------------------------------------------- | |
| 23 | ||
| 24 | # ----------------------------------------------------------------------------- | |
| 25 | # This script demonstrates using R. | |
| 26 | # ----------------------------------------------------------------------------- | |
| 27 | from sikuli import * | |
| 28 | import sys | |
| 29 | ||
| 30 | if not "../editor.sikuli" in sys.path: | |
| 31 | sys.path.append( "../editor.sikuli" ) | |
| 32 | ||
| 33 | from editor import * | |
| 34 | ||
| 35 | set_typing_speed( 220 ) | |
| 36 | ||
| 37 | # ----------------------------------------------------------------------------- | |
| 38 | # Open the demo text. | |
| 39 | # ----------------------------------------------------------------------------- | |
| 40 | file_open() | |
| 41 | type( Key.UP, Key.ALT ) | |
| 42 | wait( 0.5 ) | |
| 43 | end() | |
| 44 | wait( 0.5 ) | |
| 45 | enter() | |
| 46 | wait( 0.5 ) | |
| 47 | down() | |
| 48 | wait( 0.5 ) | |
| 49 | enter() | |
| 50 | wait( 2 ) | |
| 51 | ||
| 52 | # ----------------------------------------------------------------------------- | |
| 53 | # Re-open the corresponding definition file. | |
| 54 | # ----------------------------------------------------------------------------- | |
| 55 | file_open() | |
| 56 | recur( 2, down ) | |
| 57 | wait( 1 ) | |
| 58 | enter() | |
| 59 | wait( 2 ) | |
| 60 | ||
| 61 | # ----------------------------------------------------------------------------- | |
| 62 | # Brief introduction to R | |
| 63 | # ----------------------------------------------------------------------------- | |
| 64 | type( Key.HOME, Key.CTRL ) | |
| 65 | end() | |
| 66 | paragraph() | |
| 67 | ||
| 68 | typer( "## Using R" ) | |
| 69 | paragraph() | |
| 70 | typer( "Insert R code into documents as follows: `r# 1+1`. " ) | |
| 71 | wait( 1.5 ) | |
| 72 | typer( "Notice how the right-hand pane shows the computed result. I'll wait. " ) | |
| 73 | wait( 3 ) | |
| 74 | typer( "The syntax is: open backtick, r#, *computable expression*, close " ) | |
| 75 | typer( "backtick. That expression can be any valid R statement. The status bar " ) | |
| 76 | typer( "will provide clues when an R expression cannot be computed by the " ) | |
| 77 | typer( "editor. `r# glitch`" ) | |
| 78 | wait( 4 ) | |
| 79 | recur( 11, backspace ) | |
| 80 | typer( "Let's swap 34 storeys for a definition value and replace the number " ) | |
| 81 | typer( "according to the Chicago Manual of Style (cms) rules." ) | |
| 82 | ||
| 83 | # ----------------------------------------------------------------------------- | |
| 84 | # Demo pluralization | |
| 85 | # ----------------------------------------------------------------------------- | |
| 86 | set_typing_speed( 80 ) | |
| 87 | ||
| 88 | edit_find( "34" ) | |
| 89 | autoinsert() | |
| 90 | ||
| 91 | edit_find( "x(" ) | |
| 92 | typer( "cms(" ) | |
| 93 | ||
| 94 | edit_find( "storeys." ) | |
| 95 | typer( "34." ) | |
| 96 | autoinsert() | |
| 97 | edit_find( "x(" ) | |
| 98 | typer( "pl( 'storey'," ) | |
| 99 | wait( 4 ) | |
| 100 | ||
| 101 | tab() | |
| 102 | rename_definition( "1" ) | |
| 103 | wait( 4 ) | |
| 104 | rename_definition( "142" ) | |
| 105 | wait( 4 ) | |
| 106 | rename_definition( "34" ) | |
| 107 | wait( 4 ) | |
| 108 | tab() | |
| 109 | ||
| 110 | # ----------------------------------------------------------------------------- | |
| 111 | # Demo possessives (it, her, his, Director) | |
| 112 | # ----------------------------------------------------------------------------- | |
| 113 | type( Key.HOME, Key.CTRL ) | |
| 114 | edit_find( "Director" ) | |
| 115 | autoinsert() | |
| 116 | edit_find_next() | |
| 117 | autoinsert() | |
| 118 | edit_find_next() | |
| 119 | autoinsert() | |
| 120 | type( Key.RIGHT ) | |
| 121 | recur( 2, delete ) | |
| 122 | autoinsert() | |
| 123 | home() | |
| 124 | edit_find( "x(" ) | |
| 125 | typer( "pos(" ) | |
| 126 | wait( 2 ) | |
| 127 | ||
| 128 | tab() | |
| 129 | rename_definition( "Headmistress" ) | |
| 130 | wait( 4 ) | |
| 131 | rename_definition( "Director" ) | |
| 132 | wait( 2 ) | |
| 133 | tab() | |
| 134 | ||
| 135 | type( Key.END, Key.CTRL ) | |
| 136 | paragraph() | |
| 137 | typer( "Other possessives: `r# pos( 'it' )`, `r# pos( 'her' )`, `r# pos( 'his' )`, " ) | |
| 138 | typer( "and `r# pos( 'my' )`." ) | |
| 139 | ||
| 140 | # ----------------------------------------------------------------------------- | |
| 141 | # Demo conversion, including ordinal numbers | |
| 142 | # ----------------------------------------------------------------------------- | |
| 143 | set_typing_speed( 160 ) | |
| 144 | ||
| 145 | paragraph() | |
| 146 | heading( "Date Conversions" ) | |
| 147 | typer( "Mixing R code with definitions invites endless possibilities. " ) | |
| 148 | typer( "Imagine someone racing to the " ) | |
| 149 | typer( "`r#cms( v$location$breeder$storeys, ordinal=TRUE )` floor, whereby that " ) | |
| 150 | typer( "ordinal stems from the Hatchery's storeys' definition. Or how about " ) | |
| 151 | typer( "a complex timeline where dates are expressed in days relative to one " ) | |
| 152 | typer( "point in time. Let's call this the *anchor date* and define it." ) | |
| 153 | ||
| 154 | tab() | |
| 155 | home() | |
| 156 | typer( Key.SPACE ) | |
| 157 | insert() | |
| 158 | rename_definition( "date" ) | |
| 159 | insert() | |
| 160 | rename_definition( "anchor" ) | |
| 161 | insert() | |
| 162 | rename_definition( "1969-10-29" ) | |
| 163 | tab() | |
| 164 | ||
| 165 | paragraph() | |
| 166 | typer( "Next, set an R variable named `now` to the current date" ) | |
| 167 | typer( "`r# now = format( Sys.time(), '%Y-%m-%d' ); ''`--- the empty single quotes " ) | |
| 168 | typer( "prevent the date from appearing in the output document. " ) | |
| 169 | ||
| 170 | paragraph() | |
| 171 | typer( "We set the anchor date to `r# annal()`, which was " ) | |
| 172 | typer( "`r# elapsed( 0, days( v$date$anchor, format( Sys.time(), '%Y-%m-%d' ) ) )` " ) | |
| 173 | typer( "ago from `r# format( as.Date( now ), '%B %d, %Y' )`. " ) | |
| 174 | ||
| 175 | # ----------------------------------------------------------------------------- | |
| 176 | # Demo CSV file import | |
| 177 | # ----------------------------------------------------------------------------- | |
| 178 | paragraph() | |
| 179 | heading( "Tabular Data" ) | |
| 180 | typer( "The following table shows average Canadian lifespans by birth " ) | |
| 181 | typer( "year and sex:" ) | |
| 182 | paragraph() | |
| 183 | typer( "`r# csv2md( '../data.csv', total=FALSE )`" ) | |
| 184 | paragraph() | |
| 185 | typer( "Calling `csv2md` converts the comma-separated values in the spreadsheet " ) | |
| 186 | typer( "to a table formatted using Markdown. The HTML preview pane changes the " ) | |
| 187 | typer( "appearance of the resulting table. Using `../data.csv` instructs R to " ) | |
| 188 | typer( "open `data.csv` from one directory above the *working directory*." ) | |
| 189 | ||
| 190 | # ----------------------------------------------------------------------------- | |
| 191 | # Demo HTML export | |
| 192 | # ----------------------------------------------------------------------------- | |
| 193 | paragraph() | |
| 194 | heading( "Export" ) | |
| 195 | typer( "Retrieve the output HTML by using the **Edit > Copy HTML** menu. Let's " ) | |
| 196 | typer( "peek at the output." ) | |
| 197 | wait( 2 ) | |
| 198 | ||
| 199 | type( "e", Key.ALT ) | |
| 200 | wait( 0.5 ) | |
| 201 | down() | |
| 202 | wait( 0.25 ) | |
| 203 | enter() | |
| 204 | wait( 0.25 ) | |
| 205 | ||
| 206 | type( "a", Key.CTRL ) | |
| 207 | wait( 0.25 ) | |
| 208 | type( "v", Key.CTRL ) | |
| 209 | wait( 5 ) | |
| 210 | ||
| 211 | set_typing_speed( 40 ) | |
| 212 | ||
| 213 | # Jump to page bottom (should already be there, but just in case) | |
| 214 | type( Key.END, Key.CTRL ) | |
| 215 | recur( 3, typer, Key.PAGE_UP ) | |
| 216 | type( Key.HOME, Key.CTRL ) | |
| 217 | wait( 3 ) | |
| 218 | ||
| 219 | set_typing_speed( 220 ) | |
| 220 | type( "z", Key.CTRL ) | |
| 221 | type( Key.END, Key.CTRL ) | |
| 222 | ||
| 223 | paragraph() | |
| 224 | typer( "That's all for now, thank you!" ) | |
| 225 | wait( 5 ) | |
| 226 | ||
| 227 | # Delete the anchor date. | |
| 228 | tab() | |
| 229 | end() | |
| 230 | recur( 2, type, Key.UP ) | |
| 231 | delete() | |
| 232 | tab() | |
| 1 | 233 |
| 1 | from sikuli import * | |
| 2 | ||
| 3 | import sys | |
| 4 | import os | |
| 5 | ||
| 6 | def set_class_path(): | |
| 7 | path_script = getBundlePath() | |
| 8 | dir_script = os.path.dirname( path_script ) | |
| 9 | path_lib = dir_script + "/keycast/build/libs/keycast.jar" | |
| 10 | ||
| 11 | sys.path.append( path_lib ) | |
| 12 | ||
| 13 | def launch(): | |
| 14 | from com.whitemagicsoftware.keycast import KeyCast | |
| 15 | kc = KeyCast() | |
| 16 | kc.show() | |
| 17 | ||
| 18 | def main(): | |
| 19 | set_class_path() | |
| 20 | launch() | |
| 21 | ||
| 22 | ||
| 23 | if __name__ == "__main__": | |
| 24 | main() | |
| 1 | 25 |
| 1 | ||
| 1 | # ----------------------------------------------------------------------------- | |
| 2 | # Copyright 2020 White Magic Software, Ltd. | |
| 3 | # | |
| 4 | # Permission is hereby granted, free of charge, to any person obtaining a | |
| 5 | # copy of this software and associated documentation fityping_speed = 80 | |
| 6 | *args |
| 1 | MIT License | |
| 2 | ||
| 3 | Copyright (c) 2022 KeenWrite | |
| 4 | ||
| 5 | Permission is hereby granted, free of charge, to any person obtaining a copy | |
| 6 | of this software and associated documentation files "Software"), to deal | |
| 7 | ||
| 8 | ||
| 9 | ||
| 10 | ||
| 11 | included in all | |
| 12 | ||
| 13 | EXPRESS OR | |
| 14 | MERCHANTABILITY, | |
| 15 | ||
| 16 | ||
| 17 | LIABILITY, WHETHER IN AN ACTION | |
| 18 | OUT OF OR IN CONNECTION | |
| 19 | SOFTWARE. | |
| 1 | 20 |
| 1 | 1 | |
| 2 |  | |
| 3 | ||
| 4 |
| 1 | #!/usr/bin/env bash | |
| 2 | ||
| 3 | awk '{s+=$1} END {print s}' downloads/*-count.txt 2> /dev/null || echo 0 | |
| 4 | ||
| 1 | 5 |
| 1 | version.txt | |
| 1 | 2 |
| 1 | SetEnv no-gzip dont-vary | |
| 2 | ||
| 3 | <IfModule mod_rewrite.c> | |
| 4 | RewriteEngine On | |
| 5 | ||
| 6 | # Ensure the file exists before attemping to download it. | |
| 7 | RewriteCond %{REQUEST_FILENAME} -f | |
| 1 | 8 | |
| 9 | # Rewrite requests for file extensions t |
| 1 | <?php | |
| 2 | /* Copyright 2023 White Magic Software, Ltd. -- All rights reserved. | |
| 3 | * | |
| 4 | * SPDX-License-Identifier: MIT | |
| 5 | */ | |
| 6 | ||
| 7 | // Log all errors to a temporary file. | |
| 8 | ini_set( 'log_errors', 1 ); | |
| 9 | ini_set( 'error_log', '/tmp/php-errors.log' ); | |
| 1 | 10 | |
| 11 | // |
| 1 | 1 |
| 1 | ||
| 1 | <svg width="157.331" height="75" xmlns="http://www.w3.org/2000/svg"><!--! Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M56.862 15.625a3.122 3.122 0 0 0-3.125-3.125 3.122 3.122 0 0 0-3.125 3.125v23.701l-7.168-7.168a3.13 3.13 0 0 0-4.424 0 3.13 3.13 0 0 0 0 4.424l12.5 12.5a3.13 3.13 0 0 0 4.424 0l12.5-12.5a3.13 3.13 0 0 0 0-4.424 3.13 3.13 0 0 0-4.424 0l-7.158 7.168zm-21.875 31.25a6.256 6.256 0 0 0-6.25 6.25v3.125a6.256 6.256 0 0 0 6.25 6.25h37.5a6.256 6.256 0 0 0 6.25-6.25v-3.125a6.256 6.256 0 0 0-6.25-6.25h-9.913l-4.423 4.424a6.248 6.248 0 0 1-8.838 0l-4.414-4.424zm35.937 10.156a2.338 2.338 0 0 1-2.344-2.343 2.338 2.338 0 0 1 2.344-2.344 2.338 2.338 0 0 1 2.344 2.344 2.338 2.338 0 0 1-2.344 2.343z" style="fill:#000;fill-opacity:1;stroke-width:.0976562"/><path d="M121.707 38.922c-.022-4.096 1.83-7.189 5.581-9.466-2.098-3.003-5.268-4.655-9.454-4.978-3.963-.313-8.294 2.31-9.88 2.31-1.674 0-5.514-2.199-8.528-2.199-6.229.1-12.848 4.968-12.848 14.87q0 4.386 1.607 9.063c1.43 4.097 6.586 14.143 11.967 13.976 2.813-.067 4.8-1.998 8.461-1.998 3.55 0 5.392 1.998 8.528 1.998 5.426-.078 10.092-9.21 11.453-13.317-7.278-3.427-6.887-10.047-6.887-10.259zm-6.318-18.329c3.047-3.617 2.768-6.91 2.679-8.093-2.69.156-5.805 1.83-7.58 3.896-1.953 2.21-3.103 4.945-2.857 8.026 2.913.223 5.57-1.273 7.758-3.829z" style="fill:#000;fill-opacity:1;stroke-width:.111627"/></svg> |
| 1 | ||
| 1 | <svg width="157.331" height="75" xmlns="http://www.w3.org/2000/svg"><!--! Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M53.685 15.625A3.122 3.122 0 0 0 50.56 12.5a3.122 3.122 0 0 0-3.125 3.125v23.701l-7.168-7.168a3.13 3.13 0 0 0-4.424 0 3.13 3.13 0 0 0 0 4.424l12.5 12.5a3.13 3.13 0 0 0 4.424 0l12.5-12.5a3.13 3.13 0 0 0 0-4.424 3.13 3.13 0 0 0-4.424 0l-7.158 7.168zM31.81 46.875a6.256 6.256 0 0 0-6.25 6.25v3.125a6.256 6.256 0 0 0 6.25 6.25h37.5a6.256 6.256 0 0 0 6.25-6.25v-3.125a6.256 6.256 0 0 0-6.25-6.25h-9.912l-4.424 4.424a6.248 6.248 0 0 1-8.838 0l-4.414-4.424Zm35.938 10.156a2.338 2.338 0 0 1-2.344-2.343 2.338 2.338 0 0 1 2.344-2.344 2.338 2.338 0 0 1 2.343 2.343 2.338 2.338 0 0 1-2.343 2.344z" style="fill:#000;fill-opacity:1;stroke-width:.0976562"/><path d="M121.742 43.056c.957-.654 2.285-1.22 2.285-1.22s-3.78.683-7.54.996c-4.599.38-9.54.459-12.02.127-5.87-.782 3.222-2.94 3.222-2.94s-3.525-.234-7.87 1.856c-5.128 2.48 12.694 3.613 21.923 1.181zm-8.34-3.134c-1.855-4.17-8.115-7.832 0-14.239 10.123-7.988 4.932-13.183 4.932-13.183 2.1 8.252-7.383 10.752-10.81 15.879-2.335 3.506 1.142 7.265 5.878 11.543zm11.191-17.207c.01 0-17.109 4.277-8.935 13.69 2.412 2.774-.635 5.274-.635 5.274s6.123-3.164 3.31-7.119c-2.626-3.691-4.638-5.527 6.26-11.845zm-.595 26.415a1.19 1.19 0 0 1-.196.254c12.53-3.29 7.92-11.61 1.934-9.502a1.692 1.692 0 0 0-.801.616 6.88 6.88 0 0 1 1.074-.293c3.028-.635 7.373 4.052-2.011 8.925zm4.605 6.084s1.416 1.162-1.553 2.07c-5.654 1.71-23.515 2.227-28.476.069-1.787-.772 1.563-1.855 2.617-2.08 1.094-.234 1.729-.195 1.729-.195-1.983-1.397-12.822 2.744-5.508 3.925 19.945 3.242 36.367-1.455 31.19-3.789zm-21.832-4.043c-7.685 2.149 4.678 6.582 14.463 2.393a18.153 18.153 0 0 1-2.754-1.348c-4.365.83-6.387.889-10.351.44-3.272-.371-1.358-1.485-1.358-1.485zm17.559 9.492c-7.686 1.446-17.168 1.28-22.783.352 0-.01 1.152.947 7.07 1.328 9.004.576 22.832-.322 23.154-4.58 0 0-.625 1.611-7.441 2.9zm-4.258-13.69c-5.781 1.112-9.13 1.083-13.36.644-3.27-.342-1.132-1.924-1.132-1.924-8.477 2.812 4.707 5.996 16.552 2.53a5.895 5.895 0 0 1-2.06-1.25z" style="fill:#000;fill-opacity:1;stroke-width:.097655"/></svg> |
| 1 | ||
| 1 | <svg width="157.331" height="75" xmlns="http://www.w3.org/2000/svg"><!--! Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M111.91 24.54c.098.049.176.166.293.166.108 0 .274-.04.284-.147.02-.136-.186-.224-.313-.283-.166-.068-.38-.097-.537-.01-.039.02-.078.069-.059.108.03.127.225.107.332.166zm-2.138.166c.117 0 .195-.117.293-.166.107-.059.303-.04.342-.156.02-.04-.02-.088-.059-.108-.156-.088-.371-.058-.537.01-.127.059-.332.147-.313.283.01.098.176.147.274.137zm21.59 27.224c-.352-.39-.518-1.132-.703-1.923-.176-.791-.381-1.64-1.025-2.188a2.639 2.639 0 0 0-.391-.283 2.167 2.167 0 0 0-.4-.195c.898-2.666.546-5.322-.362-7.724-1.113-2.94-3.056-5.508-4.54-7.265-1.67-2.1-3.291-4.092-3.262-7.03.049-4.483.498-12.812-7.402-12.822-9.999-.02-7.499 10.097-7.606 13.202-.166 2.285-.625 4.082-2.197 6.318-1.846 2.197-4.443 5.741-5.674 9.442-.586 1.748-.86 3.525-.605 5.205-.635.566-1.113 1.435-1.621 1.972-.41.42-1.006.577-1.66.811-.654.234-1.367.586-1.807 1.416-.205.38-.273.79-.273 1.21 0 .382.059.772.117 1.153.117.79.244 1.533.078 2.031-.508 1.406-.576 2.383-.215 3.095.371.713 1.114 1.026 1.963 1.202 1.69.351 3.984.263 5.79 1.22 1.934 1.016 3.897 1.377 5.46 1.016 1.132-.254 2.06-.938 2.528-1.973 1.22-.01 2.568-.527 4.717-.644 1.455-.117 3.28.517 5.38.4.059.225.137.45.244.654v.01c.81 1.631 2.324 2.373 3.935 2.246 1.621-.127 3.33-1.074 4.717-2.724 1.328-1.602 3.515-2.266 4.97-3.144.723-.44 1.309-.987 1.357-1.787.04-.801-.43-1.69-1.513-2.9zm-19.168-30.905c.957-2.168 3.34-2.13 4.296-.04.635 1.387.352 3.018-.42 3.945-.156-.078-.576-.253-1.23-.478.107-.117.303-.264.38-.45.47-1.151-.019-2.636-.888-2.665-.713-.049-1.357 1.055-1.152 2.246-.4-.195-.918-.342-1.27-.43a3.89 3.89 0 0 1 .284-2.128zm-3.975-1.123c.987 0 2.031 1.386 1.865 3.27a3.511 3.511 0 0 0-.996.45c.118-.869-.322-1.963-.937-1.914-.82.069-.957 2.07-.176 2.744.098.078.186-.02-.576.537-1.523-1.426-1.025-5.087.82-5.087zm-1.328 5.927c.606-.45 1.328-.977 1.377-1.025.46-.43 1.318-1.387 2.725-1.387.693 0 1.523.225 2.529.869.615.4 1.103.43 2.206.908.82.342 1.338.947 1.026 1.777-.254.694-1.074 1.406-2.217 1.768-1.084.351-1.933 1.562-3.73 1.455a2.722 2.722 0 0 1-.937-.205c-.782-.342-1.192-1.016-1.953-1.465-.84-.469-1.29-1.016-1.436-1.494-.137-.479 0-.879.41-1.201zm.323 32.614c-.264 3.428-4.287 3.36-7.353 1.758-2.92-1.543-6.699-.635-7.47-2.138-.235-.46-.235-1.24.253-2.578v-.02c.235-.742.059-1.562-.058-2.334-.117-.761-.176-1.464.088-1.953.341-.654.83-.888 1.445-1.103 1.006-.361 1.152-.332 1.914-.967.537-.556.927-1.26 1.396-1.757.498-.538.977-.791 1.729-.674.79.117 1.474.664 2.138 1.562l1.914 3.476c.928 1.944 4.209 4.727 4.004 6.728zm-.137-2.529c-.4-.644-.938-1.328-1.406-1.914.693 0 1.386-.214 1.63-.869.225-.605 0-1.455-.722-2.431-1.318-1.777-3.74-3.174-3.74-3.174-1.318-.82-2.06-1.826-2.402-2.92-.342-1.093-.293-2.275-.03-3.437.508-2.236 1.817-4.413 2.656-5.78.225-.166.079.312-.85 2.03-.83 1.573-2.382 5.205-.253 8.047.059-2.021.537-4.082 1.348-6.005 1.171-2.676 3.642-7.314 3.837-11.005.108.078.45.312.606.4.449.264.79.654 1.23 1.006 1.21.976 2.783.898 4.14.117.606-.342 1.094-.732 1.553-.879.967-.303 1.738-.84 2.177-1.465.752 2.969 2.51 7.256 3.633 9.345.596 1.113 1.787 3.467 2.304 6.308.323-.01.684.04 1.065.137 1.347-3.486-1.143-7.245-2.275-8.29-.46-.45-.479-.645-.254-.635 1.23 1.094 2.851 3.29 3.437 5.761.273 1.133.322 2.315.039 3.486 1.601.664 3.505 1.748 2.998 3.398-.215-.01-.313 0-.41 0 .312-.986-.381-1.718-2.227-2.548-1.914-.84-3.515-.84-3.74 1.22-1.181.41-1.787 1.436-2.09 2.666-.273 1.094-.35 2.412-.43 3.896-.048.752-.35 1.758-.663 2.832-3.135 2.236-7.49 3.213-11.161.703zm25.134-1.123c-.087 1.64-4.023 1.944-6.17 4.541-1.29 1.533-2.872 2.383-4.258 2.49-1.387.107-2.588-.469-3.291-1.885-.46-1.084-.234-2.255.107-3.544.362-1.387.899-2.813.967-3.965.078-1.484.166-2.783.41-3.779.254-1.006.645-1.68 1.338-2.06.03-.02.068-.03.098-.049.078 1.289.712 2.598 1.835 2.88 1.23.323 2.998-.732 3.75-1.591.879-.03 1.533-.088 2.207.498.967.83.693 2.959 1.67 4.062 1.035 1.133 1.367 1.904 1.337 2.402zm-24.939-27.77c.195.185.46.439.781.692.645.508 1.543 1.036 2.666 1.036 1.133 0 2.197-.577 3.105-1.055.479-.254 1.065-.684 1.446-1.016.38-.332.576-.615.302-.644-.273-.03-.254.254-.586.498-.43.312-.947.723-1.357.957-.723.41-1.904.996-2.92.996-1.015 0-1.826-.469-2.431-.947-.303-.244-.557-.489-.752-.674-.146-.137-.186-.45-.42-.479-.137-.01-.176.362.166.635z" style="fill:#000;fill-opacity:1;stroke-width:.097648"/><path d="M52.578 15.625a3.122 3.122 0 0 0-3.125-3.125 3.122 3.122 0 0 0-3.125 3.125v23.701l-7.168-7.168a3.13 3.13 0 0 0-4.423 0 3.13 3.13 0 0 0 0 4.424l12.5 12.5a3.13 3.13 0 0 0 4.423 0l12.5-12.5a3.13 3.13 0 0 0 0-4.424 3.13 3.13 0 0 0-4.423 0l-7.159 7.168zm-21.875 31.25a6.256 6.256 0 0 0-6.25 6.25v3.125a6.256 6.256 0 0 0 6.25 6.25h37.5a6.256 6.256 0 0 0 6.25-6.25v-3.125a6.256 6.256 0 0 0-6.25-6.25h-9.912l-4.424 4.424a6.248 6.248 0 0 1-8.837 0l-4.415-4.424zm35.938 10.156a2.338 2.338 0 0 1-2.344-2.343 2.338 2.338 0 0 1 2.344-2.344 2.338 2.338 0 0 1 2.344 2.344 2.338 2.338 0 0 1-2.344 2.343z" style="fill:#000;fill-opacity:1;stroke-width:.0976562"/></svg> |
| 1 | ||
| 1 | <svg width="157.331" height="75" xmlns="http://www.w3.org/2000/svg"><!--! Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="m83.666 19.386 20.49-2.823v19.799h-20.49Zm0 36.228 20.49 2.823V38.884h-20.49Zm22.745 3.125 27.255 3.761V38.884H106.41zm0-42.478v20.1h27.255V12.5Z" style="fill:#000;fill-opacity:1;stroke-width:.111607"/><path d="M51.79 15.625a3.122 3.122 0 0 0-3.124-3.125 3.122 3.122 0 0 0-3.125 3.125v23.701l-7.168-7.168a3.13 3.13 0 0 0-4.424 0 3.13 3.13 0 0 0 0 4.424l12.5 12.5a3.13 3.13 0 0 0 4.424 0l12.5-12.5a3.13 3.13 0 0 0 0-4.424 3.13 3.13 0 0 0-4.424 0l-7.158 7.168zm-21.874 31.25a6.256 6.256 0 0 0-6.25 6.25v3.125a6.256 6.256 0 0 0 6.25 6.25h37.5a6.256 6.256 0 0 0 6.25-6.25v-3.125a6.256 6.256 0 0 0-6.25-6.25h-9.913l-4.423 4.424a6.248 6.248 0 0 1-8.838 0l-4.414-4.424Zm35.937 10.156a2.338 2.338 0 0 1-2.344-2.343 2.338 2.338 0 0 1 2.344-2.344 2.338 2.338 0 0 1 2.344 2.343 2.338 2.338 0 0 1-2.344 2.344z" style="fill:#000;fill-opacity:1;stroke-width:.0976562"/></svg> |
| 1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> | |
| 2 | <svg | |
| 3 | height="493.14542" | |
| 4 | viewBox="0 0 500.05118 493.14542" | |
| 5 | width="500.05118" | |
| 6 | version="1.1" | |
| 7 | id="svg37" | |
| 8 | sodipodi:docname="logo-icon.svg" | |
| 9 | inkscape:version="1.2.1 (9c6d41e410, 2022-07-14, custom)" | |
| 10 | xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | |
| 11 | xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | |
| 12 | xmlns="http://www.w3.org/2000/svg" | |
| 13 | xmlns:svg="http://www.w3.org/2000/svg" | |
| 14 | xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | |
| 15 | xmlns:cc="http://creativecommons.org/ns#" | |
| 16 | xmlns:dc="http://purl.org/dc/elements/1.1/"> | |
| 17 | <sodipodi:namedview | |
| 18 | id="namedview18" | |
| 19 | pagecolor="#ffffff" | |
| 20 | bordercolor="#666666" | |
| 21 | borderopacity="1.0" | |
| 22 | inkscape:showpageshadow="2" | |
| 23 | inkscape:pageopacity="0.0" | |
| 24 | inkscape:pagecheckerboard="0" | |
| 25 | inkscape:deskcolor="#d1d1d1" | |
| 26 | showgrid="false" | |
| 27 | inkscape:zoom="2.1352728" | |
| 28 | inkscape:cx="250.3193" | |
| 29 | inkscape:cy="246.57271" | |
| 30 | inkscape:current-layer="svg37" /> | |
| 31 | <metadata | |
| 32 | id="metadata43"> | |
| 33 | <rdf:RDF> | |
| 34 | <cc:Work | |
| 35 | rdf:about=""> | |
| 36 | <dc:format>image/svg+xml</dc:format> | |
| 37 | <dc:type | |
| 38 | rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | |
| 39 | </cc:Work> | |
| 40 | </rdf:RDF> | |
| 41 | </metadata> | |
| 42 | <defs | |
| 43 | id="defs41"> | |
| 44 | <linearGradient | |
| 45 | id="a" | |
| 46 | gradientTransform="matrix(-8.7796153,42.985832,-42.985832,-8.7796153,514.83476,136.06192)" | |
| 47 | gradientUnits="userSpaceOnUse" | |
| 48 | x1="0.152358" | |
| 49 | x2="0.96880901" | |
| 50 | y1="-0.044911999" | |
| 51 | y2="-0.049470998"> | |
| 52 | <stop | |
| 53 | offset="0" | |
| 54 | stop-color="#ec706a" | |
| 55 | id="stop2" /> | |
| 56 | <stop | |
| 57 | offset="1" | |
| 58 | stop-color="#ecd980" | |
| 59 | id="stop4" /> | |
| 60 | </linearGradient> | |
| 61 | </defs> | |
| 62 | <g | |
| 63 | id="g485" | |
| 64 | transform="matrix(2.5605898,1.4612315,-1.4612315,2.5605898,-947.38048,-777.17055)"> | |
| 65 | <path | |
| 66 | style="fill:url(#a);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.226;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0" | |
| 67 | paint-order="stroke" | |
| 68 | d="m 496.76229,150.80474 c -4.25368,20.68081 3.28191,25.95476 3.28191,25.95476 v 0 c 0,0 3.00963,-13.19543 8.64082,-10.76172 v 0 c 4.83401,2.08299 1.12516,10.97002 1.12516,10.97002 v 0 c 0,0 31.78993,-30.5076 7.60484,-40.99434 v 0 c 0,0 -5.30287,-2.76791 -10.69842,-0.65209 v 0 c -3.94735,1.54891 -7.94375,5.71058 -9.95431,15.48337" | |
| 69 | stroke-linecap="round" | |
| 70 | id="path14-3" /> | |
| 71 | <path | |
| 72 | d="m 530.80335,138.63592 -10.99206,-16.95952 1.75995,-6.49966 10.01483,2.71233 z" | |
| 73 | fill="#126d95" | |
| 74 | id="path9" /> | |
| 75 | <path | |
| 76 | d="m 533.0598,112.36676 -0.91739,3.38458 -9.99361,-2.70665 0.91739,-3.38458 z" | |
| 77 | fill="#126d95" | |
| 78 | id="path11" /> | |
| 79 | <g | |
| 80 | fill="#51a9cf" | |
| 81 | id="g19" | |
| 82 | transform="translate(-295.50101,-692.52836)"> | |
| 83 | <path | |
| 84 | d="m 834.01973,741.0381 c -1.68105,0.0185 -3.22054,1.13771 -3.68367,2.84981 -0.56186,2.07405 0.665,4.21099 2.73743,4.77241 l -13.96475,51.52944 -9.99361,-2.70665 c 8.36013,-31.46487 4.99411,-51.98144 4.99411,-51.98144 14.99782,-11.92097 23.67,-25.56577 27.63101,-32.97331 z" | |
| 85 | id="path13" /> | |
| 86 | <path | |
| 87 | d="m 818.56767,802.18881 -0.9174,3.38458 -10.03996,-2.72957 0.91314,-3.37522 z" | |
| 88 | id="path15" /> | |
| 89 | <path | |
| 90 | d="m 817.07405,807.70594 -1.75995,6.49966 -18.03534,9.08805 9.78412,-18.31044 z" | |
| 91 | id="path17" /> | |
| 92 | </g> | |
| 93 | <path | |
| 94 | d="m 540.69709,49.12083 7.72577,-28.52932 c -0.3195,8.40427 0.28451,24.55036 7.21678,42.41047 0,0 -11.89603,16.50235 -21.99788,47.3763 l -10.03442,-2.71758 13.96533,-51.5284 c 2.08221,0.56405 4.21039,-0.66603 4.77182,-2.73844 0.45427,-1.67248 -0.26571,-3.38317 -1.64739,-4.27302" | |
| 95 | fill="#126d95" | |
| 96 | id="path21" /> | |
| 97 | <text | |
| 98 | transform="translate(-295.73751,-689.6407)" | |
| 99 | id="text25" /> | |
| 100 | </g> | |
| 101 | </svg> | |
| 1 | 102 |
| 1 | ||
| 1 | <svg width="300" height="71.784" viewBox="0 0 79.375 18.993" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient xlink:href="#a" id="b" x1=".152" x2=".969" y1="-.045" y2="-.049" gradientTransform="rotate(101.544 290.55 422.146) scale(26.05808)" gradientUnits="userSpaceOnUse"/><linearGradient id="a" x1=".152" x2=".969" y1="-.045" y2="-.049" gradientTransform="rotate(101.544 290.55 422.146) scale(26.05808)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#ec706a"/><stop offset="1" stop-color="#ecd980"/></linearGradient></defs><path style="fill:#51a9cf;fill-opacity:1" d="M76.697 4.286c-.936 0-1.79.24-2.565.718-.768.473-1.376 1.143-1.823 2.01-.452.854-.678 1.816-.678 2.887 0 .65.118 1.25.355 1.798.237.543.613.981 1.13 1.315.494.333 1.134.5 1.919.5l.001.001c.365 0 .739-.044 1.12-.13a6.09 6.09 0 0 0 1.114-.378c.36-.167.688-.363.984-.59.3-.225.55-.473.75-.742l-.726-1.355c-.145.193-.363.39-.653.589a4.83 4.83 0 0 1-.944.5 2.583 2.583 0 0 1-.952.202c-.387 0-.667-.083-.84-.25-.171-.167-.274-.423-.306-.767v-.226a14.49 14.49 0 0 0 1.88-.613 7.222 7.222 0 0 0 1.525-.847 3.661 3.661 0 0 0 1.016-1.113c.247-.425.37-.906.37-1.444 0-.403-.099-.758-.298-1.065-.193-.311-.49-.556-.887-.734-.393-.177-.89-.266-1.492-.266zm-.63 1.533c.22 0 .374.064.46.193.092.124.138.329.138.614 0 .29-.062.572-.186.847-.124.269-.29.513-.5.734-.205.22-.43.397-.678.532a1.78 1.78 0 0 1-.75.225c.01-.275.046-.619.105-1.032.059-.414.201-.8.428-1.16.172-.27.33-.496.475-.679.145-.182.315-.274.508-.274zM15.617 4.286c-.936 0-1.79.24-2.565.718-.768.473-1.376 1.143-1.823 2.01-.452.854-.678 1.816-.678 2.887 0 .65.118 1.25.355 1.798.237.544.613.982 1.13 1.316.494.333 1.134.5 1.919.5h.001c.365 0 .739-.044 1.12-.13a6.09 6.09 0 0 0 1.114-.378c.36-.167.688-.363.984-.59.3-.225.55-.473.75-.742l-.726-1.355c-.145.193-.363.39-.654.589-.29.199-.604.366-.943.5a2.583 2.583 0 0 1-.952.202c-.387 0-.667-.083-.84-.25-.171-.167-.273-.423-.306-.767v-.226a14.49 14.49 0 0 0 1.88-.613 7.197 7.197 0 0 0 1.524-.847 3.656 3.656 0 0 0 1.017-1.113c.247-.425.37-.906.37-1.444 0-.403-.099-.758-.298-1.065-.193-.311-.49-.556-.887-.734-.393-.177-.89-.266-1.492-.266zm-.63 1.533c.22 0 .374.064.46.193.092.124.138.329.138.614 0 .29-.062.572-.186.847-.123.269-.29.513-.5.734-.205.22-.43.397-.678.532-.247.135-.497.21-.75.226.01-.275.046-.62.105-1.033.059-.414.201-.8.428-1.16.172-.27.33-.496.475-.679.145-.182.315-.274.508-.274zM24.377 4.286c-.935 0-1.79.24-2.565.718-.769.473-1.377 1.143-1.823 2.01-.452.854-.678 1.816-.678 2.887 0 .65.118 1.25.355 1.798.236.544.613.982 1.129 1.316.495.333 1.135.5 1.92.5.366 0 .74-.044 1.122-.13a6.091 6.091 0 0 0 1.113-.378 5.22 5.22 0 0 0 .984-.59 3.6 3.6 0 0 0 .75-.742l-.726-1.355c-.145.193-.363.39-.653.589-.29.199-.605.366-.944.5a2.583 2.583 0 0 1-.951.202c-.388 0-.668-.083-.84-.25-.171-.167-.274-.423-.307-.767v-.226a14.49 14.49 0 0 0 1.88-.613 7.222 7.222 0 0 0 1.525-.847 3.673 3.673 0 0 0 1.017-1.113c.247-.425.37-.906.37-1.444 0-.403-.1-.758-.298-1.065-.194-.311-.49-.556-.888-.734-.392-.177-.89-.266-1.492-.266zm-.63 1.533c.22 0 .375.064.461.193.092.124.137.329.137.614 0 .29-.062.572-.186.847-.123.269-.29.513-.5.734-.204.22-.43.397-.678.532a1.79 1.79 0 0 1-.75.226c.011-.275.046-.62.105-1.033.06-.414.202-.8.428-1.16.172-.27.33-.496.476-.679.145-.182.314-.274.508-.274z"/><path d="M751.566 230.706c-2.527 12.283 1.949 15.415 1.949 15.415s1.787-7.837 5.132-6.391c2.871 1.237.668 6.515.668 6.515s18.882-18.12 4.517-24.348c0 0-3.15-1.644-6.354-.387-2.345.92-4.718 3.391-5.912 9.196" paint-order="stroke" style="fill:url(#b);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:.72817;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0" transform="translate(-95.423 -31.173) scale(.20372)"/><path fill="#126d95" d="m771.784 223.478-6.529-10.073 1.046-3.86 5.948 1.61zm1.34-15.602-.545 2.01-5.935-1.607.545-2.01z" style="stroke-width:.59394" transform="translate(-95.423 -31.173) scale(.20372)"/><path d="M62.74 3.45a.467.467 0 0 0-.446.344.47.47 0 0 0 .332.578l-1.69 6.235-1.21-.328c1.012-3.807.605-6.29.605-6.29A13.105 13.105 0 0 0 63.674 0zm-1.87 7.399-.11.41-1.215-.33.11-.41zm-.18.667-.213.787-2.182 1.1 1.183-2.216z" fill="#51a9cf"/><path fill="#126d95" d="m777.66 170.312 4.589-16.945c-.19 4.992.169 14.581 4.286 25.19 0 0-7.065 9.8-13.065 28.138l-5.96-1.614 8.295-30.605a2.308 2.308 0 0 0 1.855-4.164" style="stroke-width:.59394" transform="translate(-95.423 -31.173) scale(.20372)"/><path style="fill:#51a9cf;fill-opacity:1" d="M52.691 13.385 53.917 4.4h2.71l-.129 1.872q.178-.525.516-.976.34-.452.799-.726.46-.283.992-.283.428 0 .549.097l-.5 2.856q-.057-.097-.299-.154-.242-.056-.476-.056-.347 0-.645.072-.29.065-.565.218-.266.154-.548.404l-.823 5.662zM40.107 13.385 38.639 1.334h2.823l.452 7.711.161 1.759.532-1.759 2.033-5.05-.29-2.661h2.726l.468 7.711.178 1.759.42-1.759 2.629-7.711h2.872l-4.68 12.051h-3.258l-.452-4.307-.145-1.323-.484 1.323-1.565 4.307ZM28.088 13.385 29.314 4.4h2.694l-.113 1.63q.549-.823 1.29-1.283.75-.46 1.63-.46 1.065 0 1.622.549.556.548.556 1.823 0 .177-.056.645-.049.46-.13 1.025-.072.556-.137 1.024l-.088.597q-.057.436-.137 1-.073.557-.154 1.097-.072.54-.129.912l-.056.427h-2.807q.12-.806.217-1.516.105-.718.186-1.34.08-.628.145-1.16.097-.816.153-1.356.065-.549.073-.839.016-.427-.145-.597-.161-.177-.5-.177-.218 0-.46.105-.234.104-.468.306-.234.194-.452.468-.21.274-.379.605l-.774 5.501zM0 13.385 1.726 1.334h2.71l-.774 5.275 4.243-5.275H11.1L6.324 6.642q.113.21.274.532.17.315.404.79.242.468.572 1.138.34.67.8 1.59.209.427.41.814.202.379.388.718.185.33.355.62l.33.541H6.582q-.032-.056-.12-.234-.09-.177-.227-.476-.137-.306-.33-.726l-.42-.968-1-2.307-1.29 1.356-.485 3.355zM67.21 13.547q-.854 0-1.355-.444-.5-.444-.5-1.25 0-.073.024-.347l.057-.613q.04-.347.08-.638l.565-4.146h-.661l.29-1.71h.823l.774-2.162h2.114L69.114 4.4h1.759l-.178 1.71h-1.79l-.307 2.227-.194 1.387q-.072.508-.104.774l-.049.388q-.008.12-.008.226 0 .242.113.379t.436.137q.169 0 .427-.089.258-.097.516-.242.259-.153.428-.315l.436 1.34q-.42.322-.944.605-.517.274-1.13.451-.613.17-1.314.17z"/></svg> |
| 1 | ||
| 1 | <!DOCTYPE html> | |
| 2 | <html lang="en"> | |
| 3 | <head> | |
| 4 | <title>KeenWrite</title> | |
| 5 | <meta charset="UTF-8"> | |
| 6 | <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| 7 | <meta name="description" content="cross-platform, open-source desktop editor"> | |
| 8 | <meta n./count.sh" --> |
| 1 | user-agent: * | |
| 2 | disallow: | |
| 3 | crawl-delay: 60 | |
| 4 | ||
| 5 | user-agent: Googlebot | |
| 6 | disallow: /repository/* | |
| 7 | disallow: /downloads/* | |
| 8 | user-agent: Bingbot | |
| 9 | disallow: /repository/* | |
| 10 | disallow: /downloads/* | |
| 11 | user-agent: YandexBot | |
| 12 | disallow: /repository/* | |
| 13 | disallow: /downloads/* | |
| 14 | user-agent: MicrosoftBot | |
| 15 | disallow: /repository/* | |
| 16 | disallow: /downloads/* | |
| 17 | ||
| 1 | 18 |
| 1 | ||
| 1 | <!DOCTYPE html> | |
| 2 | <html lang="en"> | |
| 3 | <head> | |
| 4 | <title>KeenWrite</title> | |
| 5 | <meta charset="UTF-8"> | |
| 6 | <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| 7 | <meta name="description" content="cross-platform, open-source desktop editor"> | |
| 8 | <meta n class="screenshots"> | |
| 9 | <p> | |
| 10 | Interpolated variable replacement | |
| 11 | </pscreenshots/05.png" class="screenshot" alt="variables"> | |
| 12 | <p> | |
| 13 | Technical diagrams | |
| 14 | </pscreenshots/01.png" class="screenshot" alt="diagrams"> | |
| 15 | <p> | |
| 16 | Internationalization | |
| 17 | </pscreenshots/02.png" class="screenshot" alt="internationalization"> | |
| 18 | <p> | |
| 19 | Mathematics | |
| 20 | </pscreenshots/03.png" class="screenshot" alt="math"> | |
| 21 | <p> | |
| 22 | Document outline | |
| 23 | </pscreenshots/04.png" class="screenshot" alt="outline"> | |
| 24 | <p> | |
| 25 | Single sourced metadata | |
| 26 | </pscreenshots/06.png" class="screenshot" alt="multi-window"> | |
| 27 | <p> | |
| 28 | R computations | |
| 29 | </pscreenshots/07.png" class="screenshot" alt="computation"> | |
| 30 | <p> | |
| 31 | Theme-driven PDF output | |
| 32 | </pscreenshots/08.png" class="screenshot" alt="output"index.html">home |
| 1 | /* | |
| 2 | * Page | |
| 3 | Ensure the pag | |
| 4 | * Header | |
| 5 | */ | |
| 6 | * Screenshots | |
| 7 | */ | |
| 8 | * Version information | |
| 9 | */ | |
| 10 | main > p.version/ | |
| 11 | width: 157px; | |
| 12 | height: 75px; | |
| 13 | } | |
| 14 | ||
| 15 | /* | |
| 16 | * Navigation | |
| 17 | */ | |
| 18 | * Footer | |
| 19 | */ | |
| 20 | footer { | |
| 1 | 21 |