nesta 0.14.0 → 0.16.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.
- checksums.yaml +4 -4
- data/.github/workflows/tests.yml +2 -2
- data/{CHANGES → CHANGELOG.md} +62 -22
- data/Gemfile.lock +16 -16
- data/LICENSE +1 -1
- data/README.md +42 -30
- data/RELEASING.md +5 -4
- data/lib/nesta/config.rb +5 -4
- data/lib/nesta/models/file_model.rb +195 -0
- data/lib/nesta/models/menu.rb +67 -0
- data/lib/nesta/models/page.rb +167 -0
- data/lib/nesta/models.rb +3 -421
- data/lib/nesta/overrides.rb +1 -15
- data/lib/nesta/version.rb +1 -1
- data/nesta.gemspec +2 -2
- data/templates/config/config.yml +2 -2
- data/test/integration/default_theme_test.rb +1 -1
- data/test/unit/config_test.rb +6 -0
- data/views/analytics.haml +6 -6
- metadata +14 -11
- /data/test/unit/{file_model_test.rb → models/file_model_test.rb} +0 -0
- /data/test/unit/{menu_test.rb → models/menu_test.rb} +0 -0
- /data/test/unit/{page_test.rb → models/page_test.rb} +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f57754ef13ef4b4533c03ab454b2114fb35d3e168d20107c1fb39941d6af4b92
|
4
|
+
data.tar.gz: 9aa4a9b8e0715d77c1ec515a114f63827e8a117e1f3b807755a59d0c0eba0c45
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: effa2dcecf9d3ed0de395102c893d9f1571171b4bc4d63968911f3538c27bd8ef15692df2586239e2986d1b32e4bd4ef23513245c2cd89d0d159df3d9bf79903
|
7
|
+
data.tar.gz: c0f318224b4f70322af4d30b55e517b1d790b3087129eb0601d434eabf79cc65e3b8ae24262f7300812a0414dd5402d2969d0f11be1f5d0516afe1ad7474d27c
|
data/.github/workflows/tests.yml
CHANGED
@@ -8,10 +8,10 @@ jobs:
|
|
8
8
|
strategy:
|
9
9
|
fail-fast: false
|
10
10
|
matrix:
|
11
|
-
ruby: ["
|
11
|
+
ruby: ["3.0", "3.1", "3.2", "3.3"]
|
12
12
|
runs-on: ubuntu-latest
|
13
13
|
steps:
|
14
|
-
- uses: actions/checkout@
|
14
|
+
- uses: actions/checkout@v4
|
15
15
|
- uses: ruby/setup-ruby@v1
|
16
16
|
with:
|
17
17
|
ruby-version: ${{ matrix.ruby }}
|
data/{CHANGES → CHANGELOG.md}
RENAMED
@@ -1,4 +1,43 @@
|
|
1
|
-
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
## 0.16.0 (11 April 2024)
|
4
|
+
|
5
|
+
* Update Google Analytics JS code to GA4. (Matthew Bass)
|
6
|
+
|
7
|
+
* Upgrade to Sinatra 3.1. (なつき)
|
8
|
+
|
9
|
+
* Tilt renderers (e.g. for Markdown, Haml, or Textile) are now configurable.
|
10
|
+
See #146 for details. (Graham Ashton)
|
11
|
+
|
12
|
+
* Drop support for Ruby 2.7, which is no longer supported by Nokogiri,
|
13
|
+
which is one of Nesta's dependencies. This is understandable; Ruby
|
14
|
+
2.7 reached end-of-life in March 2023. (Graham Ashton)
|
15
|
+
|
16
|
+
* Bug fix: Config variables that were defined for an environment (test,
|
17
|
+
dev, production), but for which there was no default, were always read
|
18
|
+
as nil. (Matthew Bass)
|
19
|
+
|
20
|
+
## 0.15.0 (11 July 2023)
|
21
|
+
|
22
|
+
* Upgrade to Sinatra 3. (Graham Ashton)
|
23
|
+
|
24
|
+
* The `models.rb` file has been long and unnecessarily hard to navigate
|
25
|
+
for too long. It has been split up into multiple files, one for each
|
26
|
+
class. (Graham Ashton, suggested by Lilith River)
|
27
|
+
|
28
|
+
* Remove support for the BlueCloth markdown library. Nesta uses Tilt
|
29
|
+
for rendering Markdown, and BlueCloth support has been removed in
|
30
|
+
Tilt 2.2.0. See rtomayko/tilt#382 for details.
|
31
|
+
|
32
|
+
If your site uses BlueCloth, remove your call to `Tilt.prefer`,
|
33
|
+
and Nesta will use its default Markdown processor. See Nesta's docs
|
34
|
+
on [configuring the Markdown processor] for more details.
|
35
|
+
|
36
|
+
[configuring the Markdown processor]: https://nestacms.com/docs/creating-content/changing-the-markdown-processor
|
37
|
+
|
38
|
+
(Graham Ashton)
|
39
|
+
|
40
|
+
## 0.14.0 (23 March 2023)
|
2
41
|
|
3
42
|
* Nesta can now be used as a Static Site Generator (SSG) with its new
|
4
43
|
`nesta build` command! Server Side Rendering (SSR) is still supported,
|
@@ -71,7 +110,7 @@
|
|
71
110
|
* The breadcrumb_label helper method (deprecated in 0.9.3) has been removed.
|
72
111
|
(Graham Ashton)
|
73
112
|
|
74
|
-
|
113
|
+
## 0.13.0 (28 September 2022)
|
75
114
|
|
76
115
|
* Update dependencies in order to support Ruby 3.0 and above.
|
77
116
|
(Graham Ashton)
|
@@ -97,7 +136,7 @@
|
|
97
136
|
* Stopped the test suite from executing external commands during tests.
|
98
137
|
(Graham Ashton)
|
99
138
|
|
100
|
-
|
139
|
+
## 0.12.0 (30 June 2020)
|
101
140
|
|
102
141
|
* Upgrade to Sinatra 2 and Rack 2. (Graham Ashton)
|
103
142
|
|
@@ -113,12 +152,12 @@
|
|
113
152
|
* Stop running the test suite under Ruby 2.3 and 2.4, both of which
|
114
153
|
have reached end-of-life. (Graham Ashton)
|
115
154
|
|
116
|
-
|
155
|
+
## 0.11.1 (26 March 2015)
|
117
156
|
|
118
157
|
* Tighten dependency on Tilt, as version 2.x is incompatible.
|
119
158
|
(Graham Ashton)
|
120
159
|
|
121
|
-
|
160
|
+
## 0.11.0 (16 March 2015)
|
122
161
|
|
123
162
|
* Allow Haml pages to use the built-in Markdown filter again, by
|
124
163
|
including the haml-contrib gem.
|
@@ -161,7 +200,7 @@
|
|
161
200
|
|
162
201
|
* Support for Ruby 2.2. (Graham Ashton)
|
163
202
|
|
164
|
-
|
203
|
+
## 0.10.0 (25 April 2014)
|
165
204
|
|
166
205
|
* Upgraded the default theme to a responsive design, using Google's
|
167
206
|
Roboto Slab web font. (Graham Ashton)
|
@@ -285,7 +324,7 @@
|
|
285
324
|
this list. See GitHub for the full list of commits.
|
286
325
|
https://github.com/gma/nesta/compare/v0.9.13...v0.10.0
|
287
326
|
|
288
|
-
|
327
|
+
## 0.9.13 (3 March 2012)
|
289
328
|
|
290
329
|
* The nesta script has a new command; edit. You can pass it the path
|
291
330
|
to a file within your content/pages folder and it will open the file
|
@@ -343,9 +382,9 @@
|
|
343
382
|
* Bug fix: Summaries on Haml pages were not marked up as paragraphs.
|
344
383
|
See #75.
|
345
384
|
|
346
|
-
|
385
|
+
## 0.9.12 (Released then pulled, due to rubygems [still] being a total mess)
|
347
386
|
|
348
|
-
|
387
|
+
## 0.9.11 (22 September 2011)
|
349
388
|
|
350
389
|
* Use Tilt to render the Markdown, Textile and Haml in content/pages.
|
351
390
|
RDiscount is now the default Markdown processor. To continue using
|
@@ -372,7 +411,7 @@
|
|
372
411
|
within the content folder by crafting a relative path containing
|
373
412
|
the string '../' (Louis Nyffenegger).
|
374
413
|
|
375
|
-
|
414
|
+
## 0.9.10 (9 September 2011)
|
376
415
|
|
377
416
|
* Load Nesta plugins from gems. Any gem whose name begins with
|
378
417
|
nesta-plugin- can be used in a project by adding it to the project's
|
@@ -390,7 +429,7 @@
|
|
390
429
|
the Sass rendering engine by default, which allows it to find .sass
|
391
430
|
files within the gem if no matching files are found locally.
|
392
431
|
|
393
|
-
|
432
|
+
## 0.9.9 (24 August 2011)
|
394
433
|
|
395
434
|
* Bug fix: What a debacle this is turning into. The new Nesta::Env
|
396
435
|
class must be required before the code in 'nesta/app' is loaded.
|
@@ -398,7 +437,7 @@
|
|
398
437
|
via config.ru. Running Nesta any other way lead to an immediate
|
399
438
|
crash.
|
400
439
|
|
401
|
-
|
440
|
+
## 0.9.8 (22 August 2011)
|
402
441
|
|
403
442
|
* Bug fix: The Sinatra app's root directory wasn't set which meant
|
404
443
|
that Nesta couldn't always find the ./public directory (such as when
|
@@ -409,12 +448,12 @@
|
|
409
448
|
Nesta::Env class. In 0.9.6 I forgot to actually set Nesta::App.root
|
410
449
|
as well, which was a big mistake. Whoops.
|
411
450
|
|
412
|
-
|
451
|
+
## 0.9.7 (19 August 2011)
|
413
452
|
|
414
453
|
* No code changes from 0.9.6; version number increased to allow new gem
|
415
454
|
to be deployed to rubygems.org.
|
416
455
|
|
417
|
-
|
456
|
+
## 0.9.6 (18 August 2011) [never released due to packaging bug]
|
418
457
|
|
419
458
|
* Nesta no longer cares whether you write your Sass stylesheets in the
|
420
459
|
original indented Sass format or the default SCSS syntax (which is a
|
@@ -440,7 +479,7 @@
|
|
440
479
|
Nesta::App.root would be before requiring nesta/app. Fixed by
|
441
480
|
creating Nesta::Env and moving root to there instead.
|
442
481
|
|
443
|
-
|
482
|
+
## 0.9.5 (1 May 2011)
|
444
483
|
|
445
484
|
* Added --version option to nesta command (Christopher Lindblom).
|
446
485
|
|
@@ -466,14 +505,14 @@
|
|
466
505
|
within Haml templates. See https://github.com/gma/nesta/pull/18
|
467
506
|
(Carl Furrow).
|
468
507
|
|
469
|
-
|
508
|
+
## 0.9.4 (18 February 2011)
|
470
509
|
|
471
510
|
* Updated the link colours in the default theme.
|
472
511
|
|
473
512
|
* Set the default encoding to UTF-8. Without it Heroku would sometimes
|
474
513
|
fail to render pages (issue 14).
|
475
514
|
|
476
|
-
|
515
|
+
## 0.9.3 (18 January 2011)
|
477
516
|
|
478
517
|
* The route and view for serving the home page (/) has been removed,
|
479
518
|
and the home page must now be created as an index page in
|
@@ -515,7 +554,7 @@
|
|
515
554
|
* Bug fix: Don't output empty <li> tags for nested submenus that are
|
516
555
|
beneath the requested number of levels.
|
517
556
|
|
518
|
-
|
557
|
+
## 0.9.2 (10 January 2011)
|
519
558
|
|
520
559
|
* Made the FileModel.metadata method public, to allow for custom
|
521
560
|
metadata at the top of each page. (Wynn Netherland)
|
@@ -525,7 +564,7 @@
|
|
525
564
|
|
526
565
|
* Added templates required by `nesta theme:create`.
|
527
566
|
|
528
|
-
|
567
|
+
## 0.9.1 (31 December 2010)
|
529
568
|
|
530
569
|
* Re-implemented the default theme, using semantic HTML5 and
|
531
570
|
Andy Clarke's Universal Internet Explorer 6 CSS. Named the previous
|
@@ -538,15 +577,16 @@
|
|
538
577
|
* Moved the navigation helpers into the Nesta::Navigation::Renderers
|
539
578
|
module.
|
540
579
|
|
541
|
-
|
580
|
+
## 0.9.0 (20 December 2010)
|
542
581
|
|
543
582
|
* Packaged Nesta as a gem for the first time, instead of as a template
|
544
583
|
site that can be cloned, edited and deployed. Added the `nesta`
|
545
584
|
command for generating new sites and managing themes.
|
546
585
|
|
547
|
-
|
586
|
+
## Previous versions (from 26 November 2008)
|
548
587
|
|
549
588
|
* Prior to 0.9.0 Nesta was distributed as a git repository that could
|
550
589
|
be forked, edited and deployed. The only change log for these
|
551
|
-
versions is the
|
590
|
+
versions is the commit history:
|
591
|
+
|
552
592
|
https://github.com/gma/nesta/commits/master
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
nesta (0.
|
4
|
+
nesta (0.16.0)
|
5
5
|
RedCloth (~> 4.2)
|
6
6
|
haml (>= 3.1, < 6.0)
|
7
7
|
haml-contrib (>= 1.0)
|
@@ -9,13 +9,13 @@ PATH
|
|
9
9
|
rake
|
10
10
|
rdiscount (~> 2.1)
|
11
11
|
sass-embedded (~> 1.58)
|
12
|
-
sinatra (~>
|
13
|
-
tilt (~> 2.
|
12
|
+
sinatra (~> 3.1)
|
13
|
+
tilt (~> 2.1)
|
14
14
|
|
15
15
|
GEM
|
16
16
|
remote: https://rubygems.org/
|
17
17
|
specs:
|
18
|
-
RedCloth (4.3.
|
18
|
+
RedCloth (4.3.3)
|
19
19
|
addressable (2.8.1)
|
20
20
|
public_suffix (>= 2.0.2, < 6.0)
|
21
21
|
ansi (1.5.0)
|
@@ -41,7 +41,7 @@ GEM
|
|
41
41
|
rb-inotify (>= 0.9)
|
42
42
|
rb-kqueue (>= 0.2)
|
43
43
|
mini_mime (1.1.2)
|
44
|
-
mini_portile2 (2.8.
|
44
|
+
mini_portile2 (2.8.5)
|
45
45
|
minitest (5.18.0)
|
46
46
|
minitest-reporters (1.6.0)
|
47
47
|
ansi
|
@@ -53,16 +53,16 @@ GEM
|
|
53
53
|
rb-fsevent (>= 0.9)
|
54
54
|
rb-inotify (>= 0.8)
|
55
55
|
unicorn (>= 4.5)
|
56
|
-
mustermann (
|
56
|
+
mustermann (3.0.0)
|
57
57
|
ruby2_keywords (~> 0.0.1)
|
58
|
-
nokogiri (1.
|
59
|
-
mini_portile2 (~> 2.8.
|
58
|
+
nokogiri (1.16.2)
|
59
|
+
mini_portile2 (~> 2.8.2)
|
60
60
|
racc (~> 1.4)
|
61
61
|
public_suffix (5.0.1)
|
62
|
-
racc (1.
|
63
|
-
rack (2.2.
|
64
|
-
rack-protection (
|
65
|
-
rack
|
62
|
+
racc (1.7.3)
|
63
|
+
rack (2.2.8.1)
|
64
|
+
rack-protection (3.1.0)
|
65
|
+
rack (~> 2.2, >= 2.2.4)
|
66
66
|
rack-test (2.0.2)
|
67
67
|
rack (>= 1.3)
|
68
68
|
raindrops (0.20.1)
|
@@ -78,10 +78,10 @@ GEM
|
|
78
78
|
sass-embedded (1.58.3)
|
79
79
|
google-protobuf (~> 3.21)
|
80
80
|
rake (>= 10.0.0)
|
81
|
-
sinatra (
|
82
|
-
mustermann (~>
|
83
|
-
rack (~> 2.2)
|
84
|
-
rack-protection (=
|
81
|
+
sinatra (3.1.0)
|
82
|
+
mustermann (~> 3.0)
|
83
|
+
rack (~> 2.2, >= 2.2.4)
|
84
|
+
rack-protection (= 3.1.0)
|
85
85
|
tilt (~> 2.0)
|
86
86
|
temple (0.10.0)
|
87
87
|
tilt (2.1.0)
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -1,34 +1,37 @@
|
|
1
|
-
#
|
1
|
+
# Lightweight file-based CMS and Static Site Generator
|
2
2
|
|
3
|
-
|
3
|
+
Nesta is a lightweight CMS for building content sites and blogs, written in
|
4
|
+
[Sinatra].
|
4
5
|
|
5
|
-
Content can be written in [Markdown]
|
6
|
-
|
7
|
-
some HTML to your pages). There's no database; write your content in
|
8
|
-
your editor. Publish by pushing to a git repository.
|
6
|
+
Content can be written in [Markdown] or [Textile], stored in text files on your
|
7
|
+
computer. There is no database.
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
You do your writing in your text editor.
|
10
|
+
|
11
|
+
Publish by pushing your changes to a git repository that's setup to deploy your
|
12
|
+
changes to the web.
|
13
|
+
|
14
|
+
[Sinatra]: http://www.sinatrarb.com/ "Sinatra"
|
15
|
+
[Markdown]: http://daringfireball.net/projects/markdown/
|
16
|
+
[Textile]: http://textism.com/tools/textile/
|
13
17
|
|
14
18
|
## Installation
|
15
19
|
|
16
|
-
Begin by installing the gem:
|
20
|
+
Begin by [installing Ruby], then the Nesta gem:
|
17
21
|
|
18
22
|
$ gem install nesta
|
19
23
|
|
20
|
-
|
24
|
+
Use the `nesta` command to generate a new site:
|
21
25
|
|
22
|
-
$ nesta new mysite.com --git
|
26
|
+
$ nesta new mysite.com --git # a git repo is optional, but recommended
|
23
27
|
|
24
28
|
Install a few dependencies, and you're away:
|
25
29
|
|
26
30
|
$ cd mysite.com
|
27
31
|
$ bundle
|
28
32
|
|
29
|
-
You'll find
|
30
|
-
|
31
|
-
before you go very far.
|
33
|
+
You'll find configuration options for your site in `config/config.yml`. The
|
34
|
+
defaults will work, but you'll want to tweak it before you go very far.
|
32
35
|
|
33
36
|
That's it - you can launch a local web server in development mode using
|
34
37
|
mr-sparkle...
|
@@ -36,34 +39,43 @@ mr-sparkle...
|
|
36
39
|
$ bundle exec mr-sparkle config.ru
|
37
40
|
|
38
41
|
...then point your web browser at http://localhost:8080. Start editing
|
39
|
-
the files in `content/pages` (see the [docs on writing content]
|
40
|
-
|
42
|
+
the files in `content/pages` (see the [docs on writing content] for full
|
43
|
+
instructions).
|
44
|
+
|
45
|
+
You can either [deploy it] behind a web server, or build a static version of
|
46
|
+
your site:
|
47
|
+
|
48
|
+
$ nesta build # but see config.yml for related settings
|
41
49
|
|
42
|
-
[
|
50
|
+
[installing Ruby]: https://www.ruby-lang.org/en/documentation/installation/
|
51
|
+
[docs on writing content]: http://nestacms.com/docs/creating-content/
|
52
|
+
[deploy it]: https://nestacms.com/docs/deployment/
|
43
53
|
|
44
54
|
## Support
|
45
55
|
|
46
56
|
There's plenty of information on <http://nestacms.com>. If you need some
|
47
57
|
help with anything feel free to file an issue, or contact me on Mastodon
|
48
|
-
(@gma@hachyderm.io) or Twitter (@grahamashton).
|
58
|
+
([@gma@hachyderm.io]) or Twitter ([@grahamashton]).
|
49
59
|
|
50
|
-
If you like Nesta you can keep up with developments by following [@nestacms]
|
51
|
-
on Twitter, and on [the blog]
|
60
|
+
If you like Nesta you can keep up with developments by following [@nestacms]
|
61
|
+
on Twitter, and on [the blog].
|
52
62
|
|
53
|
-
[@
|
54
|
-
[
|
63
|
+
[@gma@hachyderm.io]: https://hachyderm.io/@gma
|
64
|
+
[@grahamashton]: https://twitter.com/grahamashton
|
65
|
+
[@nestacms]: https://twitter.com/nestacms
|
66
|
+
[the blog]: https://nestacms.com/blog
|
55
67
|
|
56
68
|

|
57
69
|
|
58
70
|
## Contributing
|
59
71
|
|
60
|
-
If you want to add a new feature,
|
61
|
-
|
62
|
-
|
63
|
-
|
72
|
+
If you want to add a new feature, please [create an issue] to discuss it before
|
73
|
+
you start coding. I might suggest that we implement it as a [plugin] (to keep
|
74
|
+
Nesta itself lean and simple), or be able to chip in with ideas on how to
|
75
|
+
approach it.
|
64
76
|
|
65
|
-
[
|
77
|
+
[create an issue]: https://github.com/gma/nesta/issues/new
|
78
|
+
[plugin]: https://nestacms.com/docs/plugins
|
66
79
|
|
67
|
-
-- Graham
|
80
|
+
-- Graham
|
68
81
|
|
69
|
-
[@grahamashton]: http://twitter.com/grahamashton
|
data/RELEASING.md
CHANGED
@@ -8,15 +8,16 @@ the steps:
|
|
8
8
|
|
9
9
|
2. Bump the version number in `lib/nesta/version.rb`. This will cause
|
10
10
|
the version number in `Gemfile.lock` to be updated too, so regenerate
|
11
|
-
it now and check them in together.
|
11
|
+
it now (e.g. run `bundle install`) and check them in together.
|
12
12
|
|
13
|
-
3. Update the `
|
13
|
+
3. Update the `CHANGLOG.md` file with a summary of significant changes since
|
14
14
|
the previous release.
|
15
15
|
|
16
16
|
4. Commit these changes with a commit message of 'Bump version to <version>'
|
17
17
|
|
18
|
-
5.
|
19
|
-
|
18
|
+
5. Install the gem locally (`rake install`), then generate a new site
|
19
|
+
with the `nesta` command. Install the demo content site, check that
|
20
|
+
it runs okay locally.
|
20
21
|
|
21
22
|
6. If everything seems fine, run `rake release`.
|
22
23
|
|
data/lib/nesta/config.rb
CHANGED
@@ -33,10 +33,11 @@ module Nesta
|
|
33
33
|
setting = setting.to_s
|
34
34
|
self.config ||= read_config_file(setting)
|
35
35
|
env_config = config.fetch(Nesta::App.environment.to_s, {})
|
36
|
-
env_config.fetch(
|
37
|
-
setting
|
38
|
-
|
39
|
-
|
36
|
+
env_config.fetch(setting) do
|
37
|
+
config.fetch(setting) do
|
38
|
+
raise NotDefined.new(setting)
|
39
|
+
end
|
40
|
+
end
|
40
41
|
rescue NotDefined
|
41
42
|
default.empty? && raise || (return default.first)
|
42
43
|
end
|
@@ -0,0 +1,195 @@
|
|
1
|
+
def register_template_handler(class_name, *extensions)
|
2
|
+
Tilt.register Tilt.const_get(class_name), *extensions
|
3
|
+
rescue LoadError
|
4
|
+
# Only one of the Markdown processors needs to be available, so we can
|
5
|
+
# safely ignore these load errors.
|
6
|
+
end
|
7
|
+
|
8
|
+
register_template_handler :MarukuTemplate, 'mdown', 'md'
|
9
|
+
register_template_handler :KramdownTemplate, 'mdown', 'md'
|
10
|
+
register_template_handler :RDiscountTemplate, 'mdown', 'md'
|
11
|
+
register_template_handler :RedcarpetTemplate, 'mdown', 'md'
|
12
|
+
|
13
|
+
|
14
|
+
module Nesta
|
15
|
+
class MetadataParseError < RuntimeError; end
|
16
|
+
|
17
|
+
class FileModel
|
18
|
+
FORMATS = [:mdown, :md, :haml, :textile]
|
19
|
+
@@model_cache = {}
|
20
|
+
@@filename_cache = {}
|
21
|
+
|
22
|
+
attr_reader :filename, :mtime
|
23
|
+
|
24
|
+
class CaseInsensitiveHash < Hash
|
25
|
+
def [](key)
|
26
|
+
super(key.to_s.downcase)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.model_path(basename = nil)
|
31
|
+
Nesta::Config.content_path(basename)
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.find_all
|
35
|
+
file_pattern = File.join(model_path, "**", "*.{#{FORMATS.join(',')}}")
|
36
|
+
Dir.glob(file_pattern).map do |path|
|
37
|
+
relative = path.sub("#{model_path}/", "")
|
38
|
+
load(relative.sub(/\.(#{FORMATS.join('|')})/, ""))
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.find_file_for_path(path)
|
43
|
+
if ! @@filename_cache.has_key?(path)
|
44
|
+
FORMATS.each do |format|
|
45
|
+
[path, File.join(path, 'index')].each do |basename|
|
46
|
+
filename = model_path("#{basename}.#{format}")
|
47
|
+
if File.exist?(filename)
|
48
|
+
@@filename_cache[path] = filename
|
49
|
+
break
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
@@filename_cache[path]
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.needs_loading?(path, filename)
|
58
|
+
@@model_cache[path].nil? || File.mtime(filename) > @@model_cache[path].mtime
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.load(path)
|
62
|
+
if (filename = find_file_for_path(path)) && needs_loading?(path, filename)
|
63
|
+
@@model_cache[path] = self.new(filename)
|
64
|
+
end
|
65
|
+
@@model_cache[path]
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.purge_cache
|
69
|
+
@@model_cache = {}
|
70
|
+
@@filename_cache = {}
|
71
|
+
end
|
72
|
+
|
73
|
+
def initialize(filename)
|
74
|
+
@filename = filename
|
75
|
+
@format = filename.split('.').last.to_sym
|
76
|
+
if File.zero?(filename)
|
77
|
+
@metadata = {}
|
78
|
+
@markup = ''
|
79
|
+
else
|
80
|
+
@metadata, @markup = parse_file
|
81
|
+
end
|
82
|
+
@mtime = File.mtime(filename)
|
83
|
+
end
|
84
|
+
|
85
|
+
def ==(other)
|
86
|
+
other.respond_to?(:path) && (self.path == other.path)
|
87
|
+
end
|
88
|
+
|
89
|
+
def index_page?
|
90
|
+
@filename =~ /\/?index\.\w+$/
|
91
|
+
end
|
92
|
+
|
93
|
+
def abspath
|
94
|
+
file_path = @filename.sub(self.class.model_path, '')
|
95
|
+
if index_page?
|
96
|
+
File.dirname(file_path)
|
97
|
+
else
|
98
|
+
File.join(File.dirname(file_path), File.basename(file_path, '.*'))
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def path
|
103
|
+
abspath.sub(/^\//, '')
|
104
|
+
end
|
105
|
+
|
106
|
+
def permalink
|
107
|
+
File.basename(path)
|
108
|
+
end
|
109
|
+
|
110
|
+
def layout
|
111
|
+
(metadata('layout') || 'layout').to_sym
|
112
|
+
end
|
113
|
+
|
114
|
+
def template
|
115
|
+
(metadata('template') || 'page').to_sym
|
116
|
+
end
|
117
|
+
|
118
|
+
def to_html(scope = Object.new)
|
119
|
+
convert_to_html(@format, scope, markup)
|
120
|
+
end
|
121
|
+
|
122
|
+
def last_modified
|
123
|
+
@last_modified ||= File.stat(@filename).mtime
|
124
|
+
end
|
125
|
+
|
126
|
+
def description
|
127
|
+
metadata('description')
|
128
|
+
end
|
129
|
+
|
130
|
+
def keywords
|
131
|
+
metadata('keywords')
|
132
|
+
end
|
133
|
+
|
134
|
+
def metadata(key)
|
135
|
+
@metadata[key]
|
136
|
+
end
|
137
|
+
|
138
|
+
def flagged_as?(flag)
|
139
|
+
flags = metadata('flags')
|
140
|
+
flags && flags.split(',').map { |name| name.strip }.include?(flag)
|
141
|
+
end
|
142
|
+
|
143
|
+
def parse_metadata(first_paragraph)
|
144
|
+
is_metadata = first_paragraph.split("\n").first =~ /^[\w ]+:/
|
145
|
+
raise MetadataParseError unless is_metadata
|
146
|
+
metadata = CaseInsensitiveHash.new
|
147
|
+
first_paragraph.split("\n").each do |line|
|
148
|
+
key, value = line.split(/\s*:\s*/, 2)
|
149
|
+
next if value.nil?
|
150
|
+
metadata[key.downcase] = value.chomp
|
151
|
+
end
|
152
|
+
metadata
|
153
|
+
end
|
154
|
+
|
155
|
+
private
|
156
|
+
|
157
|
+
def markup
|
158
|
+
@markup
|
159
|
+
end
|
160
|
+
|
161
|
+
def parse_file
|
162
|
+
contents = File.open(@filename).read
|
163
|
+
rescue Errno::ENOENT
|
164
|
+
raise Sinatra::NotFound
|
165
|
+
else
|
166
|
+
first_paragraph, remaining = contents.split(/\r?\n\r?\n/, 2)
|
167
|
+
begin
|
168
|
+
return parse_metadata(first_paragraph), remaining
|
169
|
+
rescue MetadataParseError
|
170
|
+
return {}, contents
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def add_p_tags_to_haml(text)
|
175
|
+
contains_tags = (text =~ /^\s*%/)
|
176
|
+
if contains_tags
|
177
|
+
text
|
178
|
+
else
|
179
|
+
text.split(/\r?\n/).inject('') do |accumulator, line|
|
180
|
+
accumulator << "%p #{line}\n"
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
def convert_to_html(format, scope, text)
|
186
|
+
text = add_p_tags_to_haml(text) if @format == :haml
|
187
|
+
template = Tilt[format].new(renderer_config(@format)) { text }
|
188
|
+
template.render(scope)
|
189
|
+
end
|
190
|
+
|
191
|
+
def renderer_config(format)
|
192
|
+
{}
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|