rouge 2.0.7 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +7 -9
  3. data/lib/rouge.rb +1 -0
  4. data/lib/rouge/cli.rb +20 -0
  5. data/lib/rouge/demos/awk +4 -0
  6. data/lib/rouge/demos/console +6 -0
  7. data/lib/rouge/demos/digdag +19 -0
  8. data/lib/rouge/demos/dot +5 -0
  9. data/lib/rouge/demos/graphql +17 -0
  10. data/lib/rouge/demos/hylang +10 -0
  11. data/lib/rouge/demos/igorpro +9 -0
  12. data/lib/rouge/demos/irb +4 -0
  13. data/lib/rouge/demos/irb_output +2 -0
  14. data/lib/rouge/demos/lasso +12 -0
  15. data/lib/rouge/demos/mosel +10 -0
  16. data/lib/rouge/demos/plist +142 -0
  17. data/lib/rouge/demos/pony +17 -0
  18. data/lib/rouge/demos/q +2 -0
  19. data/lib/rouge/demos/sieve +10 -0
  20. data/lib/rouge/demos/tsx +17 -0
  21. data/lib/rouge/demos/turtle +0 -0
  22. data/lib/rouge/demos/wollok +11 -0
  23. data/lib/rouge/formatters/html_inline.rb +9 -1
  24. data/lib/rouge/formatters/html_pygments.rb +2 -2
  25. data/lib/rouge/formatters/html_table.rb +1 -1
  26. data/lib/rouge/formatters/terminal256.rb +1 -1
  27. data/lib/rouge/lexer.rb +124 -37
  28. data/lib/rouge/lexers/abap.rb +2 -2
  29. data/lib/rouge/lexers/apache.rb +1 -1
  30. data/lib/rouge/lexers/awk.rb +161 -0
  31. data/lib/rouge/lexers/clojure.rb +2 -2
  32. data/lib/rouge/lexers/coffeescript.rb +1 -1
  33. data/lib/rouge/lexers/console.rb +136 -0
  34. data/lib/rouge/lexers/csharp.rb +26 -7
  35. data/lib/rouge/lexers/digdag.rb +72 -0
  36. data/lib/rouge/lexers/docker.rb +1 -1
  37. data/lib/rouge/lexers/dot.rb +68 -0
  38. data/lib/rouge/lexers/elixir.rb +52 -27
  39. data/lib/rouge/lexers/fortran.rb +56 -28
  40. data/lib/rouge/lexers/fsharp.rb +1 -1
  41. data/lib/rouge/lexers/gherkin/keywords.rb +4 -4
  42. data/lib/rouge/lexers/graphql.rb +243 -0
  43. data/lib/rouge/lexers/groovy.rb +5 -1
  44. data/lib/rouge/lexers/haml.rb +19 -24
  45. data/lib/rouge/lexers/html.rb +48 -4
  46. data/lib/rouge/lexers/hylang.rb +93 -0
  47. data/lib/rouge/lexers/igorpro.rb +407 -0
  48. data/lib/rouge/lexers/irb.rb +66 -0
  49. data/lib/rouge/lexers/javascript.rb +21 -10
  50. data/lib/rouge/lexers/json.rb +3 -2
  51. data/lib/rouge/lexers/json_doc.rb +6 -0
  52. data/lib/rouge/lexers/jsx.rb +2 -1
  53. data/lib/rouge/lexers/lasso.rb +217 -0
  54. data/lib/rouge/lexers/lasso/keywords.yml +446 -0
  55. data/lib/rouge/lexers/lua.rb +3 -0
  56. data/lib/rouge/lexers/lua/builtins.rb +1 -1
  57. data/lib/rouge/lexers/markdown.rb +2 -3
  58. data/lib/rouge/lexers/matlab/builtins.rb +1 -1
  59. data/lib/rouge/lexers/moonscript.rb +8 -4
  60. data/lib/rouge/lexers/mosel.rb +231 -0
  61. data/lib/rouge/lexers/ocaml.rb +9 -20
  62. data/lib/rouge/lexers/php.rb +40 -20
  63. data/lib/rouge/lexers/php/builtins.rb +27 -37
  64. data/lib/rouge/lexers/plain_text.rb +4 -3
  65. data/lib/rouge/lexers/plist.rb +49 -0
  66. data/lib/rouge/lexers/pony.rb +93 -0
  67. data/lib/rouge/lexers/powershell.rb +36 -0
  68. data/lib/rouge/lexers/properties.rb +2 -2
  69. data/lib/rouge/lexers/q.rb +124 -0
  70. data/lib/rouge/lexers/r.rb +2 -2
  71. data/lib/rouge/lexers/ruby.rb +26 -13
  72. data/lib/rouge/lexers/rust.rb +7 -5
  73. data/lib/rouge/lexers/sed.rb +4 -2
  74. data/lib/rouge/lexers/shell.rb +38 -16
  75. data/lib/rouge/lexers/sieve.rb +96 -0
  76. data/lib/rouge/lexers/sml.rb +3 -2
  77. data/lib/rouge/lexers/tsx.rb +19 -0
  78. data/lib/rouge/lexers/turtle.rb +0 -0
  79. data/lib/rouge/lexers/typescript.rb +3 -27
  80. data/lib/rouge/lexers/typescript/common.rb +33 -0
  81. data/lib/rouge/lexers/viml/keywords.rb +2 -2
  82. data/lib/rouge/lexers/wollok.rb +107 -0
  83. data/lib/rouge/lexers/xml.rb +1 -1
  84. data/lib/rouge/lexers/yaml.rb +4 -1
  85. data/lib/rouge/regex_lexer.rb +1 -0
  86. data/lib/rouge/template_lexer.rb +3 -5
  87. data/lib/rouge/theme.rb +14 -4
  88. data/lib/rouge/themes/igor_pro.rb +20 -0
  89. data/lib/rouge/themes/pastie.rb +69 -0
  90. data/lib/rouge/themes/thankful_eyes.rb +8 -5
  91. data/lib/rouge/version.rb +1 -1
  92. metadata +40 -6
  93. data/lib/rouge/demos/shell_session +0 -10
  94. data/lib/rouge/lexers/shell_session.rb +0 -29
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c642d8b27b75da850a03e347206247e0396cb3cf
4
- data.tar.gz: 94198b0ec1e78e10120292d2a909879f440fc6ec
3
+ metadata.gz: 3b6d9cbc5bd266812506988d40b94a9de6436f72
4
+ data.tar.gz: 7fb0fe3816ed4d0adcc35d780640efbbfe72d6c2
5
5
  SHA512:
