front_matter_parser 0.0.4 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +5 -5
  2. data/.codeclimate.yml +19 -0
  3. data/.gitignore +1 -0
  4. data/.rspec +1 -0
  5. data/.rubocop.yml +50 -0
  6. data/.travis.yml +19 -1
  7. data/CHANGELOG.md +30 -0
  8. data/Dockerfile +5 -0
  9. data/Gemfile +0 -2
  10. data/README.md +76 -38
  11. data/Rakefile +5 -3
  12. data/bin/console +15 -0
  13. data/bin/setup +8 -0
  14. data/docker-compose.yml +12 -0
  15. data/front_matter_parser.gemspec +12 -6
  16. data/lib/front_matter_parser.rb +10 -114
  17. data/lib/front_matter_parser/loader.rb +11 -0
  18. data/lib/front_matter_parser/loader/yaml.rb +26 -0
  19. data/lib/front_matter_parser/parsed.rb +25 -14
  20. data/lib/front_matter_parser/parser.rb +82 -0
  21. data/lib/front_matter_parser/syntax_parser.rb +28 -0
  22. data/lib/front_matter_parser/syntax_parser/factorizable.rb +30 -0
  23. data/lib/front_matter_parser/syntax_parser/indentation_comment.rb +49 -0
  24. data/lib/front_matter_parser/syntax_parser/multi_line_comment.rb +50 -0
  25. data/lib/front_matter_parser/syntax_parser/single_line_comment.rb +64 -0
  26. data/lib/front_matter_parser/version.rb +3 -1
  27. data/spec/fixtures/example +6 -0
  28. data/spec/front_matter_parser/loader/yaml_spec.rb +24 -0
  29. data/spec/front_matter_parser/parsed_spec.rb +11 -21
  30. data/spec/front_matter_parser/parser_spec.rb +111 -0
  31. data/spec/front_matter_parser/syntax_parser/indentation_comment_spec.rb +166 -0
  32. data/spec/front_matter_parser/syntax_parser/multi_line_comment_spec.rb +267 -0
  33. data/spec/front_matter_parser/syntax_parser/single_line_comment_spec.rb +175 -0
  34. data/spec/front_matter_parser_spec.rb +3 -296
  35. data/spec/spec_helper.rb +9 -3
  36. data/spec/support/matcher.rb +8 -0
  37. metadata +110 -46
  38. data/spec/fixtures/example.coffee +0 -4
  39. data/spec/fixtures/example.erb +0 -6
  40. data/spec/fixtures/example.foo +0 -0
  41. data/spec/fixtures/example.haml +0 -5
  42. data/spec/fixtures/example.liquid +0 -6
  43. data/spec/fixtures/example.md +0 -4
  44. data/spec/fixtures/example.sass +0 -4
  45. data/spec/fixtures/example.scss +0 -4
  46. data/spec/fixtures/example.slim +0 -5
  47. data/spec/support/strings.rb +0 -41
  48. data/spec/support/syntaxs.rb +0 -14
  49. data/spec/support/utils.rb +0 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 411f187a41903eee5a896a2f44262d5f38aeb085
4
- data.tar.gz: 0b2e9a84f6db0fb0f525fef1c0e64d9a27a0d668
2
+ SHA256:
3
+ metadata.gz: a904dbf5bade2127e0bb2b9abb7106f179ce22876ca6e57aa9dc7c89730d2898
4
+ data.tar.gz: b43330122a6496888be51b937fc06749dd0b256394227425736b88a0e9e9f781
5
5
  SHA512:
6
- metadata.gz: 927cf23e937dbe7d51e77ede738b7ace2fbe110353a96b7903e66eaac52d6cefef7043524f502cdfd14b0676c84a02aa9f635966d3a161ce0cda655dd47eb60d
7
- data.tar.gz: ab89467326d6da288666290f14043a81a31afd2ecdf9b0e50b6028e0f78ecfeb46194adb69ec366e386c836f7aecfd19a19dd54af95fea12b212f1b390780958
6
+ metadata.gz: bf46ac330a47187dc37041b4c25ec6dd8500761ec18feaa2102659e19cda516f03be66b3ac32a9a530406b9d4fe598a86666916418ddf54f5380d9c164787095
7
+ data.tar.gz: 1d359953cd78bac9bf7186eb5b16e22f95a4d01ddaaf3d9e643580c7d407332f6730573733aa55423fd06c147e7816873b8deb62b1f1fa59ac7429e0f1490489
data/.codeclimate.yml ADDED
@@ -0,0 +1,19 @@
1
+ engines:
2
+ duplication:
3
+ enabled: true
4
+ config:
5
+ languages:
6
+ - ruby
7
+ fixme:
8
+ enabled: true
9
+ rubocop:
10
+ enabled: true
11
+ reek:
12
+ enabled: true
13
+ ratings:
14
+ paths:
15
+ - "**.rb"
16
+ exclude_paths:
17
+ - spec/
18
+ - Gemfile
19
+ - front_matter_parser.gemspec
data/.gitignore CHANGED
@@ -15,3 +15,4 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
+ .overcommit_gems.rb.lock
data/.rspec CHANGED
@@ -1 +1,2 @@
1
+ --format documentation
1
2
  --color
