diff --git a/android/app/src/main/assets/fonts/UbuntuMono-Regular.ttf b/android/app/src/main/assets/fonts/UbuntuMono-Regular.ttf new file mode 100644 index 0000000000..fdd309d716 Binary files /dev/null and b/android/app/src/main/assets/fonts/UbuntuMono-Regular.ttf differ diff --git a/ios/StatusIm.xcodeproj/project.pbxproj b/ios/StatusIm.xcodeproj/project.pbxproj index e1aa0a631a..a31af2c247 100644 --- a/ios/StatusIm.xcodeproj/project.pbxproj +++ b/ios/StatusIm.xcodeproj/project.pbxproj @@ -41,6 +41,8 @@ 65F6941A25780A4F00A45E76 /* Bridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65F6941825780A4F00A45E76 /* Bridge.swift */; }; 65F6941B25780A4F00A45E76 /* Bridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65F6941825780A4F00A45E76 /* Bridge.swift */; }; 70ADBB5ECF934DCF8A0E4919 /* Inter-Regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = 1426DF592BA248FC81D955CB /* Inter-Regular.otf */; }; + 715D8132290BE850006F5C88 /* UbuntuMono-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 715D8131290BE850006F5C88 /* UbuntuMono-Regular.ttf */; }; + 715D8133290BE850006F5C88 /* UbuntuMono-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 715D8131290BE850006F5C88 /* UbuntuMono-Regular.ttf */; }; 74B758FC20D7C00B003343C3 /* launch-image-universal.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 74B758FB20D7C00B003343C3 /* launch-image-universal.storyboard */; }; 8391E8E0E93C41A98AAA6631 /* Inter-SemiBoldItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = A4F2BBE8D4DD4140A6CCAC39 /* Inter-SemiBoldItalic.otf */; }; A0093AB50DA85E1D01818CCA /* libPods-Status-StatusIm-StatusImTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1E88D313E5D854BE6BC81FC1 /* libPods-Status-StatusIm-StatusImTests.a */; }; @@ -121,6 +123,7 @@ 65F6941725780A4E00A45E76 /* StatusImTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "StatusImTests-Bridging-Header.h"; sourceTree = ""; }; 65F6941825780A4F00A45E76 /* Bridge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Bridge.swift; sourceTree = ""; }; 693A62DB37BC4CD5A30E5C96 /* Inter-SemiBold.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Inter-SemiBold.otf"; path = "../resources/fonts/Inter-SemiBold.otf"; sourceTree = ""; }; + 715D8131290BE850006F5C88 /* UbuntuMono-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "UbuntuMono-Regular.ttf"; path = "../resources/fonts/UbuntuMono-Regular.ttf"; sourceTree = ""; }; 74B758FB20D7C00B003343C3 /* launch-image-universal.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = "launch-image-universal.storyboard"; sourceTree = ""; }; 7AFBE28450C0239119FBDBA2 /* Pods-Status-StatusIm-StatusImTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Status-StatusIm-StatusImTests.debug.xcconfig"; path = "Target Support Files/Pods-Status-StatusIm-StatusImTests/Pods-Status-StatusIm-StatusImTests.debug.xcconfig"; sourceTree = ""; }; 8B9A886A2CB448B1ABA0EB62 /* libc++.tbd */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; }; @@ -229,6 +232,7 @@ 693A62DB37BC4CD5A30E5C96 /* Inter-SemiBold.otf */, A4F2BBE8D4DD4140A6CCAC39 /* Inter-SemiBoldItalic.otf */, 9C76AF5A418D4D65A4CAD1D9 /* InterStatus-Regular.otf */, + 715D8131290BE850006F5C88 /* UbuntuMono-Regular.ttf */, ); name = Resources; sourceTree = ""; @@ -475,6 +479,7 @@ buildActionMask = 2147483647; files = ( 74B758FC20D7C00B003343C3 /* launch-image-universal.storyboard in Resources */, + 715D8132290BE850006F5C88 /* UbuntuMono-Regular.ttf in Resources */, B2F2D1BC1D9D531B00B7B453 /* Images.xcassets in Resources */, D84616FB563A48EBB1678699 /* Inter-Bold.otf in Resources */, D99C50E5E18942A39C8DDF61 /* Inter-BoldItalic.otf in Resources */, @@ -493,6 +498,7 @@ buildActionMask = 2147483647; files = ( 3AAD2ACA24A3A60E0075D594 /* launch-image-universal.storyboard in Resources */, + 715D8133290BE850006F5C88 /* UbuntuMono-Regular.ttf in Resources */, 3AAD2ACB24A3A60E0075D594 /* Images.xcassets in Resources */, 3AAD2ACC24A3A60E0075D594 /* Inter-Bold.otf in Resources */, 3AAD2ACD24A3A60E0075D594 /* Inter-BoldItalic.otf in Resources */, diff --git a/ios/StatusIm/Info.plist b/ios/StatusIm/Info.plist index 01ffa96829..2811c78ed7 100644 --- a/ios/StatusIm/Info.plist +++ b/ios/StatusIm/Info.plist @@ -105,6 +105,7 @@ Inter-Thin-BETA.otf Inter-ThinItalic-BETA.otf InterStatus-Regular.otf + UbuntuMono-Regular.ttf UIBackgroundModes diff --git a/ios/StatusImPR/Info.plist b/ios/StatusImPR/Info.plist index a98eed5d40..f1265c9e71 100644 --- a/ios/StatusImPR/Info.plist +++ b/ios/StatusImPR/Info.plist @@ -108,6 +108,7 @@ Inter-Thin-BETA.otf Inter-ThinItalic-BETA.otf InterStatus-Regular.otf + UbuntuMono-Regular.ttf UIBackgroundModes diff --git a/package.json b/package.json index 19967cf8e5..dffa444ee6 100644 --- a/package.json +++ b/package.json @@ -70,6 +70,7 @@ "react-native-svg": "^9.8.4", "react-native-touch-id": "^4.4.1", "react-native-webview": "git+https://github.com/status-im/react-native-webview.git#refs/tags/v11.16.0-status", + "react-syntax-highlighter": "^15.5.0", "rn-emoji-keyboard": "git+https://github.com/status-im/rn-emoji-keyboard.git#refs/tags/v0.4.3", "tdigest": "^0.1.1" }, diff --git a/resources/fonts/UbuntuMono-Regular.ttf b/resources/fonts/UbuntuMono-Regular.ttf new file mode 100644 index 0000000000..fdd309d716 Binary files /dev/null and b/resources/fonts/UbuntuMono-Regular.ttf differ diff --git a/src/quo2/components/code/snippet.cljs b/src/quo2/components/code/snippet.cljs new file mode 100644 index 0000000000..59e914d23d --- /dev/null +++ b/src/quo2/components/code/snippet.cljs @@ -0,0 +1,154 @@ +(ns quo2.components.code.snippet + (:require ["react-native" :as react-native] + ["react-syntax-highlighter" :default Highlighter] + [cljs-bean.core :as bean] + [clojure.string :as str] + [oops.core :as oops] + [quo.react-native :as rn] + [quo.theme :as theme] + [quo2.components.buttons.button :as button] + [quo2.components.markdown.text :as text] + [quo2.foundations.colors :as colors] + [reagent.core :as reagent] + [status-im.ui.components.react :as react])) + +;; Example themes: +;; https://github.com/react-syntax-highlighter/react-syntax-highlighter/tree/master/src/styles/hljs +(def ^:private themes + {:light {:hljs-comment {:color colors/neutral-40}, + :hljs-title {:color (colors/custom-color :blue 50)}, + :hljs-keyword {:color (colors/custom-color :green 50)}, + :hljs-string {:color (colors/custom-color :turquoise 50)}, + :hljs-literal {:color (colors/custom-color :turquoise 50)} + :hljs-number {:color (colors/custom-color :turquoise 50)} + :line-number {:color colors/neutral-40}} + :dark {:hljs-comment {:color colors/neutral-60}, + :hljs-title {:color (colors/custom-color :blue 60)}, + :hljs-keyword {:color (colors/custom-color :green 60)}, + :hljs-string {:color (colors/custom-color :turquoise 60)}, + :hljs-literal {:color (colors/custom-color :turquoise 60)} + :hljs-number {:color (colors/custom-color :turquoise 60)} + :line-number {:color colors/neutral-40}}}) + +(defn- text-style [class-names] + (->> class-names + (map keyword) + (reduce #(merge %1 (get-in themes [(theme/get-theme) %2])) + {:flex-shrink 1 + ;; Round to a nearest whole number to achieve consistent + ;; spacing (also important for calculating `max-text-height`). + ;; Line height seems to be inconsistent between text being + ;; wrapped and text being rendered on a newline using Flexbox + ;; layout. + :line-height 18}))) + +(defn- render-nodes [nodes] + (map (fn [{:keys [children value] :as node}] + ;; Node can have :children or a :value. + (if children + (into [text/text {:weight :code + :size :paragraph-2 + :style (text-style (get-in node [:properties :className]))}] + (render-nodes children)) + ;; Remove newlines as we already render each line separately. + (-> value str/trim-newline))) + nodes)) + +(defn- code-block [{:keys [rows line-number-width]}] + [into [:<>] + (->> rows + (render-nodes) + ;; Line numbers + (map-indexed (fn [idx row] + (conj [rn/view {:style {:flex-direction :row}} + [rn/view {:style {:width line-number-width + ;; 8+12 margin + :margin-right 20}} + [text/text {:weight :code + :size :paragraph-2 + :style (text-style ["line-number"])} + (inc idx)]]] + row))))]) + +(defn- native-renderer [] + (let [text-height (reagent/atom nil)] + (fn [{:keys [rows max-lines on-copy-press]}] + (let [background-color (colors/theme-colors + colors/white + colors/neutral-80-opa-40) + background-color-left (colors/theme-colors + colors/neutral-5 + colors/neutral-80) + border-color (colors/theme-colors + colors/neutral-20 + colors/neutral-80) + rows (bean/->clj rows) + font-scale (:font-scale (rn/use-window-dimensions)) + max-rows (or max-lines (count rows)) ;; Cut down on rows to process. + max-line-digits (-> rows count (min max-rows) str count) + ;; ~ 9 is char width, 18 is width used in Figma. + line-number-width (* font-scale (max 18 (* 9 max-line-digits))) + max-text-height (some-> max-lines (* font-scale 18)) ;; 18 is font's line height. + truncated? (and max-text-height (< max-text-height @text-height)) + maybe-mask-wrapper (if truncated? + [react/masked-view + {:mask-element + (reagent/as-element + [react/linear-gradient {:colors ["black" "transparent"] + :locations [0.75 1] + :style {:flex 1}}])}] + [:<>])] + + [rn/view {:style {:overflow :hidden + :padding 8 + :background-color background-color + :border-color border-color + :border-width 1 + :border-radius 8 + ;; Hide on intial render to avoid flicker when mask-wrapper is shown. + :opacity (if @text-height 1 0)}} + ;; Line number container + [rn/view {:style {:position :absolute + :bottom 0 + :top 0 + :left 0 + :width (+ line-number-width 8 8) + :background-color background-color-left + :border-right-color border-color + :border-right-width 1}}] + (conj maybe-mask-wrapper [rn/view {:max-height max-text-height} + [rn/view {:on-layout (fn [evt] + (let [height (oops/oget evt "nativeEvent.layout.height")] + (reset! text-height height)))} + [code-block {:rows (take max-rows rows) + :line-number-width line-number-width}]]]) + + ;; Copy button + [rn/view {:style {:position :absolute + :bottom 8 + :right 8}} + [button/button {:icon true + :type :grey + :size 24 + :on-press on-copy-press} + :main-icons/copy]]])))) + +(defn- wrap-renderer-fn [f {:keys [max-lines on-copy-press]}] + (fn [^js props] + (reagent/as-element [:f> f {:rows (.-rows props) + :max-lines max-lines + :on-copy-press on-copy-press}]))) + +(defn snippet [{:keys [language max-lines on-copy-press]} children] + [:> Highlighter {:language language + :renderer (wrap-renderer-fn + native-renderer {:max-lines max-lines + :on-copy-press #(when on-copy-press + (on-copy-press children))}) + ;; Default props to adapt Highlighter for react-native. + :CodeTag react-native/View + :PreTag react-native/View + :show-line-numbers false + :style #js {} + :custom-style #js {:backgroundColor nil}} + children]) diff --git a/src/quo2/components/markdown/text.cljs b/src/quo2/components/markdown/text.cljs index b0b8129fcf..2e66b86976 100644 --- a/src/quo2/components/markdown/text.cljs +++ b/src/quo2/components/markdown/text.cljs @@ -12,6 +12,7 @@ :semi-bold typography/font-semi-bold :bold typography/font-bold :monospace typography/monospace + :code typography/code :inherit nil) (case (or size :paragraph-1) :label typography/label diff --git a/src/quo2/foundations/typography.cljs b/src/quo2/foundations/typography.cljs index 47704b00d1..da26e0b16a 100644 --- a/src/quo2/foundations/typography.cljs +++ b/src/quo2/foundations/typography.cljs @@ -45,3 +45,5 @@ (def font-bold {:font-family "Inter-Bold"}) ; 700 (def monospace {:font-family "InterStatus-Regular"}) + +(def code {:font-family "UbuntuMono-Regular"}) diff --git a/src/quo2/screens/code/snippet.cljs b/src/quo2/screens/code/snippet.cljs new file mode 100644 index 0000000000..7bd1eee2b4 --- /dev/null +++ b/src/quo2/screens/code/snippet.cljs @@ -0,0 +1,92 @@ +(ns quo2.screens.code.snippet + (:require [quo.previews.preview :as preview] + [quo.react-native :as rn] + [quo2.components.code.snippet :as snippet] + [quo2.foundations.colors :as colors] + [reagent.core :as reagent])) + +(def go-example "func (s *Server) listenAndServe() { + cfg := &tls.Config{Certificates: []tls.Certificate{*s.cert}, ServerName: s.hostname, MinVersion: tls.VersionTLS12} + + // in case of restart, we should use the same port as the first start in order not to break existing links + listener, err := tls.Listen(\"tcp\", s.getHost(), cfg) + if err != nil { + s.logger.Error(\"failed to start server, retrying\", zap.Error(err)) + s.ResetPort() + err = s.Start() + if err != nil { + s.logger.Error(\"server start failed, giving up\", zap.Error(err)) + } + return + } + + err = s.SetPort(listener.Addr().(*net.TCPAddr).Port) + if err != nil { + s.logger.Error(\"failed to set Server.port\", zap.Error(err)) + return + } +}") + +(def clojure-example "(defn request->xhrio-options + [{:as request + :keys [on-success on-failure] + :or {on-success [:http-no-on-success] + on-failure [:http-no-on-failure]}}] + ; wrap events in cljs-ajax callback + (let [api (new goog.net.XhrIo)] + (-> request + (assoc + :api api + :handler (partial ajax-xhrio-handler + #(dispatch (conj on-success %)) + #(dispatch (conj on-failure %)) + api)) + (dissoc :on-success :on-failure :on-request))))") + +(def examples {:clojure {:language :clojure + :text clojure-example} + :go {:language :go + :text go-example}}) + +(def descriptor [{:label "Language:" + :key :language + :type :select + :options [{:key :clojure + :value :clojure} + {:key :go + :value :go}]} + {:label "Max lines:" + :key :max-lines + :type :text} + {:label "Syntax highlight:" + :key :syntax + :type :boolean}]) + +(defn cool-preview [] + (let [state (reagent/atom {:language :clojure + :max-lines "" + :syntax true})] + (fn [] + (let [language (if (:syntax @state) (:language @state) :text) + text (-> (:language @state) examples :text) + max-lines (as-> (:max-lines @state) max-lines + (js/parseInt max-lines) + (when-not (js/Number.isNaN max-lines) + max-lines))] + [rn/touchable-without-feedback {:on-press rn/dismiss-keyboard!} + [rn/view {:style {:padding-bottom 150}} + [preview/customizer state descriptor] + [rn/view {:style {:padding-vertical 60 + :padding-horizontal 16}} + [snippet/snippet {:language language + :max-lines max-lines + :on-copy-press #(js/alert %)} + text]]]])))) + +(defn preview-code-snippet [] + [rn/view {:background-color (colors/theme-colors colors/white colors/neutral-90) + :flex 1} + [rn/flat-list {:flex 1 + :keyboardShouldPersistTaps :always + :header [cool-preview] + :key-fn str}]]) diff --git a/src/quo2/screens/main.cljs b/src/quo2/screens/main.cljs index 11ebd381e9..a1fa7e027f 100644 --- a/src/quo2/screens/main.cljs +++ b/src/quo2/screens/main.cljs @@ -14,6 +14,7 @@ [quo2.screens.avatars.wallet-user-avatar :as wallet-user-avatar] [quo2.screens.buttons.button :as button] [quo2.screens.buttons.dynamic-button :as dynamic-button] + [quo2.screens.code.snippet :as code-snippet] [quo2.screens.counter.counter :as counter] [quo2.screens.community.community-card-view :as community-card] [quo2.screens.dividers.divider-label :as divider-label] @@ -76,6 +77,9 @@ {:name :dynamic-button :insets {:top false} :component dynamic-button/preview-dynamic-button}] + :code [{:name :snippet + :insets {:top false} + :component code-snippet/preview-code-snippet}] :community [{:name :community-cards :insets {:top false} :component community-card/preview-community-card}] diff --git a/yarn.lock b/yarn.lock index d1d8c57538..bd8a3df82a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1037,6 +1037,13 @@ dependencies: regenerator-runtime "^0.13.4" +"@babel/runtime@^7.3.1": + version "7.20.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.20.0.tgz#824a9ef325ffde6f78056059db3168c08785e24a" + integrity sha512-NDYdls71fTXoU8TZHfbBWg7DiZfNzClcKui/+kyi6ppD2L1qnWW3VV6CjtaBXSUGGhiTWJ6ereOIkUvenif66Q== + dependencies: + regenerator-runtime "^0.13.10" + "@babel/template@^7.0.0", "@babel/template@^7.4.0", "@babel/template@^7.7.4", "@babel/template@^7.8.3", "@babel/template@^7.8.6": version "7.8.6" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.6.tgz#86b22af15f828dfb086474f964dcc3e39c43ce2b" @@ -1743,6 +1750,13 @@ resolved "https://registry.yarnpkg.com/@types/hammerjs/-/hammerjs-2.0.36.tgz#17ce0a235e9ffbcdcdf5095646b374c2bf615a4c" integrity sha512-7TUK/k2/QGpEAv/BCwSHlYu3NXZhQ9ZwBYpzr9tjlPIL2C5BeGhH3DmVavRx3ZNyELX5TLC91JTz/cen6AAtIQ== +"@types/hast@^2.0.0": + version "2.3.4" + resolved "https://registry.yarnpkg.com/@types/hast/-/hast-2.3.4.tgz#8aa5ef92c117d20d974a82bdfb6a648b08c0bafc" + integrity sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g== + dependencies: + "@types/unist" "*" + "@types/invariant@^2.2.35": version "2.2.35" resolved "https://registry.yarnpkg.com/@types/invariant/-/invariant-2.2.35.tgz#cd3ebf581a6557452735688d8daba6cf0bd5a3be" @@ -1783,6 +1797,11 @@ resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e" integrity sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw== +"@types/unist@*": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d" + integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ== + "@types/yargs-parser@*": version "15.0.0" resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-15.0.0.tgz#cb3f9f741869e20cce330ffbeb9271590483882d" @@ -3008,6 +3027,21 @@ chance@^1.1.0: resolved "https://registry.yarnpkg.com/chance/-/chance-1.1.4.tgz#d8743bf8e40bb05e024c305ca1ff441195eb23db" integrity sha512-pXPDSu3knKlb6H7ahQfpq//J9mSOxYK8SMtp8MV/nRJh8aLRDIl0ipLH8At8+nVogVwtvPZzyIzY/EbcY/cLuQ== +character-entities-legacy@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz#94bc1845dce70a5bb9d2ecc748725661293d8fc1" + integrity sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA== + +character-entities@^1.0.0: + version "1.2.4" + resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-1.2.4.tgz#e12c3939b7eaf4e5b15e7ad4c5e28e1d48c5b16b" + integrity sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw== + +character-reference-invalid@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560" + integrity sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg== + chardet@^0.4.0: version "0.4.2" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2" @@ -3177,6 +3211,11 @@ combined-stream@^1.0.6, combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" +comma-separated-tokens@^1.0.0: + version "1.0.8" + resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz#632b80b6117867a158f1080ad498b2fbe7e3f5ea" + integrity sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw== + command-exists@^1.2.8: version "1.2.9" resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" @@ -4144,6 +4183,13 @@ fastify-warning@^0.2.0: resolved "https://registry.yarnpkg.com/fastify-warning/-/fastify-warning-0.2.0.tgz#e717776026a4493dc9a2befa44db6d17f618008f" integrity sha512-s1EQguBw/9qtc1p/WTY4eq9WMRIACkj+HTcOIK1in4MV5aFaQC9ZCIt0dJ7pr5bIf4lPpHvAtP2ywpTNgs7hqw== +fault@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/fault/-/fault-1.0.4.tgz#eafcfc0a6d214fc94601e170df29954a4f842f13" + integrity sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA== + dependencies: + format "^0.2.0" + fb-watchman@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.1.tgz#fc84fb39d2709cf3ff6d743706157bb5708a8a85" @@ -4318,6 +4364,11 @@ form-data@~2.3.2: combined-stream "^1.0.6" mime-types "^2.1.12" +format@^0.2.0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/format/-/format-0.2.2.tgz#d6170107e9efdc4ed30c9dc39016df942b5cb58b" + integrity sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww== + fragment-cache@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" @@ -4645,6 +4696,22 @@ hasha@^3.0.0: dependencies: is-stream "^1.0.1" +hast-util-parse-selector@^2.0.0: + version "2.2.5" + resolved "https://registry.yarnpkg.com/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz#d57c23f4da16ae3c63b3b6ca4616683313499c3a" + integrity sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ== + +hastscript@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/hastscript/-/hastscript-6.0.0.tgz#e8768d7eac56c3fdeac8a92830d58e811e5bf640" + integrity sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w== + dependencies: + "@types/hast" "^2.0.0" + comma-separated-tokens "^1.0.0" + hast-util-parse-selector "^2.0.0" + property-information "^5.0.0" + space-separated-tokens "^1.0.0" + hermes-engine@~0.5.0: version "0.5.1" resolved "https://registry.yarnpkg.com/hermes-engine/-/hermes-engine-0.5.1.tgz#601115e4b1e0a17d9aa91243b96277de4e926e09" @@ -4657,6 +4724,11 @@ hermes-profile-transformer@^0.0.6: dependencies: source-map "^0.7.3" +highlight.js@^10.4.1, highlight.js@~10.7.0: + version "10.7.3" + resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.7.3.tgz#697272e3991356e40c3cac566a74eef681756531" + integrity sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A== + hmac-drbg@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" @@ -4887,6 +4959,19 @@ is-accessor-descriptor@^1.0.0: dependencies: kind-of "^6.0.0" +is-alphabetical@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.4.tgz#9e7d6b94916be22153745d184c298cbf986a686d" + integrity sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg== + +is-alphanumerical@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz#7eb9a2431f855f6b1ef1a78e326df515696c4dbf" + integrity sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A== + dependencies: + is-alphabetical "^1.0.0" + is-decimal "^1.0.0" + is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" @@ -4935,6 +5020,11 @@ is-date-object@^1.0.1: resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e" integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g== +is-decimal@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.4.tgz#65a3a5958a1c5b63a706e1b333d7cd9f630d3fa5" + integrity sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw== + is-descriptor@^0.1.0: version "0.1.6" resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" @@ -5004,6 +5094,11 @@ is-glob@^4.0.1, is-glob@~4.0.1: dependencies: is-extglob "^2.1.1" +is-hexadecimal@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz#cc35c97588da4bd49a8eedd6bc4082d44dcb23a7" + integrity sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw== + is-installed-globally@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.4.0.tgz#9a0fd407949c30f86eb6959ef1b7994ed0b7b520" @@ -6080,6 +6175,14 @@ lowercase-keys@^2.0.0: resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== +lowlight@^1.17.0: + version "1.20.0" + resolved "https://registry.yarnpkg.com/lowlight/-/lowlight-1.20.0.tgz#ddb197d33462ad0d93bf19d17b6c301aa3941888" + integrity sha512-8Ktj+prEb1RoCPkEOrPMYUN/nCggB7qAWe3a7OpMjWQkh3l2RD5wKRQ+o8Q8YuI9RG/xs95waaI/E6ym/7NsTw== + dependencies: + fault "^1.0.0" + highlight.js "~10.7.0" + lru-cache@^4.0.1: version "4.1.5" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" @@ -7253,6 +7356,18 @@ parse-asn1@^5.0.0, parse-asn1@^5.1.5: pbkdf2 "^3.0.3" safe-buffer "^5.1.1" +parse-entities@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-2.0.0.tgz#53c6eb5b9314a1f4ec99fa0fdf7ce01ecda0cbe8" + integrity sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ== + dependencies: + character-entities "^1.0.0" + character-entities-legacy "^1.0.0" + character-reference-invalid "^1.0.0" + is-alphanumerical "^1.0.0" + is-decimal "^1.0.0" + is-hexadecimal "^1.0.0" + parse-json@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" @@ -7551,6 +7666,16 @@ pretty-format@^25.4.0: ansi-styles "^4.0.0" react-is "^16.12.0" +prismjs@^1.27.0: + version "1.29.0" + resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.29.0.tgz#f113555a8fa9b57c35e637bba27509dcf802dd12" + integrity sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q== + +prismjs@~1.27.0: + version "1.27.0" + resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.27.0.tgz#bb6ee3138a0b438a3653dd4d6ce0cc6510a45057" + integrity sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA== + private@^0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" @@ -7606,6 +7731,13 @@ prop-types@^15.5.10: object-assign "^4.1.1" react-is "^16.13.1" +property-information@^5.0.0: + version "5.6.0" + resolved "https://registry.yarnpkg.com/property-information/-/property-information-5.6.0.tgz#61675545fb23002f245c6540ec46077d4da3ed69" + integrity sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA== + dependencies: + xtend "^4.0.0" + pseudomap@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" @@ -8046,6 +8178,17 @@ react-refresh@^0.4.0: resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.4.2.tgz#54a277a6caaac2803d88f1d6f13c1dcfbd81e334" integrity sha512-kv5QlFFSZWo7OlJFNYbxRtY66JImuP2LcrFgyJfQaf85gSP+byzG21UbDQEYjU7f//ny8rwiEkO6py2Y+fEgAQ== +react-syntax-highlighter@^15.5.0: + version "15.5.0" + resolved "https://registry.yarnpkg.com/react-syntax-highlighter/-/react-syntax-highlighter-15.5.0.tgz#4b3eccc2325fa2ec8eff1e2d6c18fa4a9e07ab20" + integrity sha512-+zq2myprEnQmH5yw6Gqc8lD55QHnpKaU8TOcFeC/Lg/MQSs8UknEA0JC4nTZGFAXC2J2Hyj/ijJ7NlabyPi2gg== + dependencies: + "@babel/runtime" "^7.3.1" + highlight.js "^10.4.1" + lowlight "^1.17.0" + prismjs "^1.27.0" + refractor "^3.6.0" + react@16.13.1: version "16.13.1" resolved "https://registry.yarnpkg.com/react/-/react-16.13.1.tgz#2e818822f1a9743122c063d6410d85c1e3afe48e" @@ -8130,6 +8273,15 @@ realpath-native@^2.0.0: resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-2.0.0.tgz#7377ac429b6e1fd599dc38d08ed942d0d7beb866" integrity sha512-v1SEYUOXXdbBZK8ZuNgO4TBjamPsiSgcFr0aP+tEKpQZK8vooEUqV6nm6Cv502mX4NF2EfsnVqtNAHG+/6Ur1Q== +refractor@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/refractor/-/refractor-3.6.0.tgz#ac318f5a0715ead790fcfb0c71f4dd83d977935a" + integrity sha512-MY9W41IOWxxk31o+YvFCNyNzdkc9M20NoZK5vq6jkv4I/uh2zkWcfudj0Q1fovjUQJrNewS9NMzeTtqPf+n5EA== + dependencies: + hastscript "^6.0.0" + parse-entities "^2.0.0" + prismjs "~1.27.0" + regenerate-unicode-properties@^8.2.0: version "8.2.0" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec" @@ -8142,6 +8294,11 @@ regenerate@^1.4.0: resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== +regenerator-runtime@^0.13.10: + version "0.13.10" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.10.tgz#ed07b19616bcbec5da6274ebc75ae95634bfc2ee" + integrity sha512-KepLsg4dU12hryUO7bp/axHAKvwGOCV0sGloQtpagJ12ai+ojVDqkeGSiRX1zlq+kjIMZ1t7gpze+26QqtdGqw== + regenerator-runtime@^0.13.2, regenerator-runtime@^0.13.4: version "0.13.5" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697" @@ -8776,6 +8933,11 @@ source-map@^0.7.3: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== +space-separated-tokens@^1.0.0: + version "1.1.5" + resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz#85f32c3d10d9682007e917414ddc5c26d1aa6899" + integrity sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA== + spawn-wrap@^1.4.2: version "1.4.3" resolved "https://registry.yarnpkg.com/spawn-wrap/-/spawn-wrap-1.4.3.tgz#81b7670e170cca247d80bf5faf0cfb713bdcf848"