6
- metadata.gz: 1d36907f61fb6045cd4c0437870f98871c855ab29d1ba4a3ebc30f5f9bb33bf270e0081ff31d7e69c7bdb0536a5bdcc959c15c8dc88249a21eac45795eebe3ce
7
- data.tar.gz: ed6572d2000df7e7ccf125634e4cfa4fd2d7487015a1c082b6b787784e710622004eb59b39b22750ef3fba8dcab1d230551344832828446676b153f315ac7c30
6
+ metadata.gz: 69735105b5246d5d1a230af6c3501ab45b275d9f988a4948034205202e9c2355e1b804566d1458e17940a4dc201332ab8f5d408d236a1f92ed76134651be5d46
7
+ data.tar.gz: 5b04ba1b449cc48ae61394bc44a83c43cffd5cf333a9af73a47b476d69fe4676096b4f6a8445ed4a1f9798d2157d9bfdcb5c2676fb615d984fab650b59a957b3
data/Gemfile CHANGED
@@ -10,14 +10,12 @@ gem 'rake'
10
10
  # don't try to install redcarpet under jruby
11
11
  gem 'redcarpet', :platforms => :ruby
12
12
 
13
- group :development do
14
- gem 'pry'
13
+ gem 'pry'
15
14
 
16
- # docs
17
- gem 'yard'
18
- gem 'github-markup'
15
+ # docs
16
+ gem 'yard'
17
+ gem 'github-markup'
19
18
 
