LaravelTest

Форк
0
459 строк · 11.3 Кб
1
// CodeMirror, copyright (c) by Marijn Haverbeke and others
2
// Distributed under an MIT license: https://codemirror.net/LICENSE
3

4
(function(mod) {
5
  if (typeof exports == "object" && typeof module == "object") // CommonJS
6
    mod(require("../../lib/codemirror"), require("../css/css"));
7
  else if (typeof define == "function" && define.amd) // AMD
8
    define(["../../lib/codemirror", "../css/css"], mod);
9
  else // Plain browser env
10
    mod(CodeMirror);
11
})(function(CodeMirror) {
12
"use strict";
13

14
CodeMirror.defineMode("sass", function(config) {
15
  var cssMode = CodeMirror.mimeModes["text/css"];
16
  var propertyKeywords = cssMode.propertyKeywords || {},
17
      colorKeywords = cssMode.colorKeywords || {},
18
      valueKeywords = cssMode.valueKeywords || {},
19
      fontProperties = cssMode.fontProperties || {};
20

21
  function tokenRegexp(words) {
22
    return new RegExp("^" + words.join("|"));
23
  }
24

25
  var keywords = ["true", "false", "null", "auto"];
26
  var keywordsRegexp = new RegExp("^" + keywords.join("|"));
27

28
  var operators = ["\\(", "\\)", "=", ">", "<", "==", ">=", "<=", "\\+", "-",
29
                   "\\!=", "/", "\\*", "%", "and", "or", "not", ";","\\{","\\}",":"];
30
  var opRegexp = tokenRegexp(operators);
31

32
  var pseudoElementsRegexp = /^::?[a-zA-Z_][\w\-]*/;
33

34
  var word;
35

36
  function isEndLine(stream) {
37
    return !stream.peek() || stream.match(/\s+$/, false);
38
  }
39

40
  function urlTokens(stream, state) {
41
    var ch = stream.peek();
42

43
    if (ch === ")") {
44
      stream.next();
45
      state.tokenizer = tokenBase;
46
      return "operator";
47
    } else if (ch === "(") {
48
      stream.next();
49
      stream.eatSpace();
50

51
      return "operator";
52
    } else if (ch === "'" || ch === '"') {
53
      state.tokenizer = buildStringTokenizer(stream.next());
54
      return "string";
55
    } else {
56
      state.tokenizer = buildStringTokenizer(")", false);
57
      return "string";
58
    }
59
  }
60
  function comment(indentation, multiLine) {
61
    return function(stream, state) {
62
      if (stream.sol() && stream.indentation() <= indentation) {
63
        state.tokenizer = tokenBase;
64
        return tokenBase(stream, state);
65
      }
66

67
      if (multiLine && stream.skipTo("*/")) {
68
        stream.next();
69
        stream.next();
70
        state.tokenizer = tokenBase;
71
      } else {
72
        stream.skipToEnd();
73
      }
74

75
      return "comment";
76
    };
77
  }
78

79
  function buildStringTokenizer(quote, greedy) {
80
    if (greedy == null) { greedy = true; }
81

82
    function stringTokenizer(stream, state) {
83
      var nextChar = stream.next();
84
      var peekChar = stream.peek();
85
      var previousChar = stream.string.charAt(stream.pos-2);
86

87
      var endingString = ((nextChar !== "\\" && peekChar === quote) || (nextChar === quote && previousChar !== "\\"));
88

89
      if (endingString) {
90
        if (nextChar !== quote && greedy) { stream.next(); }
91
        if (isEndLine(stream)) {
92
          state.cursorHalf = 0;
93
        }
94
        state.tokenizer = tokenBase;
95
        return "string";
96
      } else if (nextChar === "#" && peekChar === "{") {
97
        state.tokenizer = buildInterpolationTokenizer(stringTokenizer);
98
        stream.next();
99
        return "operator";
100
      } else {
101
        return "string";
102
      }
103
    }
104

105
    return stringTokenizer;
106
  }
107

108
  function buildInterpolationTokenizer(currentTokenizer) {
109
    return function(stream, state) {
110
      if (stream.peek() === "}") {
111
        stream.next();
112
        state.tokenizer = currentTokenizer;
113
        return "operator";
114
      } else {
115
        return tokenBase(stream, state);
116
      }
117
    };
118
  }
119

120
  function indent(state) {
121
    if (state.indentCount == 0) {
122
      state.indentCount++;
123
      var lastScopeOffset = state.scopes[0].offset;
124
      var currentOffset = lastScopeOffset + config.indentUnit;
125
      state.scopes.unshift({ offset:currentOffset });
126
    }
127
  }
128

129
  function dedent(state) {
130
    if (state.scopes.length == 1) return;
131

132
    state.scopes.shift();
133
  }
134

135
  function tokenBase(stream, state) {
136
    var ch = stream.peek();
137

138
    // Comment
139
    if (stream.match("/*")) {
140
      state.tokenizer = comment(stream.indentation(), true);
141
      return state.tokenizer(stream, state);
142
    }
143
    if (stream.match("//")) {
144
      state.tokenizer = comment(stream.indentation(), false);
145
      return state.tokenizer(stream, state);
146
    }
147

148
    // Interpolation
149
    if (stream.match("#{")) {
150
      state.tokenizer = buildInterpolationTokenizer(tokenBase);
151
      return "operator";
152
    }
153

154
    // Strings
155
    if (ch === '"' || ch === "'") {
156
      stream.next();
157
      state.tokenizer = buildStringTokenizer(ch);
158
      return "string";
159
    }
160

161
    if(!state.cursorHalf){// state.cursorHalf === 0
162
    // first half i.e. before : for key-value pairs
163
    // including selectors
164

165
      if (ch === "-") {
166
        if (stream.match(/^-\w+-/)) {
167
          return "meta";
168
        }
169
      }
170

171
      if (ch === ".") {
172
        stream.next();
173
        if (stream.match(/^[\w-]+/)) {
174
          indent(state);
175
          return "qualifier";
176
        } else if (stream.peek() === "#") {
177
          indent(state);
178
          return "tag";
179
        }
180
      }
181

182
      if (ch === "#") {
183
        stream.next();
184
        // ID selectors
185
        if (stream.match(/^[\w-]+/)) {
186
          indent(state);
187
          return "builtin";
188
        }
189
        if (stream.peek() === "#") {
190
          indent(state);
191
          return "tag";
192
        }
193
      }
194

195
      // Variables
196
      if (ch === "$") {
197
        stream.next();
198
        stream.eatWhile(/[\w-]/);
199
        return "variable-2";
200
      }
201

202
      // Numbers
203
      if (stream.match(/^-?[0-9\.]+/))
204
        return "number";
205

206
      // Units
207
      if (stream.match(/^(px|em|in)\b/))
208
        return "unit";
209

210
      if (stream.match(keywordsRegexp))
211
        return "keyword";
212

213
      if (stream.match(/^url/) && stream.peek() === "(") {
214
        state.tokenizer = urlTokens;
215
        return "atom";
216
      }
217

218
      if (ch === "=") {
219
        // Match shortcut mixin definition
220
        if (stream.match(/^=[\w-]+/)) {
221
          indent(state);
222
          return "meta";
223
        }
224
      }
225

226
      if (ch === "+") {
227
        // Match shortcut mixin definition
228
        if (stream.match(/^\+[\w-]+/)){
229
          return "variable-3";
230
        }
231
      }
232

233
      if(ch === "@"){
234
        if(stream.match('@extend')){
235
          if(!stream.match(/\s*[\w]/))
236
            dedent(state);
237
        }
238
      }
239

240

241
      // Indent Directives
242
      if (stream.match(/^@(else if|if|media|else|for|each|while|mixin|function)/)) {
243
        indent(state);
244
        return "def";
245
      }
246

247
      // Other Directives
248
      if (ch === "@") {
249
        stream.next();
250
        stream.eatWhile(/[\w-]/);
251
        return "def";
252
      }
253

254
      if (stream.eatWhile(/[\w-]/)){
255
        if(stream.match(/ *: *[\w-\+\$#!\("']/,false)){
256
          word = stream.current().toLowerCase();
257
          var prop = state.prevProp + "-" + word;
258
          if (propertyKeywords.hasOwnProperty(prop)) {
259
            return "property";
260
          } else if (propertyKeywords.hasOwnProperty(word)) {
261
            state.prevProp = word;
262
            return "property";
263
          } else if (fontProperties.hasOwnProperty(word)) {
264
            return "property";
265
          }
266
          return "tag";
267
        }
268
        else if(stream.match(/ *:/,false)){
269
          indent(state);
270
          state.cursorHalf = 1;
271
          state.prevProp = stream.current().toLowerCase();
272
          return "property";
273
        }
274
        else if(stream.match(/ *,/,false)){
275
          return "tag";
276
        }
277
        else{
278
          indent(state);
279
          return "tag";
280
        }
281
      }
282

283
      if(ch === ":"){
284
        if (stream.match(pseudoElementsRegexp)){ // could be a pseudo-element
285
          return "variable-3";
286
        }
287
        stream.next();
288
        state.cursorHalf=1;
289
        return "operator";
290
      }
291

292
    } // cursorHalf===0 ends here
293
    else{
294

295
      if (ch === "#") {
296
        stream.next();
297
        // Hex numbers
298
        if (stream.match(/[0-9a-fA-F]{6}|[0-9a-fA-F]{3}/)){
299
          if (isEndLine(stream)) {
300
            state.cursorHalf = 0;
301
          }
302
          return "number";
303
        }
304
      }
305

306
      // Numbers
307
      if (stream.match(/^-?[0-9\.]+/)){
308
        if (isEndLine(stream)) {
309
          state.cursorHalf = 0;
310
        }
311
        return "number";
312
      }
313

314
      // Units
315
      if (stream.match(/^(px|em|in)\b/)){
316
        if (isEndLine(stream)) {
317
          state.cursorHalf = 0;
318
        }
319
        return "unit";
320
      }
321

322
      if (stream.match(keywordsRegexp)){
323
        if (isEndLine(stream)) {
324
          state.cursorHalf = 0;
325
        }
326
        return "keyword";
327
      }
328

329
      if (stream.match(/^url/) && stream.peek() === "(") {
330
        state.tokenizer = urlTokens;
331
        if (isEndLine(stream)) {
332
          state.cursorHalf = 0;
333
        }
334
        return "atom";
335
      }
336

337
      // Variables
338
      if (ch === "$") {
339
        stream.next();
340
        stream.eatWhile(/[\w-]/);
341
        if (isEndLine(stream)) {
342
          state.cursorHalf = 0;
343
        }
344
        return "variable-2";
345
      }
346

347
      // bang character for !important, !default, etc.
348
      if (ch === "!") {
349
        stream.next();
350
        state.cursorHalf = 0;
351
        return stream.match(/^[\w]+/) ? "keyword": "operator";
352
      }
353

354
      if (stream.match(opRegexp)){
355
        if (isEndLine(stream)) {
356
          state.cursorHalf = 0;
357
        }
358
        return "operator";
359
      }
360

361
      // attributes
362
      if (stream.eatWhile(/[\w-]/)) {
363
        if (isEndLine(stream)) {
364
          state.cursorHalf = 0;
365
        }
366
        word = stream.current().toLowerCase();
367
        if (valueKeywords.hasOwnProperty(word)) {
368
          return "atom";
369
        } else if (colorKeywords.hasOwnProperty(word)) {
370
          return "keyword";
371
        } else if (propertyKeywords.hasOwnProperty(word)) {
372
          state.prevProp = stream.current().toLowerCase();
373
          return "property";
374
        } else {
375
          return "tag";
376
        }
377
      }
378

379
      //stream.eatSpace();
380
      if (isEndLine(stream)) {
381
        state.cursorHalf = 0;
382
        return null;
383
      }
384

385
    } // else ends here
386

387
    if (stream.match(opRegexp))
388
      return "operator";
389

390
    // If we haven't returned by now, we move 1 character
391
    // and return an error
392
    stream.next();
393
    return null;
394
  }
395

396
  function tokenLexer(stream, state) {
397
    if (stream.sol()) state.indentCount = 0;
398
    var style = state.tokenizer(stream, state);
399
    var current = stream.current();
400

401
    if (current === "@return" || current === "}"){
402
      dedent(state);
403
    }
404

405
    if (style !== null) {
406
      var startOfToken = stream.pos - current.length;
407

408
      var withCurrentIndent = startOfToken + (config.indentUnit * state.indentCount);
409

410
      var newScopes = [];
411

412
      for (var i = 0; i < state.scopes.length; i++) {
413
        var scope = state.scopes[i];
414

415
        if (scope.offset <= withCurrentIndent)
416
          newScopes.push(scope);
417
      }
418

419
      state.scopes = newScopes;
420
    }
421

422

423
    return style;
424
  }
425

426
  return {
427
    startState: function() {
428
      return {
429
        tokenizer: tokenBase,
430
        scopes: [{offset: 0, type: "sass"}],
431
        indentCount: 0,
432
        cursorHalf: 0,  // cursor half tells us if cursor lies after (1)
433
                        // or before (0) colon (well... more or less)
434
        definedVars: [],
435
        definedMixins: []
436
      };
437
    },
438
    token: function(stream, state) {
439
      var style = tokenLexer(stream, state);
440

441
      state.lastToken = { style: style, content: stream.current() };
442

443
      return style;
444
    },
445

446
    indent: function(state) {
447
      return state.scopes[0].offset;
448
    },
449

450
    blockCommentStart: "/*",
451
    blockCommentEnd: "*/",
452
    lineComment: "//",
453
    fold: "indent"
454
  };
455
}, "css");
456

457
CodeMirror.defineMIME("text/x-sass", "sass");
458

459
});
460

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.