puppet-validator 0.0.9 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -8,11 +8,16 @@ function toggleMenu() {
8
8
  $('#checks-menu').slideToggle();
9
9
  }
10
10
 
11
+ function loadPaste() {
12
+ var location = $('#location').val();
13
+ window.location = "/load/"+location;
14
+ }
15
+
11
16
  function gist() {
12
- var code = $('#code').text();
17
+ var code = $('#code').val();
13
18
  if (typeof(code) == 'string' && $.trim(code).length != 0) {
14
19
  var data = {
15
- "description": "Validated by puppetlinter.com",
20
+ "description": "Validated by " + window.location.origin + '/load/referer',
16
21
  "public": true,
17
22
  "files": {
18
23
  "init.pp": {
@@ -28,71 +33,234 @@ function gist() {
28
33
  })
29
34
  .success(function(response) {
30
35
  console.log(response);
31
- popup(null, 'Gist posted to:', response['html_url']);
36
+ popup(null, { text: 'Gist posted to:', url: response['html_url'] } );
32
37
  })
33
38
  .error(function(error) {
34
39
  console.warn("Cannot save gist: ", error);
35
- popup('Gist save failed.', error);
40
+ popup('Gist save failed.', { text: error });
36
41
  });
37
42
  }
38
43
  }
39
44
 
40
- function popup(title, text, url) {
45
+ function popup(title, options) {
41
46
  var dialog = $('<div id="popup" />');
42
- $(dialog).append( $("<p/>").text(text) );
43
-
44
- if(url) {
45
- $(dialog).append( '<ul><li id="url"></li></ul>' )
46
- $(dialog).find('li#url').append( $("<a />", { href: url, text: url }) );
47
- }
48
-
49
- $(dialog).dialog({
47
+ var params = {
50
48
  modal: true,
51
49
  title: title,
52
- width: 425,
53
50
  buttons: {
54
51
  Ok: function () {
55
52
  $(this).dialog("close");
56
53
  $("#popup").remove();
57
54
  }
58
55
  }
56
+ };
57
+
58
+ if (typeof options === 'object') {
59
+ if('html' in options) {
60
+ dialog.append( $(options.html) );
61
+ }
62
+ if('text' in options) {
63
+ dialog.append( $("<p/>").text(options.text) );
64
+ }
65
+ if('url' in options) {
66
+ dialog.append( '<ul><li id="url"></li></ul>' )
67
+ dialog.find('li#url').append( $("<a />", { href: options.url, text: options.url }) );
68
+ }
69
+
70
+ if('height' in options) {
71
+ params.height = options.height;
72
+ }
73
+ if('width' in options) {
74
+ params.width = options.width;
75
+ }
76
+ }
77
+
78
+ $(dialog).dialog(params);
79
+ }
80
+
81
+ function showRelationships() {
82
+ if(typeof editor != 'undefined' ) { editor.save(); }
83
+
84
+ $('#relationships').prop("disabled",true);
85
+ $('html,body').css('cursor','wait');
86
+
87
+ $.post('/api/v0/validate/relationships', {code: $('#code').val()}, function(data) {
88
+ popup('Resource Relationships', {
89
+ html: '<center>'+data+'</center>',
90
+ width: $(window).width() * .8,
91
+ height: $(window).height() * .8
92
+ });
93
+
94
+ }).fail(function(jqXHR) {
95
+ alert("Unknown API error:\n" + jqXHR.responseText);
96
+
97
+ }).always(function() {
98
+ $('html,body').css('cursor','default');
99
+ $('#relationships').prop("disabled",false);
59
100
  });
60
101
  }
61
102
 
103
+ function puppet_validator(cm, updateLinting, options) {
104
+ if(typeof editor == 'undefined' ) { return null; }
105
+
106
+ // propogates text to the textarea
107
+ editor.save();
108
+
109
+ var output = $('#results');
110
+ var spinner = $('#spinner');
111
+ var message = $('#message');
112
+ var version = $('#version');
113
+ var wrapper = $('form');
114
+ var params = {
115
+ code: $('#code').val(),
116
+ version: $('#versions').val(),
117
+ };
118
+
119
+ if( $('input#lint').is(':checked') ) {
120
+ params['lint'] = true;
121
+ params['checks'] = $('#checks input:checked').map(function() { return this.value; }).get();
122
+ }
123
+
124
+ message.empty();
125
+ spinner.show();
126
+ output.removeClass('hidden');
127
+ output.removeClass('validated');
128
+ $('#validate').prop("disabled",true);
129
+
130
+ var errors = [];
131
+ $.post('/api/v0/validate', params, function(data) {
132
+ console.log(data);
133
+ var results = jQuery.parseJSON(data);
134
+
135
+ spinner.hide();
136
+ message.text(results['message']);
137
+ version.text(results['version']);
138
+ wrapper.addClass('validated');
139
+ output.addClass('validated');
140
+
141
+ if(results.success) {
142
+ wrapper.removeClass('failed');
143
+ output.removeClass('failed');
144
+ $('#share').show();
145
+ }
146
+ else {
147
+ wrapper.addClass('failed');
148
+ output.addClass('failed');
149
+ $('#share').hide();
150
+
151
+ if('line' in results) {
152
+ var min = Math.max(results['line'] - 3, 0);
153
+ var max = Math.min(results['line'] + 3, editor.lineCount());
154
+ editor.scrollIntoView(min, max);
155
+ }
156
+ }
157
+
158
+ if ('messages' in results) {
159
+ var messages = results['messages'];
160
+ for ( var i = 0; i < messages.length; i++) {
161
+ var item = messages[i];
162
+ errors.push({
163
+ from: CodeMirror.Pos(item.from[0], item.from[1]),
164
+ to: CodeMirror.Pos(item.to[0], item.to[1] ),
165
+ message: item.message,
166
+ severity: item.severity
167
+ });
168
+ }
169
+ updateLinting(errors);
170
+ }
171
+ }).fail(function(jqXHR) {
172
+ alert("Unknown API error:\n" + jqXHR.responseText);
173
+ }).always(function() {
174
+ spinner.hide();
175
+ $('#validate').prop("disabled",false);
176
+ });
177
+ }
178
+
179
+
62
180
  $( document ).ready(function() {
63
181
  toggleChecks();
182
+ $('#checks-menu').hide();
64
183
 
65
- $("textarea#code").keydown(function(e) {
66
- if(e.keyCode === 9) { // tab was pressed
67
- // get caret position/selection
68
- var start = this.selectionStart;
69
- var end = this.selectionEnd;
184
+ $("input#load").on('click', function(event){
185
+ event.preventDefault();
186
+ loadPaste();
187
+ });
70
188
 
71
- var $this = $(this);
72
- var value = $this.val();
189
+ $("input#relationships").on('click', function(event){
190
+ event.preventDefault();
191
+ showRelationships();
192
+ });
73
193
 
74
- // set textarea value to: text before caret + tab + text after caret
75
- $this.val(value.substring(0, start)
76
- + "\t"
77
- + value.substring(end));
194
+ // don't fail if the theme doesn't load codemirror
195
+ if(typeof CodeMirror != 'undefined') {
196
+ var textbox = $("textarea#code")[0]
197
+ editor = CodeMirror.fromTextArea(textbox, {
198
+ lineNumbers: true,
199
+ smartIndent: true,
200
+ indentWithTabs: true,
201
+ styleActiveLine: true,
202
+ mode: 'puppet',
203
+ gutters: ["CodeMirror-lint-markers"],
204
+ lint: {
205
+ getAnnotations: puppet_validator,
206
+ lintOnChange: false,
207
+ async: true
208
+ },
209
+ });
78
210
 
79
- // put caret at right position again (add one for the tab)
80
- this.selectionStart = this.selectionEnd = start + 1;
211
+ // this is slow as crap. There must be a faster way.
212
+ editor.on("renderLine", function(cm, lineHandle, element) {
213
+ if(element.querySelector('.CodeMirror-lint-mark-error')) {
214
+ //cm.getDoc().addLineClass(lineHandle, 'wrap', 'CodeMirror-lint-mark-error');
215
+ element.classList.add('CodeMirror-lint-mark-error');
216
+ }
81
217
 
82
- // prevent the loss of focus
83
- e.preventDefault();
218
+ if(element.querySelector('.CodeMirror-lint-mark-warning')) {
219
+ //cm.getDoc().addLineClass(lineHandle, 'wrap', 'CodeMirror-lint-mark-warning');
220
+ element.classList.add('CodeMirror-lint-mark-warning');
84
221
  }
85
- });
222
+ });
86
223
 
87
- if ($('select#versions option').length == 1) {
88
- $('select#versions').attr('disabled', true);
224
+ // indent with spaces to match style guide
225
+ editor.setOption("extraKeys", {
226
+ Tab: function(cm) {
227
+ var spaces = Array(cm.getOption("indentUnit") + 1).join(" ");
228
+ cm.replaceSelection(spaces);
229
+ }
230
+ });
231
+
232
+ $("input#validate").on('click', function(event){
233
+ event.preventDefault();
234
+ editor.performLint();
235
+ });
89
236
  }
90
237
  else {
91
- $('select#versions').change(function() {
92
- var action = ('/' + $( this ).val() + '/validate').replace(/^\/+/, '/');
93
- $('form').attr('action', action );
238
+ $("textarea#code").keydown(function(e) {
239
+ if(e.keyCode === 9) { // tab was pressed
240
+ // get caret position/selection
241
+ var start = this.selectionStart;
242
+ var end = this.selectionEnd;
243
+
244
+ var $this = $(this);
245
+ var value = $this.val();
246
+
247
+ // set textarea value to: text before caret + tab + text after caret
248
+ $this.val(value.substring(0, start)
249
+ + "\t"
250
+ + value.substring(end));
251
+
252
+ // put caret at right position again (add one for the tab)
253
+ this.selectionStart = this.selectionEnd = start + 1;
254
+
255
+ // prevent the loss of focus
256
+ e.preventDefault();
257
+ }
94
258
  });
95
259
  }
96
260
 
261
+ if ($('select#versions option').length == 1) {
262
+ $('select#versions').attr('disabled', true);
263
+ }
264
+
97
265
  $('.share_icon').tooltip();
98
266
  });
@@ -3,51 +3,47 @@ body {
3
3
  padding: 0 2em;
4
4
  }
5
5
 
6
- /* keeps the tooltip from clipping to the pre */
7
- pre[class*="language-"] {
8
- overflow: visible;
9
- }
10
- div.line-highlight {
11
- /* Cannot use opacity, because that affects tooltip children as well */
12
- background-color: rgba(255, 181, 181, 0.25);
13
- color: black;
14
- font-weight: bold;
15
- }
16
- div.line-highlight.with-tooltip {
17
- background-color: rgba(255, 255, 0, 0.25);
18
- pointer-events: auto;
19
- }
20
- div.line-highlight.with-tooltip .marker {
21
- width: 0px;
22
- height: 0px;
23
- border-top: 0.5em solid #000;
24
- border-left: 0.5em solid transparent;
25
- position: absolute;
26
- top: 0;
27
- right: 0;
28
- }
29
- div.line-highlight.with-tooltip .line-highlight-tooltip {
30
- position: absolute;
31
- top: -1.75em;
32
- right: 0;
33
- background-color: #aaccaa;
34
- border: 1px solid black;
35
- border-radius: 5px;
36
- padding: 0 3px;
37
- display: none;
6
+ /* css only line numbers for the fallback no-js results */
7
+ pre#highlighted {
8
+ counter-reset: line;
9
+ background-color: #f7f7f7;
10
+ line-height: 0;
11
+ }
12
+ pre#highlighted code {
13
+ counter-increment: line;
14
+ line-height: 1.25em;
38
15
  }
39
- div.line-highlight.with-tooltip:hover .line-highlight-tooltip {
40
- display: block;
16
+ pre#highlighted code:before {
17
+ content: counter(line);
18
+ -webkit-user-select: none;
19
+ display: inline-block;
20
+ width: 2em;
21
+ border-right: 2px solid #ccc;
22
+ text-align: right ;
23
+ padding-right: 0.5em;
24
+ margin-right: 0.5em;
41
25
  }
42
26
 
27
+ #location {
28
+ width: 60%;
29
+ }
30
+
43
31
  .results,
44
32
  .warning {
45
33
  width: 65%;
34
+ min-height: 3.5em;
46
35
  border: 1px solid black;
47
36
  border-radius: 0.25em;
48
37
  padding: 0.5em;
49
- margin: 0 auto;
38
+ margin: 1em auto;
39
+ background-color: #fcfcfc;
40
+ transition: opacity 1s, background-color 1s, border: 1s;
50
41
  }
42
+
43
+ .results.hidden {
44
+ opacity: 0;
45
+ }
46
+
51
47
  .results legend {
52
48
  text-align: right;
53
49
  padding: 3px;
@@ -55,19 +51,21 @@ div.line-highlight.with-tooltip {
55
51
  border: 1px solid #ccc;
56
52
  border-radius: 3px;
57
53
  }
58
- .results.success {
59
- background-color: #61ff6e;
54
+ .results.validated {
55
+ border: 2px solid #1dd12d;
60
56
  }
61
- .results.fail {
62
- background-color: #ffb6b6;
57
+ .results.validated.failed {
58
+ border: 2px solid #981818;
63
59
  }
64
60
 
65
61
  .results p {
66
- margin: 0;
62
+ margin: 0 3em 0 0;
67
63
  }
68
64
  .results img.share_icon {
65
+ display: none;
69
66
  float: right;
70
67
  cursor: pointer;
68
+ height: 2em;
71
69
  }
72
70
  .results hr {
73
71
  clear: both;
@@ -104,7 +102,21 @@ div.links {
104
102
  div.entry {
105
103
  width: 80%;
106
104
  margin: 0 auto;
105
+ border: 1px solid #ccc;
106
+ padding: 0.5em;
107
+ border-radius: 0.5em;
108
+ background-color: #f7f7f7;
107
109
  }
110
+
111
+ form.validated div.entry {
112
+ background-color: #f1ffe8;
113
+ border: 1px solid #1dd12d;
114
+ }
115
+ form.validated.failed div.entry {
116
+ background-color: #ffd4d4;
117
+ border: 1px solid #981818;
118
+ }
119
+
108
120
  div.entry textarea {
109
121
  width: 100%;
110
122
  font-family: monospace;
@@ -113,6 +125,13 @@ div.row {
113
125
  text-align: center;
114
126
  }
115
127
 
128
+ .CodeMirror-line.CodeMirror-lint-mark-warning {
129
+ background-color: #fff9d2;
130
+ }
131
+ .CodeMirror-line.CodeMirror-lint-mark-error {
132
+ background-color: #ffefed;
133
+ }
134
+
116
135
  input#validate,
117
136
  select#versions,
118
137
  a#customize {
@@ -123,7 +142,7 @@ a.button {
123
142
  font-size: small;
124
143
  background-color: #fff;
125
144
  padding: 0 2px;
126
- border: 1px solid #fff;
145
+ border: 1px solid #ccc;
127
146
  border-radius: 3px;
128
147
  text-decoration: none;
129
148
  }
@@ -132,23 +151,31 @@ a.button:hover {
132
151
  border-color: #bbb;
133
152
  }
134
153
  fieldset.menu {
135
- display: none;
136
154
  border-radius: 0.5em;
155
+ background-color: #fff;
137
156
  }
138
- fieldset.menu ul {
139
- list-style-type: none;
140
- padding: 0;
141
- margin: 0;
142
- -moz-column-count: 2;
143
- -moz-column-gap: 20px;
144
- -webkit-column-count: 2;
145
- -webkit-column-gap: 20px;
146
- column-count: 2;
147
- column-gap: 20px;
148
- }
157
+ fieldset.menu legend {
158
+ background-color: #ffffff;
159
+ border-top: 1px solid #ccc;
160
+ border-left: 1px solid #ccc;
161
+ border-right: 1px solid #ccc;
162
+ border-radius: 3px 3px 0 0;
163
+ }
164
+
165
+ fieldset.menu ul {
166
+ list-style-type: none;
167
+ padding: 0;
168
+ margin: 0;
169
+ -moz-column-count: 2;
170
+ -moz-column-gap: 20px;
171
+ -webkit-column-count: 2;
172
+ -webkit-column-gap: 20px;
173
+ column-count: 2;
174
+ column-gap: 20px;
175
+ }
149
176
 
150
177
  .info {
151
- background: #fefefe url('info.png') no-repeat 5px 5px !important;
178
+ background: #fefefe;
152
179
  border: 1px solid #efefef;
153
180
  padding: 0.5em;
154
181
  padding-left: 50px;
@@ -159,6 +186,10 @@ fieldset.menu ul {
159
186
  -khtml-border-radius: 0.5em;
160
187
  border-radius: 0.5em;
161
188
  }
189
+ .info i.fa {
190
+ float: left;
191
+ margin-left: -45px;
192
+ }
162
193
 
163
194
  /* jquery UI overrides */
164
195
  .ui-widget {