20
- # for visual tests
21
- gem 'sinatra'
22
- gem 'shotgun'
23
- end
19
+ # for visual tests
20
+ gem 'sinatra'
21
+ gem 'shotgun'
data/lib/rouge.rb CHANGED
@@ -72,6 +72,7 @@ load load_dir.join('rouge/themes/thankful_eyes.rb')
72
72
  load load_dir.join('rouge/themes/colorful.rb')
73
73
  load load_dir.join('rouge/themes/base16.rb')
74
74
  load load_dir.join('rouge/themes/github.rb')
75
+ load load_dir.join('rouge/themes/igor_pro.rb')
75
76
  load load_dir.join('rouge/themes/monokai.rb')
76
77
  load load_dir.join('rouge/themes/molokai.rb')
77
78
  load load_dir.join('rouge/themes/monokai_sublime.rb')
data/lib/rouge/cli.rb CHANGED
@@ -169,6 +169,9 @@ module Rouge
169
169
  yield %[ If not provided, rougify will default to]
170
170
  yield %[ terminal256.]
171
171
  yield %[]
172
+ yield %[--theme|-t <theme> specify the theme to use for highlighting]
173
+ yield %[ the file. (only applies to some formatters)]
174
+ yield %[]
172
175
  yield %[--mimetype|-m <mimetype> specify a mimetype for lexer guessing]
173
176
  yield %[]
174
177
  yield %[--lexer-opts|-L <opts> specify lexer options in CGI format]
@@ -176,6 +179,9 @@ module Rouge
176
179
  yield %[]
177
180
  yield %[--formatter-opts|-F <opts> specify formatter options in CGI format]
178
181
  yield %[ (opt1=val1&opt2=val2)]
182
+ yield %[]
183
+ yield %[--require|-r <filename> require a filename or library before]
184
+ yield %[ highlighting]
179
185
  end
180
186
 
181
187
  def self.parse(argv)
@@ -186,11 +192,14 @@ module Rouge
186
192
  :input_file => '-',
187
193
  :lexer_opts => {},
188
194
  :formatter_opts => {},
195
+ :requires => [],
189
196
  }
190
197
 
191
198
  until argv.empty?
192
199
  arg = argv.shift
193
200
  case arg
201
+ when '-r', '--require'
202
+ opts[:requires] << argv.shift
194
203
  when '--input-file', '-i'
195
204
  opts[:input_file] = argv.shift
196
205
  when '--mimetype', '-m'
@@ -238,6 +247,12 @@ module Rouge
238
247
  attr_reader :input_file, :lexer_name, :mimetype, :formatter
239
248
 
240
249
  def initialize(opts={})
250
+ Rouge::Lexer.enable_debug!
251
+
252
+ opts[:requires].each do |r|
253
+ require r
254
+ end
255
+
241
256
  @input_file = opts[:input_file]
242
257
 
243
258
  if opts[:lexer]
@@ -349,6 +364,11 @@ module Rouge
349
364
  desc << " [aliases: #{lexer.aliases.join(',')}]"
350
365
  end
351
366
  puts "%s: %s" % [lexer.tag, desc]
367
+
368
+ lexer.option_docs.keys.sort.each do |option|
369
+ puts " ?#{option}= #{lexer.option_docs[option]}"
370
+ end
371
+
352
372
  puts
353
373
  end
354
374
  end
