added codemirror optional js for syntax highlight of dockerfiles
This commit is contained in:
		
							parent
							
								
									81e0954a71
								
							
						
					
					
						commit
						fa63f76791
					
				|  | @ -39,7 +39,9 @@ | ||||||
|   :uberwar {:init toaster.ring/init |   :uberwar {:init toaster.ring/init | ||||||
|             :handler toaster.handler/app} |             :handler toaster.handler/app} | ||||||
|   :mail toaster.handler |   :mail toaster.handler | ||||||
|   :npm {:dependencies [[dockerlint "0.3.9"]]} |   :npm {:dependencies [[dockerlint "0.3.9"] | ||||||
|  |                        [bulma "0.7.2"] | ||||||
|  |                        [codemirror "5.40.2"]]} | ||||||
|   :profiles { :dev {:dependencies [[javax.servlet/servlet-api "2.5"] |   :profiles { :dev {:dependencies [[javax.servlet/servlet-api "2.5"] | ||||||
|                                    [ring/ring-mock "0.3.2"] |                                    [ring/ring-mock "0.3.2"] | ||||||
|                                    [midje "1.9.2"]] |                                    [midje "1.9.2"]] | ||||||
|  |  | ||||||
|  | @ -0,0 +1,346 @@ | ||||||
|  | /* BASICS */ | ||||||
|  | 
 | ||||||
|  | .CodeMirror { | ||||||
|  |   /* Set height, width, borders, and global font properties here */ | ||||||
|  |   font-family: monospace; | ||||||
|  |   height: 300px; | ||||||
|  |   color: black; | ||||||
|  |   direction: ltr; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* PADDING */ | ||||||
|  | 
 | ||||||
|  | .CodeMirror-lines { | ||||||
|  |   padding: 4px 0; /* Vertical padding around content */ | ||||||
|  | } | ||||||
|  | .CodeMirror pre { | ||||||
|  |   padding: 0 4px; /* Horizontal padding of content */ | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { | ||||||
|  |   background-color: white; /* The little square between H and V scrollbars */ | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* GUTTER */ | ||||||
|  | 
 | ||||||
|  | .CodeMirror-gutters { | ||||||
|  |   border-right: 1px solid #ddd; | ||||||
|  |   background-color: #f7f7f7; | ||||||
|  |   white-space: nowrap; | ||||||
|  | } | ||||||
|  | .CodeMirror-linenumbers {} | ||||||
|  | .CodeMirror-linenumber { | ||||||
|  |   padding: 0 3px 0 5px; | ||||||
|  |   min-width: 20px; | ||||||
|  |   text-align: right; | ||||||
|  |   color: #999; | ||||||
|  |   white-space: nowrap; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .CodeMirror-guttermarker { color: black; } | ||||||
|  | .CodeMirror-guttermarker-subtle { color: #999; } | ||||||
|  | 
 | ||||||
|  | /* CURSOR */ | ||||||
|  | 
 | ||||||
|  | .CodeMirror-cursor { | ||||||
|  |   border-left: 1px solid black; | ||||||
|  |   border-right: none; | ||||||
|  |   width: 0; | ||||||
|  | } | ||||||
|  | /* Shown when moving in bi-directional text */ | ||||||
|  | .CodeMirror div.CodeMirror-secondarycursor { | ||||||
|  |   border-left: 1px solid silver; | ||||||
|  | } | ||||||
|  | .cm-fat-cursor .CodeMirror-cursor { | ||||||
|  |   width: auto; | ||||||
|  |   border: 0 !important; | ||||||
|  |   background: #7e7; | ||||||
|  | } | ||||||
|  | .cm-fat-cursor div.CodeMirror-cursors { | ||||||
|  |   z-index: 1; | ||||||
|  | } | ||||||
|  | .cm-fat-cursor-mark { | ||||||
|  |   background-color: rgba(20, 255, 20, 0.5); | ||||||
|  |   -webkit-animation: blink 1.06s steps(1) infinite; | ||||||
|  |   -moz-animation: blink 1.06s steps(1) infinite; | ||||||
|  |   animation: blink 1.06s steps(1) infinite; | ||||||
|  | } | ||||||
|  | .cm-animate-fat-cursor { | ||||||
|  |   width: auto; | ||||||
|  |   border: 0; | ||||||
|  |   -webkit-animation: blink 1.06s steps(1) infinite; | ||||||
|  |   -moz-animation: blink 1.06s steps(1) infinite; | ||||||
|  |   animation: blink 1.06s steps(1) infinite; | ||||||
|  |   background-color: #7e7; | ||||||
|  | } | ||||||
|  | @-moz-keyframes blink { | ||||||
|  |   0% {} | ||||||
|  |   50% { background-color: transparent; } | ||||||
|  |   100% {} | ||||||
|  | } | ||||||
|  | @-webkit-keyframes blink { | ||||||
|  |   0% {} | ||||||
|  |   50% { background-color: transparent; } | ||||||
|  |   100% {} | ||||||
|  | } | ||||||
|  | @keyframes blink { | ||||||
|  |   0% {} | ||||||
|  |   50% { background-color: transparent; } | ||||||
|  |   100% {} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Can style cursor different in overwrite (non-insert) mode */ | ||||||
|  | .CodeMirror-overwrite .CodeMirror-cursor {} | ||||||
|  | 
 | ||||||
|  | .cm-tab { display: inline-block; text-decoration: inherit; } | ||||||
|  | 
 | ||||||
|  | .CodeMirror-rulers { | ||||||
|  |   position: absolute; | ||||||
|  |   left: 0; right: 0; top: -50px; bottom: -20px; | ||||||
|  |   overflow: hidden; | ||||||
|  | } | ||||||
|  | .CodeMirror-ruler { | ||||||
|  |   border-left: 1px solid #ccc; | ||||||
|  |   top: 0; bottom: 0; | ||||||
|  |   position: absolute; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* DEFAULT THEME */ | ||||||
|  | 
 | ||||||
|  | .cm-s-default .cm-header {color: blue;} | ||||||
|  | .cm-s-default .cm-quote {color: #090;} | ||||||
|  | .cm-negative {color: #d44;} | ||||||
|  | .cm-positive {color: #292;} | ||||||
|  | .cm-header, .cm-strong {font-weight: bold;} | ||||||
|  | .cm-em {font-style: italic;} | ||||||
|  | .cm-link {text-decoration: underline;} | ||||||
|  | .cm-strikethrough {text-decoration: line-through;} | ||||||
|  | 
 | ||||||
|  | .cm-s-default .cm-keyword {color: #708;} | ||||||
|  | .cm-s-default .cm-atom {color: #219;} | ||||||
|  | .cm-s-default .cm-number {color: #164;} | ||||||
|  | .cm-s-default .cm-def {color: #00f;} | ||||||
|  | .cm-s-default .cm-variable, | ||||||
|  | .cm-s-default .cm-punctuation, | ||||||
|  | .cm-s-default .cm-property, | ||||||
|  | .cm-s-default .cm-operator {} | ||||||
|  | .cm-s-default .cm-variable-2 {color: #05a;} | ||||||
|  | .cm-s-default .cm-variable-3, .cm-s-default .cm-type {color: #085;} | ||||||
|  | .cm-s-default .cm-comment {color: #a50;} | ||||||
|  | .cm-s-default .cm-string {color: #a11;} | ||||||
|  | .cm-s-default .cm-string-2 {color: #f50;} | ||||||
|  | .cm-s-default .cm-meta {color: #555;} | ||||||
|  | .cm-s-default .cm-qualifier {color: #555;} | ||||||
|  | .cm-s-default .cm-builtin {color: #30a;} | ||||||
|  | .cm-s-default .cm-bracket {color: #997;} | ||||||
|  | .cm-s-default .cm-tag {color: #170;} | ||||||
|  | .cm-s-default .cm-attribute {color: #00c;} | ||||||
|  | .cm-s-default .cm-hr {color: #999;} | ||||||
|  | .cm-s-default .cm-link {color: #00c;} | ||||||
|  | 
 | ||||||
|  | .cm-s-default .cm-error {color: #f00;} | ||||||
|  | .cm-invalidchar {color: #f00;} | ||||||
|  | 
 | ||||||
|  | .CodeMirror-composing { border-bottom: 2px solid; } | ||||||
|  | 
 | ||||||
|  | /* Default styles for common addons */ | ||||||
|  | 
 | ||||||
|  | div.CodeMirror span.CodeMirror-matchingbracket {color: #0b0;} | ||||||
|  | div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #a22;} | ||||||
|  | .CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); } | ||||||
|  | .CodeMirror-activeline-background {background: #e8f2ff;} | ||||||
|  | 
 | ||||||
|  | /* STOP */ | ||||||
|  | 
 | ||||||
|  | /* The rest of this file contains styles related to the mechanics of | ||||||
|  |    the editor. You probably shouldn't touch them. */ | ||||||
|  | 
 | ||||||
|  | .CodeMirror { | ||||||
|  |   position: relative; | ||||||
|  |   overflow: hidden; | ||||||
|  |   background: white; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .CodeMirror-scroll { | ||||||
|  |   overflow: scroll !important; /* Things will break if this is overridden */ | ||||||
|  |   /* 30px is the magic margin used to hide the element's real scrollbars */ | ||||||
|  |   /* See overflow: hidden in .CodeMirror */ | ||||||
|  |   margin-bottom: -30px; margin-right: -30px; | ||||||
|  |   padding-bottom: 30px; | ||||||
|  |   height: 100%; | ||||||
|  |   outline: none; /* Prevent dragging from highlighting the element */ | ||||||
|  |   position: relative; | ||||||
|  | } | ||||||
|  | .CodeMirror-sizer { | ||||||
|  |   position: relative; | ||||||
|  |   border-right: 30px solid transparent; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* The fake, visible scrollbars. Used to force redraw during scrolling | ||||||
|  |    before actual scrolling happens, thus preventing shaking and | ||||||
|  |    flickering artifacts. */ | ||||||
|  | .CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { | ||||||
|  |   position: absolute; | ||||||
|  |   z-index: 6; | ||||||
|  |   display: none; | ||||||
|  | } | ||||||
|  | .CodeMirror-vscrollbar { | ||||||
|  |   right: 0; top: 0; | ||||||
|  |   overflow-x: hidden; | ||||||
|  |   overflow-y: scroll; | ||||||
|  | } | ||||||
|  | .CodeMirror-hscrollbar { | ||||||
|  |   bottom: 0; left: 0; | ||||||
|  |   overflow-y: hidden; | ||||||
|  |   overflow-x: scroll; | ||||||
|  | } | ||||||
|  | .CodeMirror-scrollbar-filler { | ||||||
|  |   right: 0; bottom: 0; | ||||||
|  | } | ||||||
|  | .CodeMirror-gutter-filler { | ||||||
|  |   left: 0; bottom: 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .CodeMirror-gutters { | ||||||
|  |   position: absolute; left: 0; top: 0; | ||||||
|  |   min-height: 100%; | ||||||
|  |   z-index: 3; | ||||||
|  | } | ||||||
|  | .CodeMirror-gutter { | ||||||
|  |   white-space: normal; | ||||||
|  |   height: 100%; | ||||||
|  |   display: inline-block; | ||||||
|  |   vertical-align: top; | ||||||
|  |   margin-bottom: -30px; | ||||||
|  | } | ||||||
|  | .CodeMirror-gutter-wrapper { | ||||||
|  |   position: absolute; | ||||||
|  |   z-index: 4; | ||||||
|  |   background: none !important; | ||||||
|  |   border: none !important; | ||||||
|  | } | ||||||
|  | .CodeMirror-gutter-background { | ||||||
|  |   position: absolute; | ||||||
|  |   top: 0; bottom: 0; | ||||||
|  |   z-index: 4; | ||||||
|  | } | ||||||
|  | .CodeMirror-gutter-elt { | ||||||
|  |   position: absolute; | ||||||
|  |   cursor: default; | ||||||
|  |   z-index: 4; | ||||||
|  | } | ||||||
|  | .CodeMirror-gutter-wrapper ::selection { background-color: transparent } | ||||||
|  | .CodeMirror-gutter-wrapper ::-moz-selection { background-color: transparent } | ||||||
|  | 
 | ||||||
|  | .CodeMirror-lines { | ||||||
|  |   cursor: text; | ||||||
|  |   min-height: 1px; /* prevents collapsing before first draw */ | ||||||
|  | } | ||||||
|  | .CodeMirror pre { | ||||||
|  |   /* Reset some styles that the rest of the page might have set */ | ||||||
|  |   -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0; | ||||||
|  |   border-width: 0; | ||||||
|  |   background: transparent; | ||||||
|  |   font-family: inherit; | ||||||
|  |   font-size: inherit; | ||||||
|  |   margin: 0; | ||||||
|  |   white-space: pre; | ||||||
|  |   word-wrap: normal; | ||||||
|  |   line-height: inherit; | ||||||
|  |   color: inherit; | ||||||
|  |   z-index: 2; | ||||||
|  |   position: relative; | ||||||
|  |   overflow: visible; | ||||||
|  |   -webkit-tap-highlight-color: transparent; | ||||||
|  |   -webkit-font-variant-ligatures: contextual; | ||||||
|  |   font-variant-ligatures: contextual; | ||||||
|  | } | ||||||
|  | .CodeMirror-wrap pre { | ||||||
|  |   word-wrap: break-word; | ||||||
|  |   white-space: pre-wrap; | ||||||
|  |   word-break: normal; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .CodeMirror-linebackground { | ||||||
|  |   position: absolute; | ||||||
|  |   left: 0; right: 0; top: 0; bottom: 0; | ||||||
|  |   z-index: 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .CodeMirror-linewidget { | ||||||
|  |   position: relative; | ||||||
|  |   z-index: 2; | ||||||
|  |   padding: 0.1px; /* Force widget margins to stay inside of the container */ | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .CodeMirror-widget {} | ||||||
|  | 
 | ||||||
|  | .CodeMirror-rtl pre { direction: rtl; } | ||||||
|  | 
 | ||||||
|  | .CodeMirror-code { | ||||||
|  |   outline: none; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Force content-box sizing for the elements where we expect it */ | ||||||
|  | .CodeMirror-scroll, | ||||||
|  | .CodeMirror-sizer, | ||||||
|  | .CodeMirror-gutter, | ||||||
|  | .CodeMirror-gutters, | ||||||
|  | .CodeMirror-linenumber { | ||||||
|  |   -moz-box-sizing: content-box; | ||||||
|  |   box-sizing: content-box; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .CodeMirror-measure { | ||||||
|  |   position: absolute; | ||||||
|  |   width: 100%; | ||||||
|  |   height: 0; | ||||||
|  |   overflow: hidden; | ||||||
|  |   visibility: hidden; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .CodeMirror-cursor { | ||||||
|  |   position: absolute; | ||||||
|  |   pointer-events: none; | ||||||
|  | } | ||||||
|  | .CodeMirror-measure pre { position: static; } | ||||||
|  | 
 | ||||||
|  | div.CodeMirror-cursors { | ||||||
|  |   visibility: hidden; | ||||||
|  |   position: relative; | ||||||
|  |   z-index: 3; | ||||||
|  | } | ||||||
|  | div.CodeMirror-dragcursors { | ||||||
|  |   visibility: visible; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .CodeMirror-focused div.CodeMirror-cursors { | ||||||
|  |   visibility: visible; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .CodeMirror-selected { background: #d9d9d9; } | ||||||
|  | .CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; } | ||||||
|  | .CodeMirror-crosshair { cursor: crosshair; } | ||||||
|  | .CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; } | ||||||
|  | .CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; } | ||||||
|  | 
 | ||||||
|  | .cm-searching { | ||||||
|  |   background-color: #ffa; | ||||||
|  |   background-color: rgba(255, 255, 0, .4); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Used to force a border model for a node */ | ||||||
|  | .cm-force-border { padding-right: .1px; } | ||||||
|  | 
 | ||||||
|  | @media print { | ||||||
|  |   /* Hide the cursor when printing */ | ||||||
|  |   .CodeMirror div.CodeMirror-cursors { | ||||||
|  |     visibility: hidden; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* See issue #2901 */ | ||||||
|  | .cm-tab-wrap-hack:after { content: ''; } | ||||||
|  | 
 | ||||||
|  | /* Help users use markselection to safely style text background */ | ||||||
|  | span.CodeMirror-selectedtext { background: none; } | ||||||
|  | @ -0,0 +1,211 @@ | ||||||
|  | // CodeMirror, copyright (c) by Marijn Haverbeke and others
 | ||||||
|  | // Distributed under an MIT license: https://codemirror.net/LICENSE
 | ||||||
|  | 
 | ||||||
|  | (function(mod) { | ||||||
|  |   if (typeof exports == "object" && typeof module == "object") // CommonJS
 | ||||||
|  |     mod(require("../../lib/codemirror"), require("../../addon/mode/simple")); | ||||||
|  |   else if (typeof define == "function" && define.amd) // AMD
 | ||||||
|  |     define(["../../lib/codemirror", "../../addon/mode/simple"], mod); | ||||||
|  |   else // Plain browser env
 | ||||||
|  |     mod(CodeMirror); | ||||||
|  | })(function(CodeMirror) { | ||||||
|  |   "use strict"; | ||||||
|  | 
 | ||||||
|  |   var from = "from"; | ||||||
|  |   var fromRegex = new RegExp("^(\\s*)\\b(" + from + ")\\b", "i"); | ||||||
|  | 
 | ||||||
|  |   var shells = ["run", "cmd", "entrypoint", "shell"]; | ||||||
|  |   var shellsAsArrayRegex = new RegExp("^(\\s*)(" + shells.join('|') + ")(\\s+\\[)", "i"); | ||||||
|  | 
 | ||||||
|  |   var expose = "expose"; | ||||||
|  |   var exposeRegex = new RegExp("^(\\s*)(" + expose + ")(\\s+)", "i"); | ||||||
|  | 
 | ||||||
|  |   var others = [ | ||||||
|  |     "arg", "from", "maintainer", "label", "env", | ||||||
|  |     "add", "copy", "volume", "user", | ||||||
|  |     "workdir", "onbuild", "stopsignal", "healthcheck", "shell" | ||||||
|  |   ]; | ||||||
|  | 
 | ||||||
|  |   // Collect all Dockerfile directives
 | ||||||
|  |   var instructions = [from, expose].concat(shells).concat(others), | ||||||
|  |       instructionRegex = "(" + instructions.join('|') + ")", | ||||||
|  |       instructionOnlyLine = new RegExp("^(\\s*)" + instructionRegex + "(\\s*)(#.*)?$", "i"), | ||||||
|  |       instructionWithArguments = new RegExp("^(\\s*)" + instructionRegex + "(\\s+)", "i"); | ||||||
|  | 
 | ||||||
|  |   CodeMirror.defineSimpleMode("dockerfile", { | ||||||
|  |     start: [ | ||||||
|  |       // Block comment: This is a line starting with a comment
 | ||||||
|  |       { | ||||||
|  |         regex: /^\s*#.*$/, | ||||||
|  |         sol: true, | ||||||
|  |         token: "comment" | ||||||
|  |       }, | ||||||
|  |       { | ||||||
|  |         regex: fromRegex, | ||||||
|  |         token: [null, "keyword"], | ||||||
|  |         sol: true, | ||||||
|  |         next: "from" | ||||||
|  |       }, | ||||||
|  |       // Highlight an instruction without any arguments (for convenience)
 | ||||||
|  |       { | ||||||
|  |         regex: instructionOnlyLine, | ||||||
|  |         token: [null, "keyword", null, "error"], | ||||||
|  |         sol: true | ||||||
|  |       }, | ||||||
|  |       { | ||||||
|  |         regex: shellsAsArrayRegex, | ||||||
|  |         token: [null, "keyword", null], | ||||||
|  |         sol: true, | ||||||
|  |         next: "array" | ||||||
|  |       }, | ||||||
|  |       { | ||||||
|  |         regex: exposeRegex, | ||||||
|  |         token: [null, "keyword", null], | ||||||
|  |         sol: true, | ||||||
|  |         next: "expose" | ||||||
|  |       }, | ||||||
|  |       // Highlight an instruction followed by arguments
 | ||||||
|  |       { | ||||||
|  |         regex: instructionWithArguments, | ||||||
|  |         token: [null, "keyword", null], | ||||||
|  |         sol: true, | ||||||
|  |         next: "arguments" | ||||||
|  |       }, | ||||||
|  |       { | ||||||
|  |         regex: /./, | ||||||
|  |         token: null | ||||||
|  |       } | ||||||
|  |     ], | ||||||
|  |     from: [ | ||||||
|  |       { | ||||||
|  |         regex: /\s*$/, | ||||||
|  |         token: null, | ||||||
|  |         next: "start" | ||||||
|  |       }, | ||||||
|  |       { | ||||||
|  |         // Line comment without instruction arguments is an error
 | ||||||
|  |         regex: /(\s*)(#.*)$/, | ||||||
|  |         token: [null, "error"], | ||||||
|  |         next: "start" | ||||||
|  |       }, | ||||||
|  |       { | ||||||
|  |         regex: /(\s*\S+\s+)(as)/i, | ||||||
|  |         token: [null, "keyword"], | ||||||
|  |         next: "start" | ||||||
|  |       }, | ||||||
|  |       // Fail safe return to start
 | ||||||
|  |       { | ||||||
|  |         token: null, | ||||||
|  |         next: "start" | ||||||
|  |       } | ||||||
|  |     ], | ||||||
|  |     single: [ | ||||||
|  |       { | ||||||
|  |         regex: /(?:[^\\']|\\.)/, | ||||||
|  |         token: "string" | ||||||
|  |       }, | ||||||
|  |       { | ||||||
|  |         regex: /'/, | ||||||
|  |         token: "string", | ||||||
|  |         pop: true | ||||||
|  |       } | ||||||
|  |     ], | ||||||
|  |     double: [ | ||||||
|  |       { | ||||||
|  |         regex: /(?:[^\\"]|\\.)/, | ||||||
|  |         token: "string" | ||||||
|  |       }, | ||||||
|  |       { | ||||||
|  |         regex: /"/, | ||||||
|  |         token: "string", | ||||||
|  |         pop: true | ||||||
|  |       } | ||||||
|  |     ], | ||||||
|  |     array: [ | ||||||
|  |       { | ||||||
|  |         regex: /\]/, | ||||||
|  |         token: null, | ||||||
|  |         next: "start" | ||||||
|  |       }, | ||||||
|  |       { | ||||||
|  |         regex: /"(?:[^\\"]|\\.)*"?/, | ||||||
|  |         token: "string" | ||||||
|  |       } | ||||||
|  |     ], | ||||||
|  |     expose: [ | ||||||
|  |       { | ||||||
|  |         regex: /\d+$/, | ||||||
|  |         token: "number", | ||||||
|  |         next: "start" | ||||||
|  |       }, | ||||||
|  |       { | ||||||
|  |         regex: /[^\d]+$/, | ||||||
|  |         token: null, | ||||||
|  |         next: "start" | ||||||
|  |       }, | ||||||
|  |       { | ||||||
|  |         regex: /\d+/, | ||||||
|  |         token: "number" | ||||||
|  |       }, | ||||||
|  |       { | ||||||
|  |         regex: /[^\d]+/, | ||||||
|  |         token: null | ||||||
|  |       }, | ||||||
|  |       // Fail safe return to start
 | ||||||
|  |       { | ||||||
|  |         token: null, | ||||||
|  |         next: "start" | ||||||
|  |       } | ||||||
|  |     ], | ||||||
|  |     arguments: [ | ||||||
|  |       { | ||||||
|  |         regex: /^\s*#.*$/, | ||||||
|  |         sol: true, | ||||||
|  |         token: "comment" | ||||||
|  |       }, | ||||||
|  |       { | ||||||
|  |         regex: /"(?:[^\\"]|\\.)*"?$/, | ||||||
|  |         token: "string", | ||||||
|  |         next: "start" | ||||||
|  |       }, | ||||||
|  |       { | ||||||
|  |         regex: /"/, | ||||||
|  |         token: "string", | ||||||
|  |         push: "double" | ||||||
|  |       }, | ||||||
|  |       { | ||||||
|  |         regex: /'(?:[^\\']|\\.)*'?$/, | ||||||
|  |         token: "string", | ||||||
|  |         next: "start" | ||||||
|  |       }, | ||||||
|  |       { | ||||||
|  |         regex: /'/, | ||||||
|  |         token: "string", | ||||||
|  |         push: "single" | ||||||
|  |       }, | ||||||
|  |       { | ||||||
|  |         regex: /[^#"']+[\\`]$/, | ||||||
|  |         token: null | ||||||
|  |       }, | ||||||
|  |       { | ||||||
|  |         regex: /[^#"']+$/, | ||||||
|  |         token: null, | ||||||
|  |         next: "start" | ||||||
|  |       }, | ||||||
|  |       { | ||||||
|  |         regex: /[^#"']+/, | ||||||
|  |         token: null | ||||||
|  |       }, | ||||||
|  |       // Fail safe return to start
 | ||||||
|  |       { | ||||||
|  |         token: null, | ||||||
|  |         next: "start" | ||||||
|  |       } | ||||||
|  |     ], | ||||||
|  |     meta: { | ||||||
|  |       lineComment: "#" | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   CodeMirror.defineMIME("text/x-dockerfile", "dockerfile"); | ||||||
|  | }); | ||||||
|  | @ -0,0 +1,216 @@ | ||||||
|  | // CodeMirror, copyright (c) by Marijn Haverbeke and others
 | ||||||
|  | // Distributed under an MIT license: https://codemirror.net/LICENSE
 | ||||||
|  | 
 | ||||||
|  | (function(mod) { | ||||||
|  |   if (typeof exports == "object" && typeof module == "object") // CommonJS
 | ||||||
|  |     mod(require("../../lib/codemirror")); | ||||||
|  |   else if (typeof define == "function" && define.amd) // AMD
 | ||||||
|  |     define(["../../lib/codemirror"], mod); | ||||||
|  |   else // Plain browser env
 | ||||||
|  |     mod(CodeMirror); | ||||||
|  | })(function(CodeMirror) { | ||||||
|  |   "use strict"; | ||||||
|  | 
 | ||||||
|  |   CodeMirror.defineSimpleMode = function(name, states) { | ||||||
|  |     CodeMirror.defineMode(name, function(config) { | ||||||
|  |       return CodeMirror.simpleMode(config, states); | ||||||
|  |     }); | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   CodeMirror.simpleMode = function(config, states) { | ||||||
|  |     ensureState(states, "start"); | ||||||
|  |     var states_ = {}, meta = states.meta || {}, hasIndentation = false; | ||||||
|  |     for (var state in states) if (state != meta && states.hasOwnProperty(state)) { | ||||||
|  |       var list = states_[state] = [], orig = states[state]; | ||||||
|  |       for (var i = 0; i < orig.length; i++) { | ||||||
|  |         var data = orig[i]; | ||||||
|  |         list.push(new Rule(data, states)); | ||||||
|  |         if (data.indent || data.dedent) hasIndentation = true; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     var mode = { | ||||||
|  |       startState: function() { | ||||||
|  |         return {state: "start", pending: null, | ||||||
|  |                 local: null, localState: null, | ||||||
|  |                 indent: hasIndentation ? [] : null}; | ||||||
|  |       }, | ||||||
|  |       copyState: function(state) { | ||||||
|  |         var s = {state: state.state, pending: state.pending, | ||||||
|  |                  local: state.local, localState: null, | ||||||
|  |                  indent: state.indent && state.indent.slice(0)}; | ||||||
|  |         if (state.localState) | ||||||
|  |           s.localState = CodeMirror.copyState(state.local.mode, state.localState); | ||||||
|  |         if (state.stack) | ||||||
|  |           s.stack = state.stack.slice(0); | ||||||
|  |         for (var pers = state.persistentStates; pers; pers = pers.next) | ||||||
|  |           s.persistentStates = {mode: pers.mode, | ||||||
|  |                                 spec: pers.spec, | ||||||
|  |                                 state: pers.state == state.localState ? s.localState : CodeMirror.copyState(pers.mode, pers.state), | ||||||
|  |                                 next: s.persistentStates}; | ||||||
|  |         return s; | ||||||
|  |       }, | ||||||
|  |       token: tokenFunction(states_, config), | ||||||
|  |       innerMode: function(state) { return state.local && {mode: state.local.mode, state: state.localState}; }, | ||||||
|  |       indent: indentFunction(states_, meta) | ||||||
|  |     }; | ||||||
|  |     if (meta) for (var prop in meta) if (meta.hasOwnProperty(prop)) | ||||||
|  |       mode[prop] = meta[prop]; | ||||||
|  |     return mode; | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   function ensureState(states, name) { | ||||||
|  |     if (!states.hasOwnProperty(name)) | ||||||
|  |       throw new Error("Undefined state " + name + " in simple mode"); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   function toRegex(val, caret) { | ||||||
|  |     if (!val) return /(?:)/; | ||||||
|  |     var flags = ""; | ||||||
|  |     if (val instanceof RegExp) { | ||||||
|  |       if (val.ignoreCase) flags = "i"; | ||||||
|  |       val = val.source; | ||||||
|  |     } else { | ||||||
|  |       val = String(val); | ||||||
|  |     } | ||||||
|  |     return new RegExp((caret === false ? "" : "^") + "(?:" + val + ")", flags); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   function asToken(val) { | ||||||
|  |     if (!val) return null; | ||||||
|  |     if (val.apply) return val | ||||||
|  |     if (typeof val == "string") return val.replace(/\./g, " "); | ||||||
|  |     var result = []; | ||||||
|  |     for (var i = 0; i < val.length; i++) | ||||||
|  |       result.push(val[i] && val[i].replace(/\./g, " ")); | ||||||
|  |     return result; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   function Rule(data, states) { | ||||||
|  |     if (data.next || data.push) ensureState(states, data.next || data.push); | ||||||
|  |     this.regex = toRegex(data.regex); | ||||||
|  |     this.token = asToken(data.token); | ||||||
|  |     this.data = data; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   function tokenFunction(states, config) { | ||||||
|  |     return function(stream, state) { | ||||||
|  |       if (state.pending) { | ||||||
|  |         var pend = state.pending.shift(); | ||||||
|  |         if (state.pending.length == 0) state.pending = null; | ||||||
|  |         stream.pos += pend.text.length; | ||||||
|  |         return pend.token; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       if (state.local) { | ||||||
|  |         if (state.local.end && stream.match(state.local.end)) { | ||||||
|  |           var tok = state.local.endToken || null; | ||||||
|  |           state.local = state.localState = null; | ||||||
|  |           return tok; | ||||||
|  |         } else { | ||||||
|  |           var tok = state.local.mode.token(stream, state.localState), m; | ||||||
|  |           if (state.local.endScan && (m = state.local.endScan.exec(stream.current()))) | ||||||
|  |             stream.pos = stream.start + m.index; | ||||||
|  |           return tok; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       var curState = states[state.state]; | ||||||
|  |       for (var i = 0; i < curState.length; i++) { | ||||||
|  |         var rule = curState[i]; | ||||||
|  |         var matches = (!rule.data.sol || stream.sol()) && stream.match(rule.regex); | ||||||
|  |         if (matches) { | ||||||
|  |           if (rule.data.next) { | ||||||
|  |             state.state = rule.data.next; | ||||||
|  |           } else if (rule.data.push) { | ||||||
|  |             (state.stack || (state.stack = [])).push(state.state); | ||||||
|  |             state.state = rule.data.push; | ||||||
|  |           } else if (rule.data.pop && state.stack && state.stack.length) { | ||||||
|  |             state.state = state.stack.pop(); | ||||||
|  |           } | ||||||
|  | 
 | ||||||
|  |           if (rule.data.mode) | ||||||
|  |             enterLocalMode(config, state, rule.data.mode, rule.token); | ||||||
|  |           if (rule.data.indent) | ||||||
|  |             state.indent.push(stream.indentation() + config.indentUnit); | ||||||
|  |           if (rule.data.dedent) | ||||||
|  |             state.indent.pop(); | ||||||
|  |           var token = rule.token | ||||||
|  |           if (token && token.apply) token = token(matches) | ||||||
|  |           if (matches.length > 2 && rule.token && typeof rule.token != "string") { | ||||||
|  |             state.pending = []; | ||||||
|  |             for (var j = 2; j < matches.length; j++) | ||||||
|  |               if (matches[j]) | ||||||
|  |                 state.pending.push({text: matches[j], token: rule.token[j - 1]}); | ||||||
|  |             stream.backUp(matches[0].length - (matches[1] ? matches[1].length : 0)); | ||||||
|  |             return token[0]; | ||||||
|  |           } else if (token && token.join) { | ||||||
|  |             return token[0]; | ||||||
|  |           } else { | ||||||
|  |             return token; | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |       stream.next(); | ||||||
|  |       return null; | ||||||
|  |     }; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   function cmp(a, b) { | ||||||
|  |     if (a === b) return true; | ||||||
|  |     if (!a || typeof a != "object" || !b || typeof b != "object") return false; | ||||||
|  |     var props = 0; | ||||||
|  |     for (var prop in a) if (a.hasOwnProperty(prop)) { | ||||||
|  |       if (!b.hasOwnProperty(prop) || !cmp(a[prop], b[prop])) return false; | ||||||
|  |       props++; | ||||||
|  |     } | ||||||
|  |     for (var prop in b) if (b.hasOwnProperty(prop)) props--; | ||||||
|  |     return props == 0; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   function enterLocalMode(config, state, spec, token) { | ||||||
|  |     var pers; | ||||||
|  |     if (spec.persistent) for (var p = state.persistentStates; p && !pers; p = p.next) | ||||||
|  |       if (spec.spec ? cmp(spec.spec, p.spec) : spec.mode == p.mode) pers = p; | ||||||
|  |     var mode = pers ? pers.mode : spec.mode || CodeMirror.getMode(config, spec.spec); | ||||||
|  |     var lState = pers ? pers.state : CodeMirror.startState(mode); | ||||||
|  |     if (spec.persistent && !pers) | ||||||
|  |       state.persistentStates = {mode: mode, spec: spec.spec, state: lState, next: state.persistentStates}; | ||||||
|  | 
 | ||||||
|  |     state.localState = lState; | ||||||
|  |     state.local = {mode: mode, | ||||||
|  |                    end: spec.end && toRegex(spec.end), | ||||||
|  |                    endScan: spec.end && spec.forceEnd !== false && toRegex(spec.end, false), | ||||||
|  |                    endToken: token && token.join ? token[token.length - 1] : token}; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   function indexOf(val, arr) { | ||||||
|  |     for (var i = 0; i < arr.length; i++) if (arr[i] === val) return true; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   function indentFunction(states, meta) { | ||||||
|  |     return function(state, textAfter, line) { | ||||||
|  |       if (state.local && state.local.mode.indent) | ||||||
|  |         return state.local.mode.indent(state.localState, textAfter, line); | ||||||
|  |       if (state.indent == null || state.local || meta.dontIndentStates && indexOf(state.state, meta.dontIndentStates) > -1) | ||||||
|  |         return CodeMirror.Pass; | ||||||
|  | 
 | ||||||
|  |       var pos = state.indent.length - 1, rules = states[state.state]; | ||||||
|  |       scan: for (;;) { | ||||||
|  |         for (var i = 0; i < rules.length; i++) { | ||||||
|  |           var rule = rules[i]; | ||||||
|  |           if (rule.data.dedent && rule.data.dedentIfLineStart !== false) { | ||||||
|  |             var m = rule.regex.exec(textAfter); | ||||||
|  |             if (m && m[0]) { | ||||||
|  |               pos--; | ||||||
|  |               if (rule.next || rule.push) rules = states[rule.next || rule.push]; | ||||||
|  |               textAfter = textAfter.slice(m[0].length); | ||||||
|  |               continue scan; | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |         break; | ||||||
|  |       } | ||||||
|  |       return pos < 0 ? 0 : state.indent[pos]; | ||||||
|  |     }; | ||||||
|  |   } | ||||||
|  | }); | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -108,9 +108,18 @@ | ||||||
|     [:title title] |     [:title title] | ||||||
|     [:link {:href "https://fonts.googleapis.com/css?family=Open+Sans:300,400,700" |     [:link {:href "https://fonts.googleapis.com/css?family=Open+Sans:300,400,700" | ||||||
|             :rel "stylesheet"}] |             :rel "stylesheet"}] | ||||||
|  | 
 | ||||||
|  |     ;; non-invasive js for syntax highlight of text-area | ||||||
|  |     (page/include-js  "/static/js/codemirror.js") | ||||||
|  |     (page/include-js  "/static/js/codemirror-simple.js") | ||||||
|  |     (page/include-js  "/static/js/codemirror-dockerfile.js") | ||||||
|  | 
 | ||||||
|     ;; cascade style sheets |     ;; cascade style sheets | ||||||
|     (page/include-css "/static/css/bulma.min.css") |     (page/include-css "/static/css/bulma.min.css") | ||||||
|     (page/include-css "/static/css/json-html.css") |     (page/include-css "/static/css/json-html.css") | ||||||
|  |     (page/include-css "/static/css/codemirror.css") | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|     ;;    (page/include-css "/static/css/fa-regular.min.css") |     ;;    (page/include-css "/static/css/fa-regular.min.css") | ||||||
|     ;;    (page/include-css "/static/css/fontawesome.min.css") |     ;;    (page/include-css "/static/css/fontawesome.min.css") | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -98,11 +98,6 @@ | ||||||
|                             (views/dashboard acct)])) |                             (views/dashboard acct)])) | ||||||
|              (auth-wrap request))) |              (auth-wrap request))) | ||||||
| 
 | 
 | ||||||
|   ;; (GET "/list" request |  | ||||||
|   ;;      (->> (fn [req conf acct] |  | ||||||
|   ;;             (web/render acct (views/list-jobs acct))) |  | ||||||
|   ;;           (auth-wrap request))) |  | ||||||
| 
 |  | ||||||
|   (POST "/remove" request |   (POST "/remove" request | ||||||
|         (->> (fn [req conf acct] |         (->> (fn [req conf acct] | ||||||
|                (web/render acct [:body |                (web/render acct [:body | ||||||
|  |  | ||||||
|  | @ -152,6 +152,8 @@ | ||||||
|     dockerfile (-> jobfound :dockerfile)] |     dockerfile (-> jobfound :dockerfile)] | ||||||
|    [:div {:class "box"} |    [:div {:class "box"} | ||||||
|     [:h1 {:class "title"} (str "Viewing job: " jobid)] |     [:h1 {:class "title"} (str "Viewing job: " jobid)] | ||||||
|     [:pre dockerfile]] |     [:form [:textarea {:id "code" :name "code" } dockerfile]] | ||||||
|    (f/when-failed [e] |     [:script "var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), | ||||||
|      (web/notify (str "Failure viewing job: " (f/message e)) "is-error")))) |         { lineNumbers: true, mode: \"dockerfile\" });"]] | ||||||
|  |      (f/when-failed [e] | ||||||
|  |        (web/notify (str "Failure viewing job: " (f/message e)) "is-error")))) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue