--- title: Fixed Array in TypeScript description: Fixed Array in TypeScript image: tags: typescript robots: index, nofollow lang: zh dir: ltr breaks: # newline style GA: UA-168653916-1 disqus: hackmd slideOptions: transition: fade # https://revealjs.com/transitions/ theme: back --- # Fixed Array in TypeScript ## 簡介 近期在研究如何用透過型別推斷定義出固定長度的陣列 本篇將嘗試解釋給大家聽 ## 研究案例 先提這次的研究案例有兩個如下 (其實只有一個): - 定義型別為 從 0 到 指定數值的陣列型別 ```typescript export type Sequence<N extends number, R extends unknown[] = []> = R['length'] extends N ? R : Sequence<N, [R['length'], ...R]>; // example const a: Sequence<5> = [0, 1, 2, 3, 4]; // typeof a is [0,1,2,3,4] const b: Sequence<3> = [0, 1, 2]; // typeof a is [0,1,2] // how to use // ex: define type is 10 | 11| 12| 13| .... | 19 type ArrayToUnion<T> = T extends any[] ? T[number] : T; // [1,2,3,4] to 1 | 2 | 3 | 4 type UnionSequence<T extends number> = ArrayToUnion<Sequence<T>>; // 0 - 19 union exclude 0 - 9 union should be 10 - 19 union type Example = Exclude<UnionSequence<20>, UnionSequence<10>> ``` - 定義一個固定長度且自訂型別的陣列與矩陣 ```typescript type Fixed<N extends number, P = number, R extends P[] = []> = R['length'] extends N ? R : Sequence<N, P, [P, ...R]>; // example const a: Fixed<3> = [0,0,0]; //typeof a is [number, number, number] const b: Fixed<4, string> = ['','','',''] //typeof b is [string, string, string, string] // how to use type Matrix<X extends number, Y extends number, T = number> = Fixed<X, Fixed<Y, T>>; const m1: Matrix<2, 3> = [[0,0,0],[1,2,2]]; const m2: Matrix<3, 2, string> = [['0','0'],['1','2'],['','']]; ``` 想跳過解說直接使用的可以從這裡取得相關語法 [playground](https://www.typescriptlang.org/play?#code/C4TwDgpgBAyhCOBXCA7AxhAPAOShAHsKgCYDOUKiAtgEYQBOANFAEp6EnmIoDWKA9gHcUAbQC6UALxRxAPilQAUFFYiA5ABtUAc2AALNRIJEUZKLmUqrKgPysl16wC5YCZOizZmIgHR+WzCzqWii6BmJisgDcigD0sewAhlRgWopo-CikwFCJLnBIqBiYAKzy0iIADMwAjMwATMwAzMwALGJRUPFQoJD8AGa5UACW5FWMdY0t7emZ2VA0+W5FWE3lMtVQdVD1HV0JvRADQ6MbE4y7cQl6Qj38UIikEFfsLsQQ-cMo0Icj5DWVKAAHy2NRBNXq4KaIL8fmBWwAnEpfgBBej0RIgAAq-AAqihhplMFj1lj2CYzIkUCBxFA7FiRJRaAwJC4sZ1uiJJoxphJgPcavD6vCmvDWopfvjCSgCu5imTjJwKNQ6PR1miMdi8QSibKVsTZNElN1AQBaREPHUodhoDSId5QM1QJHcaVQUg3RAaYgLaAAqDmmouq0S8DQACi+GSqWg0kjtvtWClmT1Hkw9UqsmYyZlyzTAMNxtippLpbL5Yrlar1Zrtbr1cUocgUAAYsN8BBiDhyUqmarmAAFBR9hiBHumcgD2kVSIKSxBTQ6fSGcdmCyOKx2NiWDcuNsdrteKAD7ywgLHyIxboEaNaJQZLI5NB79udzBrBTjaqVPbxQ7HRI-hkEcmGVZlQJAsRZkfKBiBfA9MFaZhsnoL5tHWdQ1EYNQsJw7CVz-MNjhoICRBQtDkOAVDQko6jtFotCoO6G5BDuB4nibaAAFlEio9tMAADVXcgQOYABNYSwP7KAyWkED1n3N8BOYRSuzE5gSWiaD5ioGoXB4vj8HTZoMK-Rgf0YLkLguCIYgfHT6n03jUKMlodgY0JTLUSpcJ8sRLLUGpcPqQwAtwwwOiAA) ### 已知問題 這個做法目前仍存在上限問題 因為是依靠遞迴完成 所以 上限目前貌似為 999 個索引 如果要考量接續應用他們的話 大約是 900 個索引 也就是 如果寫 ```Sequence<1000>``` 會在開發階段就跳出 stackoverflow 的錯誤 後續遇到會再詳細解釋問題點 ### 詳解 這個做法主要是利用 v3.7 所更新時 允許使用 recursive 來定義型別 以及 ```Array<T>.length``` 來產生數列 尤其是後者 想出這個方法的人真的是天才 在 typescript 中如果要宣告一個值的型別為 數字 1 通常就必須先行定義出該型別 這導致可能必須先進行一串 像是宣告 keyboard code 的靜態字串 而這裡不需要這樣做 但會有一點代價 請參考已知問題 --- 這裡的型別定義宣告為 ```typescript type Sequence<N extends number, R extends unknown[] = []> = R['length'] extends N ? R : Sequence<N, [R['length'], ...R]>; ``` 1. 除了 數列長度 ```N``` 之外 還宣告了一個陣列 ```R``` 並給予預設值空陣列 而這個空陣列就是用來產生數列的主要功臣 2. 判斷邏輯為 如果陣列 R 的長度是 N 就回傳陣列 R 否則回傳 ```Sequence<N, [R['length'], ...R]>``` ```[R['length'], ...R]``` 這段語法的意思是 把陣列 ```R``` 前面再加上一個數字做為新的泛型參數帶回 ```Sequence<N, R>``` 的 ```R``` 而有趣的事情就發生了 此時因為陣列 ```R``` 多了一個元素 導致下一個 ```R['length']``` 比前一次多了 1 使得這段語法會在 typescript 的 編譯器中進行遞迴 使陣列 ```R``` 持續增加元素直到他的長度等於 ```R``` 這樣我們就可以透過 ```Sequence<N>``` 來取得指定長度的數列了 有了這個 就可以做很多過去不好處理的型別或判斷 ### 好處 1. 在參數傳遞上 如果需要 指定個數的元素陣列時 不用在刻死一個專用的型別 來限制 ex: ```typescript //old let numb5: [number,number,number,number,number] = [1,2,3,4,5]; function matrixAdd<T extends [[number, number], [number, number]]>(left: T, right: T); //new let numb5: Fixed<5> = [1,2,3,4,5]; function matrixAdd<X extends number, Y extends number>(left: Matrix<X, Y>, right: Matrix<X, Y>); ``` 2. 減少 runtime 繁瑣的結構判斷, 改成於 designTime 就進行約定加以限制 以提升執行效能 ex: ```typescript //old function runNumb5(num5: number[]) { if(num5.length === 5) return; ///.... } //new function runNumb5(num5: Fixed<5>) { // num5 length exactly equals 5 without condition ///.... } ``` ....more 還有很多可能性都可以從這個點延伸 ## 後記 我當初想做的其實就是 ```Matrix<X, Y>``` 當然在更早之前其實就已經開始思考該怎麼做 只是以前無法實現 而且這件事情對於對數理 數字有興趣的人 應該都可以腦洞大開 <style> body[style], body[style*="background-color: white;"] { background-color: #1e1e1e !important; } body { color: #abb2bf; } .ui-view-area, .markdown-body, .ui-content { background: #1e1e1e; color: #abb2bf; } h1, h2, h3, h4, h5, h6, p { color: #ddd; } hr { border-color: #6d6d6d; } .form-control { background: #333; color: #fff; } .form-control::placeholder, .form-control::-webkit-input-placeholder, .form-control:-moz-placeholder, .form-control::-moz-placeholder, .form-control:-ms-input-placeholder { color: #eee; } .header { background-color: #0e0e0e; border-color: #0e0e0e; } .navbar { background-color: #0e0e0e; border-color: #0e0e0e; } .navbar a { color: #eee !important; } .navbar .btn-group label { background-color: #0e0e0e; color: #eee; border-color: #555; } .navbar .btn-group label.btn-default:focus, .navbar .btn-group label.btn-default:hover { background-color: #2a2a2a; color: #eee; border-color: #555; } .navbar .btn-group label.active { background-color: #555; color: #eee; border-color: #555; } .navbar .btn-group label.active:focus, .navbar .btn-group label.active:hover { background-color: #555; color: #eee; border-color: #555; } .navbar-default .btn-link:focus, .navbar-default .btn-link:hover { color: #eee; } .navbar-default .navbar-nav>.open>a, .navbar-default .navbar-nav>.open>a:focus, .navbar-default .navbar-nav>.open>a:hover { background-color: #555; } .dropdown-header { color: #aaa; } .dropdown-menu { background-color: #222; border: 1px solid #555; border-top: none; } .dropdown-menu>li>a { color: #eee; } .dropdown-menu>li>a:focus, .dropdown-menu>li>a:hover { background-color: #555555; color: #eee; } .dropdown-menu .divider { background-color: #555; } .header .open .dropdown-menu { background-color: #202020; } .navbar .announcement-popover { background: #4F4F4F; } .navbar .announcement-popover .announcement-popover-header { background: #2e2e2e; border-bottom: 1px solid #2e2e2e; } .navbar .announcement-popover .announcement-popover-body { background: #4F4F4F; color: #eee; } .navbar .announcement-popover .announcement-popover-footer { background: #4F4F4F; } .navbar .announcement-area .caption.inverse { color: #eee; } .label-warning { background-color: #ffc107; color: #212529; } .list.row-layout li .item { border-color: #696c7d; } .list.row-layout li:nth-last-of-type(1) .item { border-bottom: none; } .list li .item { background: #1c1c1c; } .list li:hover .item, .list li:focus .item { background: #404040; } .list li .item h4 { color: #fff; } .list li p { color: #ccc; } .list li p i { font-style: normal; } .list li .item .content .tags span { background: #555; } .list li .item.wide .content .title a, .list li .item.wide .content .title a:focus, .list li .item.wide .content .title a:hover { color: #ddd; } .ui-item { color: #fff; opacity: 0.7; } .ui-item:hover, .ui-item:focus { opacity: 1; color: #fff; } .list li .item.wide hr { border-color: #6d6d6d; } .overview-widget-group .btn, .multi-select-dropdown-menu .ui-dropdown-label, .multi-select-dropdown-menu .dropdown-options, .form-control { border-color: #6d6d6d; } .multi-select-dropdown-menu .dropdown-options .ui-option:hover { background-color: #4d4d4d; color: #eee; } #overview-control-form #overview-keyword-input-container .select2-container { background-color: #3e4045 !important; } #overview-control-form #overview-keyword-input-container .select2-container .select2-choices { background-color: #3e4045; } .search { background-color: #3e4045; color: #eee; } .btn.btn-gray { background: #1b1b1b; } .btn.btn-gray:hover { background: #4d4d4d; color: #eee; } .search::placeholder, .search::-webkit-input-placeholder, .search:-moz-placeholder, .search::-moz-placeholder, .search:-ms-input-placeholder { color: #eee; } .btn.btn-gray { border-color: #6d6d6d; background: #333; color: #eee; } .select2-default { color: #eee !important; } .select2-results .select2-highlighted { background: #4d4d4d; color: #eee; } .select2-container-multi .select2-choices { background: #3e4045; } .select2-container-multi .select2-choices .select2-search-choice { background: #131313; color: #eee; border-color: #555; box-shadow: none; } .btn-default, .btn-default:focus { color: #eee; background-color: #2e2e2e; border-color: #6a6a6a; } .btn-default.active.focus, .btn-default.active:focus, .btn-default.active:hover, .btn-default:active.focus, .btn-default:active:focus, .btn-default:active:hover, .open>.dropdown-toggle.btn-default.focus, .open>.dropdown-toggle.btn-default:focus, .open>.dropdown-toggle.btn-default:hover { background: #737373; } .btn-default:hover { color: #fff; background-color: #7d7d7d; border-color: #6a6a6a; } .overview-widget-group .btn.active { background-color: #6a6a6a; color: #eee; } .overview-widget-group .btn:hover { background-color: #7d7d7d; color: #eee; border-color: #636363; } .overview-widget-group .slider.round { border-color: #ccc; } .overview-widget-group .slider.round:before { border-color: #ccc; } .overview-widget-group input:checked+.slider { background-color: #ccc; } .ui-category-description-icon a { color: #eee; } .item .ui-history-pin.active { color: #f00; } .ui-history-close { color: #eee; opacity: 0.5; } .pagination>li>a, .pagination>li>span { color: #eee; background-color: #2e2e2e; border-color: #6a6a6a; } .pagination>li>a:hover { color: #fff; background-color: #7d7d7d; border-color: #6a6a6a; } .pagination>.disabled>a, .pagination>.disabled>a:focus, .pagination>.disabled>a:hover, .pagination>.disabled>span, .pagination>.disabled>span:focus, .pagination>.disabled>span:hover { color: #eee; background-color: #2e2e2e; border-color: #6a6a6a; } .pagination.dark>li>a, .pagination.dark>li>span { color: #aaa; } .section .form-horizontal .form-group .btn-default { font-size: 16px; border-color: #6d6d6d; background-color: #333; color: #FFF; } .section .form-horizontal .form-group .btn-default:hover, .section .form-horizontal .form-group .btn-default:focus { background-color: #737373; color: #FFF; } .section .form-horizontal .form-control:focus { border-color: #bbb; } #notificationLabel, .ui-infobar .btn.ui-edit { color: #eee; border-color: #6a6a6a; } .ui-infobar__user-info li { color: #bbb; } footer { background: #101010; color: #bbb; border-top: 1px solid #454545; } footer a { color: #bbb; } .markdown-body h1, .markdown-body h2, .markdown-body h3, .markdown-body h4, .markdown-body h5, .markdown-body h6, .markdown-body hr, #doc>h1 { color: #ddd; border-color: #777 !important; } .h1 .small, .h1 small, .h2 .small, .h2 small, .h3 .small, .h3 small, .h4 .small, .h4 small, .h5 .small, .h5 small, .h6 .small, .h6 small, h1 .small, h1 small, h2 .small, h2 small, h3 .small, h3 small, h4 .small, h4 small, h5 .small, h5 small, h6 .small, h6 small { color: #ddd; } .markdown-body p { color: #ddd; } .markdown-body a { color: #7bf; } .markdown-body a { color: #7bf !important; } .markdown-body ul li, .markdown-body ol li { color: #ddd; } .markdown-body blockquote { color: #ddd; border-left-color: #777; font-size: 16px; } .markdown-body code, code { color: #dfdfdf !important; background-color: #424a55; } .markdown-body pre { background-color: #1e1e1e; border: 1px solid #555 !important; color: #dfdfdf; } blockquote .small, blockquote footer, blockquote small { color: #bbb; } .mark, mark { background-color: rgba(255, 255, 0, 0.32) !important; color: #ddd; margin: .1em; padding: .1em .2em; } .task-list-item-checkbox { margin: 0.18em 0 0.2em -1.3em !important; } .task-list-item input[type=checkbox] { -webkit-appearance: none; -moz-appearance: none; appearance: none; position: relative; top: -1px; margin: 0 1rem 0 0; cursor: pointer; } .task-list-item input[type=checkbox]::before { -webkit-transition: all 0.1s ease-in-out; -moz-transition: all 0.1s ease-in-out; transition: all 0.1s ease-in-out; content: ""; position: absolute; left: 0; z-index: 1; width: 16px; height: 16px; border: 2px solid #F44336; } .task-list-item input[type=checkbox]:checked::before { -webkit-transform: rotate(-48deg); -moz-transform: rotate(-48deg); -ms-transform: rotate(-48deg); -o-transform: rotate(-48deg); transform: rotate(-48deg); height: 9px; border-color: #00E676; border-top-style: none; border-right-style: none; } .task-list-item input[type=checkbox]::after { content: ""; position: absolute; top: -0.125rem; left: 0; width: 16px; height: 16px; background: #333; cursor: pointer; } .markdown-body table tr { background-color: #1e1e1e; border-top: none; border-bottom: 1px solid rgba(255, 255, 255, 0.3); } .markdown-body table tr:first-child { border-top: 1px solid rgba(255, 255, 255, 0.2); } .markdown-body table tr:nth-child(2n) { background-color: #333; } .markdown-body table tr th { color: #64B5F6; } .markdown-body table th, .markdown-body table td { border: none; } .markdown-body table tr th:first-child, .markdown-body table tr td:first-child { border-left: 1px solid rgba(255, 255, 255, 0.1); } .markdown-body table tr th:last-child, .markdown-body table tr td:last-child { border-right: 1px solid rgba(255, 255, 255, 0.1); } .markdown-body table tr td { color: #ddd; } .markdown-body pre.flow-chart, .markdown-body pre.sequence-diagram, .markdown-body pre.graphviz, .markdown-body pre.mermaid, .markdown-body pre.abc { background-color: #fff !important; } .alert h1, .alert h2, .alert h3, .alert h4, .alert h5, .alert h6, .alert p, .alert ul li, .alert ol li { color: #31708f; } .alert a { color: #002752; font-weight: 700; } .alert h1:first-child, .alert h2:first-child, .alert h3:first-child, .alert h4:first-child, .alert h5:first-child, .alert h6:first-child { margin-top: 0; } .markdown-body .alert>p { margin-top: 0px; margin-bottom: 10px; } .markdown-body .alert>ul, .markdown-body .alert>ol { margin-bottom: 16px; } .markdown-body .alert>*:last-child { margin-bottom: 0; } .alert-warning { background-color: #fff3cd; border-color: #ffeeba; } .ui-edit-area .ui-resizable-handle.ui-resizable-e { background-color: #303030; border: 1px solid #303030; box-shadow: none; } .ui-infobar { color: #999; } .permission-popover-btn-group .btn.focus, .permission-popover-btn-group .btn:active, .permission-popover-btn-group .btn:focus, .permission-popover-btn-group .btn.active { background-color: #6a6a6a !important; color: #eee !important; border-color: #555 !important; } .permission-popover-btn-group .btn:hover, .permission-popover-btn-group .btn.active:hover { background-color: #7d7d7d !important; color: #eee !important; border-color: #636363 !important; } .ui-delete-note a:hover, .ui-delete-note a:focus, .ui-delete-note a:active { background-color: #dc3545 !important; } .ui-invitee-invite { border-color: #6a6a6a !important; } .ui-invitee-invite:hover, .ui-invitee-invite:focus { background-color: #737373; color: #eee !important; } .ui-invitee.ui-invitee-list .ui-invitee-remove, .ui-invitee.ui-invitee-list .ui-invitee-remove:hover, .ui-invitee.ui-invitee-list .ui-invitee-remove:focus, .ui-invitee.ui-invitee-list .ui-invitee-remove:active { background-color: #dc3545; border: 1px solid #dc3545; } .select2-container { background: #202020; } .select2-container-multi .select2-choices .select2-search-field input { color: #eee; } .select2-container-multi .select2-choices .select2-search-field input.select2-active { color: #000; } .select2-drop { background: #202020; color: #eee; } .select2-results .select2-no-results, .select2-results .select2-searching, .select2-results .select2-ajax-error, .select2-results .select2-selection-limit { background: #202020; } .ui-toc-dropdown { width: 42vw; max-height: 90vh; overflow: auto; text-align: inherit; } .ui-toc-dropdown .nav>li>a { font-size: 14px; font-weight: bold; color: #ddd; } .ui-toc-dropdown .nav>.active:focus>a, .ui-toc-dropdown .nav>.active:hover>a, .ui-toc-dropdown .nav>.active>a { color: #7bf; border-left-color: #7bf; } .ui-toc-dropdown .nav>li>a:focus, .ui-toc-dropdown .nav>li>a:hover { color: #7bf; border-left-color: #7bf; } .ui-toc-dropdown.dropdown-menu { background: #333; } .toc-menu a { color: #ddd; } .toc-menu a:focus, .toc-menu a:hover { color: #7bf; } .cm-m-markdown { color: #ddd; } .cm-s-one-dark .cm-header, .cm-m-xml.cm-attribute { color: #ffa653; } .cm-s-one-dark .cm-string, .cm-s-one-dark .cm-variable-2 { color: #7bf; } .cm-m-markdown.cm-variable-3 { color: #ff7e7e; } .cm-s-one-dark .cm-link { color: #b0ee83; } .cm-s-one-dark .CodeMirror-linenumber { color: #666; } .cm-strong { color: #f4511e; } .cm-s-one-dark .cm-comment { color: #a9a9a9; } .cm-matchhighlight { color: #ffea00; } .cm-positive { color: #11bf64; } .cm-negative { color: #ff3e3e; } .dropdown-menu.CodeMirror-other-cursor { border: 2px solid #4d4d4d; background-color: #202020; } .dropdown-menu.CodeMirror-other-cursor li a { color: #ececec; } .topbar { background: #1e1e1e; } .btn.focus, .btn:focus, .btn:hover { color: #aaa; } .summary { background: #1e1e1e; } .summary, .toolbar { background: #1e1e1e !important; border-color: #4d4d4d !important; } .toolbar i { color: #fff; } .summary h1, .summary h2, .summary h3 .summary hr { color: #ddd; border-color: #777 !important; } .summary .nav>li>a { color: #7bf; } .summary .nav-pills>li.active>a, .summary .nav-pills>li.active>a:focus, .summary .nav-pills>li.active>a:hover { color: #ff9100; } .ui-summary-search { font-size: 16px; border: 1px solid #6D6D6D; background-color: #333; color: #FFF; } .summary h1, .summary h2, .summary h3, .summary h4, .summary h5, .summary h6 { border-color: #454545; } div[class$=container-mask] { background: #1e1e1e; z-index: 1; display: block; } .dropdown.ui-notification .ui-notification-label, .dropdown.ui-invitee .ui-invitee-label { color: #eee; border-color: #6a6a6a; } .ui-notification .dropdown-menu { border-top: 1px solid #555; } .modal-header { background-color: #2a2a2a; } .panel-default { border-color: #6d6d6d; } .panel-default>.panel-heading { background-color: #2a2a2a; color: #eee; border-color: #6d6d6d; } .panel-body { background: #2e2e2e; } .panel-body a { color: #7bf; } .table>tbody>tr>td, .table>tbody>tr>th, .table>tfoot>tr>td, .table>tfoot>tr>th, .table>thead>tr>td, .table>thead>tr>th { border-color: #6d6d6d; } .ui-comment-container .ui-comment-header { background-color: #2a2a2a; color: #eee; border-color: #6d6d6d; } .ui-comment-container { background-color: #2e2e2e; border-color: #6d6d6d; } .ui-comment-container .ui-comments-container .ui-comment .comment-author { color: #eee; } .ui-comment-container .ui-comments-container .ui-comment .timestamp { color: #aaa; } .ui-comment-container .ui-comments-container .ui-comment .comment-content { color: #eee; } .ui-comment-container .ui-comments-container .ui-comment .comment-menu { color: #eee; } .ui-comment-container .ui-comments-container .ui-comment .comment-menu .comment-dropdown-menu { background: #222; color: #eee; border-color: #555; } .ui-comment-container .ui-comments-container .ui-comment .comment-menu .comment-dropdown-menu>div:hover { background-color: #555555; color: #eee; } .ui-comment-container .ui-comments-container .ui-comment .comment-menu:hover, .ui-comment-container .ui-comments-container .ui-comment .comment-menu:active, .ui-comment-container .ui-comments-container .ui-comment .comment-menu.active { background-color: #737373; color: #eee; } .ui-comment-container .ui-comment-input-container { background-color: #3c3c3c; } .ui-comment-container textarea { background-color: #3e4045; color: #eee; border: 1px solid #6d6d6d; } .ui-comment-container textarea::placeholder, .ui-comment-container textarea::-webkit-input-placeholder, .ui-comment-container textarea:-moz-placeholder, .ui-comment-container textarea::-moz-placeholder, .ui-comment-container textarea:-ms-input-placeholder { color: #eee; } @keyframes highlight { 0% { background-color: #3c3c3c; } 30% { background-color: #3c3c3c; } 100% { background-color: transparent; } } .template-content .modal-header { background: #2a2a2a; } .template-content .close { color: #fff; } .template-content .modal-title { color: #eee; } .template-content .ui-templates-container { border-color: #6d6d6d; } .ui-templates-container .ui-create-template-btn { background: #446fab; color: #fff; } .ui-template-list-filter .ui-template-list-filter-label, .ui-template-list-filter .ui-template-list-filter-label:hover { color: #eee; } .ui-template-list .list-group-item.active { background: #4d4d4d; } .ui-template-list .list-group-item.active:focus { background: #4d4d4d !important; } .list-group-item.active, .list-group-item.active:focus, .list-group-item.active:hover { color: #eee; } .ui-template-list .list-group-item .list-group-item-heading { color: #eee; } .ui-template-list .list-group-item.active .list-group-item-heading { color: #eee; } .ui-template-list .list-group-item:hover { background: #4d4d4d !important; } .ui-template-item-menu { color: #eee !important; } .ui-template-list .list-group-item { color: #fff; } .ui-template-list .list-group-item .dropdown-container.open { background-color: #2a2a2a; } .ui-template-list .list-group-item .dropdown-container:hover { background-color: #2a2a2a !important; } .template-menu .more-template { border-color: #6d6d6d; } .template-menu .more-template:hover { color: #eee; border-color: #6d6d6d; } .modal-content { background: #1f2226; } .modal-header { border-bottom: 1px solid #46484f; } .modal-footer { border-top: 1px solid #46484f; } a.list-group-item { background: #1f2226; color: #ddd; border: 1px solid #46484f; } a.list-group-item .list-group-item-heading { color: #ddd; } a.list-group-item:focus, a.list-group-item:hover { background: #434651; color: #ddd; } button.close { color: #ddd; opacity: .5; } .close:focus, .close:hover { color: #fff; opacity: .8; } .CodeMirror { background: #1f2226; } .CodeMirror-gutters { background: #1f2226; border-right: 1px solid rgba(204, 217, 255, 0.1); } .cm-s-default .cm-comment { color: #888; } .cm-s-default .cm-quote { color: #ddd; } .cm-s-default .cm-header { color: #ffa653; } .cm-s-default .cm-link { color: #b0ee83; } .cm-s-default .cm-string, .cm-s-default .cm-variable-2 { color: #7bf; } .cm-s-default .cm-def { color: #c678dd; } .cm-s-default .cm-number, .cm-s-default .cm-attribute, .cm-s-default .cm-qualifier, .cm-s-default .cm-plus, .cm-s-default .cm-atom { color: #eda35e; } .cm-s-default .cm-property, .cm-s-default .cm-variable, .cm-s-default .cm-variable-3, .cm-s-default .cm-operator, .cm-s-default .cm-bracket { color: #f76e79; } .cm-s-default .cm-keyword, .cm-s-default .cm-builtin, .cm-s-default .cm-tag { color: #98c379; } .modal-title { color: #ccc; } .modal-body { color: #ccc !important; } div[contenteditable]:empty:not(:focus):before { color: #aaa; } .CodeMirror pre { color: #ddd; } .CodeMirror pre span[style^="background-color: rgb(221, 251, 230)"] { background-color: #288c27 !important; } .CodeMirror pre span[style^="background-color: rgb(249, 215, 220)"] { background-color: #a52721 !important; } .hljs { background: #1E1E1E; color: #DCDCDC; } .hljs-keyword, .hljs-literal, .hljs-symbol, .hljs-name { color: #569CD6; } .hljs-link { color: #569CD6; text-decoration: underline; } .hljs-built_in, .hljs-type { color: #4EC9B0; } .hljs-number, .hljs-class { color: #B8D7A3; } .hljs-string, .hljs-meta-string { color: #D69D85; } .hljs-regexp, .hljs-template-tag { color: #d16969; } .hljs-title { color: #dcdcaa; } .hljs-subst, .hljs-function, .hljs-formula { color: #DCDCDC; } .hljs-comment, .hljs-quote { color: #57A64A; } .hljs-doctag { color: #608B4E; } .hljs-meta, .hljs-meta-keyword, .hljs-tag { color: #9B9B9B; } .hljs-variable, .hljs-template-variable { color: #BD63C5; } .hljs-params, .hljs-attr, .hljs-attribute, .hljs-builtin-name { color: #9CDCFE; } .hljs-section { color: gold; } .hljs-emphasis { font-style: italic; } .hljs-strong { font-weight: bold; } .hljs-code { font-family:'Monospace'; } .hljs-bullet, .hljs-selector-tag, .hljs-selector-id, .hljs-selector-class, .hljs-selector-attr, .hljs-selector-pseudo { color: #D7BA7D; } .hljs-addition { background-color: #155a36; color: #dfdfdf; display: inline-block; width: 100%; } .hljs-deletion { background-color: #872e2e; color: #dfdfdf; display: inline-block; width: 100%; } code[class*="language-"], pre[class*="language-"] { color: #DCDCDC; } :not(pre)>code[class*="language-"], pre[class*="language-"] { background: #1E1E1E; } .token.comment, .token.block-comment, .token.prolog, .token.cdata { color: #57A64A; } .token.doctype, .token.punctuation { color: #9B9B9B; } .token.tag, .token.entity { color: #569CD6; } .token.attr-name, .token.namespace, .token.deleted, .token.property, .token.builtin { color: #9CDCFE; } .token.function, .token.function-name { color: #dcdcaa; } .token.boolean, .token.keyword, .token.important { color: #569CD6; } .token.number { color: #B8D7A3; } .token.class-name, .token.constant { color: #4EC9B0; } .token.symbol { color: #f8c555; } .token.rule { color: #c586c0; } .token.selector { color: #D7BA7D; } .token.atrule { color: #cc99cd; } .token.string, .token.attr-value { color: #D69D85; } .token.char { color: #7ec699; } .token.variable { color: #BD63C5; } .token.regex { color: #d16969; } .token.operator { color: #DCDCDC; background: transparent; } .token.url { color: #67cdcc; } .token.important, .token.bold { font-weight: bold; } .token.italic { font-style: italic; } .token.entity { cursor: help; } .token.inserted { color: green; } .gist .gist-file { border: 1px solid #555; } .gist .gist-data { background-color: #1e1e1e; border-bottom: 1px solid #555; } .gist .gist-meta { background-color: #424a55; color: #eee; } .gist .gist-meta a { color: #eee; } .gist .highlight { color: #eee; background-color: #1e1e1e; } .gist .blob-num { color: #afafaf; } .gist .blob-code-inner { color: #dfdfdf; } .pl-mb { color: #fff !important; } .pl-c { color: #57A64A !important; } .pl-ent { color: #569CD6 !important; } .pl-e { color: #9CDCFE !important; } .pl-en { color: #4EC9B0 !important; } .pl-smi { color: #9CDCFE !important; } .pl-k { color: #569cd6 !important; } .pl-c1, .pl-s .pl-v { color: #4EC9B0 !important; } .pl-pds, .pl-s, .pl-s .pl-pse .pl-s1, .pl-sr, .pl-sr .pl-cce, .pl-sr .pl-sra, .pl-sr .pl-sre, .pl-s .pl-s1 { color: #D69D85 !important; } .pl-s .pl-s1 .pl-pse { color: #c5dbff !important; } .diff-table .pl-c, .diff-table .pl-ent, .diff-table .pl-e, .diff-table .pl-en, .diff-table .pl-pds, .diff-table .pl-s, .diff-table .pl-s .pl-s1, .diff-table .pl-s .pl-pse .pl-s1, .diff-table .pl-sr, .diff-table .pl-sr .pl-cce, .diff-table .pl-sr .pl-sra, .diff-table .pl-sr .pl-sre, .diff-table .pl-k, .diff-table .pl-smi, .diff-table .pl-c1, .diff-table .pl-v { color: #eee !important; } </style>