@@ -0,0 +1,4 @@
1
+ BEGIN { # Simulate echo(1)
2
+ for (i = 1; i < ARGC; i++) printf "%s ", ARGV[i]
3
+ printf "\n"
4
+ exit }
@@ -0,0 +1,6 @@
1
+ # prints "hello, world" to the screen
2
+ ~# echo Hello, World
3
+ Hello, World
4
+
5
+ # don't run this
6
+ ~# rm -rf --no-preserve-root /
@@ -0,0 +1,19 @@
1
+ # this is digdag task definitions
2
+ timezone: UTC
3
+
4
+ +setup:
5
+ echo>: start ${session_time}
6
+
7
+ +disp_current_date:
8
+ echo>: ${moment(session_time).utc().format('YYYY-MM-DD HH:mm:ss Z')}
9
+
10
+ +repeat:
11
+ for_each>:
12
+ order: [first, second, third]
13
+ animal: [dog, cat]
14
+ _do:
15
+ echo>: ${order} ${animal}
16
+ _parallel: true
17
+
18
+ +teardown:
19
+ echo>: finish ${session_time}
@@ -0,0 +1,5 @@
1
+ // The graph name and the semicolons are optional
2
+ graph G {
3
+ a -- b -- c;
4
+ b -- d;
5
+ }
@@ -0,0 +1,17 @@
1
+ query myQuery($variable: Boolean) {
2
+ # Queries can have comments!
3
+ friends(ids: ["a1", "a2"]) {
4
+ id
5
+ name
6
+
7
+ ...someFields
8
+
9
+ ... @include(if: $variable) {
10
+ foo
11
+ }
12
+
13
+ ... @skip(if: true) {
14
+ bar
15
+ }
16
+ }
17
+ }
@@ -0,0 +1,10 @@
1
+ (defn simple-conversation []
2
+ (print "Hello! I'd like to get to know you. Tell me about yourself!")
3
+ (setv name (input "What is your name? "))
4
+ (let [age (input "What is your age? ")]
5
+ (if (and age
6
+ name)
7
+ (print (+ "Hello " name "! I see you are "
8
+ age " years old.")))))
9
+
10
+ (simple-conversation)
@@ -0,0 +1,9 @@
1
+ #pragma TextEncoding = "UTF-8"
2
+ #pragma rtGlobals=3 // Use modern global access method and strict wave access.
3
+
4
+ Function/WAVE MakeWave(name)
5
+ String name
6
+
7
+ Make/N=(8,8) root:$name/WAVE=wv = p^2 + q^2
8
+ return wv
9
+ End
@@ -0,0 +1,4 @@
1
+ irb(main):001:0> puts "Hello, world!"
2
+ Hello, world!
3
+ irb(main):002:0> Object.new
4
+ => #<Object:0x0056182cb182b8>
@@ -0,0 +1,2 @@
1
+ hello world
2
+ => #<Object:0x0056182cb182b8 @foo=#<Object:0x0056182cb63100 @bar=3>>
@@ -0,0 +1,12 @@
1
+ /**!
2
+ Inserts all of the elements from #rhs into the array.
3
+ */
4
+ define array->+(rhs::trait_forEach) => {
5
+ local(a = .asCopy);
6
+ #rhs->forEach => {
7
+ #a->insert(#1)
8
+ }
9
+ return (#a)
10
+ }
11
+
12
+ define array->onCompare(n::null) => 1
@@ -0,0 +1,10 @@
1
+ (!******************************************************
2
+ Mosel Example Problems
3
+ *******************************************************!)
4
+
5
+ ! Objective function: total daily cost
6
+ Cost:= sum(p in TYPES, t in TIME) (CSTART(p)*start(p,t) +
7
+ LEN(t)*(CMIN(p)*work(p,t) + CADD(p)*padd(p,t)))
8
+
9
+ ! Limit on power production above minimum level
10
+ forall(p in TYPES, t in TIME) padd(p,t) <= (PMAX(p)-PMIN(p))*work(p,t)
@@ -0,0 +1,142 @@
1
+ // !$*UTF8*$!
2
+ {
3
+ archiveVersion = 1;
4
+ classes = {
5
+ };
6
+ objectVersion = 46;
7
+ objects = {
8
+
9
+ /* Begin PBXGroup section */
10
+ 1D67B9537FE4C81097096F85 /* Frameworks */ = {
11
+ isa = PBXGroup;
12
+ children = (
13
+ );
14
+ name = Frameworks;
15
+ sourceTree = "<group>";
16
+ };
17
+ 74946460D3EE9E1FA4792785 = {
18
+ isa = PBXGroup;
19
+ children = (
20
+ E3060171E73473A889949AB5 /* Products */,
21
+ 1D67B9537FE4C81097096F85 /* Frameworks */,
22
+ );
23
+ sourceTree = "<group>";
24
+ };
25
+ E3060171E73473A889949AB5 /* Products */ = {
26
+ isa = PBXGroup;
27
+ children = (
28
+ );
29
+ name = Products;
30
+ sourceTree = "<group>";
31
+ };
32
+ /* End PBXGroup section */
33
+
34
+ /* Begin PBXProject section */
35
+ B3A67937542EC2041CBF1CA2 /* Project object */ = {
36
+ isa = PBXProject;
37
+ attributes = {
38
+ LastSwiftUpdateCheck = 0730;
39
+ LastUpgradeCheck = 0700;
40
+ };
41
+ buildConfigurationList = 442CE273DD7DF2DFDC620C8B /* Build configuration list for PBXProject "foo" */;
42
+ compatibilityVersion = "Xcode 3.2";
43
+ developmentRegion = English;
44
+ hasScannedForEncodings = 0;
45
+ knownRegions = (
46
+ en,
47
+ );
48
+ mainGroup = 74946460D3EE9E1FA4792785;
49
+ productRefGroup = E3060171E73473A889949AB5 /* Products */;
50
+ projectDirPath = "";
51
+ projectRoot = "";
52
+ targets = (
53
+ );
54
+ };
55
+ /* End PBXProject section */
56
+
57
+ /* Begin XCBuildConfiguration section */
58
+ 09AC0D63F19B6944E1045E60 /* Release */ = {
59
+ isa = XCBuildConfiguration;
60
+ buildSettings = {
61
+ ALWAYS_SEARCH_USER_PATHS = NO;
62
+ CLANG_ANALYZER_NONNULL = YES;
63
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
64
+ CLANG_CXX_LIBRARY = "libc++";
65
+ CLANG_ENABLE_MODULES = YES;
66
+ CLANG_ENABLE_OBJC_ARC = YES;
67
+ CLANG_WARN_BOOL_CONVERSION = YES;
68
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
69
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES;
70
+ CLANG_WARN_EMPTY_BODY = YES;
71
+ CLANG_WARN_ENUM_CONVERSION = YES;
72
+ CLANG_WARN_INT_CONVERSION = YES;
73
+ CLANG_WARN_OBJC_ROOT_CLASS = YES;
74
+ CLANG_WARN_UNREACHABLE_CODE = YES;
75
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
76
+ COPY_PHASE_STRIP = YES;
77
+ ENABLE_NS_ASSERTIONS = NO;
78
+ GCC_C_LANGUAGE_STANDARD = gnu99;
79
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
80
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
81
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
82
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
83
+ GCC_WARN_UNUSED_FUNCTION = YES;
84
+ GCC_WARN_UNUSED_VARIABLE = YES;
85
+ VALIDATE_PRODUCT = YES;
86
+ };
87
+ name = Release;
88
+ };
89
+ 4D494CA5F82DCCAB3194BA09 /* Debug */ = {
90
+ isa = XCBuildConfiguration;
91
+ buildSettings = {
92
+ ALWAYS_SEARCH_USER_PATHS = NO;
93
+ CLANG_ANALYZER_NONNULL = YES;
94
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
95
+ CLANG_CXX_LIBRARY = "libc++";
96
+ CLANG_ENABLE_MODULES = YES;
97
+ CLANG_ENABLE_OBJC_ARC = YES;
98
+ CLANG_WARN_BOOL_CONVERSION = YES;
99
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
100
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES;
101
+ CLANG_WARN_EMPTY_BODY = YES;
102
+ CLANG_WARN_ENUM_CONVERSION = YES;
103
+ CLANG_WARN_INT_CONVERSION = YES;
104
+ CLANG_WARN_OBJC_ROOT_CLASS = YES;
105
+ CLANG_WARN_UNREACHABLE_CODE = YES;
106
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
107
+ COPY_PHASE_STRIP = NO;
108
+ ENABLE_TESTABILITY = YES;
109
+ GCC_C_LANGUAGE_STANDARD = gnu99;
110
+ GCC_DYNAMIC_NO_PIC = NO;
111
+ GCC_OPTIMIZATION_LEVEL = 0;
112
+ GCC_PREPROCESSOR_DEFINITIONS = (
113
+ "DEBUG=1",
114
+ "$(inherited)",
115
+ );
116
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
117
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
118
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
119
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
120
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
121
+ GCC_WARN_UNUSED_FUNCTION = YES;
122
+ GCC_WARN_UNUSED_VARIABLE = YES;
123
+ ONLY_ACTIVE_ARCH = YES;
124
+ };
125
+ name = Debug;
126
+ };
127
+ /* End XCBuildConfiguration section */
128
+
129
+ /* Begin XCConfigurationList section */
130
+ 442CE273DD7DF2DFDC620C8B /* Build configuration list for PBXProject "foo" */ = {
131
+ isa = XCConfigurationList;
132
+ buildConfigurations = (
133
+ 4D494CA5F82DCCAB3194BA09 /* Debug */,
134
+ 09AC0D63F19B6944E1045E60 /* Release */,
135
+ );
136
+ defaultConfigurationIsVisible = 0;
137
+ defaultConfigurationName = Release;
138
+ };
139
+ /* End XCConfigurationList section */
140
+ };
141
+ rootObject = B3A67937542EC2041CBF1CA2 /* Project object */;
142
+ }
@@ -0,0 +1,17 @@
1
+ use "ponytest"
2
+
3
+ actor Main is TestList
4
+ new create(env: Env) => PonyTest(env, this)
5
+ new make() => None
6
+
7
+ fun tag tests(test: PonyTest) =>
8
+ test(_TestAddition)
9
+
10
+ class iso _TestAddition is UnitTest
11
+ """
12
+ Adding 2 numbers
13
+ """
14
+ fun name(): String => "u32/add"
15
+
16
+ fun apply(h: TestHelper): TestResult =>
17
+ h.expect_eq[U32](2 + 2, 4)
data/lib/rouge/demos/q ADDED
@@ -0,0 +1,2 @@
1
+ / comment
2
+ x: til 10
@@ -0,0 +1,10 @@
1
+ require "fileinto";
2
+ require "imap4flags";
3
+
4
+ if header :is "X-Spam" "Yes" {
5
+ fileinto "Junk";
6
+ setflag "\\seen";
7
+ stop;
8
+ }
9
+
10
+ /* Other messages get filed into Inbox or to user's scripts */
@@ -0,0 +1,17 @@
1
+ class HelloWorld extends React.Component<{date: Date}, void> {
2
+ render() {
3
+ return (
4
+ <p>
5
+ Hello, <input type="text" placeholder="Your name here" />!
6
+ It is {this.props.date.toTimeString()}
7
+ </p>
8
+ );
9
+ }
10
+ }
11
+
12
+ setInterval(function() {
13
+ ReactDOM.render(
14
+ <HelloWorld date={new Date()} />,
15
+ document.getElementById('example')
16
+ );
17
+ }, 500);
File without changes
@@ -0,0 +1,11 @@
1
+ object pepita {
2
+ var energy = 100
3
+
4
+ method energy() = energy
5
+
6
+ method fly(kilometers) {
7
+ energy -= kilometers + 10
8
+ }
9
+
10
+ method sayHi() = "Coo!"
11
+ }
@@ -6,7 +6,15 @@ module Rouge
6
6
  tag 'html_inline'
7
7
 
8
8
  def initialize(theme)
9
- @theme = theme
9
+ if theme.is_a?(Class) && theme < Rouge::Theme
10
+ @theme = theme.new
11
+ elsif theme.is_a?(Rouge::Theme)
12
+ @theme = theme
13
+ elsif theme.is_a?(String)
14
+ @theme = Rouge::Theme.find(theme).new
15
+ else
16
+ raise ArgumentError, "invalid theme: #{theme.inspect}"
17
+ end
10
18
  end
11
19
 
12
20
  def safe_span(tok, safe_val)