data/.rubocop.yml ADDED
@@ -0,0 +1,50 @@
1
+ require: rubocop-rspec
2
+ AllCops:
3
+ TargetRubyVersion: 3.0
4
+ Exclude:
5
+ - Gemfile
6
+ - front_matter_parser.gemspec
7
+ - vendor/**/*
8
+ RSpec/NestedGroups:
9
+ Max: 3
10
+ RSpec/MessageExpectation:
11
+ EnforcedStyle: 'expect'
12
+ Metrics/BlockLength:
13
+ Exclude:
14
+ - "spec/**/*.rb"
15
+ Style/SafeNavigation:
16
+ Enabled: false
17
+ Layout/EmptyLinesAroundAttributeAccessor:
18
+ Enabled: true
19
+ Layout/SpaceAroundMethodCallOperator:
20
+ Enabled: true
21
+ Lint/DeprecatedOpenSSLConstant:
22
+ Enabled: true
23
+ Lint/MixedRegexpCaptureTypes:
24
+ Enabled: true
25
+ Lint/RaiseException:
26
+ Enabled: true
27
+ Lint/StructNewOverride:
28
+ Enabled: true
29
+ Style/AccessorGrouping:
30
+ Enabled: true
31
+ Style/BisectedAttrAccessor:
32
+ Enabled: true
33
+ Style/ExponentialNotation:
34
+ Enabled: true
35
+ Style/HashEachMethods:
36
+ Enabled: true
37
+ Style/HashTransformKeys:
38
+ Enabled: true
39
+ Style/HashTransformValues:
40
+ Enabled: true
41
+ Style/RedundantAssignment:
42
+ Enabled: true
43
+ Style/RedundantFetchBlock:
44
+ Enabled: true
45
+ Style/RedundantRegexpCharacterClass:
46
+ Enabled: true
47
+ Style/RedundantRegexpEscape:
48
+ Enabled: true
49
+ Style/SlicingWithRange:
50
+ Enabled: false
data/.travis.yml CHANGED
@@ -1,3 +1,21 @@
1
1
  language: ruby
2
+ cache: bundler
2
3
  rvm:
3
- - 1.9.3
4
+ - 2.6
5
+ - 2.7
6
+ - 3.0
7
+ - ruby-head
8
+ before_install:
9
+ - gem update --system --no-doc
10
+ - gem install bundler
11
+ script:
12
+ - bundle exec rspec
13
+ - bundle exec rubocop
14
+ - bundle exec codeclimate-test-reporter
15
+ jobs:
16
+ allow_failures:
17
+ - rvm: ruby-head
18
+ addons:
19
+ code_climate:
20
+ repo_token:
21
+ secure: cgk8uvht7GhBupk3mYwjMVx73r/YzJ0YaiwKI66x150CIfvqS5bheZR/Wn6wb09llB1giuyEh32TLqbScQoPW/dFynO7FsvXIMHxn4Gup2Nkc36LkQhg+8EN3xxrzirNoqfxfaFWzJh7X/jbNdmLKLQvlh+5ey+nNPF+gdPVerXhqxg8AjE4EbDbeq3JnCi+jHlr/SxMB+zJe4PipLbeVSONSfSbraN/1IPJzHvItfQWSnEGIpRnAAb7URt2SAWcje/5CiH6QUA9C/ZyztfPEeCPfO2L1V3dp3pxbAyxzrhBtbVhw66mBO+Q6xB1xK8qv5LBQhlosn+TPOA66GMfHGo/tFP+aksq3CiVj6YfMaVy6AqzT0uocXFKvweznAfgiF5N+k4rq4+YBRXPEUtqmfaDka2hekKfewvMTDFGWQaoetU1Z/9WWJqaVlJQVSdeqYYLYpwur1wEeiPrz2nR0z3xn2LpdyGAeCpZW08dLBr/ASsjQhKGs3woIV+ZKSH3fJMmEh0CIulIm4qkcXN7izUUrNaPfNi4sUvaNNiomdLkaVbuv9hLlJByGciPHbBzajeqYFsPrGQWynHHDoFZ4/Tt2kTryNLqXGzqAqe0GozSRYx13z7frrGBYAXXMLPtViA2y568W2wiRh/MXM4noBRTQY8rETAfuaS+XuKfqTw=
data/CHANGELOG.md ADDED
@@ -0,0 +1,30 @@
1
+ # Change Log
2
+ All notable changes to this project will be documented in this file.
3
+
4
+ The format is based on [Keep a Changelog](http://keepachangelog.com/)
5
+ and this project adheres to [Semantic Versioning](http://semver.org/).
6
+
7
+ ## [1.0.0] - 2020-08-31
8
+ - Depreciate "whitelist" in favor of "allowlist" by renaming the `whitelist_classes` param to `allowlist_classes`.
9
+
10
+ If your project uses the `whitelist_classes` param, you will need to upgrade your code as follows:
11
+
12
+ ```ruby
13
+ ## before
14
+ loader = FrontMatterParser::Loader::Yaml.new(whitelist_classes: [Time])
15
+
16
+ ## after
17
+ loader = FrontMatterParser::Loader::Yaml.new(allowlist_classes: [Time])
18
+ ```
19
+
20
+ ## [0.2.1] - 2019-06-06
21
+ ### Fixed
22
+ - Do not add `bin` development executables to generated gem.
23
+
24
+ ## [0.2.0] - 2018-06-11
25
+ ### Added
26
+ - Allow whitelisting classes in YAML loader.
27
+
28
+ ## [0.1.1] - 2017-07-19
29
+ ### Fixed
30
+ - Don't be greedy with front matter end delimiters.
data/Dockerfile ADDED
@@ -0,0 +1,5 @@
1
+ FROM ruby:3.0.0
2
+ ENV APP_USER front_matter_parser_user
3
+ RUN useradd -ms /bin/bash $APP_USER
4
+ USER $APP_USER
5
+ WORKDIR /home/$APP_USER/app
data/Gemfile CHANGED
@@ -1,6 +1,4 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- ruby File.read('.ruby-version').strip
4
-
5
3
  # Specify your gem's dependencies in front_matter_parser.gemspec
6
4
  gemspec
data/README.md CHANGED
@@ -1,6 +1,11 @@
1
1
  # FrontMatterParser
2
2
 
3
- FrontMatterParser is a library to parse files or strings with YAML front matters. It can automatically detect the syntax of a file from its extension and it supposes that the front matter is marked as that syntax comments.
3
+ [![Gem Version](https://badge.fury.io/rb/front_matter_parser.svg)](https://badge.fury.io/rb/front_matter_parser)
4
+ [![Build Status](https://travis-ci.org/waiting-for-dev/front_matter_parser.svg?branch=master)](https://travis-ci.org/waiting-for-dev/front_matter_parser)
5
+ [![Code Climate](https://codeclimate.com/github/waiting-for-dev/front_matter_parser/badges/gpa.svg)](https://codeclimate.com/github/waiting-for-dev/front_matter_parser)
6
+ [![Test Coverage](https://codeclimate.com/github/waiting-for-dev/front_matter_parser/badges/coverage.svg)](https://codeclimate.com/github/waiting-for-dev/front_matter_parser/coverage)
7
+
8
+ FrontMatterParser is a library to parse a front matter from strings or files. It allows writing syntactically correct source files, marking front matters as comments in the source file language.
4
9
 
5
10
  ## Installation
6
11
 
@@ -24,7 +29,7 @@ Or install it yourself as:
24
29
 
25
30
  Front matters must be between two lines with three dashes `---`.
26
31
 
27
- Given a file `example.md`:
32
+ For example, given a file `example.md`:
28
33
 
29
34
  ```md
30
35
  ---
@@ -37,12 +42,12 @@ Some actual content
37
42
  You can parse it:
38
43
 
39
44
  ```ruby
40
- parsed = FrontMatterParser.parse_file('example.md')
45
+ parsed = FrontMatterParser::Parser.parse_file('example.md')
41
46
  parsed.front_matter #=> {'title' => 'Hello World', 'category' => 'Greetings'}
42
47
  parsed.content #=> 'Some actual content'
43
48
  ```
44
49
 
45
- You can apply directly `[]` method to get a front matter value:
50
+ You can directly apply `[]` method to get a front matter value:
46
51
 
47
52
  ```ruby
48
53
  parsed['category'] #=> 'Greetings'
@@ -50,9 +55,9 @@ parsed['category'] #=> 'Greetings'
50
55
 
51
56
  ### Syntax autodetection
52
57
 
53
- `FrontMatterParser` detects the syntax of a file by its extension and it supposes that the front matter is within that syntax comments delimiters.
58
+ `FrontMatterParser` detects the syntax of a file by its extension and it supposes that the front matter is within that syntax comment delimiters.
54
59
 
55
- Given a file `example.haml`:
60
+ For example, given a file `example.haml`:
56
61
 
57
62
  ```haml
58
63
  -#
@@ -65,49 +70,88 @@ Content
65
70
  The `-#` and the indentation enclose the front matter as a comment. `FrontMatterParser` is aware of that, so you can simply do:
66
71
 
67
72
  ```ruby
68
- title = FrontMatterParser.parse_file('example.haml')['title'] #=> 'Hello'
73
+ title = FrontMatterParser::Parser.parse_file('example.haml')['title'] #=> 'Hello'
69
74
  ```
70
75
 
71
76
  Following there is a relation of known syntaxes and their known comment delimiters:
72
77
 
73
- <pre>
74
- | Syntax | Single line comment | Start multiline comment | End multiline comment |
75
- | ------ | ------------------- | ----------------------- | ---------------------- |
76
- | haml | | -# | (indentation) |
77
- | slim | | / | (indentation) |
78
- | liquid | | {% comment %} | {% endcomment %} |
79
- | md | | | |
80
- | html | | &lt;!-- | --&gt; |
81
- | erb | | &lt;%# | %&gt; |
82
- | coffee | # | | |
83
- | sass | // | | |
84
- | scss | // | | |
85
- </pre>
86
-
87
- For unknown syntaxes or alternative ones, you can provide your own single line comment delimiter with the `:comment` option, or multiline comment delimiters with `:start_comment` and `:end_comment`. If `:start_comment` is provided but it isn't `:end_comment`, then it is supposed that the multiline comment is ended by indentation.
78
+ | Syntax | Single line comment | Start multiline comment | End multiline comment |
79
+ | ------ | ------------------- | ----------------------- | --------------------- |
80
+ | haml | | -# | (indentation) |
81
+ | slim | | / | (indentation) |
82
+ | liquid | | {% comment %} | {% endcomment %} |
83
+ | md | | | |
84
+ | html | | &lt;!-- | --&gt; |
85
+ | erb | | &lt;%# | %&gt; |
86
+ | coffee | # | | |
87
+ | sass | // | | |
88
+ | scss | // | | |
89
+
90
+ ### Parsing a string
91
+
92
+ You can as well parse a string providing manually the syntax:
88
93
 
89
94
  ```ruby
90
- FrontMatterParser.parse_file('example.haml', start_comment: '<!--', end_comment: '-->') # start and end multiline comment delimiters
91
- FrontMatterParser.parse_file('example.slim', start_comment: '/!') # multiline comment closed by indentation
92
- FrontMatterParser.parse_file('example.foo', comment: '#') # single line comments
95
+ string = File.read('example.slim')
96
+ FrontMatterParser::Parser.new(:slim).call(string)
93
97
  ```
94
98
 
95
- ### Parsing a string
99
+ ### Custom parsers
96
100
 
97
- You can as well parse a string, providing manually the `syntax`:
101
+ You can implement your own parsers for other syntaxes. Most of the times, they will need to parse a syntax with single line comments, multi line comments or closed by indentation comments. For these cases, this library provides helper factory methods. For example, if they weren't already implemented, you could do something like:
98
102
 
99
103
  ```ruby
100
- string = File.read('example.slim')
101
- FrontMatterParser.parse(string, syntax: :slim)
104
+ CoffeeParser = FrontMatterParser::SyntaxParser::SingleLineComment['#']
105
+ HtmlParser = FrontMatterParser::SyntaxParser::MultiLineComment['<!--', '-->']
106
+ SlimParser = FrontMatterParser::SyntaxParser::IndentationComment['/']
102
107
  ```
103
108
 
104
- or the comment delimiters:
109
+ You would use them like this:
105
110
 
106
111
  ```ruby
107
- string = File.read('example.slim')
108
- FrontMatterParser.parse(string, start_comment: '/!')
112
+ slim_parser = SlimParser.new
113
+
114
+ # For a file
115
+ FrontMatterParser::Parser.parse_file('example.slim', syntax_parser: slim_parser)
116
+
117
+ # For a string
118
+ FrontMatterParser::Parser.new(slim_parser).call(string)
109
119
  ```
110
120
 
121
+ For more complex scenarios, a parser can be anything responding to a method `call(string)` which returns a hash interface with `:front_matter` and `:content` keys, or `nil` if no front matter is found.
122
+
123
+ ### Custom loaders
124
+
125
+ Once a front matter is matched from a string, it is loaded as if it were a YAML text. However, you can also implement your own loaders. They just need to implement a `call(string)` method. You would use it like the following:
126
+
127
+ ```ruby
128
+ json_loader = ->(string) { JSON.load(string) }
129
+
130
+ # For a file
131
+ FrontMatterParser::Parser.parse_file('example.md', loader: json_loader)
132
+
133
+ # For a string
134
+ FrontMatterParser::Parser.new(:md, loader: json_loader).call(string)
135
+ ```
136
+
137
+ If you need to allow one or more classes for the built-in YAML loader, you can just create a custom loader based on it and provide needed classes in a `allowlist_classes:` param:
138
+
139
+ ```ruby
140
+ loader = FrontMatterParser::Loader::Yaml.new(allowlist_classes: [Time])
141
+ parsed = FrontMatterParser::Parser.parse_file('example.md', loader: loader)
142
+ puts parsed['timestamp']
143
+ ```
144
+
145
+ ## Development
146
+
147
+ There are docker and docker-compose files configured to create a development environment for this gem. So, if you use Docker you only need to run:
148
+
149
+ `docker-compose up -d`
150
+
151
+ An then, for example:
152
+
153
+ `docker-compose exec app rspec`
154
+
111
155
  ## Contributing
112
156
 
113
157
  1. Fork it
@@ -120,12 +164,6 @@ FrontMatterParser.parse(string, start_comment: '/!')
120
164
 
121
165
  `front_matter_parser` follows the principles of [semantic versioning](http://semver.org/).
122
166
 
123
- ## To Do
124
-
125
- * Add more known syntaxes.
126
- * Allow configuration of global front matter delimiters. It would be easy, but I'm not sure if too useful.
127
- * Allow different formats (as JSON). Again, I'm not sure if it would be very useful.
128
-
129
167
  ## Other ruby front matter parsers
130
168
 
131
169
  * [front-matter](https://github.com/zhaocai/front-matter.rb) Can parse YAML front matters with single line comments delimiters. YAML must be correctly indented.
data/Rakefile CHANGED
@@ -1,6 +1,8 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
3
5
 
4
6
  RSpec::Core::RakeTask.new(:spec)
5
7
 
6
- task :default => :spec
8
+ task default: :spec
data/bin/console ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+ require 'front_matter_parser'
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ require 'irb'
15
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,12 @@
1
+ version: '2'
2
+ services:
3
+ app:
4
+ build: .
5
+ image: front_matter_parser_user
6
+ command: bash -c "bundle && tail -f Gemfile"
7
+ volumes:
8
+ - .:/home/front_matter_parser_user/app
9
+ tty: true
10
+ stdin_open: true
11
+ tmpfs:
12
+ - /tmp
@@ -8,17 +8,23 @@ Gem::Specification.new do |spec|
8
8
  spec.version = FrontMatterParser::VERSION
9
9
  spec.authors = ["marc"]
10
10
  spec.email = ["marc@lamarciana.com"]
11
- spec.description = %q{Library to parse files or strings with YAML front matters with syntax autodetection.}
12
- spec.summary = %q{FrontMatterParser is a library to parse files or strings with YAML front matters. When working with files, it can automatically detect the syntax of a file from its extension and it supposes that the front matter is marked as that syntax comments.}
11
+ spec.description = %q{Parse a front matter from syntactically correct strings or files}
12
+ spec.summary = %q{Library to parse a front matter from strings or files. It allows writing syntactically correct source files, marking front matters as comments in the source file language.}
13
13
  spec.homepage = "https://github.com/waiting-for-dev/front_matter_parser"
14
14
  spec.license = "LGPL3"
15
15
 
16
16
  spec.files = `git ls-files`.split($/)
17
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_development_dependency "bundler", "~> 1.5", "<1.6"
22
- spec.add_development_dependency "rake", "~>10.1"
23
- spec.add_development_dependency "rspec", "~> 2.14"
21
+ spec.add_development_dependency "bundler"
22
+ spec.add_development_dependency "rake", "~> 12.0"
23
+ spec.add_development_dependency "rspec", "~> 3.8"
24
+ spec.add_development_dependency "pry-byebug", "~> 3.7"
25
+ # Test reporting
26
+ spec.add_development_dependency 'rubocop', '~> 1.9'
27
+ spec.add_development_dependency 'rubocop-rspec', '~> 2.2'
28
+ spec.add_development_dependency 'simplecov', '0.17'
29
+ spec.add_development_dependency 'codeclimate-test-reporter', '~> 1.0'
24
30
  end
@@ -1,117 +1,13 @@
1
- require 'yaml'
2
- require "front_matter_parser/version"
3
- require "front_matter_parser/parsed"
1
+ # frozen_string_literal: true
4
2
 
5
- # FrontMatterParser module is the entry point to parse strings or files with YAML front matters. When working with files, it can automatically detect the syntax of a file from its extension and it supposes that the front matter is marked as that syntax comments.
6
- module FrontMatterParser
7
- # {Hash {Symbol => Array}} Comments delimiters for FrontMatterParser known syntaxes. Keys are file extensions for {FrontMatterParser.parse_file} or :syntax option values for {FrontMatterParser.parse}, and values are three elements array:
8
- #
9
- # * First element is single line comment delimiter.
10
- # * Second element is the start multiline comment delimiter.
11
- # * Third element is the end multiline comment delimiter. If it is `nil` and start multiline comment delimiter isn't, it means that the comment is closed by indentation.
12
- COMMENT_DELIMITERS = {
13
- slim: [nil, '/', nil],
14
- html: [nil, '<!--', '-->'],
15
- erb: [nil, '<%#', '%>'],
16
- coffee: ['#', nil, nil],
17
- haml: [nil, '-#', nil],
18
- liquid: [nil, '{% comment %}', '{% endcomment %}'],
19
- sass: ['//', nil, nil],
20
- scss: ['//', nil, nil],
21
- md: [nil, nil, nil],
22
- }
23
-
24
- # Parses a string into a {Parsed} instance. The syntax of the string can be set with :syntax option. Otherwise, comment marks can be manually indicated with :comment, :start_comment and :end_comment options.
25
- #
26
- # @param string [String] The string to parse
27
- # @param opts [Hash] Options
28
- # @option opts [Symbol] :syntax The syntax used in the string. See {FrontMatterParser::COMMENT_DELIMITERS} for allowed values and the comment delimiters that are supposed.
29
- # @option opts [String, nil] :comment Single line comment delimiter
30
- # @option opts [String, nil] :start_comment Start multiline comment delimiter
31
- # @option opts [String, nil] :end_comment End multiline comment delimiter. If it is `nil` and :start_comment isn't, the multiline comment is supposed to be closed by indentation
32
- # @return [Parsed]
33
- # @raise [ArgumentError] If :syntax is not within {COMMENT_DELIMITERS} keys
34
- # @raise [ArgumentError] If :end_comment option is given but not :start_comment
35
- # @raise [ArgumentError] If :comment and :start_comment options are given
36
- # @see COMMENT_DELIMITERS
37
- def self.parse(string, opts = {})
38
- opts = {
39
- comment: nil,
40
- start_comment: nil,
41
- end_comment: nil,
42
- syntax: nil,
43
- }.merge(opts)
44
-
45
- raise(ArgumentError, "If you provide :end_comment, you must also provide :start_comment") if (opts[:end_comment] != nil and opts[:start_comment] == nil)
46
- raise(ArgumentError, "You can not provide :comment and :start_comment options at the same time") if (opts[:start_comment] != nil and opts[:comment] != nil)
3
+ require 'front_matter_parser/version'
4
+ require 'front_matter_parser/syntax_parser'
5
+ require 'front_matter_parser/loader'
6
+ require 'front_matter_parser/parser'
7
+ require 'front_matter_parser/parsed'
47
8
 
48
- if opts[:comment].nil? and opts[:start_comment].nil? and not opts[:syntax].nil?
49
- raise(ArgumentError, "#{opts[:syntax]} syntax not known. Please call parse providing manually comment delimiters for that syntax.") unless COMMENT_DELIMITERS.has_key?(opts[:syntax])
50
- opts[:comment], opts[:start_comment], opts[:end_comment] = COMMENT_DELIMITERS[opts[:syntax]]
51
- end
52
-
53
- parsed = Parsed.new
54
- if matches = (string.match(/
55
- # Start of string
56
- \A
57
- # Zero or more space characters
58
- ([[:space:]]*)
59
- # Start multiline comment
60
- #{'(?-x:(?<multiline_comment_indentation>^[[:blank:]]*)'+opts[:start_comment]+'[[:blank:]]*[\n\r][[:space:]]*)' unless opts[:start_comment].nil?}
61
- # Begin front matter
62
- (?-x:^[[:blank:]]*#{opts[:comment]}[[:blank:]]*---[[:blank:]]*$[\n\r])
63
- # The front matter
64
- (?<front_matter>.*)
65
- # End front matter
66
- (?-x:^[[:blank:]]*#{opts[:comment]}[[:blank:]]*---[[:blank:]]*$[\n\r])
67
- # End multiline comment
68
- #{'(?-x:\k<multiline_comment_indentation>)' if opts[:end_comment].nil? and not opts[:start_comment].nil?}
69
- #{'(?-x:[[:space:]]*^[[:blank:]]*'+opts[:end_comment]+'[[:blank:]]*[\n\r])' if not opts[:end_comment].nil?}
70
- # The content
71
- (?<content>.*)
72
- # End of string
73
- \z
74
- /mx))
75
- front_matter = matches[:front_matter].gsub(/^[[:blank:]]*#{opts[:comment]}/, '')
76
- parsed.front_matter = YAML.load(front_matter)
77
- parsed.content = matches[:content]
78
- else
79
- parsed.front_matter = {}
80
- parsed.content = string
81
- end
82
- parsed
83
- end
84
-
85
- # Parses a file into a {Parsed} instance. Syntax is automatically guessed from the file extension, unless :comment, :start_comment or :end_comment options are given. See {COMMENT_DELIMITERS} for a list of known extensions and the comment delimiters values that are supposed.
86
- #
87
- # @param pathname [String] The path to the file
88
- # @param opts [Hash] Options
89
- # @option opts [String, nil] :comment Single line comment delimiter
90
- # @option opts [String, nil] :start_comment Start multiline comment delimiter
91
- # @option opts [String, nil] :end_comment End multiline comment delimiter. If it is `nil`, the multiline comment is supposed to be closed by indentation.
92
- # @return [Parsed]
93
- # @raise [ArgumentError] If :start_comment option is provided but not :end_comment
94
- # @raise [ArgumentError] If :comment and :start_comment options are both provided
95
- # @raise [ArgumentError] If :end_comment is provided but :start_comment isn't
96
- # @raise [RuntimeError] If the syntax of the file (the extension) is not within the keys of {COMMENT_DELIMITERS} or the file has no extension, and none of :comment, :start_comment or :end_comment are provided
97
- # @see COMMENT_DELIMITERS
98
- def self.parse_file(pathname, opts={})
99
- opts = {
100
- comment: nil,
101
- start_comment: nil,
102
- end_comment: nil,
103
- }.merge(opts)
104
- if opts[:comment].nil? and opts[:start_comment].nil?
105
- ext = File.extname(pathname)[1 .. -1]
106
- ext = ext.to_sym unless ext.nil?
107
- raise(RuntimeError, "Comment delimiters for extension #{ext.to_s} not known. Please, call #parse_file providing manually comment delimiters for that extension.") unless COMMENT_DELIMITERS.has_key?(ext)
108
- File.open(pathname) do |file|
109
- parse(file.read, syntax: ext)
110
- end
111
- else
112
- File.open(pathname) do |file|
113
- parse(file.read, comment: opts[:comment], start_comment: opts[:start_comment], end_comment: opts[:end_comment])
114
- end
115
- end
116
- end
9
+ # FrontMatterParser is a library to parse a front matter from strings or
10
+ # files. It allows writing syntactically correct source files, marking front
11
+ # matters as comments in the source file language.
12
+ module FrontMatterParser
117
13
  end