mirror of
https://github.com/jekyll/jekyll.git
synced 2026-04-28 03:01:03 -04:00
Compare commits
2055 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2b4a3c008d | ||
|
|
9bc926be3f | ||
|
|
d7dc9d8091 | ||
|
|
6a98ab2a15 | ||
|
|
03d3eb7191 | ||
|
|
f783cc33d6 | ||
|
|
b1f1a5d65f | ||
|
|
7b9e1a8e93 | ||
|
|
1b91e6d89a | ||
|
|
f69c920364 | ||
|
|
5da9333f69 | ||
|
|
fcfc10747f | ||
|
|
c984d8c531 | ||
|
|
eec94cd964 | ||
|
|
e0fb513df4 | ||
|
|
45b40782db | ||
|
|
95f325898f | ||
|
|
1b3cb4515a | ||
|
|
dc14a1ac05 | ||
|
|
55a759357e | ||
|
|
59f80ac371 | ||
|
|
246ff3f9b6 | ||
|
|
294f25b126 | ||
|
|
7678de537c | ||
|
|
5f7df357d4 | ||
|
|
1c515c9789 | ||
|
|
e43db41e80 | ||
|
|
d1cbea8a37 | ||
|
|
4fa7aa2613 | ||
|
|
5e790a6d49 | ||
|
|
455e18624d | ||
|
|
7f1c3d4b7a | ||
|
|
61c8ab662b | ||
|
|
db6103bdee | ||
|
|
6e8fd8cb50 | ||
|
|
bbc2b66a84 | ||
|
|
a0bc843d9f | ||
|
|
b4ae9c6dc6 | ||
|
|
1bfe5a6f95 | ||
|
|
3b42be6e39 | ||
|
|
a5b46821ad | ||
|
|
f5da607792 | ||
|
|
05a982e5bc | ||
|
|
e5279d4773 | ||
|
|
a64a5b9571 | ||
|
|
3a225c2ed6 | ||
|
|
9d1641f163 | ||
|
|
a67adabf98 | ||
|
|
16844d168a | ||
|
|
6e30e177d1 | ||
|
|
121a0471f2 | ||
|
|
e007a14cf1 | ||
|
|
04b2f48bbd | ||
|
|
3b55bd1a51 | ||
|
|
3c60d63f0b | ||
|
|
e6afa6f07a | ||
|
|
48b23858ad | ||
|
|
b50056e8df | ||
|
|
528ec27df0 | ||
|
|
1c4b4ae271 | ||
|
|
0f4aed9ccf | ||
|
|
71f4383d18 | ||
|
|
dfae4669e4 | ||
|
|
a0f3860cfa | ||
|
|
3e5a1af234 | ||
|
|
e5f26b5a36 | ||
|
|
8f5465dfa4 | ||
|
|
86ea57ba58 | ||
|
|
031ff12eaf | ||
|
|
5082e144d8 | ||
|
|
e813e26da4 | ||
|
|
2ca9329a8d | ||
|
|
12225f49ea | ||
|
|
7b81f00137 | ||
|
|
45f69bb8cd | ||
|
|
170d6de8d9 | ||
|
|
f25a4ddfda | ||
|
|
f8dbbb1288 | ||
|
|
e45b6f91e7 | ||
|
|
5e425a99b4 | ||
|
|
7ac05b2b88 | ||
|
|
79c33af3fc | ||
|
|
35ddbe9398 | ||
|
|
05ba1afc29 | ||
|
|
6bcef622f5 | ||
|
|
d6176d6010 | ||
|
|
afd1c21af4 | ||
|
|
2a040fd527 | ||
|
|
ef5e131f53 | ||
|
|
8738a66f9f | ||
|
|
d9b12bc090 | ||
|
|
2e7c471c70 | ||
|
|
74734d46f8 | ||
|
|
7fbe61fc77 | ||
|
|
e9e4a5d21e | ||
|
|
260ad9a3fb | ||
|
|
e58d0ae0ef | ||
|
|
b89f943bf2 | ||
|
|
2f5303dd67 | ||
|
|
58365ae898 | ||
|
|
7330b499f1 | ||
|
|
ae993cbd6a | ||
|
|
c84627b2e1 | ||
|
|
915f8d3eb6 | ||
|
|
36f35bfe00 | ||
|
|
d8f38eef0e | ||
|
|
2cde74c44b | ||
|
|
5d92a90bde | ||
|
|
c2c671641d | ||
|
|
9186345eca | ||
|
|
4e01722941 | ||
|
|
aa9927f073 | ||
|
|
d63acc140d | ||
|
|
62d628c7e0 | ||
|
|
271dc42724 | ||
|
|
ff55da727e | ||
|
|
fb042ef624 | ||
|
|
87f9ed94a9 | ||
|
|
16c0bf8db8 | ||
|
|
18bdfac542 | ||
|
|
14f351fc19 | ||
|
|
d3e4c93163 | ||
|
|
84089f9ebe | ||
|
|
b1125f53de | ||
|
|
20303de60d | ||
|
|
ff504a39ba | ||
|
|
b72556fd03 | ||
|
|
8add5aec4b | ||
|
|
8fec927f83 | ||
|
|
63144fd46d | ||
|
|
7ae044ee44 | ||
|
|
e830e7954c | ||
|
|
8e1dd75312 | ||
|
|
53f975feb4 | ||
|
|
1d9c095b80 | ||
|
|
2410bcc001 | ||
|
|
e7043ac4f3 | ||
|
|
fa2c8d2a96 | ||
|
|
3eb25217ce | ||
|
|
45902b2047 | ||
|
|
611af3f456 | ||
|
|
9b091f8d5d | ||
|
|
6cda306bbf | ||
|
|
bc3e67da62 | ||
|
|
b9bdb85a47 | ||
|
|
4e0a803c01 | ||
|
|
30d82aff5d | ||
|
|
3435d05c2a | ||
|
|
464d4b0254 | ||
|
|
bb9462f12f | ||
|
|
9f4d4bbae0 | ||
|
|
a1fdf830db | ||
|
|
9c9481a8a9 | ||
|
|
ca29e4f585 | ||
|
|
ed7fcf6773 | ||
|
|
25cea4d3d2 | ||
|
|
951c604017 | ||
|
|
269018b011 | ||
|
|
2807b8a012 | ||
|
|
5a765affa3 | ||
|
|
1703b59ce8 | ||
|
|
85b6d936d8 | ||
|
|
abcab4b91f | ||
|
|
e193f5a738 | ||
|
|
51f32502b9 | ||
|
|
c91b622967 | ||
|
|
16eef80539 | ||
|
|
f9925bef2b | ||
|
|
e01c40f575 | ||
|
|
22b59ae793 | ||
|
|
c7bc76269c | ||
|
|
8563f59125 | ||
|
|
1bb8f9cf81 | ||
|
|
38a561a14c | ||
|
|
a82b063d42 | ||
|
|
f3b99ebda7 | ||
|
|
9181d22391 | ||
|
|
bea64a2cf7 | ||
|
|
666df42a28 | ||
|
|
402643435d | ||
|
|
d6b37a1644 | ||
|
|
908bb2e7af | ||
|
|
f1fd89bd8e | ||
|
|
92647c58aa | ||
|
|
b02ae4fad1 | ||
|
|
b732667aea | ||
|
|
1dc2a34252 | ||
|
|
93d282a5c1 | ||
|
|
baafe24e4a | ||
|
|
8ce4ff9060 | ||
|
|
47df90583a | ||
|
|
a7378da16c | ||
|
|
11da2e0d90 | ||
|
|
0340fea808 | ||
|
|
fffb834e63 | ||
|
|
87517af979 | ||
|
|
d35f0a8e16 | ||
|
|
d18d1bc43b | ||
|
|
edcbe99b58 | ||
|
|
f2d31a1b20 | ||
|
|
831eb17b29 | ||
|
|
4169075dd1 | ||
|
|
cd4829d28d | ||
|
|
75007cb26d | ||
|
|
47cb3a8fd7 | ||
|
|
14a5646730 | ||
|
|
7c5eae5ea2 | ||
|
|
1eb1f4ea4d | ||
|
|
12fc4c5ef4 | ||
|
|
34afc7784d | ||
|
|
8927898e1f | ||
|
|
753bdbefbf | ||
|
|
8c509bcf40 | ||
|
|
a446589cdc | ||
|
|
4c1427c400 | ||
|
|
1c767febe5 | ||
|
|
47c9ed0829 | ||
|
|
2db01b9651 | ||
|
|
010038e78a | ||
|
|
44a43b757d | ||
|
|
399606c544 | ||
|
|
8b72f14217 | ||
|
|
63a51df909 | ||
|
|
559cd6c7e7 | ||
|
|
2812341c37 | ||
|
|
ac56e9dd16 | ||
|
|
af3fe0f30d | ||
|
|
571f75ee64 | ||
|
|
d652f6e337 | ||
|
|
aecfe4c160 | ||
|
|
7c8e24a488 | ||
|
|
d1620db235 | ||
|
|
489b9c3639 | ||
|
|
11230718a4 | ||
|
|
7970abebf6 | ||
|
|
1f29e5b5dc | ||
|
|
44f0e5b14a | ||
|
|
d3c327e184 | ||
|
|
a849674f7d | ||
|
|
627af07c3e | ||
|
|
e9b1f6db3d | ||
|
|
585cd268ef | ||
|
|
775645e31c | ||
|
|
86696f6322 | ||
|
|
84ca5780df | ||
|
|
1b88345933 | ||
|
|
76c96fc7ac | ||
|
|
6fee5e3066 | ||
|
|
90586d229c | ||
|
|
b4ac044c29 | ||
|
|
371ca58e69 | ||
|
|
5cfef073a5 | ||
|
|
432ff579d9 | ||
|
|
0b79059310 | ||
|
|
1eba5093bd | ||
|
|
498ad6e83a | ||
|
|
611489aae1 | ||
|
|
14e6809bcd | ||
|
|
7c4f319442 | ||
|
|
3e29aaf785 | ||
|
|
3ab386f1b0 | ||
|
|
8c485155ce | ||
|
|
fe36329004 | ||
|
|
0eee6990d1 | ||
|
|
b0fa2462a6 | ||
|
|
5af105ca71 | ||
|
|
56622c7ab6 | ||
|
|
e164c2194d | ||
|
|
910cab5f84 | ||
|
|
48d6eea9b2 | ||
|
|
dba6df907f | ||
|
|
8bdfdae0ab | ||
|
|
90514b3536 | ||
|
|
eeb6ef46f1 | ||
|
|
32c3089ea9 | ||
|
|
b9f8fc1715 | ||
|
|
f4bbbd6952 | ||
|
|
5bf5c36ce0 | ||
|
|
feb84043dd | ||
|
|
3a49770ce2 | ||
|
|
6d196275fc | ||
|
|
250b6ebb7e | ||
|
|
8c9e9497a2 | ||
|
|
5db3b5d709 | ||
|
|
4dd66e9448 | ||
|
|
0125af80a3 | ||
|
|
2eae07b7d9 | ||
|
|
197dd184f9 | ||
|
|
68c3988861 | ||
|
|
fcb882e791 | ||
|
|
3c656ae2ed | ||
|
|
5647b91689 | ||
|
|
8cecdde288 | ||
|
|
a14f08b2bf | ||
|
|
4b2b5ea8b1 | ||
|
|
d09c4cdf79 | ||
|
|
9c4bf19c71 | ||
|
|
c6ee8a150a | ||
|
|
8b44a7bb42 | ||
|
|
407fc82b2d | ||
|
|
b6e15977de | ||
|
|
32cb87af90 | ||
|
|
137efdc9f4 | ||
|
|
872efb0bcc | ||
|
|
80f63949cd | ||
|
|
649399dcf8 | ||
|
|
83a29e7f4e | ||
|
|
e84a7aadee | ||
|
|
7bc9e1aae6 | ||
|
|
1e9163fdf4 | ||
|
|
6dbb5ac80c | ||
|
|
e9215ec047 | ||
|
|
d2fdac12c2 | ||
|
|
c421a4148a | ||
|
|
f00e217448 | ||
|
|
a134e05fda | ||
|
|
37f373fd38 | ||
|
|
2c0a535801 | ||
|
|
2567c885b0 | ||
|
|
bc806fd2a7 | ||
|
|
bba7870f8b | ||
|
|
bbd32980a1 | ||
|
|
fb716d6b83 | ||
|
|
6f2e3b8238 | ||
|
|
174d2f98ed | ||
|
|
0435871785 | ||
|
|
f04c9bb469 | ||
|
|
e68d18c3cc | ||
|
|
c1d44fc83f | ||
|
|
60bdc7119a | ||
|
|
33fcb0a263 | ||
|
|
f6bc58dd30 | ||
|
|
82bb18176f | ||
|
|
581dee7ba9 | ||
|
|
14ed5cc954 | ||
|
|
981e32d462 | ||
|
|
7a12f32078 | ||
|
|
f6b34f74a9 | ||
|
|
a2ee820609 | ||
|
|
87400f2155 | ||
|
|
376c87b62e | ||
|
|
73db98c244 | ||
|
|
d99f257665 | ||
|
|
b75fb37b4e | ||
|
|
3151aacbad | ||
|
|
498ea4fd24 | ||
|
|
f764ae6a76 | ||
|
|
06777a51c8 | ||
|
|
3474481043 | ||
|
|
5928618de1 | ||
|
|
87829b3da1 | ||
|
|
c61a5adb05 | ||
|
|
d063e6abe7 | ||
|
|
8bb7861162 | ||
|
|
ae11cae659 | ||
|
|
e4e14e8860 | ||
|
|
35a7d94202 | ||
|
|
ee666e319b | ||
|
|
0f447751be | ||
|
|
f054bae503 | ||
|
|
4a0a3dbf39 | ||
|
|
8a289793bb | ||
|
|
60a811d405 | ||
|
|
b90f6f77e8 | ||
|
|
15c4d9bee2 | ||
|
|
b69eaa34dd | ||
|
|
221c0b62b6 | ||
|
|
ba12d28fbe | ||
|
|
f34a00490f | ||
|
|
ce9fcfaebb | ||
|
|
e68609c849 | ||
|
|
5acac3561a | ||
|
|
2b9ce826d6 | ||
|
|
9c5c9d826a | ||
|
|
56c38f87b2 | ||
|
|
f99abc5314 | ||
|
|
015e9570cd | ||
|
|
3b48dd2652 | ||
|
|
46895b46a6 | ||
|
|
cd912b5233 | ||
|
|
b1e984128e | ||
|
|
c19ad411a4 | ||
|
|
a1d78cdea6 | ||
|
|
4b038259c7 | ||
|
|
79a178f7f1 | ||
|
|
736e6a78f1 | ||
|
|
245d9677d7 | ||
|
|
6ca9633354 | ||
|
|
ae584e43ed | ||
|
|
51adebd0db | ||
|
|
95a30fa51d | ||
|
|
f5351f7268 | ||
|
|
bd25c62f55 | ||
|
|
cf778e2be6 | ||
|
|
bda515bfc7 | ||
|
|
e5bbdb1c83 | ||
|
|
6a26907495 | ||
|
|
8546298047 | ||
|
|
eab92d3b96 | ||
|
|
d3e867d4a0 | ||
|
|
ee7f7baef2 | ||
|
|
4e34d2627b | ||
|
|
9ab3c201c8 | ||
|
|
786f6e1985 | ||
|
|
6597bacee8 | ||
|
|
e93e49c269 | ||
|
|
166fdf35a3 | ||
|
|
159dbd0170 | ||
|
|
bac28fcfce | ||
|
|
987309917a | ||
|
|
76c1dcc791 | ||
|
|
7be47c2c48 | ||
|
|
c59d02d6c6 | ||
|
|
6ce345be59 | ||
|
|
095736b5ef | ||
|
|
791b2eccf6 | ||
|
|
4302604c89 | ||
|
|
269662d0f0 | ||
|
|
9c03fc3f27 | ||
|
|
f908051aa4 | ||
|
|
80a921ccfd | ||
|
|
ab83f0bf2e | ||
|
|
701617cb0e | ||
|
|
e3ab992f75 | ||
|
|
a682ca1600 | ||
|
|
fff7bb31f5 | ||
|
|
0072865512 | ||
|
|
da80240fac | ||
|
|
3aaa889218 | ||
|
|
f26cdd8da4 | ||
|
|
00aa2955d8 | ||
|
|
dead70724e | ||
|
|
d15e4a9c8a | ||
|
|
ff3edbc16b | ||
|
|
68907ab833 | ||
|
|
7d3a5f82be | ||
|
|
5a60adb6bd | ||
|
|
4f06ba7884 | ||
|
|
ae039663b9 | ||
|
|
6dcdf06c8a | ||
|
|
e19d6c3f7e | ||
|
|
62cfd45d79 | ||
|
|
ab35d32feb | ||
|
|
d870dfedee | ||
|
|
c916f08aa3 | ||
|
|
059c7c6adf | ||
|
|
7126792d85 | ||
|
|
f645cd3377 | ||
|
|
b718d4ea46 | ||
|
|
ec90210ed4 | ||
|
|
9e86650df2 | ||
|
|
53ca3446eb | ||
|
|
c76c4e478b | ||
|
|
25af3e785f | ||
|
|
0374ad2668 | ||
|
|
66a9e6909b | ||
|
|
2f75ade1b7 | ||
|
|
1b5977c018 | ||
|
|
4b108df3ab | ||
|
|
279fb6af11 | ||
|
|
2c316188fe | ||
|
|
20d48fcfe9 | ||
|
|
70a3156385 | ||
|
|
bf98004843 | ||
|
|
436c98ad9b | ||
|
|
12b16dde52 | ||
|
|
9f55b1ff66 | ||
|
|
eeb13872e3 | ||
|
|
f14af82da5 | ||
|
|
b6ea045e1b | ||
|
|
6d6c15eba2 | ||
|
|
a91775fcfe | ||
|
|
2c373e6fe9 | ||
|
|
f86727c45a | ||
|
|
76416e50e8 | ||
|
|
90793b12e7 | ||
|
|
9c02353b3c | ||
|
|
329ed07405 | ||
|
|
305a22a5bf | ||
|
|
a9dbb0de57 | ||
|
|
28a1d2445e | ||
|
|
f0cac685de | ||
|
|
0e52b83b6f | ||
|
|
1ac7f5cb15 | ||
|
|
397492fa38 | ||
|
|
fa435fae94 | ||
|
|
b2aa8b6e68 | ||
|
|
f75346c799 | ||
|
|
ec7474f55c | ||
|
|
799edabc3d | ||
|
|
6d3fc08a40 | ||
|
|
e82cb3115d | ||
|
|
ebc6dff37e | ||
|
|
017a26457c | ||
|
|
18209ff78c | ||
|
|
d10c46d4fd | ||
|
|
391a672ac4 | ||
|
|
86211a020d | ||
|
|
c6dce1660b | ||
|
|
1f8157022a | ||
|
|
d67ad64335 | ||
|
|
44b13f408e | ||
|
|
d98047ef74 | ||
|
|
8f4194eea5 | ||
|
|
a95b861d69 | ||
|
|
dc617767b3 | ||
|
|
cc3ee868f4 | ||
|
|
407eda8e83 | ||
|
|
e7d0b6c5a5 | ||
|
|
1503ccce7d | ||
|
|
5a702bfe13 | ||
|
|
5960069cd0 | ||
|
|
3a85aa0dac | ||
|
|
dfb5a2f2fc | ||
|
|
55c890f73a | ||
|
|
d39d0cea19 | ||
|
|
d4b8f0d9dd | ||
|
|
f635f3d34b | ||
|
|
db0e1a683c | ||
|
|
eea4a82dc6 | ||
|
|
334cc5a6ea | ||
|
|
e91527058a | ||
|
|
706007ead9 | ||
|
|
fa3a912e89 | ||
|
|
88d9cf4816 | ||
|
|
27d3efecc1 | ||
|
|
ed3fe2e2b4 | ||
|
|
75afac9bc0 | ||
|
|
7edde72523 | ||
|
|
a7dff06175 | ||
|
|
a8b7a224c8 | ||
|
|
6e3bba154c | ||
|
|
a5b9df7287 | ||
|
|
4ef30b3a6f | ||
|
|
f30dba8883 | ||
|
|
780755a8a5 | ||
|
|
2bcfdb9662 | ||
|
|
80bd6d311d | ||
|
|
99a9e0a74d | ||
|
|
8d54eb8f6b | ||
|
|
77a381c542 | ||
|
|
55392fd8d2 | ||
|
|
7630f5408c | ||
|
|
b647037643 | ||
|
|
8d1f8ee7a0 | ||
|
|
63a1ec8949 | ||
|
|
d9958de9d1 | ||
|
|
e82eaa4b0f | ||
|
|
e770a080a7 | ||
|
|
324748a5a6 | ||
|
|
15ebf929e1 | ||
|
|
c96062781d | ||
|
|
adce349d7a | ||
|
|
e268ee0f33 | ||
|
|
b02342312b | ||
|
|
06c4b42a5a | ||
|
|
6988eea9ce | ||
|
|
333b9f5f93 | ||
|
|
6d20525dce | ||
|
|
16a2cfed49 | ||
|
|
767c18e93b | ||
|
|
4835e9317a | ||
|
|
c83b016219 | ||
|
|
778429c6cc | ||
|
|
eb2fc89776 | ||
|
|
fccc02be6f | ||
|
|
506a1db116 | ||
|
|
6a387b45aa | ||
|
|
bb57c80478 | ||
|
|
b6424c9197 | ||
|
|
6a66a3af5a | ||
|
|
10967d8904 | ||
|
|
3c9e43eb36 | ||
|
|
0ca5bd3224 | ||
|
|
0d288c54da | ||
|
|
41fb36a36f | ||
|
|
c6d62828ba | ||
|
|
29853ab46d | ||
|
|
f4a14b60ba | ||
|
|
045f38d467 | ||
|
|
00093b91fa | ||
|
|
2d0d27da73 | ||
|
|
7d93e3fdcd | ||
|
|
d3bd81361c | ||
|
|
06785f2bfd | ||
|
|
d36c3b0073 | ||
|
|
eb064b6684 | ||
|
|
d3e23c2fae | ||
|
|
59add4737b | ||
|
|
b5a73373ff | ||
|
|
dac2b17123 | ||
|
|
007c059315 | ||
|
|
7a7ecbadea | ||
|
|
0d96ad21d2 | ||
|
|
3a3b528014 | ||
|
|
1100ca0782 | ||
|
|
0e10503259 | ||
|
|
9021e98721 | ||
|
|
67ba8ad0cb | ||
|
|
269bcbb7a8 | ||
|
|
50a41100e7 | ||
|
|
b178358cf9 | ||
|
|
00cdcbc184 | ||
|
|
bebd80342e | ||
|
|
013f7edc83 | ||
|
|
c371926e09 | ||
|
|
66785b43ba | ||
|
|
6d9258bcdc | ||
|
|
6b4219f0e2 | ||
|
|
bb4d47b905 | ||
|
|
b41ddbb8a9 | ||
|
|
02e98f238e | ||
|
|
2185339ee0 | ||
|
|
3a4d826852 | ||
|
|
4a89db2102 | ||
|
|
4b8e3cfdbd | ||
|
|
7806f9ed52 | ||
|
|
489da6784a | ||
|
|
117bd8a6f0 | ||
|
|
e229e3285f | ||
|
|
a608494e18 | ||
|
|
f6f2626828 | ||
|
|
252665ddc6 | ||
|
|
51dc0dfcf5 | ||
|
|
c8d23ffee2 | ||
|
|
ced9146c11 | ||
|
|
ca7375a51b | ||
|
|
9e1cb96a7e | ||
|
|
c1562c8997 | ||
|
|
7114380da7 | ||
|
|
1b796354fb | ||
|
|
f252a82afc | ||
|
|
2f88a0c0a1 | ||
|
|
2857350df1 | ||
|
|
9bcad08e3a | ||
|
|
a4adeb446b | ||
|
|
504c9a34ad | ||
|
|
29169aa858 | ||
|
|
67a2369854 | ||
|
|
537235c38b | ||
|
|
5b0e2a294d | ||
|
|
e586105b46 | ||
|
|
ddfecb0f53 | ||
|
|
6e06fd8734 | ||
|
|
05bbcddb29 | ||
|
|
c836ec613d | ||
|
|
bb9d43dff5 | ||
|
|
0d1586a5c4 | ||
|
|
2ef9bae75a | ||
|
|
fa31fcb3bf | ||
|
|
d40b6d6ee0 | ||
|
|
5e9b7343bf | ||
|
|
5d1a24e291 | ||
|
|
d56df7592c | ||
|
|
669c803912 | ||
|
|
8917ef011c | ||
|
|
27a02e163b | ||
|
|
7a31029c79 | ||
|
|
48bf711ec7 | ||
|
|
b3371119fd | ||
|
|
dae5d30096 | ||
|
|
bc2b87ca92 | ||
|
|
f251848283 | ||
|
|
2b1b7b977b | ||
|
|
c2b613d05e | ||
|
|
5ee4e6d9c9 | ||
|
|
92a9582733 | ||
|
|
78af3c5018 | ||
|
|
0565308ce6 | ||
|
|
9437bd4669 | ||
|
|
9b962dc565 | ||
|
|
f1edf9e692 | ||
|
|
fbe52bca85 | ||
|
|
60f0977a50 | ||
|
|
7d6d29b4ca | ||
|
|
6b09d1818d | ||
|
|
50a4b2824b | ||
|
|
6c073ec476 | ||
|
|
8e87e9ebec | ||
|
|
e777c9b213 | ||
|
|
d79c0fc4dd | ||
|
|
dae77e9a63 | ||
|
|
e4b1382bfd | ||
|
|
cd7b3f54f1 | ||
|
|
a25f2d7dd6 | ||
|
|
ed953e6e1f | ||
|
|
5a84d1960e | ||
|
|
e56f2414ae | ||
|
|
531d0fb261 | ||
|
|
14fa3287b7 | ||
|
|
8997212222 | ||
|
|
a621752425 | ||
|
|
90c974c4e2 | ||
|
|
3f3b203992 | ||
|
|
4da6bfd81a | ||
|
|
21fa47f92b | ||
|
|
03d21b0cd1 | ||
|
|
c1f7684b92 | ||
|
|
7fb71871cf | ||
|
|
b75db477e0 | ||
|
|
9e0bad7255 | ||
|
|
bebb75ff0e | ||
|
|
a43d3d1dc8 | ||
|
|
5d97ec9174 | ||
|
|
929d18fefc | ||
|
|
422fd7d304 | ||
|
|
a4db7ec63c | ||
|
|
e2306ed79b | ||
|
|
13f8227877 | ||
|
|
5c388309b2 | ||
|
|
faa5a446ba | ||
|
|
0903515c39 | ||
|
|
6cc298d615 | ||
|
|
7a93ca6f6c | ||
|
|
1923fc39df | ||
|
|
e888a41b2d | ||
|
|
6bc3dee98d | ||
|
|
7db9397a9d | ||
|
|
ae244c4425 | ||
|
|
c40272cebd | ||
|
|
26acb3f9d9 | ||
|
|
7ad0597bff | ||
|
|
ace1b6b8d2 | ||
|
|
52c4ce2a5a | ||
|
|
8186873e27 | ||
|
|
4b59eb4175 | ||
|
|
d2b19963c1 | ||
|
|
47ee5db5fc | ||
|
|
3e030ea784 | ||
|
|
e240bbb1bf | ||
|
|
04430b2c17 | ||
|
|
80f64dea89 | ||
|
|
29534469c3 | ||
|
|
705fdfb23d | ||
|
|
cd1326d457 | ||
|
|
1beee0d59d | ||
|
|
4d0cb3345f | ||
|
|
9a0db42436 | ||
|
|
dbead70168 | ||
|
|
e9638fa6a2 | ||
|
|
9caa47d164 | ||
|
|
05dc4df7e4 | ||
|
|
7fb3b096c3 | ||
|
|
32cc745142 | ||
|
|
17e4c8ab42 | ||
|
|
5fa1aadf7f | ||
|
|
edb50b81a3 | ||
|
|
a2bf106c47 | ||
|
|
ae0b13b531 | ||
|
|
f2696c1c4c | ||
|
|
ac7c1d0cd6 | ||
|
|
e81b020d7e | ||
|
|
9f22749ebb | ||
|
|
6e89c1c02b | ||
|
|
fa6981fb8c | ||
|
|
5f38430304 | ||
|
|
22759edf3e | ||
|
|
00ec13c11b | ||
|
|
9b50fc9f3b | ||
|
|
58dc1f77e9 | ||
|
|
461ea2f147 | ||
|
|
30b42c4700 | ||
|
|
c6d5a913f1 | ||
|
|
712d8d617d | ||
|
|
7c9ad82b2a | ||
|
|
491cce7a99 | ||
|
|
e99a9e5821 | ||
|
|
249249f76b | ||
|
|
0d602018bd | ||
|
|
a907addbe2 | ||
|
|
7a5a90de82 | ||
|
|
a64b7e7a62 | ||
|
|
f933164a2a | ||
|
|
0914948099 | ||
|
|
c96abf7e82 | ||
|
|
8fe9561f64 | ||
|
|
83ad59841b | ||
|
|
33c3b41f69 | ||
|
|
c08c794801 | ||
|
|
b81f6ed38c | ||
|
|
1f503b24b3 | ||
|
|
bf149a0b97 | ||
|
|
a0134dea4f | ||
|
|
c625b94bc0 | ||
|
|
72e297366d | ||
|
|
11b38568fa | ||
|
|
4ce60741d9 | ||
|
|
56102ce50c | ||
|
|
4d20462da5 | ||
|
|
571800c8ad | ||
|
|
d795113e94 | ||
|
|
dbc8530068 | ||
|
|
90370c0d0b | ||
|
|
dc9db9cbe2 | ||
|
|
bee4d93114 | ||
|
|
7858f80823 | ||
|
|
2b95fb924e | ||
|
|
ea9b959c23 | ||
|
|
a87bf521c8 | ||
|
|
20bfdbb794 | ||
|
|
6a74c09185 | ||
|
|
943070aac6 | ||
|
|
1fa428c6e4 | ||
|
|
fdc0e33ebc | ||
|
|
aec5ceb184 | ||
|
|
6d4a1ec4e6 | ||
|
|
e3d2578230 | ||
|
|
fbb766becc | ||
|
|
85a89d3e22 | ||
|
|
1df8801957 | ||
|
|
7abc8c8025 | ||
|
|
77216b61dc | ||
|
|
4f078ee2e8 | ||
|
|
6521b84aac | ||
|
|
120d3e07ca | ||
|
|
0bf17923b5 | ||
|
|
5e541b5eb0 | ||
|
|
128427cc87 | ||
|
|
2bec317a2a | ||
|
|
2745be736e | ||
|
|
32c48bb78d | ||
|
|
d24ea66933 | ||
|
|
e71c23981d | ||
|
|
403aade8c1 | ||
|
|
8e1b9fcdf5 | ||
|
|
c8602d7af7 | ||
|
|
9e717a61e7 | ||
|
|
9ba9c47cd6 | ||
|
|
8f9d3c9647 | ||
|
|
9815a7b0ee | ||
|
|
8da7d1a5bc | ||
|
|
0154c580cd | ||
|
|
3318c38eec | ||
|
|
f55eb1f3fb | ||
|
|
3d843d81e6 | ||
|
|
a87cda4b12 | ||
|
|
65d43ef398 | ||
|
|
057b8cae7f | ||
|
|
336bb44750 | ||
|
|
18e0d2fe75 | ||
|
|
63792ad322 | ||
|
|
6883a0b397 | ||
|
|
922a92d67a | ||
|
|
ec397e1629 | ||
|
|
ec7d2ed5b6 | ||
|
|
aceb5b5d53 | ||
|
|
32a2e8b4ef | ||
|
|
9f4aeaddea | ||
|
|
a2b19c1d2b | ||
|
|
01f7b9ccef | ||
|
|
c6166ab485 | ||
|
|
18893b828b | ||
|
|
3bac8a2034 | ||
|
|
51d8d5e267 | ||
|
|
0c624eb11b | ||
|
|
b100b3b121 | ||
|
|
e2e6e7dc22 | ||
|
|
dcd3dafdbc | ||
|
|
fe08405ae1 | ||
|
|
bfe28cbead | ||
|
|
63bca94bde | ||
|
|
e1e60499b1 | ||
|
|
ff646738fc | ||
|
|
aa44c7f53d | ||
|
|
368b862ebb | ||
|
|
69e8f1923c | ||
|
|
5e0341c9b3 | ||
|
|
382c54e057 | ||
|
|
3e609b1cd9 | ||
|
|
97797cb241 | ||
|
|
31b03e9b86 | ||
|
|
317e2f460e | ||
|
|
980dbdbcc4 | ||
|
|
a94ffd8eb9 | ||
|
|
d20df4120d | ||
|
|
b360154973 | ||
|
|
4bcb0a322c | ||
|
|
ef54bfe5a1 | ||
|
|
cecd974d8e | ||
|
|
3be90c7822 | ||
|
|
d2c717c3c6 | ||
|
|
ef426cd490 | ||
|
|
053ba68a15 | ||
|
|
51e2cb3629 | ||
|
|
b951696114 | ||
|
|
5d750f5a71 | ||
|
|
5ed24cfd71 | ||
|
|
88348ae0ee | ||
|
|
c4255ebc58 | ||
|
|
53a59544e8 | ||
|
|
018f333973 | ||
|
|
c2f0b9a799 | ||
|
|
58e231ce40 | ||
|
|
29aabd84bd | ||
|
|
90eecc5da6 | ||
|
|
3d60299ea9 | ||
|
|
382049d558 | ||
|
|
fe5f0d124c | ||
|
|
589919d58a | ||
|
|
e58f8776b9 | ||
|
|
c378f741a8 | ||
|
|
6f440f55e0 | ||
|
|
cbe5f8e4dd | ||
|
|
dec27bc166 | ||
|
|
2b29e09177 | ||
|
|
9d547f74cc | ||
|
|
c1da91cf5c | ||
|
|
877cba9811 | ||
|
|
2547d8adf3 | ||
|
|
091e86aa22 | ||
|
|
f11837dd7b | ||
|
|
d28fb07bb9 | ||
|
|
aaf0ba15cc | ||
|
|
ef2d558874 | ||
|
|
f7271a6ef9 | ||
|
|
10659e1eef | ||
|
|
aaea08e094 | ||
|
|
6081fcd75a | ||
|
|
18fb1bafa0 | ||
|
|
cf2f439db1 | ||
|
|
87500addd5 | ||
|
|
5868ba1691 | ||
|
|
3fe80929ad | ||
|
|
57b43e2229 | ||
|
|
b2099ac763 | ||
|
|
c7d92c4e6d | ||
|
|
7f44500b4b | ||
|
|
6d9b4c2aba | ||
|
|
1715956baa | ||
|
|
a312115a5a | ||
|
|
3d69582d36 | ||
|
|
84cfc1ceff | ||
|
|
153db8a230 | ||
|
|
18f3d76603 | ||
|
|
8692822631 | ||
|
|
07ccbd9fac | ||
|
|
1fc3887d4f | ||
|
|
ba2e1390ad | ||
|
|
a1ea8b9798 | ||
|
|
f5fbf4ffd1 | ||
|
|
02aa2a1c33 | ||
|
|
60da4ef010 | ||
|
|
b1fd7377fd | ||
|
|
5d6fe236b2 | ||
|
|
3cb0f4f590 | ||
|
|
2547df81a1 | ||
|
|
8e7d40ed90 | ||
|
|
99ae1023b4 | ||
|
|
59e1e2dd84 | ||
|
|
ce78ea7818 | ||
|
|
b2e114ed5b | ||
|
|
06b6e86d52 | ||
|
|
5b50687e22 | ||
|
|
763118a381 | ||
|
|
80465efff7 | ||
|
|
588bba39ad | ||
|
|
936c737a32 | ||
|
|
b31d8a1ecd | ||
|
|
e13c800b3a | ||
|
|
e724622a92 | ||
|
|
e378b2efd3 | ||
|
|
12cbfa8cf4 | ||
|
|
aedff733e0 | ||
|
|
fa7d4cde67 | ||
|
|
7be49c99c1 | ||
|
|
d2b33144a7 | ||
|
|
60921132c6 | ||
|
|
e7dcc2424a | ||
|
|
7439d303c4 | ||
|
|
e7feae98f5 | ||
|
|
c26f040bcf | ||
|
|
5e9706e2aa | ||
|
|
965e3a1173 | ||
|
|
09230cde50 | ||
|
|
312717b56d | ||
|
|
f228b31c2e | ||
|
|
244310fbaa | ||
|
|
6816b5ea76 | ||
|
|
7c8e4d46eb | ||
|
|
585a31d8aa | ||
|
|
e2a5a9dbc1 | ||
|
|
f2650e7b0f | ||
|
|
8b6a9d66ec | ||
|
|
0bf82e9cf7 | ||
|
|
4e9b0663be | ||
|
|
b9542c5426 | ||
|
|
0a4bd99e6b | ||
|
|
5536f950f9 | ||
|
|
989639256d | ||
|
|
9a52d56b5a | ||
|
|
a6238c36d5 | ||
|
|
730aedd0a3 | ||
|
|
4cbd814546 | ||
|
|
cae9d96cc4 | ||
|
|
8a9c48c7b4 | ||
|
|
faccf8f802 | ||
|
|
a0f2b5f944 | ||
|
|
bce4680182 | ||
|
|
b92274b101 | ||
|
|
e7c0e313a3 | ||
|
|
54d0bf47e8 | ||
|
|
d47b882af2 | ||
|
|
2f4e5fa28b | ||
|
|
c4d617e6aa | ||
|
|
f95d0ba840 | ||
|
|
502fd94f2c | ||
|
|
c58ac78a5e | ||
|
|
7655b533c9 | ||
|
|
b6c197d312 | ||
|
|
1062fdf89f | ||
|
|
a2b6aa263e | ||
|
|
620115a986 | ||
|
|
1ca06e70d3 | ||
|
|
919d37fb37 | ||
|
|
f7dafb1f04 | ||
|
|
6504645c60 | ||
|
|
fc0ea20a85 | ||
|
|
b20a175c27 | ||
|
|
2f06f4aad7 | ||
|
|
ff3fa84b8a | ||
|
|
7f370cb82f | ||
|
|
51951c43e8 | ||
|
|
a88f2567f7 | ||
|
|
d159684f87 | ||
|
|
d29dd11ae3 | ||
|
|
8d968ebae0 | ||
|
|
86f7196ef5 | ||
|
|
064d6de48d | ||
|
|
21bd3e6c5a | ||
|
|
07bd3a3759 | ||
|
|
e40e12fabd | ||
|
|
a098dc80cd | ||
|
|
419aaba07c | ||
|
|
7cd5847826 | ||
|
|
9109da32f9 | ||
|
|
7bcf8d689e | ||
|
|
f66862c508 | ||
|
|
cb95a72f5a | ||
|
|
9b81f29625 | ||
|
|
5e10958faa | ||
|
|
7f034f51e3 | ||
|
|
1fc99bdd97 | ||
|
|
7fc47bfc43 | ||
|
|
b2146e8659 | ||
|
|
e0a011c917 | ||
|
|
63ec07a062 | ||
|
|
5f03314d85 | ||
|
|
442deb6a7e | ||
|
|
d7d7d924f7 | ||
|
|
35a5af783a | ||
|
|
a6781bda30 | ||
|
|
bab7ef4b1d | ||
|
|
6f7ea381b3 | ||
|
|
612eb737a5 | ||
|
|
004f923644 | ||
|
|
191c2279d2 | ||
|
|
e39dfa3f0b | ||
|
|
5af7694f3b | ||
|
|
6e5850c6ab | ||
|
|
be23e18555 | ||
|
|
928be16fab | ||
|
|
eac3ac095f | ||
|
|
aa4beda868 | ||
|
|
1fad3a074f | ||
|
|
0fe2094dd2 | ||
|
|
c576d23908 | ||
|
|
8c19a6f430 | ||
|
|
ac41312c5d | ||
|
|
232a58d5b4 | ||
|
|
0c0aea3ad7 | ||
|
|
657b16519e | ||
|
|
f81601ee53 | ||
|
|
b6641be8ef | ||
|
|
a8ec9cd507 | ||
|
|
2f8248a6f1 | ||
|
|
0eb2796a66 | ||
|
|
e120c255ff | ||
|
|
990a9e6e6d | ||
|
|
c24c6b7f3d | ||
|
|
039c521e8c | ||
|
|
d35af9c1f3 | ||
|
|
f6bff6fb61 | ||
|
|
a103898980 | ||
|
|
3957efac15 | ||
|
|
38309569c4 | ||
|
|
8bfc696569 | ||
|
|
b68dd3a5cb | ||
|
|
3940e1e9df | ||
|
|
70a331d854 | ||
|
|
5bf1596414 | ||
|
|
3234041510 | ||
|
|
37631eefac | ||
|
|
82b1ad0552 | ||
|
|
2c2347fac1 | ||
|
|
0aa61f66a8 | ||
|
|
b1a517ccb6 | ||
|
|
4070143d5b | ||
|
|
6e4e290ab0 | ||
|
|
d6995d347a | ||
|
|
52085d2e34 | ||
|
|
f3a274377a | ||
|
|
0fcba080c3 | ||
|
|
922ba5d0ea | ||
|
|
cb2eea0e41 | ||
|
|
8284714d8a | ||
|
|
aaf6f28fde | ||
|
|
7227ad4ebb | ||
|
|
c3e47437a3 | ||
|
|
76301722e9 | ||
|
|
d05df326b9 | ||
|
|
dc12bd3023 | ||
|
|
878c689f76 | ||
|
|
68a7ebf2ee | ||
|
|
63ed335463 | ||
|
|
fe14434f8d | ||
|
|
a069ad77c0 | ||
|
|
5343fc3b54 | ||
|
|
2dad0d3304 | ||
|
|
f789168522 | ||
|
|
7656b9d295 | ||
|
|
176dc3cef7 | ||
|
|
360412364e | ||
|
|
49115dbdab | ||
|
|
383a0d0aa7 | ||
|
|
b735170ceb | ||
|
|
59acdaab9a | ||
|
|
12651c19e5 | ||
|
|
1694f8609c | ||
|
|
e80469b7b0 | ||
|
|
032139bd2f | ||
|
|
6deed4c66b | ||
|
|
253bcc2faf | ||
|
|
43a28aed96 | ||
|
|
5d9662f80f | ||
|
|
ed9cc80ff9 | ||
|
|
9b6eeba81e | ||
|
|
40e4c031e3 | ||
|
|
f80dc07f82 | ||
|
|
52f0b36558 | ||
|
|
f8af94431d | ||
|
|
89bdd47ebc | ||
|
|
2c85f4ef24 | ||
|
|
c8fc567c8d | ||
|
|
460dd81fe1 | ||
|
|
7c8c41f0d7 | ||
|
|
3b57879e71 | ||
|
|
19527b47ab | ||
|
|
8298733e67 | ||
|
|
64b0102686 | ||
|
|
bfab00a65a | ||
|
|
fea79dcbab | ||
|
|
b4bc3b0aa0 | ||
|
|
ac7f592839 | ||
|
|
4ccf9ea683 | ||
|
|
7de9433fbc | ||
|
|
9c8acdd3ea | ||
|
|
e9904fd44b | ||
|
|
ba9a309572 | ||
|
|
d0e12d69bc | ||
|
|
75cf2d73f6 | ||
|
|
974fab6c9c | ||
|
|
2a37f459d4 | ||
|
|
5a554572e3 | ||
|
|
a701e59c07 | ||
|
|
b6d81c58df | ||
|
|
4776b27ff3 | ||
|
|
87d08ec827 | ||
|
|
229303bbc8 | ||
|
|
8603738a89 | ||
|
|
932cd3b575 | ||
|
|
02f281eef3 | ||
|
|
8a257aca6b | ||
|
|
588f21f5cd | ||
|
|
0662d31bf6 | ||
|
|
a6f8b6c7d6 | ||
|
|
e51f94a038 | ||
|
|
1aa5c7a820 | ||
|
|
37af23b5d7 | ||
|
|
df87a51ade | ||
|
|
2a138e4ca9 | ||
|
|
e546eb3e9f | ||
|
|
d250efccb9 | ||
|
|
dc30114605 | ||
|
|
2a5cf11ee2 | ||
|
|
e23a74aad9 | ||
|
|
5b77d02e3b | ||
|
|
c2b24e82e5 | ||
|
|
10030ae8cd | ||
|
|
75c5c16297 | ||
|
|
ef53e677a4 | ||
|
|
03d9396b85 | ||
|
|
4acf343fea | ||
|
|
665178d210 | ||
|
|
b1bba1945a | ||
|
|
8ed6c7b077 | ||
|
|
9a94829bcb | ||
|
|
d17b80bf2a | ||
|
|
ac03af3229 | ||
|
|
fe6bfc6f1b | ||
|
|
d438362971 | ||
|
|
842470b0c4 | ||
|
|
11917645f2 | ||
|
|
cb8a4b4d62 | ||
|
|
a75ed0b33d | ||
|
|
58511822e6 | ||
|
|
876253edce | ||
|
|
d7e3d4df8f | ||
|
|
0f669ba9b1 | ||
|
|
a9a21e6572 | ||
|
|
3b05b0d867 | ||
|
|
b16d47a444 | ||
|
|
d2d3087d3b | ||
|
|
b9a4cf0485 | ||
|
|
848e402937 | ||
|
|
c0951b0a19 | ||
|
|
3592284969 | ||
|
|
0f458edf2b | ||
|
|
1adf8974bf | ||
|
|
da443039e1 | ||
|
|
4aee950418 | ||
|
|
9e454d24a0 | ||
|
|
5185c8d72b | ||
|
|
6f9d28f398 | ||
|
|
2195e5e469 | ||
|
|
60202782ea | ||
|
|
32b14d6402 | ||
|
|
22275e571d | ||
|
|
4142630614 | ||
|
|
3d8368fa4f | ||
|
|
687b9cdf19 | ||
|
|
ecca3accdc | ||
|
|
5aa747e99a | ||
|
|
b5a32a6d46 | ||
|
|
426f2a79fc | ||
|
|
d9cdc7992a | ||
|
|
829133cf98 | ||
|
|
27362a1984 | ||
|
|
3014fbd344 | ||
|
|
596b9e0785 | ||
|
|
39c9fb120f | ||
|
|
314fb875b5 | ||
|
|
3b40d964fb | ||
|
|
a48379a715 | ||
|
|
d4c15efff9 | ||
|
|
2a41945014 | ||
|
|
dc248345a9 | ||
|
|
b6f3adb6e3 | ||
|
|
472c18e409 | ||
|
|
e42f5ac2dc | ||
|
|
06750b8502 | ||
|
|
bd907c5be6 | ||
|
|
c79fe1125c | ||
|
|
20f0940455 | ||
|
|
84cef2202d | ||
|
|
eaa132c65b | ||
|
|
2d31d07602 | ||
|
|
d99814baa5 | ||
|
|
ab05a2cd4f | ||
|
|
db8163b6e8 | ||
|
|
22d11bef2d | ||
|
|
70159ac8cb | ||
|
|
5eb300043f | ||
|
|
95b62e564b | ||
|
|
ad745702ca | ||
|
|
4b0089712e | ||
|
|
264caac94c | ||
|
|
58180b1ac1 | ||
|
|
067f8b6be7 | ||
|
|
4df73ced0d | ||
|
|
c7603f3ebf | ||
|
|
ae7f10b922 | ||
|
|
023e4e6ceb | ||
|
|
742893410c | ||
|
|
c1aba46a1e | ||
|
|
23712cf4dc | ||
|
|
21de59a90e | ||
|
|
e11fb4d427 | ||
|
|
328fbd83d4 | ||
|
|
ffe7860625 | ||
|
|
5b54f78875 | ||
|
|
989c70fe4a | ||
|
|
2f4448eab6 | ||
|
|
90bdcaddb7 | ||
|
|
a0afa19e9a | ||
|
|
7918dad26f | ||
|
|
13bb7360c0 | ||
|
|
5d23760280 | ||
|
|
5a350788e7 | ||
|
|
e543fedf3f | ||
|
|
b02a5ba76a | ||
|
|
5a288e7de4 | ||
|
|
8ee1b2a1fd | ||
|
|
b0a7f9c8c9 | ||
|
|
519b60d012 | ||
|
|
0ad2c338c4 | ||
|
|
34de676713 | ||
|
|
01b11d098e | ||
|
|
1b68a29f29 | ||
|
|
18930b01f6 | ||
|
|
b29fd6d380 | ||
|
|
9a15a09028 | ||
|
|
774c65a869 | ||
|
|
a822219086 | ||
|
|
2ec1dc1831 | ||
|
|
50d0fc3c85 | ||
|
|
90cddade53 | ||
|
|
2ee8d690c4 | ||
|
|
ca40c771d0 | ||
|
|
0c6137b2d3 | ||
|
|
4bccbdead4 | ||
|
|
8d02c5cd94 | ||
|
|
68e9c84a18 | ||
|
|
f7b1782294 | ||
|
|
2690c045ec | ||
|
|
656e772388 | ||
|
|
817f6cb658 | ||
|
|
179b5ab193 | ||
|
|
b4a2788626 | ||
|
|
3762878381 | ||
|
|
9cbc24fce5 | ||
|
|
4078bde3ba | ||
|
|
3b634134a0 | ||
|
|
461e16f8bc | ||
|
|
0bc88975c8 | ||
|
|
98182aab4a | ||
|
|
3a3be7e5a7 | ||
|
|
7e1cc4b684 | ||
|
|
0f2a3a606b | ||
|
|
314dce62cf | ||
|
|
bd72265e74 | ||
|
|
ab8441259e | ||
|
|
ccd1941378 | ||
|
|
4272537f69 | ||
|
|
23f4c5804c | ||
|
|
a16dfef840 | ||
|
|
e1f7139b9c | ||
|
|
f9e249ae20 | ||
|
|
81f4abdbcd | ||
|
|
9a82b474aa | ||
|
|
57ca3a04d5 | ||
|
|
257f852b96 | ||
|
|
8dcf7a6680 | ||
|
|
02e53fb6ff | ||
|
|
485f7634bd | ||
|
|
0fc256dbef | ||
|
|
3fb1356593 | ||
|
|
cd9d38c5ea | ||
|
|
0fe1d0686a | ||
|
|
4e8ebd999a | ||
|
|
578f38748d | ||
|
|
ae01b1d5df | ||
|
|
5cb0aee251 | ||
|
|
2eb318a929 | ||
|
|
ab3f27e674 | ||
|
|
e028d50b3f | ||
|
|
a30498ba42 | ||
|
|
7c05312d5c | ||
|
|
7e37892bbd | ||
|
|
4e07dfef1f | ||
|
|
0511ece2f5 | ||
|
|
1395d5686b | ||
|
|
3227c4ecea | ||
|
|
b9c4fc93d7 | ||
|
|
95e96a0f83 | ||
|
|
c92ad3b595 | ||
|
|
3285aebd4f | ||
|
|
9cc3085dd0 | ||
|
|
5b37ad57cc | ||
|
|
3dedcbf894 | ||
|
|
2ca2990f6b | ||
|
|
7fd9f102c0 | ||
|
|
cc3a31e363 | ||
|
|
5ed4638400 | ||
|
|
a64e7e8814 | ||
|
|
6723db8157 | ||
|
|
996db6912d | ||
|
|
c77d06446d | ||
|
|
68c0e8f847 | ||
|
|
4b4a46579a | ||
|
|
c95f4c0f5b | ||
|
|
078b2785e4 | ||
|
|
1d726a87b9 | ||
|
|
90b6723288 | ||
|
|
a9d7031e7c | ||
|
|
db220a9de6 | ||
|
|
9f5835871b | ||
|
|
b62415019b | ||
|
|
00d29e7e77 | ||
|
|
5b5a25a03a | ||
|
|
be3d723d73 | ||
|
|
7cad48a3ee | ||
|
|
b564214535 | ||
|
|
63a6d595c4 | ||
|
|
22cc393cd4 | ||
|
|
0400ffe377 | ||
|
|
b07cbcecbd | ||
|
|
626706c8c5 | ||
|
|
a7c0fffcec | ||
|
|
73ca205a5c | ||
|
|
4942b2947b | ||
|
|
fbe98df488 | ||
|
|
44c9f81921 | ||
|
|
681d71ac04 | ||
|
|
3902e373d8 | ||
|
|
ce8d8d929c | ||
|
|
3994d9116d | ||
|
|
c2caaeaf11 | ||
|
|
ae57f693e4 | ||
|
|
3c5e9f5334 | ||
|
|
46e76bde3f | ||
|
|
56ac50c568 | ||
|
|
25d77cb05a | ||
|
|
70174e8831 | ||
|
|
f6ea8b4d50 | ||
|
|
9083511de3 | ||
|
|
8cc07231df | ||
|
|
94a1330d61 | ||
|
|
13919b4f3c | ||
|
|
8fe9c76d08 | ||
|
|
d674305092 | ||
|
|
ac1d1a4053 | ||
|
|
66578b0c90 | ||
|
|
a84af462d4 | ||
|
|
ceaa2eb267 | ||
|
|
ec0e1dcb14 | ||
|
|
fb435c2c7e | ||
|
|
ba31c5c387 | ||
|
|
5ea3286b09 | ||
|
|
b0c0fbd70b | ||
|
|
28bb15d4ee | ||
|
|
1db62cca9e | ||
|
|
ad9a656d8d | ||
|
|
cae5958362 | ||
|
|
f0e22be32b | ||
|
|
6657e374b2 | ||
|
|
b965d44b5f | ||
|
|
1ccd2156c5 | ||
|
|
8e481cdf8e | ||
|
|
7aa43f37fb | ||
|
|
2a83bdccd5 | ||
|
|
97ed8622c7 | ||
|
|
7a2f7a569b | ||
|
|
aed5554a1b | ||
|
|
961a3504ba | ||
|
|
592cee9596 | ||
|
|
7869586e43 | ||
|
|
42a8dba642 | ||
|
|
98b5ff0d17 | ||
|
|
dd25ca30d4 | ||
|
|
d57d248152 | ||
|
|
314f476d11 | ||
|
|
0e6dc41db5 | ||
|
|
1b923fb504 | ||
|
|
7539e2109b | ||
|
|
4a5f70b315 | ||
|
|
bec32b14cb | ||
|
|
a041d50681 | ||
|
|
0553dc2f85 | ||
|
|
0701fa7b16 | ||
|
|
f80d82cfcc | ||
|
|
aaf813902a | ||
|
|
e3c74d5365 | ||
|
|
1f2250e7a4 | ||
|
|
6dbe112f79 | ||
|
|
ccef84a803 | ||
|
|
3a96d01e4a | ||
|
|
95644a844f | ||
|
|
bd0eebdb05 | ||
|
|
3319c0ab56 | ||
|
|
dc0add15af | ||
|
|
6f585e5da5 | ||
|
|
0c32f389bc | ||
|
|
8990d7199e | ||
|
|
e6f89074d4 | ||
|
|
633c9be95c | ||
|
|
14c58213c7 | ||
|
|
f2689ddf8f | ||
|
|
a5a8be97de | ||
|
|
1a88178fbf | ||
|
|
e013c16ba9 | ||
|
|
52c76b5d93 | ||
|
|
e68a584a27 | ||
|
|
bc9699e420 | ||
|
|
951fa8981f | ||
|
|
6a06a627f8 | ||
|
|
a7eeeda99f | ||
|
|
0f008c02d8 | ||
|
|
3086ea3036 | ||
|
|
2efe14d656 | ||
|
|
c03dadbe2c | ||
|
|
9efb68f957 | ||
|
|
2c9f6b0bd5 | ||
|
|
84ce5c3589 | ||
|
|
bfe83cdec2 | ||
|
|
51ebd69162 | ||
|
|
c11edf5272 | ||
|
|
a3f8336571 | ||
|
|
36baf435b5 | ||
|
|
1416e0e0ce | ||
|
|
c789a93bc8 | ||
|
|
121a06a9eb | ||
|
|
24d13fcc55 | ||
|
|
bf1a2320e2 | ||
|
|
fdf58c5ce2 | ||
|
|
5445a1bead | ||
|
|
566eb6ef3b | ||
|
|
19b2d2eeb6 | ||
|
|
c08a7f3fbd | ||
|
|
a0d46942b9 | ||
|
|
7cf64b6ab5 | ||
|
|
a34dbd45cf | ||
|
|
44506bf376 | ||
|
|
86af9952ce | ||
|
|
12046270a6 | ||
|
|
f7ef16ba06 | ||
|
|
65bcf2adb2 | ||
|
|
7790b42f8c | ||
|
|
6ed54bd31a | ||
|
|
d9e5fdde5b | ||
|
|
c3ec158f2d | ||
|
|
bf8cc236ee | ||
|
|
6c0e791236 | ||
|
|
960a918330 | ||
|
|
671b435b3b | ||
|
|
219a52e37b | ||
|
|
a4f0f0dd0c | ||
|
|
838753cc96 | ||
|
|
8f41d3db61 | ||
|
|
928e5e1c07 | ||
|
|
b99ec48407 | ||
|
|
7c128bc7a2 | ||
|
|
99b5569ffa | ||
|
|
1c2f7cb182 | ||
|
|
e72f8cf5b1 | ||
|
|
39783a6f46 | ||
|
|
88244ff71d | ||
|
|
1cb1cbba50 | ||
|
|
87f72f0c63 | ||
|
|
c776a657af | ||
|
|
568a0b0e08 | ||
|
|
196a56e3ec | ||
|
|
80106f1b67 | ||
|
|
3994faaeaa | ||
|
|
95dd0dc479 | ||
|
|
4fb6e1cde9 | ||
|
|
cab4333f70 | ||
|
|
d786e81f46 | ||
|
|
06c9b1b33c | ||
|
|
deb4e0d24a | ||
|
|
5fe73a6671 | ||
|
|
0675f2a423 | ||
|
|
41a6037a11 | ||
|
|
6644c77d23 | ||
|
|
a569799ffc | ||
|
|
3668437c96 | ||
|
|
afd30b0a9b | ||
|
|
4da07bb2c3 | ||
|
|
e7c8bbf5df | ||
|
|
934c37b578 | ||
|
|
0e4549013d | ||
|
|
39172e53bf | ||
|
|
0422c5fde6 | ||
|
|
192e5b9188 | ||
|
|
c3dc5cceee | ||
|
|
1a11a994ea | ||
|
|
a2fedfc615 | ||
|
|
77297744ce | ||
|
|
394eab4a3a | ||
|
|
2d3ca08d91 | ||
|
|
d950680bbe | ||
|
|
9f558d1cec | ||
|
|
787bb582da | ||
|
|
b5020bc590 | ||
|
|
64b2e11106 | ||
|
|
7215c44146 | ||
|
|
4435bcb1f8 | ||
|
|
fa86afb336 | ||
|
|
58a76911bb | ||
|
|
aa97f1025d | ||
|
|
62a3961739 | ||
|
|
4adc35aaf3 | ||
|
|
702b39dec5 | ||
|
|
3ca1245027 | ||
|
|
5674226b68 | ||
|
|
6928adf501 | ||
|
|
cfd17b2e7d | ||
|
|
e4975836f4 | ||
|
|
820d6b3543 | ||
|
|
05d65f0341 | ||
|
|
be2b16507e | ||
|
|
a5e51cfdbe | ||
|
|
93f63df172 | ||
|
|
4dec3c8c6b | ||
|
|
cca9c50c26 | ||
|
|
bcb6798838 | ||
|
|
9e9f4f1c53 | ||
|
|
18eb8e6fb7 | ||
|
|
8993cbe445 | ||
|
|
5b6b558c5a | ||
|
|
081e34a5ab | ||
|
|
8f46e23aa1 | ||
|
|
27d3126d54 | ||
|
|
b5dbc36975 | ||
|
|
6cee2a87cc | ||
|
|
7de681ef58 | ||
|
|
ba05d00ac4 | ||
|
|
943dc27e78 | ||
|
|
eea5921856 | ||
|
|
ca2e291306 | ||
|
|
7baa56e1b2 | ||
|
|
7ff5505e97 | ||
|
|
106148280d | ||
|
|
f9bc50e010 | ||
|
|
efd2c17eba | ||
|
|
f90d8db827 | ||
|
|
2d485ab6fe | ||
|
|
30d1f90b44 | ||
|
|
cd50388781 | ||
|
|
190ab7f6b8 | ||
|
|
0c42174917 | ||
|
|
d395183ee2 | ||
|
|
5330980c5f | ||
|
|
5475c64d89 | ||
|
|
41311841f4 | ||
|
|
98ed3b1c8f | ||
|
|
d84b801fec | ||
|
|
1238ccefcc | ||
|
|
55de135467 | ||
|
|
79992fc3c8 | ||
|
|
71b10e2d4a | ||
|
|
927edfc078 | ||
|
|
568464bc0e | ||
|
|
37db35dc10 | ||
|
|
56cd73eb35 | ||
|
|
a72706ace6 | ||
|
|
cc4a0d1704 | ||
|
|
67422e42c6 | ||
|
|
ac1f2e2049 | ||
|
|
d9da7cbd76 | ||
|
|
e8b00fb6f2 | ||
|
|
069805c6f7 | ||
|
|
caec5339e8 | ||
|
|
9560429ac3 | ||
|
|
ca1e6071e3 | ||
|
|
1aa9d6255e | ||
|
|
3b7091aab7 | ||
|
|
00c898b2e9 | ||
|
|
25f5bb2795 | ||
|
|
9df020f7e9 | ||
|
|
9b5f766333 | ||
|
|
11f629b00e | ||
|
|
a90a7b2fba | ||
|
|
c54fb1aa20 | ||
|
|
c4a2ac2c4b | ||
|
|
e8f2272918 | ||
|
|
be74029960 | ||
|
|
74c812b565 | ||
|
|
8959ec448d | ||
|
|
034b3e94a5 | ||
|
|
ce37de30a5 | ||
|
|
f7a4cdbf2b | ||
|
|
133463235a | ||
|
|
5d67438612 | ||
|
|
cccfda7de8 | ||
|
|
4fb022ce33 | ||
|
|
9d4c3fbbdf | ||
|
|
5931b80ef3 | ||
|
|
7b09a80dc7 | ||
|
|
866935dadf | ||
|
|
3a89923142 | ||
|
|
687176e22c | ||
|
|
166298e3f5 | ||
|
|
f2b9154fa9 | ||
|
|
59b6cafef7 | ||
|
|
f4726d0ebc | ||
|
|
1591557bc4 | ||
|
|
20f1cce6a5 | ||
|
|
7f6b1dd458 | ||
|
|
bc954683cb | ||
|
|
1f877fde1e | ||
|
|
d70f9d4a29 | ||
|
|
17a4d15d3b | ||
|
|
135c5f313b | ||
|
|
72cfee7ea6 | ||
|
|
7c266e0fb9 | ||
|
|
a97659a4a1 | ||
|
|
4e7dd8a563 | ||
|
|
038baa12c7 | ||
|
|
e5306284ff | ||
|
|
c4abe6ec8f | ||
|
|
4d8e335da1 | ||
|
|
f84cd4e4ed | ||
|
|
adb6d4d2d7 | ||
|
|
9738ea452f | ||
|
|
839501e012 | ||
|
|
59b32626a8 | ||
|
|
fac5a2eb02 | ||
|
|
566d3718b0 | ||
|
|
2b81e5ed19 | ||
|
|
315cc386e5 | ||
|
|
10cc45fc45 | ||
|
|
141ce32382 | ||
|
|
56b9238af5 | ||
|
|
5031dfa3b9 | ||
|
|
c0df4b1047 | ||
|
|
530e049d2d | ||
|
|
f16a5cbae1 | ||
|
|
bcc539999b | ||
|
|
7b1763a124 | ||
|
|
b0e144065c | ||
|
|
eabde41267 | ||
|
|
14b73667b8 | ||
|
|
707278f099 | ||
|
|
a330bb0801 | ||
|
|
5c9eb324e8 | ||
|
|
ba63a2c6d1 | ||
|
|
8ff9074ce5 | ||
|
|
db34c48927 | ||
|
|
5367bc3416 | ||
|
|
871e425fa0 | ||
|
|
90ec93373b | ||
|
|
2fd155615f | ||
|
|
e36d433100 | ||
|
|
9c090c862f | ||
|
|
60c29561f2 | ||
|
|
d57c4f1c01 | ||
|
|
f190a960a1 | ||
|
|
1dcf241677 | ||
|
|
1de1ab9303 | ||
|
|
7b9d392d6f | ||
|
|
1666bbc52e | ||
|
|
ebb4a4c1b6 | ||
|
|
fd2d7df9b7 | ||
|
|
8c0cd10b07 | ||
|
|
6f8b8816f5 | ||
|
|
6470804a51 | ||
|
|
47b38cf9ee | ||
|
|
e4b829da3b | ||
|
|
3ad202429c | ||
|
|
fb02ce1e33 | ||
|
|
11373acb15 | ||
|
|
9b3ccee3dd | ||
|
|
f0e91b3667 | ||
|
|
966b22488c | ||
|
|
67da09e5e0 | ||
|
|
e5463b41f2 | ||
|
|
68fb130fd0 | ||
|
|
45a347c022 | ||
|
|
b2eae2e676 | ||
|
|
29254150b1 | ||
|
|
d74b179ecd | ||
|
|
69cc414c1b | ||
|
|
533ed6eb38 | ||
|
|
3264766762 | ||
|
|
c7c1eddd47 | ||
|
|
d0d8759c10 | ||
|
|
1261c1cd66 | ||
|
|
5a0c066845 | ||
|
|
d4fbf5c056 | ||
|
|
a2dfd6eddc | ||
|
|
d452fa65ba | ||
|
|
c8d1c3d264 | ||
|
|
3768d90278 | ||
|
|
939c67222a | ||
|
|
23515acc31 | ||
|
|
a0f449d613 | ||
|
|
565bbada08 | ||
|
|
a0b30a9cc7 | ||
|
|
311f3be63b | ||
|
|
f29884593b | ||
|
|
d0ac4915cb | ||
|
|
d004bc4ea5 | ||
|
|
b00c5e9587 | ||
|
|
229cedfc50 | ||
|
|
5796690827 | ||
|
|
cb671acd0c | ||
|
|
85bd3836d0 | ||
|
|
a959c06e44 | ||
|
|
99a48499c7 | ||
|
|
21b6a01980 | ||
|
|
df91299550 | ||
|
|
5eacc9e831 | ||
|
|
9e679e7d4a | ||
|
|
f0105158bf | ||
|
|
8999df2f46 | ||
|
|
441a2496b8 | ||
|
|
e5a7f842be | ||
|
|
7f92e7ce00 | ||
|
|
b3069c0802 | ||
|
|
f39c2610ee | ||
|
|
4c4f803df2 | ||
|
|
a27313b1d0 | ||
|
|
9fd872e7b8 | ||
|
|
6ca8baa572 | ||
|
|
018390cf64 | ||
|
|
13425266eb | ||
|
|
738dd502b4 | ||
|
|
0594adb8fd | ||
|
|
83f726f503 | ||
|
|
36006fa68a | ||
|
|
a49244f4dd | ||
|
|
020f684093 | ||
|
|
101d614351 | ||
|
|
af1cc06184 | ||
|
|
d1b9dfc6c9 | ||
|
|
d8c330b215 | ||
|
|
e4029426de | ||
|
|
7d865269fd | ||
|
|
b24b870ec6 | ||
|
|
74974979ba | ||
|
|
4336e8e4b9 | ||
|
|
c7f8c70935 | ||
|
|
4cfbdb07bb | ||
|
|
3e98860241 | ||
|
|
81807cb5af | ||
|
|
d5322a73bf | ||
|
|
bd59fa14f3 | ||
|
|
5fdf637c6a | ||
|
|
9a6dc7b520 | ||
|
|
e75dc74bb1 | ||
|
|
ea7e8951d8 | ||
|
|
b906bff832 | ||
|
|
e44cfe29a8 | ||
|
|
989d5d357b | ||
|
|
f8c19df79a | ||
|
|
02b60d6d00 | ||
|
|
cfe9983741 | ||
|
|
4ca3fe5137 | ||
|
|
8db8b19ea0 | ||
|
|
503e54779a | ||
|
|
fd0c1f2273 | ||
|
|
36996107e1 | ||
|
|
cf2fe606a6 | ||
|
|
27f2d75d88 | ||
|
|
a902fefed5 | ||
|
|
274c6d3667 | ||
|
|
99f99169a4 | ||
|
|
1c8ae63ec3 | ||
|
|
da98869327 | ||
|
|
cf44052b0f | ||
|
|
febf2ea3cf | ||
|
|
df9c2f8371 | ||
|
|
b63d113fe0 | ||
|
|
7f5e04980c | ||
|
|
bc3b82850d | ||
|
|
89e45afcc1 | ||
|
|
7e2298b8d0 | ||
|
|
96b1778434 | ||
|
|
5fc3361720 | ||
|
|
d8bb7f7ad7 | ||
|
|
ff14d7b853 | ||
|
|
650d78c2cf | ||
|
|
0ed02e9c1e | ||
|
|
33cd956e4e | ||
|
|
413e22ce2b | ||
|
|
579a18c93b | ||
|
|
f6682de390 | ||
|
|
470d3a2a23 | ||
|
|
1d669ed34b | ||
|
|
8dd54b9ec3 | ||
|
|
cf94820e1a | ||
|
|
3f6b8468f2 | ||
|
|
d050fd11b5 | ||
|
|
9ccbfa0bae | ||
|
|
f57f1c7eef | ||
|
|
d8a7d770b4 | ||
|
|
6d62dbbafc | ||
|
|
9437a7abcd | ||
|
|
2642bd7415 | ||
|
|
30da34358b | ||
|
|
ab4b05127e | ||
|
|
2953a7c663 | ||
|
|
b53b4a5e5a | ||
|
|
e57cd0031d | ||
|
|
03bca72af6 | ||
|
|
2d3d65a930 | ||
|
|
5767346e9d | ||
|
|
dc894e41af | ||
|
|
5f828c6c2e | ||
|
|
2045984cee | ||
|
|
4df274f96d | ||
|
|
ee5828b2f7 | ||
|
|
3cb2e74b5c | ||
|
|
a4c9925e99 | ||
|
|
502f7991ad | ||
|
|
592afc270e | ||
|
|
2785d702e2 | ||
|
|
0fbdc69440 | ||
|
|
c99af68967 | ||
|
|
56a82b1e8a | ||
|
|
e9ae079fc3 | ||
|
|
fab2b1d3a0 | ||
|
|
18c033dc5c | ||
|
|
592630d48c | ||
|
|
d2aa8dcc43 | ||
|
|
9b107a129a | ||
|
|
10d6dcc4a9 | ||
|
|
16dbe54560 | ||
|
|
812c0e9281 | ||
|
|
7c021657e1 | ||
|
|
5dff30d90c | ||
|
|
3cc1b56810 | ||
|
|
fea4af0e63 | ||
|
|
a776fdabb9 | ||
|
|
2eb57279fe | ||
|
|
863ae5652f | ||
|
|
d0faba12a3 | ||
|
|
63991822e7 | ||
|
|
1404e041e8 | ||
|
|
55d78f3c9f | ||
|
|
e9f427c75b | ||
|
|
a661cd8295 | ||
|
|
1be83e4e33 | ||
|
|
9109495894 | ||
|
|
7586538432 | ||
|
|
4bd5614f4c | ||
|
|
c8e0fcfcdf | ||
|
|
7fa30c0dec | ||
|
|
a0d679439f | ||
|
|
072ddb799f | ||
|
|
ac744a6313 | ||
|
|
c8b22a19ad | ||
|
|
a262ea02d9 | ||
|
|
de9c591ffc | ||
|
|
70e535bee3 | ||
|
|
749def2ef5 | ||
|
|
c0750c1a3f | ||
|
|
475e08bba3 | ||
|
|
2a1e7cb5c9 | ||
|
|
c4ae4aee2b | ||
|
|
8e3ad082e2 | ||
|
|
b48123c1e1 | ||
|
|
aa3b001a04 | ||
|
|
c0707844e6 | ||
|
|
bf465cd904 | ||
|
|
d8140f4142 | ||
|
|
e6698fc65a | ||
|
|
ab66326f97 | ||
|
|
9d07a97945 | ||
|
|
86cbffbae0 | ||
|
|
10d4e023c8 | ||
|
|
51c7757543 | ||
|
|
27f307b428 | ||
|
|
a92fe17ae0 | ||
|
|
275a2e79ee | ||
|
|
7f48331ed4 | ||
|
|
e511550c91 | ||
|
|
7f68b471aa | ||
|
|
73893a921c | ||
|
|
70ca41dd44 | ||
|
|
22af1f07bf | ||
|
|
cfecc151d9 | ||
|
|
fde3a02b71 | ||
|
|
56b0582272 | ||
|
|
b67dae1f65 | ||
|
|
d1057e821a | ||
|
|
5314bbf952 | ||
|
|
c7cc36abdb | ||
|
|
a97ae67552 | ||
|
|
4cc6a0f263 | ||
|
|
04d744fda3 | ||
|
|
4b67c31277 | ||
|
|
84e0b1c904 | ||
|
|
61a8512805 | ||
|
|
08a4c02d38 | ||
|
|
1cbff6b771 | ||
|
|
9df9edc4c7 | ||
|
|
685cdbe124 | ||
|
|
2716f65010 | ||
|
|
8006024715 | ||
|
|
2616a4cf5e | ||
|
|
57a9deb98d | ||
|
|
ece22497dd | ||
|
|
fb170007c8 | ||
|
|
36c5017300 | ||
|
|
e8e245e20f | ||
|
|
2141ea6564 | ||
|
|
d3959d5899 | ||
|
|
cbb4b10ce6 | ||
|
|
861c81b590 | ||
|
|
28131624b8 | ||
|
|
ce1f01c494 | ||
|
|
a13a4ca532 | ||
|
|
f830120044 | ||
|
|
7645a72b2f | ||
|
|
ff8a8b8302 | ||
|
|
a7cc026e2c | ||
|
|
c78bf2775f | ||
|
|
0082bb22fb | ||
|
|
febf80cccd | ||
|
|
4d8dab6e33 | ||
|
|
f385fd9efd | ||
|
|
a66d96ce0a | ||
|
|
05f1fac2a7 | ||
|
|
03ae38a41e | ||
|
|
fbb8c056d4 | ||
|
|
0e68d34e1b | ||
|
|
a62027d5f3 | ||
|
|
db38498d06 | ||
|
|
af11f66646 | ||
|
|
2a422e1d83 | ||
|
|
f463aea399 | ||
|
|
f93da3cfb1 | ||
|
|
253b10818c | ||
|
|
2c0e086761 | ||
|
|
8882f4dd14 | ||
|
|
2cf76cb701 | ||
|
|
bb9517b73f | ||
|
|
f681b35b65 | ||
|
|
8c5d36f0ee | ||
|
|
08d0ff0922 | ||
|
|
e5683b1da5 | ||
|
|
3dffa8284f | ||
|
|
e332197660 | ||
|
|
8b36b71833 | ||
|
|
7eb5e07e9d | ||
|
|
0b9eb3c111 | ||
|
|
5f7a3f2b69 | ||
|
|
02676572dd | ||
|
|
404661fc72 | ||
|
|
5c3f013325 | ||
|
|
ea4aa4f149 | ||
|
|
0c8fc63b33 | ||
|
|
c239746363 | ||
|
|
12b47cc037 | ||
|
|
2c636086bd | ||
|
|
6a7386e6ba | ||
|
|
21ab9f8b9e | ||
|
|
eab113e4f5 | ||
|
|
bd4a8c1ce2 | ||
|
|
e2de7ab0c7 | ||
|
|
a6e80b2bc1 | ||
|
|
3f5a55e240 | ||
|
|
b79be6d320 | ||
|
|
60bb78e25b | ||
|
|
281fb549f8 | ||
|
|
d16f62cb38 | ||
|
|
912bd84629 | ||
|
|
d77078518d | ||
|
|
e310af00b4 | ||
|
|
cedbdf43ca | ||
|
|
911559fe05 | ||
|
|
c958eae551 | ||
|
|
053ba9a9ca | ||
|
|
c5aa74f823 | ||
|
|
20180923cf | ||
|
|
6e104c3ed0 | ||
|
|
880a503094 | ||
|
|
edbc273829 | ||
|
|
5f807e7421 | ||
|
|
b202b508f2 | ||
|
|
a7d20df95a | ||
|
|
674b540c6f | ||
|
|
8b860d3f0e | ||
|
|
a79279b1cc |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -12,4 +12,9 @@ gh-pages/
|
||||
site/_site/
|
||||
coverage
|
||||
.ruby-version
|
||||
.ruby-gemset
|
||||
.sass-cache
|
||||
tmp/*
|
||||
.jekyll-metadata
|
||||
/vendor
|
||||
/test/source/file_name.txt
|
||||
|
||||
6
.jrubyrc
Normal file
6
.jrubyrc
Normal file
@@ -0,0 +1,6 @@
|
||||
backtrace.mask=true
|
||||
compile.invokedynamic=true
|
||||
objectspace.enabled=true
|
||||
backtrace.color=true
|
||||
compat.version=2.2
|
||||
backtrace.style=mri
|
||||
32
.travis.yml
32
.travis.yml
@@ -1,27 +1,35 @@
|
||||
language: ruby
|
||||
cache: bundler
|
||||
install:
|
||||
- script/rebund download
|
||||
- travis_retry bundle install --path vendor/bundle
|
||||
sudo: false
|
||||
rvm:
|
||||
- 2.2
|
||||
- 2.1
|
||||
- 2.0
|
||||
- 1.9.3
|
||||
- ruby-head
|
||||
- jruby-9.0.3.0
|
||||
matrix:
|
||||
allow_failures:
|
||||
- rvm: ruby-head
|
||||
- rvm: jruby-9.0.3.0
|
||||
exclude:
|
||||
- rvm: jruby-9.0.3.0
|
||||
env: TEST_SUITE=cucumber
|
||||
env:
|
||||
matrix:
|
||||
- TEST_SUITE=test
|
||||
- TEST_SUITE=cucumber
|
||||
before_script: bundle update
|
||||
script: script/cibuild
|
||||
after_script:
|
||||
- script/rebund upload
|
||||
notifications:
|
||||
irc:
|
||||
on_success: change
|
||||
on_failure: change
|
||||
channels:
|
||||
- irc.freenode.org#jekyll
|
||||
- irc.freenode.org#jekyll
|
||||
template:
|
||||
- '%{repository}#%{build_number} (%{branch}) %{message} %{build_url}'
|
||||
- "%{repository}#%{build_number} (%{branch}) %{message} %{build_url}"
|
||||
email:
|
||||
on_success: never
|
||||
on_failure: never
|
||||
env:
|
||||
global:
|
||||
- secure: bt5nglPTdsc0N5fB1dOJz2WbM81dGpDuVD8PnhEsxgUfoo6xavhU4+pNrUADlSUqQ1aJrdU+MKW4x+JZ2ZnJS8vOpNzRymuMZSbFaljK4pgFGiKFgBdMKxVikvoYcxKCjLAl7NJZ11W6hUw+JtJScClDZwrJJAQB6I7Isp/LsdM=
|
||||
- secure: Ym8nx7nbfGYGo47my92M+deJykaiMkdZdb615EO51liv/xy/0aQ919Jpfieugc9d3zVnm+zFGPbpv4YzRpsik6OlVBNa4lP+BnQ27ptf5YcLWD8Hksi7845WFLecXMoaTCoYer/TvYZsIWJb2nSDMH9qbfZhnd1YZKuvUpK0rEU=
|
||||
slack:
|
||||
secure: dNdKk6nahNURIUbO3ULhA09/vTEQjK0fNbgjVjeYPEvROHgQBP1cIP3AJy8aWs8rl5Yyow4YGEilNRzKPz18AsFptVXofpwyqcBxaCfmHP809NX5PHBaadydveLm+TNVao2XeLXSWu+HUNAYO1AanCUbJSEyJTju347xCBGzESU=
|
||||
|
||||
22
CONDUCT.md
Normal file
22
CONDUCT.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# Contributor Code of Conduct
|
||||
|
||||
As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
|
||||
|
||||
We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality.
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery
|
||||
* Personal attacks
|
||||
* Trolling or insulting/derogatory comments
|
||||
* Public or private harassment
|
||||
* Publishing other's private information, such as physical or electronic addresses, without explicit permission
|
||||
* Other unethical or unprofessional conduct.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team.
|
||||
|
||||
This code of conduct applies both within project spaces and in public spaces when an individual is representing the project or its community.
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.2.0, available at [http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/)
|
||||
@@ -4,18 +4,19 @@ Contribute
|
||||
So you've got an awesome idea to throw into Jekyll. Great! Please keep the
|
||||
following in mind:
|
||||
|
||||
* **Use https://talk.jekyllrb.com for non-technical or indirect Jekyll questions that are not bugs.**
|
||||
* **Contributions will not be accepted without tests or necessary documentation updates.**
|
||||
* If you're creating a small fix or patch to an existing feature, just a simple
|
||||
test will do. Please stay in the confines of the current test suite and use
|
||||
[Shoulda](https://github.com/thoughtbot/shoulda/tree/master) and
|
||||
[RR](https://github.com/rr/rr).
|
||||
[RSpec-Mocks](https://github.com/rspec/rspec-mocks).
|
||||
* If it's a brand new feature, make sure to create a new
|
||||
[Cucumber](https://github.com/cucumber/cucumber/) feature and reuse steps
|
||||
where appropriate. Also, whipping up some documentation in your fork's `site`
|
||||
would be appreciated, and once merged it will be transferred over to the main
|
||||
`site`, jekyllrb.com.
|
||||
* If your contribution changes any Jekyll behavior, make sure to update the
|
||||
documentation. It lives in `site/docs`. If the docs are missing information,
|
||||
documentation. It lives in `site/_docs`. If the docs are missing information,
|
||||
please feel free to add it in. Great docs make a great project!
|
||||
* Please follow the [GitHub Ruby Styleguide](https://github.com/styleguide/ruby)
|
||||
when modifying Ruby code.
|
||||
@@ -30,16 +31,25 @@ Test Dependencies
|
||||
-----------------
|
||||
|
||||
To run the test suite and build the gem you'll need to install Jekyll's
|
||||
dependencies. Jekyll uses Bundler, so a quick run of the bundle command and
|
||||
you're all set!
|
||||
dependencies. Simply run this command to get all setup:
|
||||
|
||||
$ bundle
|
||||
$ script/bootstrap
|
||||
|
||||
Before you start, run the tests and make sure that they pass (to confirm your
|
||||
environment is configured properly):
|
||||
|
||||
$ bundle exec rake test
|
||||
$ bundle exec rake features
|
||||
$ script/cibuild
|
||||
|
||||
If you are only updating a file in `test/`, you can use the command:
|
||||
|
||||
$ script/test test/blah_test.rb
|
||||
|
||||
If you are only updating a `.feature` file, you can use the command:
|
||||
|
||||
$ script/cucumber features/blah.feature
|
||||
|
||||
Both `script/test` and `script/cucumber` can be run without arguments to
|
||||
run its entire respective suite.
|
||||
|
||||
Workflow
|
||||
--------
|
||||
@@ -47,10 +57,10 @@ Workflow
|
||||
Here's the most direct way to get your work merged into the project:
|
||||
|
||||
* Fork the project.
|
||||
* Clone down your fork ( `git clone git@github.com:<username>/jekyll.git` ).
|
||||
* Clone down your fork ( `git clone git@github.com:[username]/jekyll.git` ).
|
||||
* Create a topic branch to contain your change ( `git checkout -b my_awesome_feature` ).
|
||||
* Hack away, add tests. Not necessarily in that order.
|
||||
* Make sure everything still passes by running `rake`.
|
||||
* Make sure everything still passes by running `script/cibuild`.
|
||||
* If necessary, rebase your commits into logical chunks, without errors.
|
||||
* Push the branch up ( `git push origin my_awesome_feature` ).
|
||||
* Create a pull request against jekyll/jekyll and describe what your change
|
||||
@@ -67,17 +77,22 @@ You can find the documentation for jekyllrb.com in the
|
||||
[site](https://github.com/jekyll/jekyll/tree/master/site) directory of
|
||||
Jekyll's repo on GitHub.com.
|
||||
|
||||
All documentation pull requests should be directed at `master`. Pull
|
||||
All documentation pull requests should be directed at `master`. Pull
|
||||
requests directed at another branch will not be accepted.
|
||||
|
||||
The [Jekyll wiki](https://github.com/jekyll/jekyll/wiki) on GitHub
|
||||
can be freely updated without a pull request as all GitHub users have access.
|
||||
|
||||
If you want to add your plugin to the
|
||||
[list of plugins](http://jekyllrb.com/docs/plugins/#available-plugins),
|
||||
please submit a pull request modifying the
|
||||
[plugins page source file](site/_docs/plugins.md) by adding a
|
||||
link to your plugin under the proper subheading depending upon its type.
|
||||
|
||||
Gotchas
|
||||
-------
|
||||
|
||||
* If you want to bump the gem version, please put that in a separate commit.
|
||||
This way, the maintainers can control when the gem gets released.
|
||||
* Please do not bump the gem version in your pull requests.
|
||||
* Try to keep your patch(es) based from the latest commit on jekyll/jekyll.
|
||||
The easier it is to apply your work, the less work the maintainers have to do,
|
||||
which is always a good thing.
|
||||
|
||||
55
Gemfile
55
Gemfile
@@ -1,2 +1,55 @@
|
||||
source 'https://rubygems.org'
|
||||
gemspec
|
||||
gemspec name: 'jekyll'
|
||||
|
||||
gem 'rake', '~> 10.1'
|
||||
group :development do
|
||||
gem 'rdoc', '~> 4.2'
|
||||
gem 'launchy', '~> 2.3'
|
||||
gem 'toml', '~> 0.1.0'
|
||||
gem 'pry'
|
||||
end
|
||||
|
||||
group :test do
|
||||
gem 'redgreen', '~> 1.2'
|
||||
gem 'shoulda', '~> 3.5'
|
||||
gem 'cucumber', '~> 2.0', '< 2.1'
|
||||
gem 'simplecov', '~> 0.9'
|
||||
gem 'jekyll_test_plugin'
|
||||
gem 'jekyll_test_plugin_malicious'
|
||||
gem 'minitest-reporters'
|
||||
gem 'minitest-profile'
|
||||
gem 'minitest'
|
||||
gem 'rspec-mocks'
|
||||
|
||||
if RUBY_PLATFORM =~ /cygwin/ || RUBY_VERSION.start_with?("2.2")
|
||||
gem 'test-unit'
|
||||
end
|
||||
|
||||
if ENV['PROOF']
|
||||
gem 'html-proofer', '~> 2.0'
|
||||
end
|
||||
end
|
||||
|
||||
group :benchmark do
|
||||
if ENV['BENCHMARK']
|
||||
gem 'ruby-prof'
|
||||
gem 'rbtrace'
|
||||
gem 'stackprof'
|
||||
gem 'benchmark-ips'
|
||||
end
|
||||
end
|
||||
|
||||
gem 'jekyll-paginate', '~> 1.0'
|
||||
gem 'jekyll-coffeescript', '~> 1.0'
|
||||
gem 'jekyll-feed'
|
||||
gem 'jekyll-gist', '~> 1.0'
|
||||
gem 'mime-types', '~> 2.6'
|
||||
gem 'kramdown', '~> 1.9'
|
||||
|
||||
platform :ruby, :mswin, :mingw do
|
||||
gem 'rdiscount', '~> 2.0'
|
||||
gem 'pygments.rb', '~> 0.6.0'
|
||||
gem 'redcarpet', '~> 3.2', '>= 3.2.3'
|
||||
gem 'classifier-reborn', '~> 2.0'
|
||||
gem 'liquid-c', '~> 3.0'
|
||||
end
|
||||
|
||||
636
History.markdown
636
History.markdown
@@ -1,7 +1,600 @@
|
||||
## HEAD
|
||||
## 3.0.1 / 2015-11-17
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Document: only superdirectories of the collection are categories (#4110)
|
||||
* `Convertible#render_liquid` should use `render!` to cause failure on bad Liquid (#4077)
|
||||
* Don't generate `.jekyll-metadata` in non-incremental build (#4079)
|
||||
* Set `highlighter` config val to `kramdown.syntax_highlighter` (#4090)
|
||||
* Align hooks implementation with documentation (#4104)
|
||||
* Fix the deprecation warning in the doctor command (#4114)
|
||||
* Fix case in `:title` and add `:slug` which is downcased (#4100)
|
||||
|
||||
### Development Fixes
|
||||
|
||||
* Fix test warnings when doing rake {test,spec} or script/test (#4078)
|
||||
|
||||
### Site Enhancements
|
||||
|
||||
* Update normalize.css to v3.0.3. (#4085)
|
||||
* Update Font Awesome to v4.4.0. (#4086)
|
||||
* Adds a note about installing the jekyll-gist gem to make gist tag work (#4101)
|
||||
* Align hooks documentation with implementation (#4104)
|
||||
* Add Jekyll Flickr Plugin to the list of third party plugins (#4111)
|
||||
* Remove link to now-deleted blog post (#4125)
|
||||
* Update the liquid syntax in the pagination docs (#4130)
|
||||
* Add jekyll-language-plugin to plugins.md (#4134)
|
||||
* Updated to reflect feedback in #4129 (#4137)
|
||||
* Clarify assets.md based on feedback of #4129 (#4142)
|
||||
* Re-correct the liquid syntax in the pagination docs (#4140)
|
||||
|
||||
## 3.0.0 / 2015-10-26
|
||||
|
||||
### Major Enhancements
|
||||
|
||||
* Liquid profiler (i.e. know how fast or slow your templates render) (#3762)
|
||||
* Incremental regeneration (#3116)
|
||||
* Add Hooks: a new kind of plugin (#3553)
|
||||
* Upgrade to Liquid 3.0.0 (#3002)
|
||||
* `site.posts` is now a Collection instead of an Array (#4055)
|
||||
* Add basic support for JRuby (commit: 0f4477)
|
||||
* Drop support for Ruby 1.9.3. (#3235)
|
||||
* Support Ruby v2.2 (#3234)
|
||||
* Support RDiscount 2 (#2767)
|
||||
* Remove most runtime deps (#3323)
|
||||
* Move to Rouge as default highlighter (#3323)
|
||||
* Mimic GitHub Pages `.html` extension stripping behavior in WEBrick (#3452)
|
||||
* Always include file extension on output files (#3490)
|
||||
* Improved permalinks for pages and collections (#3538)
|
||||
* Sunset (i.e. remove) Maruku (#3655)
|
||||
* Remove support for relative permalinks (#3679)
|
||||
* Iterate over `site.collections` as an array instead of a hash. (#3670)
|
||||
* Adapt StaticFile for collections, config defaults (#3823)
|
||||
* Add a Code of Conduct for the Jekyll project (#3925)
|
||||
* Added permalink time variables (#3990)
|
||||
* Add `--incremental` flag to enable incremental regen (disabled by default) (#4059)
|
||||
|
||||
### Minor Enhancements
|
||||
|
||||
* Deprecate access to Document#data properties and Collection#docs methods (#4058)
|
||||
* Sort static files just once, and call `site_payload` once for all collections (#3204)
|
||||
* Separate `jekyll docs` and optimize external gem handling (#3241)
|
||||
* Improve `Site#getConverterImpl` and call it `Site#find_converter_instance` (#3240)
|
||||
* Use relative path for `path` Liquid variable in Documents for consistency (#2908)
|
||||
* Generalize `Utils#slugify` for any scripts (#3047)
|
||||
* Added basic microdata to post template in site template (#3189)
|
||||
* Store log messages in an array of messages. (#3244)
|
||||
* Allow collection documents to override `output` property in front matter (#3172)
|
||||
* Keep file modification times between builds for static files (#3220)
|
||||
* Only downcase mixed-case categories for the URL (#2571)
|
||||
* Added per post `excerpt_separator` functionality (#3274)
|
||||
* Allow collections YAML to end with three dots (#3134)
|
||||
* Add mode parameter to `slugify` Liquid filter (#2918)
|
||||
* Perf: `Markdown#matches` should avoid regexp (#3321)
|
||||
* Perf: Use frozen regular expressions for `Utils#slugify` (#3321)
|
||||
* Split off Textile support into jekyll-textile-converter (#3319)
|
||||
* Improve the navigation menu alignment in the site template on small
|
||||
screens (#3331)
|
||||
* Show the regeneration time after the initial generation (#3378)
|
||||
* Site template: Switch default font to Helvetica Neue (#3376)
|
||||
* Make the `include` tag a teensy bit faster. (#3391)
|
||||
* Add `pkill -f jekyll` to ways to kill. (#3397)
|
||||
* Site template: collapsed, variable-driven font declaration (#3360)
|
||||
* Site template: Don't always show the scrollbar in code blocks (#3419)
|
||||
* Site template: Remove undefined `text` class from `p` element (#3440)
|
||||
* Site template: Optimize text rendering for legibility (#3382)
|
||||
* Add `draft?` method to identify if Post is a Draft & expose to Liquid (#3456)
|
||||
* Write regeneration metadata even on full rebuild (#3464)
|
||||
* Perf: Use `String#end_with?("/")` instead of regexp when checking paths (#3516)
|
||||
* Docs: document 'ordinal' built-in permalink style (#3532)
|
||||
* Upgrade liquid-c to 3.x (#3531)
|
||||
* Use consistent syntax for deprecation warning (#3535)
|
||||
* Added build --destination and --source flags (#3418)
|
||||
* Site template: remove unused `page.meta` attribute (#3537)
|
||||
* Improve the error message when sorting null objects (#3520)
|
||||
* Added liquid-md5 plugin (#3598)
|
||||
* Documentation: RR replaced with RSpec Mocks (#3600)
|
||||
* Documentation: Fix subpath. (#3599)
|
||||
* Create 'tmp' dir for test_tags if it doesn't exist (#3609)
|
||||
* Extract reading of data from `Site` to reduce responsibilities. (#3545)
|
||||
* Removed the word 'Jekyll' a few times from the comments (#3617)
|
||||
* `bin/jekyll`: with no args, exit with exit code 1 (#3619)
|
||||
* Incremental build if destination file missing (#3614)
|
||||
* Static files `mtime` liquid should return a `Time` obj (#3596)
|
||||
* Use `Jekyll::Post`s for both LSI indexing and lookup. (#3629)
|
||||
* Add `charset=utf-8` for HTML and XML pages in WEBrick (#3649)
|
||||
* Set log level to debug when verbose flag is set (#3665)
|
||||
* Added a mention on the Gemfile to complete the instructions (#3671)
|
||||
* Perf: Cache `Document#to_liquid` and invalidate where necessary (#3693)
|
||||
* Perf: `Jekyll::Cleaner#existing_files`: Call `keep_file_regex` and
|
||||
`keep_dirs` only once, not once per iteration (#3696)
|
||||
* Omit jekyll/jekyll-help from list of resources. (#3698)
|
||||
* Add basic `jekyll doctor` test to detect fsnotify (OSX) anomalies. (#3704)
|
||||
* Added talk.jekyllrb.com to "Have questions?" (#3694)
|
||||
* Performance: Sort files only once (#3707)
|
||||
* Performance: Marshal metadata (#3706)
|
||||
* Upgrade highlight wrapper from `div` to `figure` (#3779)
|
||||
* Upgrade mime-types to `~> 2.6` (#3795)
|
||||
* Update windows.md with Ruby version info (#3818)
|
||||
* Make the directory for includes configurable (#3782)
|
||||
* Rename directory configurations to match `*_dir` convention for consistency (#3782)
|
||||
* Internal: trigger hooks by owner symbol (#3871)
|
||||
* Update MIME types from mime-db (#3933)
|
||||
* Add header to site template `_config.yml` for clarity & direction (#3997)
|
||||
* Site template: add timezone offset to post date frontmatter (#4001)
|
||||
* Make a constant for the regex to find hidden files (#4032)
|
||||
* Site template: refactor github & twitter icons into includes (#4049)
|
||||
* Site template: add background to Kramdown Rouge-ified backtick code blocks (#4053)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* `post_url`: fix access deprecation warning & fix deprecation msg (#4060)
|
||||
* Perform jekyll-paginate deprecation warning correctly. (#3580)
|
||||
* Make permalink parsing consistent with pages (#3014)
|
||||
* `time()`pre-filter method should accept a `Date` object (#3299)
|
||||
* Remove unneeded end tag for `link` in site template (#3236)
|
||||
* Kramdown: Use `enable_coderay` key instead of `use_coderay` (#3237)
|
||||
* Unescape `Document` output path (#2924)
|
||||
* Fix nav items alignment when on multiple rows (#3264)
|
||||
* Highlight: Only Strip Newlines/Carriage Returns, not Spaces (#3278)
|
||||
* Find variables in front matter defaults by searching with relative file path. (#2774)
|
||||
* Allow variables (e.g `:categories`) in YAML front matter permalinks (#3320)
|
||||
* Handle nil URL placeholders in permalinks (#3325)
|
||||
* Template: Fix nav items alignment when in "burger" mode (#3329)
|
||||
* Template: Remove `!important` from nav SCSS introduced in #3329 (#3375)
|
||||
* The `:title` URL placeholder for collections should be the filename slug. (#3383)
|
||||
* Trim the generate time diff to just 3 places past the decimal place (#3415)
|
||||
* The highlight tag should only clip the newlines before and after the *entire* block, not in between (#3401)
|
||||
* highlight: fix problem with linenos and rouge. (#3436)
|
||||
* `Site#read_data_file`: read CSV's with proper file encoding (#3455)
|
||||
* Ignore `.jekyll-metadata` in site template (#3496)
|
||||
* Template: Point documentation link to the documentation pages (#3502)
|
||||
* Removed the trailing slash from the example `/blog` baseurl comment (#3485)
|
||||
* Clear the regenerator cache every time we process (#3592)
|
||||
* Readd (bring back) minitest-profile (#3628)
|
||||
* Add WOFF2 font MIME type to Jekyll server MIME types (#3647)
|
||||
* Be smarter about extracting the extname in `StaticFile` (#3632)
|
||||
* Process metadata for all dependencies (#3608)
|
||||
* Show error message if the YAML front matter on a page/post is invalid. (#3643)
|
||||
* Upgrade redcarpet to 3.2 (Security fix: OSVDB-120415) (#3652)
|
||||
* Create #mock_expects that goes directly to RSpec Mocks. (#3658)
|
||||
* Open `.jekyll-metadata` in binary mode to read binary Marshal data (#3713)
|
||||
* Incremental regeneration: handle deleted, renamed, and moved dependencies (#3717)
|
||||
* Fix typo on line 19 of pagination.md (#3760)
|
||||
* Fix it so that 'blog.html' matches 'blog.html' (#3732)
|
||||
* Remove occasionally-problematic `ensure` in `LiquidRenderer` (#3811)
|
||||
* Fixed an unclear code comment in site template SCSS (#3837)
|
||||
* Fix reading of binary metadata file (#3845)
|
||||
* Remove var collision with site template header menu iteration variable (#3838)
|
||||
* Change non-existent `hl_linenos` to `hl_lines` to allow passthrough in safe mode (#3787)
|
||||
* Add missing flag to disable the watcher (#3820)
|
||||
* Update CI guide to include more direct explanations of the flow (#3891)
|
||||
* Set `future` to `false` in the default config (#3892)
|
||||
* filters: `where` should compare stringified versions of input & comparator (#3935)
|
||||
* Read build options for `jekyll clean` command (#3828)
|
||||
* Fix #3970: Use Gem::Version to compare versions, not `>`.
|
||||
* Abort if no subcommand. Fixes confusing message. (#3992)
|
||||
* Whole-post excerpts should match the post content (#4004)
|
||||
* Change default font weight to 400 to fix bold/strong text issues (#4050)
|
||||
* Document: Only auto-generate the excerpt if it's not overridden (#4062)
|
||||
* Utils: `deep_merge_hashes` should also merge `default_proc` (45f69bb)
|
||||
* Defaults: compare paths in `applies_path?` as `String`s to avoid confusion (7b81f00)
|
||||
|
||||
### Development Fixes
|
||||
|
||||
* Remove loader.rb and "modernize" `script/test`. (#3574)
|
||||
* Improve the grammar in the documentation (#3233)
|
||||
* Update the LICENSE text to match the MIT license exactly (#3253)
|
||||
* Update rake task `site:publish` to fix minor bugs. (#3254)
|
||||
* Switch to shields.io for the README badges. (#3255)
|
||||
* Use `FileList` instead of `Dir.glob` in `site:publish` rake task (#3261)
|
||||
* Fix test script to be platform-independent (#3279)
|
||||
* Instead of symlinking `/tmp`, create and symlink a local `tmp` in the tests (#3258)
|
||||
* Fix some spacing (#3312)
|
||||
* Fix comment typo in `lib/jekyll/frontmatter_defaults.rb` (#3322)
|
||||
* Move all `regenerate?` checking to `Regenerator` (#3326)
|
||||
* Factor out a `read_data_file` call to keep things clean (#3380)
|
||||
* Proof the site with CircleCI. (#3427)
|
||||
* Update LICENSE to 2015. (#3477)
|
||||
* Upgrade tests to use Minitest (#3492)
|
||||
* Remove trailing whitespace (#3497)
|
||||
* Use `fixture_site` for Document tests (#3511)
|
||||
* Remove adapters deprecation warning (#3529)
|
||||
* Minor fixes to `url.rb` to follow GitHub style guide (#3544)
|
||||
* Minor changes to resolve deprecation warnings (#3547)
|
||||
* Convert remaining textile test documents to markdown (#3528)
|
||||
* Migrate the tests to use rspec-mocks (#3552)
|
||||
* Remove `activesupport` (#3612)
|
||||
* Added tests for `Jekyll:StaticFile` (#3633)
|
||||
* Force minitest version to 5.5.1 (#3657)
|
||||
* Update the way cucumber accesses Minitest assertions (#3678)
|
||||
* Add `script/rubyprof` to generate cachegrind callgraphs (#3692)
|
||||
* Upgrade cucumber to 2.x (#3795)
|
||||
* Update Kramdown. (#3853)
|
||||
* Updated the scripts shebang for portability (#3858)
|
||||
* Update JRuby testing to 9K ([3ab386f](https://github.com/jekyll/jekyll/commit/3ab386f1b096be25a24fe038fc70fd0fb08d545d))
|
||||
* Organize dependencies into dev and test groups. (#3852)
|
||||
* Contributing.md should refer to `script/cucumber` (#3894)
|
||||
* Update contributing documentation to reflect workflow updates (#3895)
|
||||
* Add script to vendor mime types (#3933)
|
||||
* Ignore .bundle dir in SimpleCov (#4033)
|
||||
|
||||
### Site Enhancements
|
||||
|
||||
* Add 'info' labels to certain notes in collections docs (#3601)
|
||||
* Remove extra spaces, make the last sentence less awkward in permalink docs (#3603)
|
||||
* Update the permalinks documentation to reflect the updates for 3.0 (#3556)
|
||||
* Add blog post announcing Jekyll Help (#3523)
|
||||
* Add Jekyll Talk to Help page on site (#3518)
|
||||
* Change Ajax pagination resource link to use HTTPS (#3570)
|
||||
* Fixing the default host on docs (#3229)
|
||||
* Add `jekyll-thumbnail-filter` to list of third-party plugins (#2790)
|
||||
* Add link to 'Adding Ajax pagination to Jekyll' to Resources page (#3186)
|
||||
* Add a Resources link to tutorial on building dynamic navbars (#3185)
|
||||
* Semantic structure improvements to the post and page layouts (#3251)
|
||||
* Add new AsciiDoc plugin to list of third-party plugins. (#3277)
|
||||
* Specify that all transformable collection documents must contain YAML front matter (#3271)
|
||||
* Assorted accessibility fixes (#3256)
|
||||
* Update configuration docs to mention `keep_files` for `destination` (#3288, #3296)
|
||||
* Break when we successfully generate nav link to save CPU cycles. (#3291)
|
||||
* Update usage docs to mention `keep_files` and a warning about `destination` cleaning (#3295)
|
||||
* Add logic to automatically generate the `next_section` and `prev_section` navigation items (#3292)
|
||||
* Some small fixes for the Plugins TOC. (#3306)
|
||||
* Added versioning comment to configuration file (#3314)
|
||||
* Add `jekyll-minifier` to list of third-party plugins (#3333)
|
||||
* Add blog post about the Jekyll meet-up (#3332)
|
||||
* Use `highlight` Liquid tag instead of the four-space tabs for code (#3336)
|
||||
* 3.0.0.beta1 release post (#3346)
|
||||
* Add `twa` to the list of third-party plugins (#3384)
|
||||
* Remove extra spaces (#3388)
|
||||
* Fix small grammar errors on a couple pages (#3396)
|
||||
* Fix typo on Templates docs page (#3420)
|
||||
* s/three/four for plugin type list (#3424)
|
||||
* Release jekyllrb.com as a locally-compiled site. (#3426)
|
||||
* Add a jekyllrb.com/help page which elucidates places from which to get help (#3428)
|
||||
* Remove extraneous dash on Plugins doc page which caused a formatting error (#3431)
|
||||
* Fix broken link to Jordan Thornquest's website. (#3438)
|
||||
* Change the link to an extension (#3457)
|
||||
* Fix Twitter link on the help page (#3466)
|
||||
* Fix wording in code snippet highlighting section (#3475)
|
||||
* Add a `/` to `paginate_path` in the Pagination documentation (#3479)
|
||||
* Add a link on all the docs pages to "Improve this page". (#3510)
|
||||
* Add jekyll-auto-image generator to the list of third-party plugins (#3489)
|
||||
* Replace link to the proposed `picture` element spec (#3530)
|
||||
* Add frontmatter date formatting information (#3469)
|
||||
* Improve consistency and clarity of plugins options note (#3546)
|
||||
* Add permalink warning to pagination docs (#3551)
|
||||
* Fix grammar in Collections docs API stability warning (#3560)
|
||||
* Restructure `excerpt_separator` documentation for clarity (#3550)
|
||||
* Fix accidental line break in collections docs (#3585)
|
||||
* Add information about the `.jekyll-metadata` file (#3597)
|
||||
* Document addition of variable parameters to an include (#3581)
|
||||
* Add `jekyll-files` to the list of third-party plugins. (#3586)
|
||||
* Define the `install` step in the CI example `.travis.yml` (#3622)
|
||||
* Expand collections documentation. (#3638)
|
||||
* Add the "warning" note label to excluding `vendor` in the CI docs page (#3623)
|
||||
* Upgrade pieces of the Ugrading guide for Jekyll 3 (#3607)
|
||||
* Showing how to access specific data items (#3468)
|
||||
* Clarify pagination works from within HTML files (#3467)
|
||||
* Add note to `excerpt_separator` documentation that it can be set globally (#3667)
|
||||
* Fix some names on Troubleshooting page (#3683)
|
||||
* Add `remote_file_content` tag plugin to list of third-party plugins (#3691)
|
||||
* Update the Redcarpet version on the Configuration page. (#3743)
|
||||
* Update the link in the welcome post to point to Jekyll Talk (#3745)
|
||||
* Update link for navbars with data attributes tutorial (#3728)
|
||||
* Add `jekyll-asciinema` to list of third-party plugins (#3750)
|
||||
* Update pagination example to be agnostic to first pagination dir (#3763)
|
||||
* Detailed instructions for rsync deployment method (#3848)
|
||||
* Add Jekyll Portfolio Generator to list of plugins (#3883)
|
||||
* Add `site.html_files` to variables docs (#3880)
|
||||
* Add Static Publisher tool to list of deployment methods (#3865)
|
||||
* Fix a few typos. (#3897)
|
||||
* Add `jekyll-youtube` to the list of third-party plugins (#3931)
|
||||
* Add Views Router plugin (#3950)
|
||||
* Update install docs (Core dependencies, Windows reqs, etc) (#3769)
|
||||
* Use Jekyll Feed for jekyllrb.com (#3736)
|
||||
* Add jekyll-umlauts to plugins.md ($3966)
|
||||
* Troubleshooting: fix broken link, add other mac-specific info (#3968)
|
||||
* Add a new site for learning purposes (#3917)
|
||||
* Added documentation for Jekyll environment variables (#3989)
|
||||
* Fix broken configuration documentation page (#3994)
|
||||
* Add troubleshooting docs for installing on El Capitan (#3999)
|
||||
* Add Lazy Tweet Embedding to the list of third-party plugins (#4015)
|
||||
* Add installation instructions for 2 of 3 options for plugins (#4013)
|
||||
* Add alternative jekyll gem installation instructions (#4018)
|
||||
* Fix a few typos and formatting problems. (#4022)
|
||||
* Fix pretty permalink example (#4029)
|
||||
* Note that `_config.yml` is not reloaded during regeneration (#4034)
|
||||
* Apply code block figure syntax to blocks in CONTRIBUTING (#4046)
|
||||
* Add jekyll-smartify to the list of third-party plugins (#3572)
|
||||
|
||||
## 2.5.3 / 2014-12-22
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* When checking a Markdown extname, include position of the `.` (#3147)
|
||||
* Fix `jsonify` Liquid filter handling of boolean values (#3154)
|
||||
* Add comma to value of `viewport` meta tag (#3170)
|
||||
* Set the link type for the RSS feed to `application/rss+xml` (#3176)
|
||||
* Refactor `#as_liquid` (#3158)
|
||||
|
||||
### Development Fixes
|
||||
|
||||
* Exclude built-in bundles from being added to coverage report (#3180)
|
||||
|
||||
### Site Enhancements
|
||||
|
||||
* Add `@alfredxing` to the `@jekyll/core` team. :tada: (#3218)
|
||||
* Document the `-q` option for the `build` and `serve` commands (#3149)
|
||||
* Fix some minor typos/flow fixes in documentation website content (#3165)
|
||||
* Add `keep_files` to configuration documentation (#3162)
|
||||
* Repeat warning about cleaning of the `destination` directory (#3161)
|
||||
* Add jekyll-500px-embed to list of third-party plugins (#3163)
|
||||
* Simplified platform detection in Gemfile example for Windows (#3177)
|
||||
* Add the `jekyll-jalali` plugin added to the list of third-party plugins. (#3198)
|
||||
* Add Table of Contents to Troubleshooting page (#3196)
|
||||
* Add `inline_highlight` plugin to list of third-party plugins (#3212)
|
||||
* Add `jekyll-mermaid` plugin to list of third-party plugins (#3222)
|
||||
|
||||
## 2.5.2 / 2014-11-17
|
||||
|
||||
### Minor Enhancements
|
||||
|
||||
* `post_url` should match `post.name` instead of slugs and dates (#3058)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Fix bundle require for `:jekyll_plugins` (#3119)
|
||||
* Remove duplicate regexp phrase: `^\A` (#3089)
|
||||
* Remove duplicate `Conversion error:` message in `Convertible` (#3088)
|
||||
* Print full conversion error message in `Renderer#convert` (#3090)
|
||||
|
||||
### Site Enhancements
|
||||
|
||||
* Change variable names in Google Analytics script (#3093)
|
||||
* Mention CSV files in the docs for data files (#3101)
|
||||
* Add trailing slash to `paginate_path` example. (#3091)
|
||||
* Get rid of noifniof (`excerpt_separator`) (#3094)
|
||||
* Sass improvements, around nesting mostly. (#3123)
|
||||
* Add webmentions.io plugin to the list of third-party plugins (#3127)
|
||||
* Add Sass mixins and use them. (#2904)
|
||||
* Slightly compress jekyll-sticker.jpg. (#3133)
|
||||
* Update gridism and separate out related but custom styles. (#3132)
|
||||
* Add remote-include plugin to list of third-party plugins (#3136)
|
||||
|
||||
## 2.5.1 / 2014-11-09
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Fix path sanitation bug related to Windows drive names (#3077)
|
||||
|
||||
### Development Fixes
|
||||
|
||||
* Add development time dependencies on minitest and test-unit to gemspec for cygwin (#3064)
|
||||
* Use Travis's built-in caching. (#3075)
|
||||
|
||||
## 2.5.0 / 2014-11-06
|
||||
|
||||
### Minor Enhancements
|
||||
|
||||
* Require gems in `:jekyll_plugins` Gemfile group unless `JEKYLL_NO_BUNDLER_REQUIRE` is specified in the environment. (#2865)
|
||||
* Centralize path sanitation in the `Site` object (#2882)
|
||||
* Allow placeholders in permalinks (#3031)
|
||||
* Allow users to specify the log level via `JEKYLL_LOG_LEVEL`. (#3067)
|
||||
* Fancy Indexing with WEBrick (#3018)
|
||||
* Allow Enumerables to be used with `where` filter. (#2986)
|
||||
* Meta descriptions in the site template now use `page.excerpt` if it's available (#2964)
|
||||
* Change indentation in `head.html` of site template to 2 spaces from 4 (#2973)
|
||||
* Use a `$content-width` variable instead of a fixed value in the site template CSS (#2972)
|
||||
* Strip newlines in site template `<meta>` description. (#2982)
|
||||
* Add link to atom feed in `head` of site template files (#2996)
|
||||
* Performance optimizations (#2994)
|
||||
* Use `Hash#each_key` instead of `Hash#keys.each` to speed up iteration
|
||||
over hash keys. (#3017)
|
||||
* Further minor performance enhancements. (#3022)
|
||||
* Add 'b' and 's' aliases for build and serve, respectively (#3065)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Fix Rouge's RedCarpet plugin interface integration (#2951)
|
||||
* Remove `--watch` from the site template blog post since it defaults
|
||||
to watching in in 2.4.0 (#2922)
|
||||
* Fix code for media query mixin in site template (#2946)
|
||||
* Allow post URL's to have `.htm` extensions (#2925)
|
||||
* `Utils.slugify`: Don't create new objects when gsubbing (#2997)
|
||||
* The jsonify filter should deep-convert to Liquid when given an Array. (#3032)
|
||||
* Apply `jsonify` filter to Hashes deeply and effectively (#3063)
|
||||
* Use `127.0.0.1` as default host instead of `0.0.0.0` (#3053)
|
||||
* In the case that a Gemfile does not exist, ensure Jekyll doesn't fail on requiring the Gemfile group (#3066)
|
||||
|
||||
### Development Fixes
|
||||
|
||||
* Fix a typo in the doc block for `Jekyll::URL.escape_path` (#3052)
|
||||
* Add integration test for `jekyll new --blank` in TestUnit (#2913)
|
||||
* Add unit test for `jekyll new --force` logic (#2929)
|
||||
* Update outdated comment for `Convertible#transform` (#2957)
|
||||
* Add Hakiri badge to README. (#2953)
|
||||
* Add some simple benchmarking tools. (#2993)
|
||||
|
||||
### Site Enhancements
|
||||
|
||||
* `NOKOGIRI_USE_SYSTEM_LIBRARIES=true` **decreases** installation time. (#3040)
|
||||
* Add FormKeep to resources as Jekyll form backend (#3010)
|
||||
* Fixing a mistake in the name of the new Liquid tag (#2969)
|
||||
* Update Font Awesome to v4.2.0. (#2898)
|
||||
* Fix link to #2895 in 2.4.0 release post. (#2899)
|
||||
* Add Big Footnotes for Kramdown plugin to list of third-party plugins (#2916)
|
||||
* Remove warning regarding GHP use of singular types for front matter defaults (#2919)
|
||||
* Fix quote character typo in site documentation for templates (#2917)
|
||||
* Point Liquid links to Liquid’s Github wiki (#2887)
|
||||
* Add HTTP Basic Auth (.htaccess) plugin to list of third-party plugins (#2931)
|
||||
* (Minor) Grammar & `_config.yml` filename fixes (#2911)
|
||||
* Added `mathml.rb` to the list of third-party plugins. (#2937)
|
||||
* Add `--force_polling` to the list of configuration options (#2943)
|
||||
* Escape unicode characters in site CSS (#2906)
|
||||
* Add note about using the github-pages gem via pages.github.com/versions.json (#2939)
|
||||
* Update usage documentation to reflect 2.4 auto-enabling of `--watch`. (#2954)
|
||||
* Add `--skip-initial-build` to configuration docs (#2949)
|
||||
* Fix a minor typo in Templates docs page (#2959)
|
||||
* Add a ditaa-ditaa plugin under Other section on the Plugins page (#2967)
|
||||
* Add `build/serve -V` option to configuration documentation (#2948)
|
||||
* Add 'Jekyll Twitter Plugin' to list of third-party plugins (#2979)
|
||||
* Docs: Update normalize.css to v3.0.2. (#2981)
|
||||
* Fix typo in Continuous Integration documentation (#2984)
|
||||
* Clarify behavior of `:categories` in permalinks (#3011)
|
||||
|
||||
## 2.4.0 / 2014-09-09
|
||||
|
||||
### Minor Enhancements
|
||||
|
||||
* Support a new `relative_include` tag (#2870)
|
||||
* Auto-enable watch on 'serve' (#2858)
|
||||
* Render Liquid in CoffeeScript files (#2830)
|
||||
* Array Liquid filters: `push`, `pop`, `unshift`, `shift` (#2895)
|
||||
* Add `:title` to collection URL template fillers (#2864)
|
||||
* Add support for CSV files in the `_data` directory (#2761)
|
||||
* Add the `name` variable to collection permalinks (#2799)
|
||||
* Add `inspect` liquid filter. (#2867)
|
||||
* Add a `slugify` Liquid filter (#2880)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Use `Jekyll.sanitized_path` when adding static files to Collections (#2849)
|
||||
* Fix encoding of `main.scss` in site template (#2771)
|
||||
* Fix orientation bugs in default site template (#2862)
|
||||
|
||||
### Development Fixes
|
||||
|
||||
* Update simplecov gem to 0.9 (#2748)
|
||||
* Remove `docs/` dir (#2768)
|
||||
* add class `<< self` idiom to `New` command (#2817)
|
||||
* Allow Travis to 'parallelize' our tests (#2859)
|
||||
* Fix test for Liquid rendering in Sass (#2856)
|
||||
* Fixing "vertycal" typo in site template's `_base.scss` (#2889)
|
||||
|
||||
### Site Enhancements
|
||||
|
||||
* Document the `name` variable for collection permalinks (#2829)
|
||||
* Adds info about installing jekyll in current dir (#2839)
|
||||
* Remove deprecated `jekyll-projectlist` plugin from list of third-party
|
||||
plugins (#2742)
|
||||
* Remove tag plugins that are built in to Jekyll (#2751)
|
||||
* Add `markdown-writer` package for Atom Editor to list of third-party
|
||||
plugins (#2763)
|
||||
* Fix typo in site documentation for collections (#2764)
|
||||
* Fix minor typo on plugins docs page (#2765)
|
||||
* Replace markdown with HTML in `sass_dir` note on assets page (#2791)
|
||||
* Fixed "bellow" typo in datafiles docs (#2879)
|
||||
* Fix code/markdown issue in documentation for variables (#2877)
|
||||
* Remove Good Include third-party plugin from plugins page (#2881)
|
||||
* Add some more docs on `include_relative` (#2884)
|
||||
|
||||
## 2.3.0 / 2014-08-10
|
||||
|
||||
### Minor Enhancements
|
||||
|
||||
* Allow Convertibles to be converted by >= 1 converters (#2704)
|
||||
* Allow Sass files to be rendered in Liquid, but never place them in layouts. (#2733)
|
||||
* Add `jekyll help` command (#2707)
|
||||
* Use `.scss` for `site_template` styles. (#2667)
|
||||
* Don't require the `scope` key in front matter defaults (#2659)
|
||||
* No longer set `permalink: pretty` in the `_config.yml` for the site template (#2680)
|
||||
* Rework site template to utilize Sass (#2687)
|
||||
* Notify the user when auto-regeneration is disabled. (#2696)
|
||||
* Allow partial variables in include tag filename argument (#2693)
|
||||
* Move instances of `Time.parse` into a Utils method (#2682)
|
||||
* Ignore subfolders in the `_posts` folder (#2705) REVERTS (#2633)
|
||||
* Front Matter default types should always be pluralized (#2732)
|
||||
* Read in static files into `collection.files` as `StaticFile`s (#2737)
|
||||
* Add `sassify` and `scssify` Liquid filters (#2739)
|
||||
* Replace `classifier` gem with `classifier-reborn` (#2721)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Use only the last extname when multiple converters exist (#2722)
|
||||
* Call `#to_liquid` before calling `#to_json` in jsonify filter (#2729)
|
||||
* Use non padded config in `strftime` to avoid parse string twice (#2673)
|
||||
* Replace deprecated Ruby methods with undeprecated ones (#2664)
|
||||
* Catch errors when parsing Post `date` front matter value & produce nice error message (#2649)
|
||||
* Allow static files in Collections (#2615)
|
||||
* Fixed typo in `Deprecator#gracefully_require` error message (#2694)
|
||||
* Remove preemptive loading of the 'classifier' gem. (#2697)
|
||||
* Use case-insensitive checking for the file extensions when loading config files (#2718)
|
||||
* When Reading Documents, Respect `encoding` Option (#2720)
|
||||
* Refactor based on jekyll-watch clean-up. (#2716)
|
||||
* `Document#to_s` should produce just the content of the document (#2731)
|
||||
|
||||
### Development Fixes
|
||||
|
||||
* Only include lib files in the gem (#2671)
|
||||
* Fix `git diff` command in `proof` script (#2672)
|
||||
* Make default rake task a multitask so tests run in parallel (#2735)
|
||||
|
||||
### Site Enhancements
|
||||
|
||||
* Use Sass and a Docs Collection (#2651)
|
||||
* Add `latest_version.txt` file to the site (#2740)
|
||||
* Be more ambiguous about `page.content`. But more transparent. (#2522)
|
||||
* Streamlining front matter wording (instead of front-matter/frontmatter) (#2674)
|
||||
* Add note that source directory cannot be modified in GitHub Pages (#2669)
|
||||
* Fix links from #2669 to be actual HTML. Whoops. (#2679)
|
||||
* Add link to `jekyll-slim` in list of third-party plugins (#2689)
|
||||
* Add Barry Clark's Smashing Magazine tutorial to resources page (#2688)
|
||||
* Reorganize and update default configuration settings (#2456)
|
||||
* Fixing indentation in the configuration docs about Redcarpet exts (#2717)
|
||||
* Use `null` in YAML instead of `nil` in default config list (#2719)
|
||||
* Fix typo in Continuous Integration docs (#2708)
|
||||
|
||||
## 2.2.0 / 2014-07-29
|
||||
|
||||
### Minor Enhancements
|
||||
|
||||
* Throw a warning if the specified layout does not exist (#2620)
|
||||
* Whitelist Pygments options in safe mode (#2642)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Remove unnecessary `Jekyll::Tags::IncludeTag#blank?` method (#2625)
|
||||
* Categories in the path are ignored (#2633)
|
||||
|
||||
### Development Fixes
|
||||
|
||||
* Refactoring Errors & Requires of Third-Party stuff (#2591)
|
||||
* Add further tests for categories (#2584)
|
||||
* Proof site with html-proofer on change (#2605)
|
||||
* Fix up bug in #2605 which caused proofing the site not to function (#2608)
|
||||
* Use `bundle exec` in `script/proof` (#2610)
|
||||
|
||||
### Site Enhancements
|
||||
|
||||
* Update Kramdown urls (#2588)
|
||||
* Add `Jekyll::AutolinkEmail` and `Jekyll::GitMetadata` to the list of
|
||||
third-party plugins (#2596)
|
||||
* Fix a bunch of broken links in the site (#2601)
|
||||
* Replace dead links with working links (#2611)
|
||||
* Add jekyll-hook to deployment methods (#2617)
|
||||
* Added kramdown-with-pygments plugin to the list of third-party plugins (#2623)
|
||||
* Update outdated "Extras" page and remove duplicate documentation (#2622)
|
||||
* Add co2 plugin to list of third-party plugins (#2639)
|
||||
* Attempt to clarify the way Sass imports happen (#2642)
|
||||
|
||||
## 2.1.1 / 2014-07-01
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Patch read vulnerabilities for data & confirm none for layouts (#2563)
|
||||
* Update Maruku dependency to allow use of the latest version (#2576)
|
||||
* Remove conditional assignment from document URL to prevent stale urls (#2575)
|
||||
|
||||
### Site Enhancements
|
||||
|
||||
* Add vertical margin to `highlight` to separate code blocks (#2558)
|
||||
* Add `html_pages` to Variables docs (#2567)
|
||||
* Fixed broken link to Permalinks page (#2572)
|
||||
* Update link to Windows installation guide (#2578)
|
||||
|
||||
## 2.1.0 / 2014-06-28
|
||||
|
||||
### Minor Enhancements
|
||||
|
||||
* Bump to the latest Liquid version, 2.6.1 (#2495)
|
||||
@@ -22,11 +615,13 @@
|
||||
* Upgrade listen to `2.7.6 <= x < 3.0.0` (#2492)
|
||||
* Allow configuration of different Twitter and GitHub usernames in site template (#2485)
|
||||
* Bump Pygments to v0.6.0 (#2504)
|
||||
* Front-matter defaults for documents in collections (#2419)
|
||||
* Front matter defaults for documents in collections (#2419)
|
||||
* Include files with a url which ends in `/` in the `site.html_pages` list (#2524)
|
||||
* Make `highlight` tag use `language-` prefix in CSS class (#2511)
|
||||
* Lookup item property via `item#to_liquid` before `#data` or `#[]` in filters (#2493)
|
||||
* Skip initial build of site on serve with flag (#2477)
|
||||
* Add support for `hl_lines` in `highlight` tag (#2532)
|
||||
* Spike out `--watch` flag into a separate gem (#2550)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -38,7 +633,7 @@
|
||||
* Prevent code from overflowing container in site template (#2429)
|
||||
* Encode URLs in UTF-8 when escaping and unescaping (#2420)
|
||||
* No Layouts or Liquid for Asset Files (#2431)
|
||||
* Allow front-matter defaults to set post categories (#2373)
|
||||
* Allow front matter defaults to set post categories (#2373)
|
||||
* Fix command in subcommand deprecation warning (#2457)
|
||||
* Keep all parent directories of files/dirs in `keep_files` (#2458)
|
||||
* When using RedCarpet and Rouge without Rouge installed, fixed erroneous
|
||||
@@ -46,6 +641,11 @@
|
||||
* Ignore *all* directories and files that merit it on auto-generation (#2459)
|
||||
* Before copying file, explicitly remove the old one (#2535)
|
||||
* Merge file system categories with categories from YAML. (#2531)
|
||||
* Deep merge front matter defaults (#2490)
|
||||
* Ensure exclude and include arrays are arrays of strings (#2542)
|
||||
* Allow collections to have dots in their filenames (#2552)
|
||||
* Collections shouldn't try to read in directories as files (#2552)
|
||||
* Be quiet very quickly. (#2520)
|
||||
|
||||
### Development Fixes
|
||||
|
||||
@@ -53,6 +653,7 @@
|
||||
* Add test for sorting UTF-8 characters (#2384)
|
||||
* Use `https` for GitHub links in documentation (#2470)
|
||||
* Remove coverage reporting with Coveralls (#2494)
|
||||
* Fix a bit of missing TomDoc to `Jekyll::Commands::Build#build` (#2554)
|
||||
|
||||
### Site Enhancements
|
||||
|
||||
@@ -65,7 +666,7 @@
|
||||
* Prevent table from extending parent width in permalink style table (#2424)
|
||||
* Add collections to info about pagination support (#2389)
|
||||
* Add `jekyll_github_sample` plugin to list of third-party plugins (#2463)
|
||||
* Clarify documentation around front-matter defaults and add details
|
||||
* Clarify documentation around front matter defaults and add details
|
||||
about defaults for collections. (#2439)
|
||||
* Add Jekyll Project Version Tag to list of third-party plugins (#2468)
|
||||
* Use `https` for GitHub links across whole site (#2470)
|
||||
@@ -74,6 +675,9 @@
|
||||
* Add link to jekyll-compress-html to list of third-party plugins (#2514)
|
||||
* Add Piwigo Gallery to list of third-party plugins (#2526)
|
||||
* Set `show_drafts` to `false` in default configuration listing (#2536)
|
||||
* Provide an updated link for Windows installation instructions (#2544)
|
||||
* Remove `url` from configuration docs (#2547)
|
||||
* Documentation for Continuous Integration for your Jekyll Site (#2432)
|
||||
|
||||
## 2.0.3 / 2014-05-08
|
||||
|
||||
@@ -97,7 +701,7 @@
|
||||
* Update docs to reflect new `baseurl` default (#2341)
|
||||
* Add links to headers who have an ID. (#2342)
|
||||
* Use symbol instead of HTML number in `upgrading.md` (#2351)
|
||||
* Fix link to frontmatter defaults docs (#2353)
|
||||
* Fix link to front matter defaults docs (#2353)
|
||||
* Fix for `History.markdown` in order to fix history page in docs (#2363)
|
||||
|
||||
## 2.0.2 / 2014-05-07
|
||||
@@ -137,7 +741,7 @@
|
||||
* Expose `site.static_files` to Liquid (#2075)
|
||||
* Complete redesign of the template site generated by `jekyll new` (#2050)
|
||||
* Update Listen from 1.x to 2.x (#2097)
|
||||
* Front-matter defaults (#2205)
|
||||
* Front matter defaults (#2205)
|
||||
* Deprecate `relative_permalinks` configuration option (default to `false`) (#2307)
|
||||
* Exclude files based on prefix as well as `fnmatch?` (#2303)
|
||||
|
||||
@@ -182,12 +786,12 @@
|
||||
* Permit YAML blocks to end with three dots to better conform with the
|
||||
YAML spec (#2110)
|
||||
* Use `File.exist?` instead of deprecated `File.exists?` (#2214)
|
||||
* Require newline after start of YAML front-matter header (#2211)
|
||||
* Require newline after start of YAML Front Matter header (#2211)
|
||||
* Add the ability for pages to be marked as `published: false` (#1492)
|
||||
* Add `Jekyll::LiquidExtensions` with `.lookup_variable` method for easy
|
||||
looking up of variable values in a Liquid context. (#2253)
|
||||
* Remove literal lang name from class (#2292)
|
||||
* Return `utf-8` encoding in header for webrick error page response (#2289)
|
||||
* Return `utf-8` encoding in header for webrick error page response (#2289)
|
||||
* Make template site easier to customize (#2268)
|
||||
* Add two-digit year to permalink template option (#2301)
|
||||
* Add `site.documents` to Liquid payload (list of all docs) (#2295)
|
||||
@@ -855,7 +1459,7 @@
|
||||
* Bullet-proof `limit_posts` option (#1004)
|
||||
* Read in YAML as UTF-8 to accept non-ASCII chars (#836)
|
||||
* Fix the CLI option `--plugins` to actually accept dirs and files (#993)
|
||||
* Allow 'excerpt' in YAML Front-Matter to override the extracted excerpt (#946)
|
||||
* Allow 'excerpt' in YAML front matter to override the extracted excerpt (#946)
|
||||
* Fix cascade problem with site.baseurl, site.port and site.host. (#935)
|
||||
* Filter out directories with valid post names (#875)
|
||||
* Fix symlinked static files not being correctly built in unsafe mode (#909)
|
||||
@@ -867,7 +1471,7 @@
|
||||
* Patch for multibyte URI problem with `jekyll serve` (#723)
|
||||
* Order plugin execution by priority (#864)
|
||||
* Fixed Page#dir and Page#url for edge cases (#536)
|
||||
* Fix broken `post_url` with posts with a time in their YAML Front-Matter (#831)
|
||||
* Fix broken `post_url` with posts with a time in their YAML front matter (#831)
|
||||
* Look for plugins under the source directory (#654)
|
||||
* Tumblr Migrator: finds `_posts` dir correctly, fixes truncation of long
|
||||
post names (#775)
|
||||
@@ -926,7 +1530,7 @@
|
||||
* Fix error with `limit_posts` (#442)
|
||||
* Properly select dotfile during directory scan (#363, #431, #377)
|
||||
* Allow setting of Kramdown `smart_quotes` (#482)
|
||||
* Ensure front-matter is at start of file (#562)
|
||||
* Ensure front matter is at start of file (#562)
|
||||
|
||||
## 0.11.2 / 2011-12-27
|
||||
* Bug Fixes
|
||||
@@ -1047,7 +1651,7 @@
|
||||
## 0.5.6 / 2010-01-08
|
||||
* Bug Fixes
|
||||
* Require redcloth >= 4.2.1 in tests (#92)
|
||||
* Don't break on triple dashes in yaml frontmatter (#93)
|
||||
* Don't break on triple dashes in yaml front matter (#93)
|
||||
|
||||
### Minor Enhancements
|
||||
* Allow .mkd as markdown extension
|
||||
@@ -1082,9 +1686,9 @@
|
||||
* Configuration options set in config.yml are now available through the
|
||||
site payload (@vilcans)
|
||||
* Posts can now have an empty YAML front matter or none at all
|
||||
(@bahuvrihi)
|
||||
(@ bahuvrihi)
|
||||
* Bug Fixes
|
||||
* Fixing Ruby 1.9 issue that requires to_s on the err object
|
||||
* Fixing Ruby 1.9 issue that requires `#to_s` on the err object
|
||||
(@Chrononaut)
|
||||
* Fixes for pagination and ordering posts on the same day (@ujh)
|
||||
* Made pages respect permalinks style and permalinks in yml front matter
|
||||
@@ -1094,8 +1698,8 @@
|
||||
* Added trailing slash to pretty permalink style so Apache is happy
|
||||
(@eugenebolshakov)
|
||||
* Bad markdown processor in config fails sooner and with better message
|
||||
(@gcnovus)
|
||||
* Allow CRLFs in yaml frontmatter (@juretta)
|
||||
(@ gcnovus)
|
||||
* Allow CRLFs in yaml front matter (@juretta)
|
||||
* Added Date#xmlschema for Ruby versions < 1.9
|
||||
|
||||
## 0.5.1 / 2009-05-06
|
||||
|
||||
8
LICENSE
8
LICENSE
@@ -1,9 +1,9 @@
|
||||
(The MIT License)
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2008-2014 Tom Preston-Werner
|
||||
Copyright (c) 2008-2015 Tom Preston-Werner
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the 'Software'), to deal
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
@@ -12,7 +12,7 @@ furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
# [Jekyll](http://jekyllrb.com/)
|
||||
|
||||
[](https://rubygems.org/gems/jekyll)
|
||||
[](https://travis-ci.org/jekyll/jekyll)
|
||||
[](https://codeclimate.com/github/jekyll/jekyll)
|
||||
[](https://gemnasium.com/jekyll/jekyll)
|
||||
[](https://rubygems.org/gems/jekyll)
|
||||
[](https://travis-ci.org/jekyll/jekyll)
|
||||
[](https://codeclimate.com/github/jekyll/jekyll)
|
||||
[](https://gemnasium.com/jekyll/jekyll)
|
||||
[](https://hakiri.io/github/jekyll/jekyll/master)
|
||||
|
||||
By Tom Preston-Werner, Nick Quaranto, and many [awesome contributors](https://github.com/jekyll/jekyll/graphs/contributors)!
|
||||
By Tom Preston-Werner, Nick Quaranto, Parker Moore, and many [awesome contributors](https://github.com/jekyll/jekyll/graphs/contributors)!
|
||||
|
||||
Jekyll is a simple, blog-aware, static site generator perfect for personal, project, or organization sites. Think of it like a file-based CMS, without all the complexity. Jekyll takes your content, renders Markdown and Liquid templates, and spits out a complete, static website ready to be served by Apache, Nginx or another web server. Jekyll is the engine behind [GitHub Pages](http://pages.github.com), which you can use to host sites right from your GitHub repositories.
|
||||
|
||||
@@ -13,13 +14,29 @@ Jekyll is a simple, blog-aware, static site generator perfect for personal, proj
|
||||
|
||||
Jekyll does what you tell it to do — no more, no less. It doesn't try to outsmart users by making bold assumptions, nor does it burden them with needless complexity and configuration. Put simply, Jekyll gets out of your way and allows you to concentrate on what truly matters: your content.
|
||||
|
||||
## Having trouble with OS X El Capitan?
|
||||
|
||||
See: http://jekyllrb.com/docs/troubleshooting/#jekyll-amp-mac-os-x-1011
|
||||
|
||||
## Getting Started
|
||||
|
||||
* [Install](http://jekyllrb.com/docs/installation/) the gem
|
||||
* Read up about its [Usage](http://jekyllrb.com/docs/usage/) and [Configuration](http://jekyllrb.com/docs/configuration/)
|
||||
* Take a gander at some existing [Sites](https://wiki.github.com/jekyll/jekyll/sites)
|
||||
* Fork and [Contribute](http://jekyllrb.com/docs/contributing/) your own modifications
|
||||
* Have questions? Check out [`#jekyll` on irc.freenode.net](https://botbot.me/freenode/jekyll/).
|
||||
* Have questions? Check out our official forum community [Jekyll Talk](https://talk.jekyllrb.com/) or [`#jekyll` on irc.freenode.net](https://botbot.me/freenode/jekyll/)
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
In order to have a more open and welcoming community, Jekyll adheres to a
|
||||
[code of conduct](CONDUCT.md) adapted from the Ruby on Rails code of
|
||||
conduct.
|
||||
|
||||
Please adhere to this code of conduct in any interactions you have in the
|
||||
Jekyll community. It is strictly enforced on all official Jekyll
|
||||
repositories, websites, and resources. If you encounter someone violating
|
||||
these terms, please let a maintainer (@parkr, @envygeeks, or @mattr-) know
|
||||
and we will address it as soon as possible.
|
||||
|
||||
## Diving In
|
||||
|
||||
|
||||
110
Rakefile
110
Rakefile
@@ -14,7 +14,7 @@ require 'jekyll/version'
|
||||
#############################################################################
|
||||
|
||||
def name
|
||||
@name ||= Dir['*.gemspec'].first.split('.').first
|
||||
'jekyll'.freeze
|
||||
end
|
||||
|
||||
def version
|
||||
@@ -26,7 +26,7 @@ def gemspec_file
|
||||
end
|
||||
|
||||
def gem_file
|
||||
"#{name}-#{version}.gem"
|
||||
"#{name}-#{Gem::Version.new(version).to_s}.gem"
|
||||
end
|
||||
|
||||
def normalize_bullets(markdown)
|
||||
@@ -53,13 +53,32 @@ def liquid_escape(markdown)
|
||||
markdown.gsub(/(`{[{%].+[}%]}`)/, "{% raw %}\\1{% endraw %}")
|
||||
end
|
||||
|
||||
def custom_release_header_anchors(markdown)
|
||||
header_regexp = /^(\d{1,2})\.(\d{1,2})\.(\d{1,2}) \/ \d{4}-\d{2}-\d{2}/
|
||||
section_regexp = /^### \w+ \w+$/
|
||||
markdown.split(/^##\s/).map do |release_notes|
|
||||
_, major, minor, patch = *release_notes.match(header_regexp)
|
||||
release_notes
|
||||
.gsub(header_regexp, "\\0\n{: #v\\1-\\2-\\3}")
|
||||
.gsub(section_regexp) { |section| "#{section}\n{: ##{sluffigy(section)}-v#{major}-#{minor}-#{patch}}" }
|
||||
end.join("\n## ")
|
||||
end
|
||||
|
||||
def sluffigy(header)
|
||||
header.gsub(/#/, '').strip.downcase.gsub(/\s+/, '-')
|
||||
end
|
||||
|
||||
def remove_head_from_history(markdown)
|
||||
index = markdown =~ /^##\s+\d+\.\d+\.\d+/
|
||||
markdown[index..-1]
|
||||
end
|
||||
|
||||
def converted_history(markdown)
|
||||
remove_head_from_history(liquid_escape(linkify(normalize_bullets(markdown))))
|
||||
remove_head_from_history(
|
||||
custom_release_header_anchors(
|
||||
liquid_escape(
|
||||
linkify(
|
||||
normalize_bullets(markdown)))))
|
||||
end
|
||||
|
||||
#############################################################################
|
||||
@@ -68,8 +87,9 @@ end
|
||||
#
|
||||
#############################################################################
|
||||
|
||||
task :default => [:test, :features]
|
||||
multitask :default => [:test, :features]
|
||||
|
||||
task :spec => :test
|
||||
require 'rake/testtask'
|
||||
Rake::TestTask.new(:test) do |test|
|
||||
test.libs << 'lib' << 'test'
|
||||
@@ -115,6 +135,7 @@ namespace :site do
|
||||
desc "Generate and view the site locally"
|
||||
task :preview do
|
||||
require "launchy"
|
||||
require "jekyll"
|
||||
|
||||
# Yep, it's a hack! Wait a few seconds for the Jekyll site to generate and
|
||||
# then open it in a browser. Someday we can do better than this, I hope.
|
||||
@@ -126,47 +147,76 @@ namespace :site do
|
||||
|
||||
# Generate the site in server mode.
|
||||
puts "Running Jekyll..."
|
||||
Dir.chdir("site") do
|
||||
sh "#{File.expand_path('bin/jekyll', File.dirname(__FILE__))} serve --watch"
|
||||
end
|
||||
options = {
|
||||
"source" => File.expand_path("site"),
|
||||
"destination" => File.expand_path("site/_site"),
|
||||
"watch" => true,
|
||||
"serving" => true
|
||||
}
|
||||
Jekyll::Commands::Build.process(options)
|
||||
Jekyll::Commands::Serve.process(options)
|
||||
end
|
||||
|
||||
desc "Generate the site"
|
||||
task :generate => [:history, :version_file] do
|
||||
require "jekyll"
|
||||
Jekyll::Commands::Build.process({
|
||||
"source" => File.expand_path("site"),
|
||||
"destination" => File.expand_path("site/_site")
|
||||
})
|
||||
end
|
||||
|
||||
desc "Update normalize.css library to the latest version and minify"
|
||||
task :update_normalize_css do
|
||||
Dir.chdir("site/_includes/css") do
|
||||
Dir.chdir("site/_sass") do
|
||||
sh 'curl "http://necolas.github.io/normalize.css/latest/normalize.css" -o "normalize.scss"'
|
||||
sh 'sass "normalize.scss":"normalize.css" --style compressed'
|
||||
sh 'rm "normalize.scss"'
|
||||
sh 'sass "normalize.scss":"_normalize.scss" --style compressed'
|
||||
rm ['normalize.scss', Dir.glob('*.map')].flatten
|
||||
end
|
||||
end
|
||||
|
||||
desc "Commit the local site to the gh-pages branch and publish to GitHub Pages"
|
||||
task :publish => [:history] do
|
||||
task :publish => [:history, :version_file] do
|
||||
# Ensure the gh-pages dir exists so we can generate into it.
|
||||
puts "Checking for gh-pages dir..."
|
||||
unless File.exist?("./gh-pages")
|
||||
puts "No gh-pages directory found. Run the following commands first:"
|
||||
puts " `git clone git@github.com:jekyll/jekyll gh-pages"
|
||||
puts " `cd gh-pages"
|
||||
puts " `git checkout gh-pages`"
|
||||
exit(1)
|
||||
puts "Creating gh-pages dir..."
|
||||
sh "git clone git@github.com:jekyll/jekyll gh-pages"
|
||||
end
|
||||
|
||||
# Ensure gh-pages branch is up to date.
|
||||
# Ensure latest gh-pages branch history.
|
||||
Dir.chdir('gh-pages') do
|
||||
sh "git checkout gh-pages"
|
||||
sh "git pull origin gh-pages"
|
||||
end
|
||||
|
||||
# Copy to gh-pages dir.
|
||||
puts "Copying site to gh-pages branch..."
|
||||
Dir.glob("site/*") do |path|
|
||||
next if path.include? "_site"
|
||||
sh "cp -R #{path} gh-pages/"
|
||||
# Proceed to purge all files in case we removed a file in this release.
|
||||
puts "Cleaning gh-pages directory..."
|
||||
purge_exclude = %w[
|
||||
gh-pages/.
|
||||
gh-pages/..
|
||||
gh-pages/.git
|
||||
gh-pages/.gitignore
|
||||
]
|
||||
FileList["gh-pages/{*,.*}"].exclude(*purge_exclude).each do |path|
|
||||
sh "rm -rf #{path}"
|
||||
end
|
||||
|
||||
# Copy site to gh-pages dir.
|
||||
puts "Building site into gh-pages branch..."
|
||||
ENV['JEKYLL_ENV'] = 'production'
|
||||
require "jekyll"
|
||||
Jekyll::Commands::Build.process({
|
||||
"source" => File.expand_path("site"),
|
||||
"destination" => File.expand_path("gh-pages"),
|
||||
"sass" => { "style" => "compressed" }
|
||||
})
|
||||
|
||||
File.open('gh-pages/.nojekyll', 'wb') { |f| f.puts(":dog: food.") }
|
||||
|
||||
# Commit and push.
|
||||
puts "Committing and pushing to GitHub Pages..."
|
||||
sha = `git log`.match(/[a-z0-9]{40}/)[0]
|
||||
sha = `git rev-parse HEAD`.strip
|
||||
Dir.chdir('gh-pages') do
|
||||
sh "git add ."
|
||||
sh "git commit --allow-empty -m 'Updating to #{sha}.'"
|
||||
@@ -182,10 +232,9 @@ namespace :site do
|
||||
front_matter = {
|
||||
"layout" => "docs",
|
||||
"title" => "History",
|
||||
"permalink" => "/docs/history/",
|
||||
"prev_section" => "contributing"
|
||||
"permalink" => "/docs/history/"
|
||||
}
|
||||
Dir.chdir('site/docs/') do
|
||||
Dir.chdir('site/_docs/') do
|
||||
File.open("history.md", "w") do |file|
|
||||
file.write("#{front_matter.to_yaml}---\n\n")
|
||||
file.write(converted_history(history_file))
|
||||
@@ -196,6 +245,11 @@ namespace :site do
|
||||
end
|
||||
end
|
||||
|
||||
desc "Write the site latest_version.txt file"
|
||||
task :version_file do
|
||||
File.open('site/latest_version.txt', 'wb') { |f| f.puts(version) } unless version =~ /(beta|rc|alpha)/i
|
||||
end
|
||||
|
||||
namespace :releases do
|
||||
desc "Create new release post"
|
||||
task :new, :version do |t, args|
|
||||
@@ -228,18 +282,20 @@ end
|
||||
#
|
||||
#############################################################################
|
||||
|
||||
desc "Release #{name} v#{version}"
|
||||
task :release => :build do
|
||||
unless `git branch` =~ /^\* master$/
|
||||
puts "You must be on the master branch to release!"
|
||||
exit!
|
||||
end
|
||||
sh "git commit --allow-empty -m 'Release #{version}'"
|
||||
sh "git commit --allow-empty -m 'Release :gem: #{version}'"
|
||||
sh "git tag v#{version}"
|
||||
sh "git push origin master"
|
||||
sh "git push origin v#{version}"
|
||||
sh "gem push pkg/#{name}-#{version}.gem"
|
||||
end
|
||||
|
||||
desc "Build #{name} v#{version} into pkg/"
|
||||
task :build do
|
||||
mkdir_p "pkg"
|
||||
sh "gem build #{gemspec_file}"
|
||||
|
||||
13
benchmark/end-with-vs-regexp
Normal file
13
benchmark/end-with-vs-regexp
Normal file
@@ -0,0 +1,13 @@
|
||||
require 'benchmark/ips'
|
||||
|
||||
Benchmark.ips do |x|
|
||||
path_without_ending_slash = '/some/very/very/long/path/to/a/file/i/like'
|
||||
x.report('no slash regexp') { path_without_ending_slash =~ /\/$/ }
|
||||
x.report('no slash end_with?') { path_without_ending_slash.end_with?("/") }
|
||||
end
|
||||
|
||||
Benchmark.ips do |x|
|
||||
path_with_ending_slash = '/some/very/very/long/path/to/a/file/i/like/'
|
||||
x.report('slash regexp') { path_with_ending_slash =~ /\/$/ }
|
||||
x.report('slash end_with?') { path_with_ending_slash.end_with?("/") }
|
||||
end
|
||||
16
benchmark/flat-map
Normal file
16
benchmark/flat-map
Normal file
@@ -0,0 +1,16 @@
|
||||
require 'benchmark/ips'
|
||||
|
||||
enum = (0..50).to_a
|
||||
nested = enum.map { |i| [i] }
|
||||
|
||||
def do_thing(blah)
|
||||
blah * 1
|
||||
end
|
||||
|
||||
Benchmark.ips do |x|
|
||||
x.report('.map.flatten with nested arrays') { nested.map { |i| do_thing(i) }.flatten(1) }
|
||||
x.report('.flat_map with nested arrays') { nested.flat_map { |i| do_thing(i) } }
|
||||
|
||||
x.report('.map.flatten with no nested arrays') { enum.map { |i| do_thing(i) }.flatten(1) }
|
||||
x.report('.flat_map with no nested arrays') { enum.flat_map { |i| do_thing(i) } }
|
||||
end
|
||||
9
benchmark/hash-fetch
Normal file
9
benchmark/hash-fetch
Normal file
@@ -0,0 +1,9 @@
|
||||
require 'benchmark/ips'
|
||||
|
||||
h = {:bar => 'uco'}
|
||||
|
||||
Benchmark.ips do |x|
|
||||
x.report('fetch with no block') { h.fetch(:bar, (0..9).to_a) }
|
||||
x.report('fetch with a block') { h.fetch(:bar) { (0..9).to_a } }
|
||||
x.report('brackets with an ||') { h[:bar] || (0..9).to_a }
|
||||
end
|
||||
46
benchmark/jekyll-sanitize-path
Normal file
46
benchmark/jekyll-sanitize-path
Normal file
@@ -0,0 +1,46 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
require_relative '../lib/jekyll'
|
||||
require 'benchmark/ips'
|
||||
|
||||
base_directory = Dir.pwd
|
||||
|
||||
Benchmark.ips do |x|
|
||||
#
|
||||
# Does not include the base_directory
|
||||
#
|
||||
x.report('with no questionable path') do
|
||||
Jekyll.sanitized_path(base_directory, '')
|
||||
end
|
||||
x.report('with a single-part questionable path') do
|
||||
Jekyll.sanitized_path(base_directory, 'thingy')
|
||||
end
|
||||
x.report('with a multi-part questionable path') do
|
||||
Jekyll.sanitized_path(base_directory, 'thingy/in/my/soup')
|
||||
end
|
||||
x.report('with a single-part traversal path') do
|
||||
Jekyll.sanitized_path(base_directory, '../thingy')
|
||||
end
|
||||
x.report('with a multi-part traversal path') do
|
||||
Jekyll.sanitized_path(base_directory, '../thingy/in/my/../../soup')
|
||||
end
|
||||
|
||||
#
|
||||
# Including the base_directory
|
||||
#
|
||||
x.report('with the exact same paths') do
|
||||
Jekyll.sanitized_path(base_directory, base_directory)
|
||||
end
|
||||
x.report('with a single-part absolute path including the base_directory') do
|
||||
Jekyll.sanitized_path(base_directory, File.join(base_directory, 'thingy'))
|
||||
end
|
||||
x.report('with a multi-part absolute path including the base_directory') do
|
||||
Jekyll.sanitized_path(base_directory, File.join(base_directory, 'thingy/in/my/soup'))
|
||||
end
|
||||
x.report('with a single-part traversal path including the base_directory') do
|
||||
Jekyll.sanitized_path(base_directory, File.join(base_directory, 'thingy/..'))
|
||||
end
|
||||
x.report('with a multi-part traversal path including the base_directory') do
|
||||
Jekyll.sanitized_path(base_directory, File.join('thingy/in/my/../../soup'))
|
||||
end
|
||||
end
|
||||
14
benchmark/proc-call-vs-yield
Normal file
14
benchmark/proc-call-vs-yield
Normal file
@@ -0,0 +1,14 @@
|
||||
require 'benchmark/ips'
|
||||
|
||||
def fast
|
||||
yield
|
||||
end
|
||||
|
||||
def slow(&block)
|
||||
block.call
|
||||
end
|
||||
|
||||
Benchmark.ips do |x|
|
||||
x.report('yield') { fast { (0..9).to_a } }
|
||||
x.report('block.call') { slow { (0..9).to_a } }
|
||||
end
|
||||
11
benchmark/sequential-assignment
Normal file
11
benchmark/sequential-assignment
Normal file
@@ -0,0 +1,11 @@
|
||||
require 'benchmark/ips'
|
||||
|
||||
Benchmark.ips do |x|
|
||||
x.report('parallel assignment') do
|
||||
a, b = 1, 2
|
||||
end
|
||||
x.report('multi-line assignment') do
|
||||
a = 1
|
||||
b = 2
|
||||
end
|
||||
end
|
||||
8
benchmark/string-concat
Normal file
8
benchmark/string-concat
Normal file
@@ -0,0 +1,8 @@
|
||||
require 'benchmark/ips'
|
||||
|
||||
url = "http://jekyllrb.com"
|
||||
|
||||
Benchmark.ips do |x|
|
||||
x.report('+=') { url += '/' }
|
||||
x.report('<<') { url << '/' }
|
||||
end
|
||||
13
benchmark/string-replacement
Normal file
13
benchmark/string-replacement
Normal file
@@ -0,0 +1,13 @@
|
||||
require 'benchmark/ips'
|
||||
|
||||
def str
|
||||
'http://baruco.org/2014/some-talk-with-some-amount-of-value'
|
||||
end
|
||||
|
||||
Benchmark.ips do |x|
|
||||
x.report('#tr') { str.tr('some', 'a') }
|
||||
x.report('#gsub') { str.gsub('some', 'a') }
|
||||
x.report('#gsub!') { str.gsub!('some', 'a') }
|
||||
x.report('#sub') { str.sub('some', 'a') }
|
||||
x.report('#sub!') { str.sub!('some', 'a') }
|
||||
end
|
||||
6
benchmark/symbol-to-proc
Normal file
6
benchmark/symbol-to-proc
Normal file
@@ -0,0 +1,6 @@
|
||||
require 'benchmark/ips'
|
||||
|
||||
Benchmark.ips do |x|
|
||||
x.report('block') { (1..100).map { |i| i.to_s } }
|
||||
x.report('&:to_s') { (1..100).map(&:to_s) }
|
||||
end
|
||||
18
bin/jekyll
18
bin/jekyll
@@ -6,12 +6,11 @@ $:.unshift File.join(File.dirname(__FILE__), *%w{ .. lib })
|
||||
require 'jekyll'
|
||||
require 'mercenary'
|
||||
|
||||
%w[jekyll-import].each do |blessed_gem|
|
||||
begin
|
||||
require blessed_gem
|
||||
rescue LoadError
|
||||
end
|
||||
end
|
||||
Jekyll::External.require_if_present(
|
||||
Jekyll::External.blessed_gems
|
||||
)
|
||||
|
||||
Jekyll::PluginManager.require_from_bundler
|
||||
|
||||
Jekyll::Deprecator.process(ARGV)
|
||||
|
||||
@@ -23,14 +22,17 @@ Mercenary.program(:jekyll) do |p|
|
||||
p.option 'source', '-s', '--source [DIR]', 'Source directory (defaults to ./)'
|
||||
p.option 'destination', '-d', '--destination [DIR]', 'Destination directory (defaults to ./_site)'
|
||||
p.option 'safe', '--safe', 'Safe mode (defaults to false)'
|
||||
p.option 'plugins', '-p', '--plugins PLUGINS_DIR1[,PLUGINS_DIR2[,...]]', Array, 'Plugins directory (defaults to ./_plugins)'
|
||||
p.option 'layouts', '--layouts DIR', String, 'Layouts directory (defaults to ./_layouts)'
|
||||
p.option 'plugins_dir', '-p', '--plugins PLUGINS_DIR1[,PLUGINS_DIR2[,...]]', Array, 'Plugins directory (defaults to ./_plugins)'
|
||||
p.option 'layouts_dir', '--layouts DIR', String, 'Layouts directory (defaults to ./_layouts)'
|
||||
p.option 'profile', '--profile', 'Generate a Liquid rendering profile'
|
||||
|
||||
Jekyll::Command.subclasses.each { |c| c.init_with_program(p) }
|
||||
|
||||
p.action do |args, options|
|
||||
if args.empty?
|
||||
Jekyll.logger.error "A subcommand is required."
|
||||
puts p
|
||||
abort
|
||||
else
|
||||
unless p.has_command?(args.first)
|
||||
Jekyll.logger.abort_with "Invalid command. Use --help for more information"
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
default: --format pretty
|
||||
travis: --format progress
|
||||
html_report: --format progress --format html --out=features_report.html
|
||||
@@ -1,93 +0,0 @@
|
||||
コントリビュート
|
||||
==========
|
||||
|
||||
あなたは Jekyll に投じるすばらしいアイディアを持っています。
|
||||
すばらしいことです!次の事柄を心に留めてください。
|
||||
|
||||
* **テストなしではコントリビュートはできません。**
|
||||
* もし、既存の機能への小さな修正やパッチを作成したなら、シンプルなテストを行います。
|
||||
現在のテストスイートの範囲にとどまり、そして
|
||||
[Shoulda](https://github.com/thoughtbot/shoulda/tree/master) や
|
||||
[RR](https://github.com/btakita/rr/tree/master) を使用してください。
|
||||
* もし、それが新しい機能の場合は、必ず新しい
|
||||
[Cucumber](https://github.com/cucumber/cucumber/) の機能を作成し、
|
||||
必要に応じて手順を再利用します。
|
||||
また、あなたがフォークした `site` に
|
||||
急ぎいくつかのドキュメントを用意し、一度マージを行い
|
||||
メイン `site` の jekyllrb.com に転送していただければ幸いです。
|
||||
* あなたのコントリビュートによって Jekyll の振る舞いが変わった場合、ドキュメントを更新すべきです。
|
||||
それは `site/docs` にあります。
|
||||
もし、 docs に情報の誤りがあった場合、遠慮なく追加してください。
|
||||
すばらしいドキュメントはすばらしいプロジェクトを作ります!
|
||||
* Ruby のコードを変更するときは、 [GitHub Ruby Styleguide](https://github.com/styleguide/ruby)
|
||||
に従ってください。
|
||||
* **小さなプルリクエスト** に最善を尽くしてください。
|
||||
簡単に提案された変更はレビューされ、マージされる可能性が高いです。
|
||||
* プルリクエストを送信するとき、プルリクエストのボディを賢明に使用してください。
|
||||
変更されたかどうかの記述、変更の背後にある動機、 [完了したかどうかのタスクリスト](http://git.io/gfm-tasks)
|
||||
もレビュー時間を早めます。
|
||||
|
||||
テストの依存関係
|
||||
-----------------
|
||||
|
||||
テストスイートの実行や gem のビルドのために、
|
||||
Jekyll の依存ツールをインストールする必要があります。
|
||||
Jekyll は Bundler を使用しており、 `bundle` コマンドを実行すると全ての設定が迅速に行われます!
|
||||
|
||||
$ bundle
|
||||
|
||||
はじめる前に、テストを実行し、必ずテストが通ることを
|
||||
確認してください(あなたの環境が適切に設定されているかを確認するために):
|
||||
|
||||
$ bundle exec rake test
|
||||
$ bundle exec rake features
|
||||
|
||||
ワークフロー
|
||||
--------
|
||||
|
||||
これは、あなたの作業がプロジェクトにマージされるもっとも直接的な方法です:
|
||||
|
||||
* プロジェクトをフォークします。
|
||||
* あなたのフォークプロジェクトをクローンします ( `git clone git@github.com:<username>/jekyll.git` )。
|
||||
* トピックブランチを作成し、あなたの変更を含んでください ( `git checkout -b my_awesome_feature` )。
|
||||
* ハックし、テストを追加します。必ずしもこの順番でなくてかまいません
|
||||
* `rake` を実行し、テストが必ず全て通ることを確認してください
|
||||
* 必要に応じて、エラーがないようにコミットを論理的な塊にリベースしてください
|
||||
* ブランチをプッシュしてください ( `git push origin my_awesome_feature` ).
|
||||
* jekyll/jekyll プロジェクトの master ブランチに対してプルリクエストを作成し、
|
||||
あなたの変更内容と、なぜそれをマージすべきかを記述してください
|
||||
|
||||
ドキュメントの更新
|
||||
----------------------
|
||||
|
||||
私たちは Jekyll のドキュメントについて最善を尽くしたいです。
|
||||
私たちはドキュメントをオープンソース化しました、そして
|
||||
あなたが Jekyll に欠けているものを見つけた場合、私たちはプルリクエストを歓迎しています。
|
||||
|
||||
あなたは、 GitHub.com 上の Jekyll リポジトリの [site]({{ site.repository }}/tree/master/site) で
|
||||
jekyllrb.comのドキュメントを見つけることができます。
|
||||
|
||||
全てのドキュメントのプルリクエストは `master` に向けられる必要があります。
|
||||
他のブランチに向けたプルリクエストは受け入れられません。
|
||||
|
||||
GitHub の [Jekyll wiki](https://github.com/jekyll/jekyll/wiki) は、
|
||||
自由に更新することができるように、プルリクエストなしで
|
||||
全ての GitHub ユーザがアクセス権を持つことができます。
|
||||
|
||||
落とし穴
|
||||
-------
|
||||
|
||||
* もし、 gem のバージョンがかちあった場合、コミットを分けてください。
|
||||
この方法だと、メンテナが gem をリリースするときに制御できます。
|
||||
* jekyll/jekyll の最新コミットに基づいて(複数の)パッチを維持してください。
|
||||
それは適用するためのあなたの仕事で、メンテナがしなければならないことを少なくするのは
|
||||
とてもよいことです。
|
||||
* あなたの GitHub issue で [fix], [feature] などのタグをつけないでください。
|
||||
メンテナは積極的に issue を読み、彼らが問題に出くわしたらラベルをつけるでしょう。
|
||||
|
||||
最後に…
|
||||
----------
|
||||
|
||||
ありがとう! Jekyll のハックは楽しいものでなければなりません。
|
||||
もし、あなたがこのハードを理解するための何かを発見した場合、知らせてください。
|
||||
我々のプロセスやドキュメントを改善することができます!
|
||||
@@ -1,68 +0,0 @@
|
||||
# [Jekyll](http://jekyllrb.com/)
|
||||
|
||||
[](http://badge.fury.io/rb/jekyll)
|
||||
|
||||
[](https://travis-ci.org/jekyll/jekyll)
|
||||
[](https://codeclimate.com/github/jekyll/jekyll)
|
||||
[](https://gemnasium.com/jekyll/jekyll)
|
||||
|
||||
Tom Preston-Werner, Nick Quaranto や多くの[素晴らしいコントリビュータ](https://github.com/jekyll/jekyll/graphs/contributors)によって作成されています!
|
||||
|
||||
Jekyll は個人プロジェクトや組織のサイトに最適な、シンプルで、ブログを意識した静的サイトジェネレータです。
|
||||
複雑さを排除したファイルベースのCMSのようなものと考えてください。
|
||||
Jekyll はコンテンツを受け取り、 Markdown や Liquid テンプレート をレンダリングし、
|
||||
Apache や Nginx やその他の Web サーバに提供する準備ができた静的な Web サイトを完全に出力してくれます。
|
||||
Jekyll は [GitHub Pages](http://pages.github.com) の背後にあるエンジンなので、
|
||||
あなたの GitHub リポジトリからサイトをホストするために使用する事ができます。
|
||||
|
||||
## 原理
|
||||
|
||||
Jekyll あなたがするように伝えたことをします ― それ以上でもそれ以下でもありません。
|
||||
それは、大胆な仮定によってユーザの裏をかこうとせず、
|
||||
また、不必要な複雑さや設定をユーザに負担しません。
|
||||
簡単に言えば、 Jekyll はあなたの道を開け、
|
||||
真に重要なもの: コンテンツに集中することができます。
|
||||
|
||||
## 開始方法
|
||||
|
||||
* gem を[インストール](http://jekyllrb.com/docs/installation/)します
|
||||
* [使用方法](http://jekyllrb.com/docs/usage/) と [設定方法](http://jekyllrb.com/docs/configuration/) を読みます
|
||||
* 既存の [Jekyll で作られたサイト](https://wiki.github.com/jekyll/jekyll/sites) をチラッと見ます
|
||||
* Fork し、あなたの変更を [コントリビュート](http://jekyllrb.com/docs/contributing/) します
|
||||
* 質問があったら? irc.freenode.net の `#jekyll` チャンネルをチェックしてください
|
||||
|
||||
## より深く
|
||||
|
||||
* 以前のシステムからの[移行](http://jekyllrb.com/docs/migrations/)
|
||||
* [YAML Front Matter](http://jekyllrb.com/docs/frontmatter/) がどのように働くかを学ぶ
|
||||
* [変数](http://jekyllrb.com/docs/variables/)を使ってサイトに情報を表示する
|
||||
* posts が生成される時の[パーマリンク](http://jekyllrb.com/docs/permalinks/)をカスタマイズ
|
||||
* 人生を容易にするために、組み込みの [Liquid 拡張](http://jekyllrb.com/docs/templates/)を使用する
|
||||
* あなたのサイト固有のコンテンツを生成するために、カスタム[プラグイン](http://jekyllrb.com/docs/plugins/)を使用する
|
||||
|
||||
## 実行時の依存関係
|
||||
|
||||
* Commander: コマンドラインインターフェース構築 (Ruby)
|
||||
* Colorator: コマンドライン出力に色付け (Ruby)
|
||||
* Classifier: posts の関連を生成 (Ruby)
|
||||
* Directory Watcher: サイトの自動再生成 (Ruby)
|
||||
* Kramdown: デフォルトの Markdown エンジン (Ruby)
|
||||
* Liquid: テンプレートシステム (Ruby)
|
||||
* Pygments.rb: シンタックスハイライト (Ruby/Python)
|
||||
* RedCarpet: Markdown エンジン (Ruby)
|
||||
* Safe YAML: セキュリティのために構築された YAML パーサ (Ruby)
|
||||
|
||||
## 開発時の依存関係
|
||||
|
||||
* Launchy: クロスプラットフォーム ファイルランチャ (Ruby)
|
||||
* Maruku: Markdown スーパーセット インタプリタ (Ruby)
|
||||
* RDiscount: Discount Markdown プロセッサ (Ruby)
|
||||
* RedCloth: Textile サポート (Ruby)
|
||||
* RedGreen: よりよいテスト出力 (Ruby)
|
||||
* RR: モック (Ruby)
|
||||
* Shoulda: テストフレームワーク (Ruby)
|
||||
* SimpleCov: カバレッジフレームワーク (Ruby)
|
||||
|
||||
## ライセンス
|
||||
|
||||
[ライセンス](https://github.com/jekyll/jekyll/blob/master/LICENSE)を見てください。
|
||||
@@ -9,12 +9,12 @@ Feature: Collections
|
||||
And I have a configuration file with "collections" set to "['methods']"
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "Collections: <p>Use <code>Jekyll.configuration</code> to build a full configuration for use w/Jekyll.</p>\n\n<p>Whatever: foo.bar</p>\n<p><code>Jekyll.sanitized_path</code> is used to make sure your path is in your source.</p>\n<p>Run your generators! default</p>\n<p>Page without title.</p>\n<p>Run your generators! default</p>" in "_site/index.html"
|
||||
And I should see "Collections: <p>Use <code class=\"highlighter-rouge\">Jekyll.configuration</code> to build a full configuration for use w/Jekyll.</p>\n\n<p>Whatever: foo.bar</p>\n<p>Signs are nice</p>\n<p><code class=\"highlighter-rouge\">Jekyll.sanitized_path</code> is used to make sure your path is in your source.</p>\n<p>Run your generators! default</p>\n<p>Page without title.</p>\n<p>Run your generators! default</p>" in "_site/index.html"
|
||||
And the "_site/methods/configuration.html" file should not exist
|
||||
|
||||
Scenario: Rendered collection
|
||||
Given I have an "index.html" page that contains "Collections: {{ site.collections }}"
|
||||
And I have an "collection_metadata.html" page that contains "Methods metadata: {{ site.collections.methods.foo }} {{ site.collections.methods }}"
|
||||
And I have an "collection_metadata.html" page that contains "Methods metadata: {{ site.collections[0].foo }} {{ site.collections[0] }}"
|
||||
And I have fixture collections
|
||||
And I have a "_config.yml" file with content:
|
||||
"""
|
||||
@@ -25,7 +25,8 @@ Feature: Collections
|
||||
"""
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "Collections: {\"methods" in "_site/index.html"
|
||||
And I should see "Collections: {\"output\"=>true" in "_site/index.html"
|
||||
And I should see "\"label\"=>\"methods\"," in "_site/index.html"
|
||||
And I should see "Methods metadata: bar" in "_site/collection_metadata.html"
|
||||
And I should see "<p>Whatever: foo.bar</p>" in "_site/methods/configuration.html"
|
||||
|
||||
@@ -56,7 +57,8 @@ Feature: Collections
|
||||
"""
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "Collections: {\"methods" in "_site/index.html"
|
||||
And I should see "Collections: {\"output\"=>true" in "_site/index.html"
|
||||
And I should see "\"label\"=>\"methods\"," in "_site/index.html"
|
||||
And I should see "<p>Run your generators! default</p>" in "_site/methods/site/generate.html"
|
||||
And I should see "<div class='title'>Tom Preston-Werner</div>" in "_site/methods/site/generate.html"
|
||||
|
||||
@@ -70,7 +72,7 @@ Feature: Collections
|
||||
"""
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "Collections: _methods/configuration.md _methods/sanitized_path.md _methods/site/generate.md _methods/site/initialize.md _methods/um_hi.md" in "_site/index.html"
|
||||
And I should see "Collections: _methods/configuration.md _methods/escape-\+ #%20\[\].md _methods/sanitized_path.md _methods/site/generate.md _methods/site/initialize.md _methods/um_hi.md" in "_site/index.html"
|
||||
|
||||
Scenario: Collections specified as an hash
|
||||
Given I have an "index.html" page that contains "Collections: {% for method in site.methods %}{{ method.relative_path }} {% endfor %}"
|
||||
@@ -82,7 +84,7 @@ Feature: Collections
|
||||
"""
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "Collections: _methods/configuration.md _methods/sanitized_path.md _methods/site/generate.md _methods/site/initialize.md _methods/um_hi.md" in "_site/index.html"
|
||||
And I should see "Collections: _methods/configuration.md _methods/escape-\+ #%20\[\].md _methods/sanitized_path.md _methods/site/generate.md _methods/site/initialize.md _methods/um_hi.md" in "_site/index.html"
|
||||
|
||||
Scenario: All the documents
|
||||
Given I have an "index.html" page that contains "All documents: {% for doc in site.documents %}{{ doc.relative_path }} {% endfor %}"
|
||||
@@ -94,7 +96,7 @@ Feature: Collections
|
||||
"""
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "All documents: _methods/configuration.md _methods/sanitized_path.md _methods/site/generate.md _methods/site/initialize.md _methods/um_hi.md" in "_site/index.html"
|
||||
And I should see "All documents: _methods/configuration.md _methods/escape-\+ #%20\[\].md _methods/sanitized_path.md _methods/site/generate.md _methods/site/initialize.md _methods/um_hi.md" in "_site/index.html"
|
||||
|
||||
Scenario: Documents have an output attribute, which is the converted HTML
|
||||
Given I have an "index.html" page that contains "First document's output: {{ site.documents.first.output }}"
|
||||
@@ -106,7 +108,7 @@ Feature: Collections
|
||||
"""
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "First document's output: <p>Use <code>Jekyll.configuration</code> to build a full configuration for use w/Jekyll.</p>\n\n<p>Whatever: foo.bar</p>" in "_site/index.html"
|
||||
And I should see "First document's output: <p>Use <code class=\"highlighter-rouge\">Jekyll.configuration</code> to build a full configuration for use w/Jekyll.</p>\n\n<p>Whatever: foo.bar</p>" in "_site/index.html"
|
||||
|
||||
Scenario: Filter documents by where
|
||||
Given I have an "index.html" page that contains "{% assign items = site.methods | where: 'whatever','foo.bar' %}Item count: {{ items.size }}"
|
||||
@@ -118,7 +120,7 @@ Feature: Collections
|
||||
"""
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "Item count: 1" in "_site/index.html"
|
||||
And I should see "Item count: 2" in "_site/index.html"
|
||||
|
||||
Scenario: Sort by title
|
||||
Given I have an "index.html" page that contains "{% assign items = site.methods | sort: 'title' %}1. of {{ items.size }}: {{ items.first.output }}"
|
||||
@@ -130,7 +132,7 @@ Feature: Collections
|
||||
"""
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "1. of 5: <p>Page without title.</p>" in "_site/index.html"
|
||||
And I should see "1. of 7: <p>Page without title.</p>" in "_site/index.html"
|
||||
|
||||
Scenario: Sort by relative_path
|
||||
Given I have an "index.html" page that contains "Collections: {% assign methods = site.methods | sort: 'relative_path' %}{% for method in methods %}{{ method.title }}, {% endfor %}"
|
||||
@@ -142,4 +144,4 @@ Feature: Collections
|
||||
"""
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "Collections: Jekyll.configuration, Jekyll.sanitized_path, Site#generate, , Site#generate," in "_site/index.html"
|
||||
And I should see "Collections: Jekyll.configuration, Jekyll.escape, Jekyll.sanitized_path, Site#generate, , Site#generate," in "_site/index.html"
|
||||
|
||||
@@ -112,16 +112,16 @@ Feature: Create sites
|
||||
And I should see "Basic Site with include tag: Generated by Jekyll" in "_site/index.html"
|
||||
|
||||
Scenario: Basic site with internal post linking
|
||||
Given I have an "index.html" page that contains "URL: {% post_url 2020-01-31-entry2 %}"
|
||||
Given I have an "index.html" page that contains "URL: {% post_url 2008-01-01-entry2 %}"
|
||||
And I have a configuration file with "permalink" set to "pretty"
|
||||
And I have a _posts directory
|
||||
And I have the following posts:
|
||||
| title | date | layout | content |
|
||||
| entry1 | 2007-12-31 | post | content for entry1. |
|
||||
| entry2 | 2020-01-31 | post | content for entry2. |
|
||||
| entry2 | 2008-01-01 | post | content for entry2. |
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "URL: /2020/01/31/entry2/" in "_site/index.html"
|
||||
And I should see "URL: /2008/01/01/entry2/" in "_site/index.html"
|
||||
|
||||
Scenario: Basic site with whitelisted dotfile
|
||||
Given I have an ".htaccess" file that contains "SomeDirective"
|
||||
@@ -156,3 +156,17 @@ Feature: Create sites
|
||||
And the "_site/index.html" file should exist
|
||||
And the "_site/public.html" file should exist
|
||||
And the "_site/secret.html" file should exist
|
||||
|
||||
Scenario: Basic site with page with future date
|
||||
Given I have a _posts directory
|
||||
And I have the following post:
|
||||
| title | date | layout | content |
|
||||
| entry1 | 2020-12-31 | post | content for entry1. |
|
||||
| entry2 | 2007-12-31 | post | content for entry2. |
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "content for entry2" in "_site/2007/12/31/entry2.html"
|
||||
And the "_site/2020/12/31/entry1.html" file should not exist
|
||||
When I run jekyll build --future
|
||||
Then the _site directory should exist
|
||||
And the "_site/2020/12/31/entry1.html" file should exist
|
||||
|
||||
@@ -45,6 +45,20 @@ Feature: Data
|
||||
And I should see "Jack" in "_site/index.html"
|
||||
And I should see "Leon" in "_site/index.html"
|
||||
|
||||
Scenario: autoload *.csv files in _data directory
|
||||
Given I have a _data directory
|
||||
And I have a "_data/members.csv" file with content:
|
||||
"""
|
||||
name,age
|
||||
Jack,28
|
||||
Leon,34
|
||||
"""
|
||||
And I have an "index.html" page that contains "{% for member in site.data.members %}{{member.name}}{% endfor %}"
|
||||
When I run jekyll build
|
||||
Then the "_site/index.html" file should exist
|
||||
And I should see "Jack" in "_site/index.html"
|
||||
And I should see "Leon" in "_site/index.html"
|
||||
|
||||
Scenario: autoload *.yml files in _data directory with space in file name
|
||||
Given I have a _data directory
|
||||
And I have a "_data/team members.yml" file with content:
|
||||
|
||||
@@ -43,4 +43,4 @@ Feature: Draft Posts
|
||||
| Recipe | 2009-03-27 | simple | Post path: {{ page.path }} |
|
||||
When I run jekyll build --drafts
|
||||
Then the _site directory should exist
|
||||
And I should see "Post path: _drafts/recipe.textile" in "_site/recipe.html"
|
||||
And I should see "Post path: _drafts/recipe.markdown" in "_site/recipe.html"
|
||||
|
||||
@@ -20,8 +20,6 @@ Feature: Embed filters
|
||||
And I have the following post:
|
||||
| title | date | layout | content |
|
||||
| Star & Wars | 2009-03-27 | default | These aren't the droids you're looking for. |
|
||||
|
||||
|
||||
And I have a default layout that contains "{{ page.title | xml_escape }}"
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
@@ -33,7 +31,7 @@ Feature: Embed filters
|
||||
And I have the following post:
|
||||
| title | date | layout | content |
|
||||
| Star Wars | 2009-03-27 | default | These aren't the droids you're looking for. |
|
||||
And I have a default layout that contains "{{ content | xml_escape }}"
|
||||
And I have a default layout that contains "{{ content | number_of_words }}"
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "7" in "_site/2009/03/27/star-wars.html"
|
||||
@@ -49,13 +47,13 @@ Feature: Embed filters
|
||||
Then the _site directory should exist
|
||||
And I should see "scifi, movies, and force" in "_site/2009/03/27/star-wars.html"
|
||||
|
||||
Scenario: Textilize a given string
|
||||
Scenario: Markdownify a given string
|
||||
Given I have a _posts directory
|
||||
And I have a _layouts directory
|
||||
And I have the following post:
|
||||
| title | date | layout | content |
|
||||
| Star Wars | 2009-03-27 | default | These aren't the droids you're looking for. |
|
||||
And I have a default layout that contains "By {{ '_Obi-wan_' | textilize }}"
|
||||
And I have a default layout that contains "By {{ '_Obi-wan_' | markdownify }}"
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "By <p><em>Obi-wan</em></p>" in "_site/2009/03/27/star-wars.html"
|
||||
|
||||
@@ -25,7 +25,7 @@ Feature: frontmatter defaults
|
||||
And I have a configuration file with "defaults" set to "[{scope: {path: ""}, values: {custom: "some special data", author: "Ben"}}]"
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "<p>some special data</p><div>Ben</div>" in "_site/2013/09/11/default-data.html"
|
||||
And I should see "<p>some special data</p>\n<div>Ben</div>" in "_site/2013/09/11/default-data.html"
|
||||
And I should see "just some special data by Ben" in "_site/index.html"
|
||||
|
||||
Scenario: Override frontmatter defaults by path
|
||||
@@ -54,6 +54,28 @@ Feature: frontmatter defaults
|
||||
And I should see "root: Overview for the webpage" in "_site/index.html"
|
||||
And I should see "subfolder: Overview for the special section" in "_site/special/index.html"
|
||||
|
||||
Scenario: Use frontmatter variables by relative path
|
||||
Given I have a _layouts directory
|
||||
And I have a main layout that contains "main: {{ content }}"
|
||||
|
||||
And I have a _posts directory
|
||||
And I have the following post:
|
||||
| title | date | content |
|
||||
| about | 2013-10-14 | content of site/2013/10/14/about.html |
|
||||
And I have a special/_posts directory
|
||||
And I have the following post in "special":
|
||||
| title | date | path | content |
|
||||
| about1 | 2013-10-14 | local | content of site/special/2013/10/14/about1.html |
|
||||
| about2 | 2013-10-14 | local | content of site/special/2013/10/14/about2.html |
|
||||
|
||||
And I have a configuration file with "defaults" set to "[{scope: {path: "special"}, values: {layout: "main"}}, {scope: {path: "special/_posts"}, values: {layout: "main"}}, {scope: {path: "_posts"}, values: {layout: "main"}}]"
|
||||
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "main: <p>content of site/2013/10/14/about.html</p>" in "_site/2013/10/14/about.html"
|
||||
And I should see "main: <p>content of site/special/2013/10/14/about1.html</p>" in "_site/special/2013/10/14/about1.html"
|
||||
And I should see "main: <p>content of site/special/2013/10/14/about2.html</p>" in "_site/special/2013/10/14/about2.html"
|
||||
|
||||
Scenario: Override frontmatter defaults by type
|
||||
Given I have a _posts directory
|
||||
And I have the following post:
|
||||
@@ -78,11 +100,22 @@ Feature: frontmatter defaults
|
||||
And I should see "nothing" in "_site/override.html"
|
||||
But the "_site/perma.html" file should not exist
|
||||
|
||||
Scenario: Define permalink default for posts
|
||||
Given I have a _posts directory
|
||||
And I have the following post:
|
||||
| title | date | category | content |
|
||||
| testpost | 2013-10-14 | blog | blabla |
|
||||
And I have a configuration file with "defaults" set to "[{scope: {path: "", type: "posts"}, values: {permalink: "/:categories/:title/"}}]"
|
||||
When I run jekyll build
|
||||
Then I should see "blabla" in "_site/blog/testpost/index.html"
|
||||
|
||||
Scenario: Use frontmatter defaults in collections
|
||||
Given I have a _slides directory
|
||||
And I have a "index.html" file that contains "nothing"
|
||||
And I have a "_slides/slide1.html" file with content:
|
||||
And I have a "_slides/slide1.html" file with content:
|
||||
"""
|
||||
---
|
||||
---
|
||||
Value: {{ page.myval }}
|
||||
"""
|
||||
And I have a "_config.yml" file with content:
|
||||
@@ -105,7 +138,7 @@ Feature: frontmatter defaults
|
||||
Scenario: Override frontmatter defaults inside a collection
|
||||
Given I have a _slides directory
|
||||
And I have a "index.html" file that contains "nothing"
|
||||
And I have a "_slides/slide2.html" file with content:
|
||||
And I have a "_slides/slide2.html" file with content:
|
||||
"""
|
||||
---
|
||||
myval: Override
|
||||
@@ -128,3 +161,9 @@ Feature: frontmatter defaults
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "Value: Override" in "_site/slides/slide2.html"
|
||||
|
||||
Scenario: Deep merge frontmatter defaults
|
||||
Given I have an "index.html" page with fruit "{orange: 1}" that contains "Fruits: {{ page.fruit.orange | plus: page.fruit.apple }}"
|
||||
And I have a configuration file with "defaults" set to "[{scope: {path: ""}, values: {fruit: {apple: 2}}}]"
|
||||
When I run jekyll build
|
||||
Then I should see "Fruits: 3" in "_site/index.html"
|
||||
|
||||
326
features/hooks.feature
Normal file
326
features/hooks.feature
Normal file
@@ -0,0 +1,326 @@
|
||||
Feature: Hooks
|
||||
As a plugin author
|
||||
I want to be able to run code during various stages of the build process
|
||||
|
||||
Scenario: Run some code after site reset
|
||||
Given I have a _plugins directory
|
||||
And I have a "_plugins/ext.rb" file with content:
|
||||
"""
|
||||
Jekyll::Hooks.register :site, :after_reset do |site|
|
||||
pageklass = Class.new(Jekyll::Page) do
|
||||
def initialize(site, base)
|
||||
@site = site
|
||||
@base = base
|
||||
@data = {}
|
||||
@dir = '/'
|
||||
@name = 'foo.html'
|
||||
@content = 'mytinypage'
|
||||
|
||||
self.process(@name)
|
||||
end
|
||||
end
|
||||
|
||||
site.pages << pageklass.new(site, site.source)
|
||||
end
|
||||
"""
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "mytinypage" in "_site/foo.html"
|
||||
|
||||
Scenario: Modify the payload before rendering the site
|
||||
Given I have a _plugins directory
|
||||
And I have a "index.html" page that contains "{{ site.injected }}!"
|
||||
And I have a "_plugins/ext.rb" file with content:
|
||||
"""
|
||||
Jekyll::Hooks.register :site, :pre_render do |site, payload|
|
||||
payload['site']['injected'] = 'myparam'
|
||||
end
|
||||
"""
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "myparam!" in "_site/index.html"
|
||||
|
||||
Scenario: Modify the site contents after reading
|
||||
Given I have a _plugins directory
|
||||
And I have a "page1.html" page that contains "page1"
|
||||
And I have a "page2.html" page that contains "page2"
|
||||
And I have a "_plugins/ext.rb" file with content:
|
||||
"""
|
||||
Jekyll::Hooks.register :site, :post_read do |site|
|
||||
site.pages.delete_if { |p| p.name == 'page1.html' }
|
||||
end
|
||||
"""
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And the "_site/page1.html" file should not exist
|
||||
And I should see "page2" in "_site/page2.html"
|
||||
|
||||
Scenario: Work with the site files after they've been written to disk
|
||||
Given I have a _plugins directory
|
||||
And I have a "_plugins/ext.rb" file with content:
|
||||
"""
|
||||
Jekyll::Hooks.register :site, :post_write do |site|
|
||||
firstpage = site.pages.first
|
||||
content = File.read firstpage.destination(site.dest)
|
||||
File.write(File.join(site.dest, 'firstpage.html'), content)
|
||||
end
|
||||
"""
|
||||
And I have a "page1.html" page that contains "page1"
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "page1" in "_site/firstpage.html"
|
||||
|
||||
Scenario: Alter a page right after it is initialized
|
||||
Given I have a _plugins directory
|
||||
And I have a "_plugins/ext.rb" file with content:
|
||||
"""
|
||||
Jekyll::Hooks.register :pages, :post_init do |page|
|
||||
page.name = 'renamed.html'
|
||||
page.process(page.name)
|
||||
end
|
||||
"""
|
||||
And I have a "page1.html" page that contains "page1"
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "page1" in "_site/renamed.html"
|
||||
|
||||
Scenario: Alter the payload for one page but not another
|
||||
Given I have a _plugins directory
|
||||
And I have a "_plugins/ext.rb" file with content:
|
||||
"""
|
||||
Jekyll::Hooks.register :pages, :pre_render do |page, payload|
|
||||
payload['myparam'] = 'special' if page.name == 'page1.html'
|
||||
end
|
||||
"""
|
||||
And I have a "page1.html" page that contains "{{ myparam }}"
|
||||
And I have a "page2.html" page that contains "{{ myparam }}"
|
||||
When I run jekyll build
|
||||
Then I should see "special" in "_site/page1.html"
|
||||
And I should not see "special" in "_site/page2.html"
|
||||
|
||||
Scenario: Modify page contents before writing to disk
|
||||
Given I have a _plugins directory
|
||||
And I have a "index.html" page that contains "WRAP ME"
|
||||
And I have a "_plugins/ext.rb" file with content:
|
||||
"""
|
||||
Jekyll::Hooks.register :pages, :post_render do |page|
|
||||
page.output = "{{{{{ #{page.output.chomp} }}}}}"
|
||||
end
|
||||
"""
|
||||
When I run jekyll build
|
||||
Then I should see "{{{{{ WRAP ME }}}}}" in "_site/index.html"
|
||||
|
||||
Scenario: Work with a page after writing it to disk
|
||||
Given I have a _plugins directory
|
||||
And I have a "index.html" page that contains "HELLO FROM A PAGE"
|
||||
And I have a "_plugins/ext.rb" file with content:
|
||||
"""
|
||||
Jekyll::Hooks.register :pages, :post_write do |page|
|
||||
require 'fileutils'
|
||||
filename = page.destination(page.site.dest)
|
||||
FileUtils.mv(filename, "#{filename}.moved")
|
||||
end
|
||||
"""
|
||||
When I run jekyll build
|
||||
Then I should see "HELLO FROM A PAGE" in "_site/index.html.moved"
|
||||
|
||||
Scenario: Alter a post right after it is initialized
|
||||
Given I have a _plugins directory
|
||||
And I have a "_plugins/ext.rb" file with content:
|
||||
"""
|
||||
Jekyll::Hooks.register :posts, :post_init do |post|
|
||||
post.data['harold'] = "content for entry1.".tr!('abcdefghijklmnopqrstuvwxyz',
|
||||
'nopqrstuvwxyzabcdefghijklm')
|
||||
end
|
||||
"""
|
||||
And I have a _posts directory
|
||||
And I have the following posts:
|
||||
| title | date | layout | content |
|
||||
| entry1 | 2015-03-14 | nil | {{ page.harold }} |
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "pbagrag sbe ragel1." in "_site/2015/03/14/entry1.html"
|
||||
|
||||
Scenario: Alter the payload for certain posts
|
||||
Given I have a _plugins directory
|
||||
And I have a "_plugins/ext.rb" file with content:
|
||||
"""
|
||||
# Add myvar = 'old' to posts before 2015-03-15, and myvar = 'new' for
|
||||
# others
|
||||
Jekyll::Hooks.register :posts, :pre_render do |post, payload|
|
||||
if post.date < Time.new(2015, 3, 15)
|
||||
payload['myvar'] = 'old'
|
||||
else
|
||||
payload['myvar'] = 'new'
|
||||
end
|
||||
end
|
||||
"""
|
||||
And I have a _posts directory
|
||||
And I have the following posts:
|
||||
| title | date | layout | content |
|
||||
| entry1 | 2015-03-14 | nil | {{ myvar }} post |
|
||||
| entry2 | 2015-03-15 | nil | {{ myvar }} post |
|
||||
When I run jekyll build
|
||||
Then I should see "old post" in "_site/2015/03/14/entry1.html"
|
||||
And I should see "new post" in "_site/2015/03/15/entry2.html"
|
||||
|
||||
Scenario: Modify post contents before writing to disk
|
||||
Given I have a _plugins directory
|
||||
And I have a "_plugins/ext.rb" file with content:
|
||||
"""
|
||||
# Replace content after rendering
|
||||
Jekyll::Hooks.register :posts, :post_render do |post|
|
||||
post.output.gsub! /42/, 'the answer to life, the universe and everything'
|
||||
end
|
||||
"""
|
||||
And I have a _posts directory
|
||||
And I have the following posts:
|
||||
| title | date | layout | content |
|
||||
| entry1 | 2015-03-14 | nil | {{ 6 \| times: 7 }} |
|
||||
| entry2 | 2015-03-15 | nil | {{ 6 \| times: 8 }} |
|
||||
When I run jekyll build
|
||||
Then I should see "the answer to life, the universe and everything" in "_site/2015/03/14/entry1.html"
|
||||
And I should see "48" in "_site/2015/03/15/entry2.html"
|
||||
|
||||
Scenario: Work with a post after writing it to disk
|
||||
Given I have a _plugins directory
|
||||
And I have a "_plugins/ext.rb" file with content:
|
||||
"""
|
||||
# Log all post filesystem writes
|
||||
Jekyll::Hooks.register :posts, :post_write do |post|
|
||||
filename = post.destination(post.site.dest)
|
||||
open('_site/post-build.log', 'a') do |f|
|
||||
f.puts "Wrote #{filename} at #{Time.now}"
|
||||
end
|
||||
end
|
||||
"""
|
||||
And I have a _posts directory
|
||||
And I have the following posts:
|
||||
| title | date | layout | content |
|
||||
| entry1 | 2015-03-14 | nil | entry one |
|
||||
| entry2 | 2015-03-15 | nil | entry two |
|
||||
When I run jekyll build
|
||||
Then I should see "_site/2015/03/14/entry1.html at" in "_site/post-build.log"
|
||||
Then I should see "_site/2015/03/15/entry2.html at" in "_site/post-build.log"
|
||||
|
||||
Scenario: Register a hook on multiple owners at the same time
|
||||
Given I have a _plugins directory
|
||||
And I have a "_plugins/ext.rb" file with content:
|
||||
"""
|
||||
Jekyll::Hooks.register [:pages, :posts], :post_render do |owner|
|
||||
owner.output = "{{{{{ #{owner.output.chomp} }}}}}"
|
||||
end
|
||||
"""
|
||||
And I have a "index.html" page that contains "WRAP ME"
|
||||
And I have a _posts directory
|
||||
And I have the following posts:
|
||||
| title | date | layout | content |
|
||||
| entry1 | 2015-03-14 | nil | entry one |
|
||||
When I run jekyll build
|
||||
Then I should see "{{{{{ WRAP ME }}}}}" in "_site/index.html"
|
||||
And I should see "{{{{{ <p>entry one</p> }}}}}" in "_site/2015/03/14/entry1.html"
|
||||
|
||||
Scenario: Allow hooks to have a named priority
|
||||
Given I have a _plugins directory
|
||||
And I have a "_plugins/ext.rb" file with content:
|
||||
"""
|
||||
Jekyll::Hooks.register :pages, :post_render, priority: :normal do |owner|
|
||||
# first normal runs second
|
||||
owner.output = "1 #{owner.output.chomp}"
|
||||
end
|
||||
Jekyll::Hooks.register :pages, :post_render, priority: :high do |owner|
|
||||
# high runs last
|
||||
owner.output = "2 #{owner.output.chomp}"
|
||||
end
|
||||
Jekyll::Hooks.register :pages, :post_render do |owner|
|
||||
# second normal runs third (normal is default)
|
||||
owner.output = "3 #{owner.output.chomp}"
|
||||
end
|
||||
Jekyll::Hooks.register :pages, :post_render, priority: :low do |owner|
|
||||
# low runs first
|
||||
owner.output = "4 #{owner.output.chomp}"
|
||||
end
|
||||
"""
|
||||
And I have a "index.html" page that contains "WRAP ME"
|
||||
When I run jekyll build
|
||||
Then I should see "2 3 1 4 WRAP ME" in "_site/index.html"
|
||||
|
||||
Scenario: Alter a document right after it is initialized
|
||||
Given I have a _plugins directory
|
||||
And I have a "_plugins/ext.rb" file with content:
|
||||
"""
|
||||
Jekyll::Hooks.register :documents, :pre_render do |doc, payload|
|
||||
doc.data['text'] = doc.data['text'] << ' are belong to us'
|
||||
end
|
||||
"""
|
||||
And I have a "_config.yml" file that contains "collections: [ memes ]"
|
||||
And I have a _memes directory
|
||||
And I have a "_memes/doc1.md" file with content:
|
||||
"""
|
||||
---
|
||||
text: all your base
|
||||
---
|
||||
"""
|
||||
And I have an "index.md" file with content:
|
||||
"""
|
||||
---
|
||||
---
|
||||
{{ site.memes.first.text }}
|
||||
"""
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "all your base are belong to us" in "_site/index.html"
|
||||
|
||||
Scenario: Update a document after rendering it, but before writing it to disk
|
||||
Given I have a _plugins directory
|
||||
And I have a "_plugins/ext.rb" file with content:
|
||||
"""
|
||||
Jekyll::Hooks.register :documents, :post_render do |doc|
|
||||
doc.output.gsub! /<p>/, '<p class="meme">'
|
||||
end
|
||||
"""
|
||||
And I have a "_config.yml" file with content:
|
||||
"""
|
||||
collections:
|
||||
memes:
|
||||
output: true
|
||||
"""
|
||||
And I have a _memes directory
|
||||
And I have a "_memes/doc1.md" file with content:
|
||||
"""
|
||||
---
|
||||
text: all your base are belong to us
|
||||
---
|
||||
{{ page.text }}
|
||||
"""
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "<p class=\"meme\">all your base are belong to us" in "_site/memes/doc1.html"
|
||||
|
||||
Scenario: Perform an action after every document is written
|
||||
Given I have a _plugins directory
|
||||
And I have a "_plugins/ext.rb" file with content:
|
||||
"""
|
||||
Jekyll::Hooks.register :documents, :post_write do |doc|
|
||||
open('_site/document-build.log', 'a') do |f|
|
||||
f.puts "Wrote document #{doc.collection.docs.index doc} at #{Time.now}"
|
||||
end
|
||||
end
|
||||
"""
|
||||
And I have a "_config.yml" file with content:
|
||||
"""
|
||||
collections:
|
||||
memes:
|
||||
output: true
|
||||
"""
|
||||
And I have a _memes directory
|
||||
And I have a "_memes/doc1.md" file with content:
|
||||
"""
|
||||
---
|
||||
text: all your base are belong to us
|
||||
---
|
||||
{{ page.text }}
|
||||
"""
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "Wrote document 0" in "_site/document-build.log"
|
||||
@@ -9,15 +9,15 @@ Feature: Include tags
|
||||
And I have an "_includes/params.html" file that contains "Parameters:<ul>{% for param in include %}<li>{{param[0]}} = {{param[1]}}</li>{% endfor %}</ul>"
|
||||
And I have an "_includes/ignore.html" file that contains "<footer>My blog footer</footer>"
|
||||
And I have a _posts directory
|
||||
And I have the following post:
|
||||
| title | date | layout | content |
|
||||
| Include Files | 2013-03-21 | default | {% include header.html param="myparam" %} |
|
||||
| Ignore params if unused | 2013-03-21 | default | {% include ignore.html date="today" %} |
|
||||
| List multiple parameters | 2013-03-21 | default | {% include params.html date="today" start="tomorrow" %} |
|
||||
| Dont keep parameters | 2013-03-21 | default | {% include ignore.html param="test" %}\n{% include header.html %} |
|
||||
| Allow params with spaces and quotes | 2013-04-07 | default | {% include params.html cool="param with spaces" super="\"quoted\"" single='has "quotes"' escaped='\'single\' quotes' %} |
|
||||
| Parameter syntax | 2013-04-12 | default | {% include params.html param1_or_2="value" %} |
|
||||
| Pass a variable | 2013-06-22 | default | {% assign var = 'some text' %}{% include params.html local=var layout=page.layout %} |
|
||||
And I have the following posts:
|
||||
| title | date | type | content |
|
||||
| Include Files | 2013-03-21 | html | {% include header.html param="myparam" %} |
|
||||
| Ignore params if unused | 2013-03-21 | html | {% include ignore.html date="today" %} |
|
||||
| List multiple parameters | 2013-03-21 | html | {% include params.html date="today" start="tomorrow" %} |
|
||||
| Dont keep parameters | 2013-03-21 | html | {% include ignore.html param="test" %}\n{% include header.html %} |
|
||||
| Allow params with spaces and quotes | 2013-04-07 | html | {% include params.html cool="param with spaces" super="\"quoted\"" single='has "quotes"' escaped='\'single\' quotes' %} |
|
||||
| Parameter syntax | 2013-04-12 | html | {% include params.html param1_or_2="value" %} |
|
||||
| Pass a variable | 2013-06-22 | html | {% assign var = 'some text' %}{% include params.html local=var title=page.title %} |
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "<header>My awesome blog header: myparam</header>" in "_site/2013/03/21/include-files.html"
|
||||
@@ -27,12 +27,12 @@ Feature: Include tags
|
||||
And I should not see "<header>My awesome blog header: myparam</header>" in "_site/2013/03/21/dont-keep-parameters.html"
|
||||
But I should see "<header>My awesome blog header: </header>" in "_site/2013/03/21/dont-keep-parameters.html"
|
||||
And I should see "<li>cool = param with spaces</li>" in "_site/2013/04/07/allow-params-with-spaces-and-quotes.html"
|
||||
And I should see "<li>super = “quoted”</li>" in "_site/2013/04/07/allow-params-with-spaces-and-quotes.html"
|
||||
And I should see "<li>single = has “quotes”</li>" in "_site/2013/04/07/allow-params-with-spaces-and-quotes.html"
|
||||
And I should see "<li>escaped = ‘single’ quotes</li>" in "_site/2013/04/07/allow-params-with-spaces-and-quotes.html"
|
||||
And I should see "<li>super = \"quoted\"</li>" in "_site/2013/04/07/allow-params-with-spaces-and-quotes.html"
|
||||
And I should see "<li>single = has \"quotes\"</li>" in "_site/2013/04/07/allow-params-with-spaces-and-quotes.html"
|
||||
And I should see "<li>escaped = 'single' quotes</li>" in "_site/2013/04/07/allow-params-with-spaces-and-quotes.html"
|
||||
And I should see "<li>param1_or_2 = value</li>" in "_site/2013/04/12/parameter-syntax.html"
|
||||
And I should see "<li>local = some text</li>" in "_site/2013/06/22/pass-a-variable.html"
|
||||
And I should see "<li>layout = default</li>" in "_site/2013/06/22/pass-a-variable.html"
|
||||
And I should see "<li>title = Pass a variable</li>" in "_site/2013/06/22/pass-a-variable.html"
|
||||
|
||||
Scenario: Include a file from a variable
|
||||
Given I have an _includes directory
|
||||
@@ -66,3 +66,14 @@ Feature: Include tags
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "one included" in "_site/index.html"
|
||||
|
||||
Scenario: Include a file with partial variables
|
||||
Given I have an _includes directory
|
||||
And I have an "_includes/one.html" file that contains "one included"
|
||||
And I have a configuration file with:
|
||||
| key | value |
|
||||
| include_file | one |
|
||||
And I have an "index.html" page that contains "{% include {{ site.include_file }}.html %}"
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "one included" in "_site/index.html"
|
||||
|
||||
60
features/incremental_rebuild.feature
Normal file
60
features/incremental_rebuild.feature
Normal file
@@ -0,0 +1,60 @@
|
||||
Feature: Incremental rebuild
|
||||
As an impatient hacker who likes to blog
|
||||
I want to be able to make a static site
|
||||
Without waiting too long for it to build
|
||||
|
||||
Scenario: Produce correct output site
|
||||
Given I have a _layouts directory
|
||||
And I have a _posts directory
|
||||
And I have the following posts:
|
||||
| title | date | layout | content |
|
||||
| Wargames | 2009-03-27 | default | The only winning move is not to play. |
|
||||
And I have a default layout that contains "Post Layout: {{ content }}"
|
||||
When I run jekyll build -I
|
||||
Then the _site directory should exist
|
||||
And I should see "Post Layout: <p>The only winning move is not to play.</p>" in "_site/2009/03/27/wargames.html"
|
||||
When I run jekyll build -I
|
||||
Then the _site directory should exist
|
||||
And I should see "Post Layout: <p>The only winning move is not to play.</p>" in "_site/2009/03/27/wargames.html"
|
||||
|
||||
Scenario: Generate a metadata file
|
||||
Given I have an "index.html" file that contains "Basic Site"
|
||||
When I run jekyll build -I
|
||||
Then the ".jekyll-metadata" file should exist
|
||||
|
||||
Scenario: Rebuild when content is changed
|
||||
Given I have an "index.html" file that contains "Basic Site"
|
||||
When I run jekyll build -I
|
||||
Then the _site directory should exist
|
||||
And I should see "Basic Site" in "_site/index.html"
|
||||
When I wait 1 second
|
||||
Then I have an "index.html" file that contains "Bacon Site"
|
||||
When I run jekyll build -I
|
||||
Then the _site directory should exist
|
||||
And I should see "Bacon Site" in "_site/index.html"
|
||||
|
||||
Scenario: Rebuild when layout is changed
|
||||
Given I have a _layouts directory
|
||||
And I have an "index.html" page with layout "default" that contains "Basic Site with Layout"
|
||||
And I have a default layout that contains "Page Layout: {{ content }}"
|
||||
When I run jekyll build -I
|
||||
Then the _site directory should exist
|
||||
And I should see "Page Layout: Basic Site with Layout" in "_site/index.html"
|
||||
When I wait 1 second
|
||||
Then I have a default layout that contains "Page Layout Changed: {{ content }}"
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "Page Layout Changed: Basic Site with Layout" in "_site/index.html"
|
||||
|
||||
Scenario: Rebuild when an include is changed
|
||||
Given I have a _includes directory
|
||||
And I have an "index.html" page that contains "Basic Site with include tag: {% include about.textile %}"
|
||||
And I have an "_includes/about.textile" file that contains "Generated by Jekyll"
|
||||
When I run jekyll build -I
|
||||
Then the _site directory should exist
|
||||
And I should see "Basic Site with include tag: Generated by Jekyll" in "_site/index.html"
|
||||
When I wait 1 second
|
||||
Then I have an "_includes/about.textile" file that contains "Regenerated by Jekyll"
|
||||
When I run jekyll build -I
|
||||
Then the _site directory should exist
|
||||
And I should see "Basic Site with include tag: Regenerated by Jekyll" in "_site/index.html"
|
||||
@@ -17,7 +17,10 @@ Feature: Markdown
|
||||
And I should see "<h1 id=\"my-title\">My Title</h1>" in "_site/index.html"
|
||||
|
||||
Scenario: Markdown in pagination on index
|
||||
Given I have a configuration file with "paginate" set to "5"
|
||||
Given I have a configuration file with:
|
||||
| key | value |
|
||||
| paginate | 5 |
|
||||
| gems | [jekyll-paginate] |
|
||||
And I have an "index.html" page that contains "Index - {% for post in paginator.posts %} {{ post.content }} {% endfor %}"
|
||||
And I have a _posts directory
|
||||
And I have the following post:
|
||||
@@ -27,41 +30,3 @@ Feature: Markdown
|
||||
Then the _site directory should exist
|
||||
And I should see "Index" in "_site/index.html"
|
||||
And I should see "<h1 id=\"my-title\">My Title</h1>" in "_site/index.html"
|
||||
|
||||
Scenario: Maruku fenced codeblocks
|
||||
Given I have a configuration file with "markdown" set to "maruku"
|
||||
And I have an "index.markdown" file with content:
|
||||
"""
|
||||
---
|
||||
title: My title
|
||||
---
|
||||
|
||||
# My title
|
||||
|
||||
```
|
||||
My awesome code
|
||||
```
|
||||
"""
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "My awesome code" in "_site/index.html"
|
||||
And I should see "<pre><code>\nMy awesome code\n</code></pre>" in "_site/index.html"
|
||||
|
||||
Scenario: Maruku fenced codeblocks
|
||||
Given I have a configuration file with "markdown" set to "maruku"
|
||||
And I have an "index.markdown" file with content:
|
||||
"""
|
||||
---
|
||||
title: My title
|
||||
---
|
||||
|
||||
# My title
|
||||
|
||||
```ruby
|
||||
puts "My awesome string"
|
||||
```
|
||||
"""
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "My awesome string" in "_site/index.html"
|
||||
And I should see "<pre class="ruby"><code class="ruby">\nputs "My awesome string"\n</code></pre>" in "_site/index.html"
|
||||
|
||||
@@ -4,7 +4,10 @@ Feature: Site pagination
|
||||
I want divide the posts in several pages
|
||||
|
||||
Scenario Outline: Paginate with N posts per page
|
||||
Given I have a configuration file with "paginate" set to "<num>"
|
||||
Given I have a configuration file with:
|
||||
| key | value |
|
||||
| paginate | <num> |
|
||||
| gems | [jekyll-paginate] |
|
||||
And I have a _layouts directory
|
||||
And I have an "index.html" page that contains "{{ paginator.posts.size }}"
|
||||
And I have a _posts directory
|
||||
@@ -32,6 +35,7 @@ Feature: Site pagination
|
||||
| paginate | 1 |
|
||||
| paginate_path | /blog/page-:num |
|
||||
| permalink | /blog/:year/:month/:day/:title |
|
||||
| gems | [jekyll-paginate] |
|
||||
And I have a blog directory
|
||||
And I have an "blog/index.html" page that contains "{{ paginator.posts.size }}"
|
||||
And I have a _posts directory
|
||||
@@ -59,6 +63,7 @@ Feature: Site pagination
|
||||
| paginate | 1 |
|
||||
| paginate_path | /blog/page/:num |
|
||||
| permalink | /blog/:year/:month/:day/:title |
|
||||
| gems | [jekyll-paginate] |
|
||||
And I have a blog directory
|
||||
And I have an "blog/index.html" page that contains "{{ paginator.posts.size }}"
|
||||
And I have an "index.html" page that contains "Don't pick me!"
|
||||
|
||||
@@ -39,7 +39,7 @@ Feature: Fancy permalinks
|
||||
And I have the following post:
|
||||
| title | category | date | content |
|
||||
| Custom Permalink Schema | stuff | 2009-03-27 | Totally custom. |
|
||||
And I have a configuration file with "permalink" set to "/blog/:year/:month/:day/:title"
|
||||
And I have a configuration file with "permalink" set to "/blog/:year/:month/:day/:title/"
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "Totally custom." in "_site/blog/2009/03/27/custom-permalink-schema/index.html"
|
||||
@@ -64,11 +64,24 @@ Feature: Fancy permalinks
|
||||
Then the _site directory should exist
|
||||
And I should see "Totally custom." in "_site/03-27-2009/custom-permalink-schema.html"
|
||||
|
||||
Scenario: Use custom permalink schema with date and time
|
||||
Given I have a _posts directory
|
||||
And I have the following post:
|
||||
| title | category | date | content |
|
||||
| Custom Permalink Schema | stuff | 2009-03-27 22:31:07 | Totally custom. |
|
||||
And I have a configuration file with:
|
||||
| key | value |
|
||||
| permalink | "/:year:month:day:hour:minute:second.html" |
|
||||
| timezone | UTC |
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "Totally custom." in "_site/20090327223107.html"
|
||||
|
||||
Scenario: Use per-post permalink
|
||||
Given I have a _posts directory
|
||||
And I have the following post:
|
||||
| title | date | permalink | content |
|
||||
| Some post | 2013-04-14 | /custom/posts/1 | bla bla |
|
||||
| Some post | 2013-04-14 | /custom/posts/1/ | bla bla |
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And the _site/custom/posts/1 directory should exist
|
||||
@@ -83,3 +96,27 @@ Feature: Fancy permalinks
|
||||
Then the _site directory should exist
|
||||
And the _site/custom/posts directory should exist
|
||||
And I should see "bla bla" in "_site/custom/posts/some.html"
|
||||
|
||||
Scenario: Use pretty permalink schema with cased file name
|
||||
Given I have a _posts directory
|
||||
And I have an "_posts/2009-03-27-Pretty-Permalink-Schema.md" page that contains "Totally wordpress"
|
||||
And I have a configuration file with "permalink" set to "pretty"
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "Totally wordpress." in "_site/2009/03/27/Pretty-Permalink-Schema/index.html"
|
||||
|
||||
Scenario: Use custom permalink schema with cased file name
|
||||
Given I have a _posts directory
|
||||
And I have an "_posts/2009-03-27-Custom-Schema.md" page with title "Custom Schema" that contains "Totally awesome"
|
||||
And I have a configuration file with "permalink" set to "/:year/:month/:day/:slug/"
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "Totally awesome" in "_site/2009/03/27/custom-schema/index.html"
|
||||
|
||||
Scenario: Use pretty permalink schema with title containing underscore
|
||||
Given I have a _posts directory
|
||||
And I have an "_posts/2009-03-27-Custom_Schema.md" page with title "Custom Schema" that contains "Totally awesome"
|
||||
And I have a configuration file with "permalink" set to "pretty"
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "Totally awesome" in "_site/2009/03/27/Custom_Schema/index.html"
|
||||
|
||||
34
features/plugins.feature
Normal file
34
features/plugins.feature
Normal file
@@ -0,0 +1,34 @@
|
||||
Feature: Configuring and using plugins
|
||||
As a hacker
|
||||
I want to specify my own plugins that can modify Jekyll's behaviour
|
||||
|
||||
Scenario: Add a gem-based plugin
|
||||
Given I have an "index.html" file that contains "Whatever"
|
||||
And I have a configuration file with "gems" set to "[jekyll_test_plugin]"
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "Whatever" in "_site/index.html"
|
||||
And I should see "this is a test" in "_site/test.txt"
|
||||
|
||||
Scenario: Add an empty whitelist to restrict all gems
|
||||
Given I have an "index.html" file that contains "Whatever"
|
||||
And I have a configuration file with:
|
||||
| key | value |
|
||||
| gems | [jekyll_test_plugin] |
|
||||
| whitelist | [] |
|
||||
When I run jekyll build --safe
|
||||
Then the _site directory should exist
|
||||
And I should see "Whatever" in "_site/index.html"
|
||||
And the "_site/test.txt" file should not exist
|
||||
|
||||
Scenario: Add a whitelist to restrict some gems but allow others
|
||||
Given I have an "index.html" file that contains "Whatever"
|
||||
And I have a configuration file with:
|
||||
| key | value |
|
||||
| gems | [jekyll_test_plugin, jekyll_test_plugin_malicious] |
|
||||
| whitelist | [jekyll_test_plugin] |
|
||||
When I run jekyll build --safe
|
||||
Then the _site directory should exist
|
||||
And I should see "Whatever" in "_site/index.html"
|
||||
And the "_site/test.txt" file should exist
|
||||
And I should see "this is a test" in "_site/test.txt"
|
||||
@@ -70,17 +70,41 @@ Feature: Post data
|
||||
Then the _site directory should exist
|
||||
And I should see "Post category: movies" in "_site/movies/2009/03/27/star-wars.html"
|
||||
|
||||
Scenario: Use post.categories variable when category is in a folder and has category in YAML
|
||||
Given I have a movies directory
|
||||
And I have a movies/_posts directory
|
||||
And I have a _layouts directory
|
||||
And I have the following post in "movies":
|
||||
| title | date | layout | category | content |
|
||||
| Star Wars | 2009-03-27 | simple | film | Luke, I am your father. |
|
||||
And I have a simple layout that contains "Post category: {{ page.categories }}"
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "Post category: movies" in "_site/movies/film/2009/03/27/star-wars.html"
|
||||
|
||||
Scenario: Use post.categories variable when category is in a folder and has categories in YAML
|
||||
Given I have a movies directory
|
||||
And I have a movies/_posts directory
|
||||
And I have a _layouts directory
|
||||
And I have the following post in "movies":
|
||||
| title | date | layout | categories | content |
|
||||
| Star Wars | 2009-03-27 | simple | [film] | Luke, I am your father. |
|
||||
| title | date | layout | categories | content |
|
||||
| Star Wars | 2009-03-27 | simple | [film, scifi] | Luke, I am your father. |
|
||||
And I have a simple layout that contains "Post category: {{ page.categories }}"
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "Post category: movies" in "_site/movies/film/2009/03/27/star-wars.html"
|
||||
And I should see "Post category: movies" in "_site/movies/film/scifi/2009/03/27/star-wars.html"
|
||||
|
||||
Scenario: Use post.categories variable when category is in a folder and duplicated category is in YAML
|
||||
Given I have a movies directory
|
||||
And I have a movies/_posts directory
|
||||
And I have a _layouts directory
|
||||
And I have the following post in "movies":
|
||||
| title | date | layout | category | content |
|
||||
| Star Wars | 2009-03-27 | simple | movies | Luke, I am your father. |
|
||||
And I have a simple layout that contains "Post category: {{ page.categories }}"
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "Post category: movies" in "_site/movies/2009/03/27/star-wars.html"
|
||||
|
||||
Scenario: Use post.tags variable
|
||||
Given I have a _posts directory
|
||||
@@ -117,7 +141,7 @@ Feature: Post data
|
||||
And I have a simple layout that contains "Post categories: {{ page.categories | array_to_sentence_string }}"
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "Post categories: scifi and movies" in "_site/scifi/movies/2009/03/27/star-wars.html"
|
||||
And I should see "Post categories: scifi and Movies" in "_site/scifi/movies/2009/03/27/star-wars.html"
|
||||
|
||||
Scenario: Use post.categories variable when category is in YAML
|
||||
Given I have a _posts directory
|
||||
@@ -139,14 +163,43 @@ Feature: Post data
|
||||
And I have a simple layout that contains "Post category: {{ page.categories }}"
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "Post category: movies" in "_site/movies/2009/03/27/star-wars.html"
|
||||
And I should see "Post category: Movies" in "_site/movies/2009/03/27/star-wars.html"
|
||||
|
||||
Scenario: Use post.categories variable when category is in YAML
|
||||
Scenario: Use post.categories variable when categories are in YAML
|
||||
Given I have a _posts directory
|
||||
And I have a _layouts directory
|
||||
And I have the following post:
|
||||
| title | date | layout | category | content |
|
||||
| Star Wars | 2009-03-27 | simple | movies | Luke, I am your father. |
|
||||
| title | date | layout | categories | content |
|
||||
| Star Wars | 2009-03-27 | simple | ['scifi', 'movies'] | Luke, I am your father. |
|
||||
And I have a simple layout that contains "Post categories: {{ page.categories | array_to_sentence_string }}"
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "Post categories: scifi and movies" in "_site/scifi/movies/2009/03/27/star-wars.html"
|
||||
|
||||
Scenario: Use post.categories variable when categories are in YAML and are duplicated
|
||||
Given I have a _posts directory
|
||||
And I have a _layouts directory
|
||||
And I have the following post:
|
||||
| title | date | layout | categories | content |
|
||||
| Star Wars | 2009-03-27 | simple | ['movies', 'movies'] | Luke, I am your father. |
|
||||
And I have a simple layout that contains "Post category: {{ page.categories }}"
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "Post category: movies" in "_site/movies/2009/03/27/star-wars.html"
|
||||
|
||||
Scenario: Superdirectories of _posts applied to post.categories
|
||||
Given I have a movies/_posts directory
|
||||
And I have a "movies/_posts/2009-03-27-star-wars.html" page with layout "simple" that contains "hi"
|
||||
And I have a _layouts directory
|
||||
And I have a simple layout that contains "Post category: {{ page.categories }}"
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "Post category: movies" in "_site/movies/2009/03/27/star-wars.html"
|
||||
|
||||
Scenario: Subdirectories of _posts not applied to post.categories
|
||||
Given I have a movies/_posts/scifi directory
|
||||
And I have a "movies/_posts/scifi/2009-03-27-star-wars.html" page with layout "simple" that contains "hi"
|
||||
And I have a _layouts directory
|
||||
And I have a simple layout that contains "Post category: {{ page.categories }}"
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
@@ -162,8 +215,8 @@ Feature: Post data
|
||||
And I have a simple layout that contains "Post categories: {{ page.categories | array_to_sentence_string }}"
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "Post categories: scifi and movies" in "_site/scifi/movies/2009/03/27/star-wars.html"
|
||||
And I should see "Post categories: scifi and movies" in "_site/scifi/movies/2013/03/17/star-trek.html"
|
||||
And I should see "Post categories: scifi and Movies" in "_site/scifi/movies/2009/03/27/star-wars.html"
|
||||
And I should see "Post categories: SciFi and movies" in "_site/scifi/movies/2013/03/17/star-trek.html"
|
||||
|
||||
Scenario Outline: Use page.path variable
|
||||
Given I have a <dir>/_posts directory
|
||||
|
||||
@@ -46,5 +46,5 @@ Feature: Post excerpts
|
||||
And the _site/2007/12 directory should exist
|
||||
And the _site/2007/12/31 directory should exist
|
||||
And the "_site/2007/12/31/entry1.html" file should exist
|
||||
And I should see exactly "<p>content for entry1.</p>" in "_site/index.html"
|
||||
And I should see exactly "<html><head></head><body><p>content for entry1.</p></body></html>" in "_site/2007/12/31/entry1.html"
|
||||
And I should see "<p>content for entry1.</p>" in "_site/index.html"
|
||||
And I should see "<html><head></head><body><p>content for entry1.</p>\n</body></html>" in "_site/2007/12/31/entry1.html"
|
||||
|
||||
@@ -5,6 +5,13 @@ Feature: Rendering
|
||||
But I want to make it as simply as possible
|
||||
So render with Liquid and place in Layouts
|
||||
|
||||
Scenario: When receiving bad Liquid
|
||||
Given I have a "index.html" page with layout "simple" that contains "{% include invalid.html %}"
|
||||
And I have a simple layout that contains "{{ content }}"
|
||||
When I run jekyll build
|
||||
Then I should get a non-zero exit-status
|
||||
And I should see "Liquid Exception" in the build output
|
||||
|
||||
Scenario: Render Liquid and place in layout
|
||||
Given I have a "index.html" page with layout "simple" that contains "Hi there, Jekyll {{ jekyll.environment }}!"
|
||||
And I have a simple layout that contains "{{ content }}Ahoy, indeed!"
|
||||
@@ -15,20 +22,29 @@ Feature: Rendering
|
||||
Scenario: Don't place asset files in layout
|
||||
Given I have an "index.scss" page with layout "simple" that contains ".foo-bar { color:black; }"
|
||||
And I have an "index.coffee" page with layout "simple" that contains "whatever()"
|
||||
And I have a configuration file with "gems" set to "[jekyll-coffeescript]"
|
||||
And I have a simple layout that contains "{{ content }}Ahoy, indeed!"
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should not see "Ahoy, indeed!" in "_site/index.css"
|
||||
And I should not see "Ahoy, indeed!" in "_site/index.js"
|
||||
|
||||
Scenario: Don't render liquid in Sass
|
||||
Scenario: Render liquid in Sass
|
||||
Given I have an "index.scss" page that contains ".foo-bar { color:{{site.color}}; }"
|
||||
When I run jekyll build
|
||||
Then the _site directory should not exist
|
||||
And I should see "Invalid CSS after" in the build output
|
||||
|
||||
Scenario: Don't render liquid in CoffeeScript
|
||||
Given I have an "index.coffee" page that contains "hey='for {{site.animal}}'"
|
||||
And I have a configuration file with "color" set to "red"
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "hey = 'for {{site.animal}}';" in "_site/index.js"
|
||||
And I should see ".foo-bar {\n color: red; }" in "_site/index.css"
|
||||
|
||||
Scenario: Not render liquid in CoffeeScript without explicitly including jekyll-coffeescript
|
||||
Given I have an "index.coffee" page with animal "cicada" that contains "hey='for {{page.animal}}'"
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And the "_site/index.js" file should not exist
|
||||
|
||||
Scenario: Render liquid in CoffeeScript with jekyll-coffeescript enabled
|
||||
Given I have an "index.coffee" page with animal "cicada" that contains "hey='for {{page.animal}}'"
|
||||
And I have a configuration file with "gems" set to "[jekyll-coffeescript]"
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "hey = 'for cicada';" in "_site/index.js"
|
||||
|
||||
@@ -83,13 +83,6 @@ Feature: Site configuration
|
||||
Then the _site directory should exist
|
||||
And I should see "<a href=\"http://google.com\">Google</a>" in "_site/index.html"
|
||||
|
||||
Scenario: Use Maruku for markup
|
||||
Given I have an "index.markdown" page that contains "[Google](http://google.com)"
|
||||
And I have a configuration file with "markdown" set to "maruku"
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "<a href=\"http://google.com\">Google</a>" in "_site/index.html"
|
||||
|
||||
Scenario: Highlight code with pygments
|
||||
Given I have an "index.html" page that contains "{% highlight ruby %} puts 'Hello world!' {% endhighlight %}"
|
||||
When I run jekyll build
|
||||
@@ -170,8 +163,8 @@ Feature: Site configuration
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "Page Layout: 2" in "_site/index.html"
|
||||
And I should see "Post Layout: <p>content for entry1.</p> built at 2013-04-09T23:22:00-04:00" in "_site/2013/04/09/entry1.html"
|
||||
And I should see "Post Layout: <p>content for entry2.</p> built at 2013-04-10T03:14:00-04:00" in "_site/2013/04/10/entry2.html"
|
||||
And I should see "Post Layout: <p>content for entry1.</p>\n built at 2013-04-09T23:22:00-04:00" in "_site/2013/04/09/entry1.html"
|
||||
And I should see "Post Layout: <p>content for entry2.</p>\n built at 2013-04-10T03:14:00-04:00" in "_site/2013/04/10/entry2.html"
|
||||
|
||||
Scenario: Generate proper dates with explicitly set timezone (different than posts' time)
|
||||
Given I have a _layouts directory
|
||||
@@ -180,19 +173,19 @@ Feature: Site configuration
|
||||
And I have an "index.html" page with layout "page" that contains "site index page"
|
||||
And I have a configuration file with:
|
||||
| key | value |
|
||||
| timezone | Australia/Melbourne |
|
||||
| timezone | Pacific/Honolulu |
|
||||
And I have a _posts directory
|
||||
And I have the following posts:
|
||||
| title | date | layout | content |
|
||||
| entry1 | 2013-04-09 23:22 -0400 | post | content for entry1. |
|
||||
| entry2 | 2013-04-10 03:14 -0400 | post | content for entry2. |
|
||||
| entry1 | 2013-04-09 23:22 +0400 | post | content for entry1. |
|
||||
| entry2 | 2013-04-10 03:14 +0400 | post | content for entry2. |
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "Page Layout: 2" in "_site/index.html"
|
||||
And the "_site/2013/04/10/entry1.html" file should exist
|
||||
And the "_site/2013/04/10/entry2.html" file should exist
|
||||
And I should see escaped "Post Layout: <p>content for entry1.</p> built at 2013-04-10T13:22:00+10:00" in "_site/2013/04/10/entry1.html"
|
||||
And I should see escaped "Post Layout: <p>content for entry2.</p> built at 2013-04-10T17:14:00+10:00" in "_site/2013/04/10/entry2.html"
|
||||
And the "_site/2013/04/09/entry1.html" file should exist
|
||||
And the "_site/2013/04/09/entry2.html" file should exist
|
||||
And I should see "Post Layout: <p>content for entry1.</p>\n built at 2013-04-09T09:22:00-10:00" in "_site/2013/04/09/entry1.html"
|
||||
And I should see "Post Layout: <p>content for entry2.</p>\n built at 2013-04-09T13:14:00-10:00" in "_site/2013/04/09/entry2.html"
|
||||
|
||||
Scenario: Limit the number of posts generated by most recent date
|
||||
Given I have a _posts directory
|
||||
@@ -231,7 +224,7 @@ Feature: Site configuration
|
||||
| key | value |
|
||||
| time | 2010-01-01 |
|
||||
| future | true |
|
||||
| layouts | _theme |
|
||||
| layouts_dir | _theme |
|
||||
And I have a _posts directory
|
||||
And I have the following posts:
|
||||
| title | date | layout | content |
|
||||
@@ -243,33 +236,10 @@ Feature: Site configuration
|
||||
And I should see "Post Layout: <p>content for entry1.</p>" in "_site/2007/12/31/entry1.html"
|
||||
And I should see "Post Layout: <p>content for entry2.</p>" in "_site/2020/01/31/entry2.html"
|
||||
|
||||
Scenario: Add a gem-based plugin
|
||||
Given I have an "index.html" file that contains "Whatever"
|
||||
And I have a configuration file with "gems" set to "[jekyll_test_plugin]"
|
||||
Scenario: arbitrary file reads via layouts
|
||||
Given I have an "index.html" page with layout "page" that contains "FOO"
|
||||
And I have a "_config.yml" file that contains "layouts: '../../../../../../../../../../../../../../usr/include'"
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "Whatever" in "_site/index.html"
|
||||
And I should see "this is a test" in "_site/test.txt"
|
||||
|
||||
Scenario: Add an empty whitelist to restrict all gems
|
||||
Given I have an "index.html" file that contains "Whatever"
|
||||
And I have a configuration file with:
|
||||
| key | value |
|
||||
| gems | [jekyll_test_plugin] |
|
||||
| whitelist | [] |
|
||||
When I run jekyll build --safe
|
||||
Then the _site directory should exist
|
||||
And I should see "Whatever" in "_site/index.html"
|
||||
And the "_site/test.txt" file should not exist
|
||||
|
||||
Scenario: Add a whitelist to restrict some gems but allow others
|
||||
Given I have an "index.html" file that contains "Whatever"
|
||||
And I have a configuration file with:
|
||||
| key | value |
|
||||
| gems | [jekyll_test_plugin, jekyll_test_plugin_malicious] |
|
||||
| whitelist | [jekyll_test_plugin] |
|
||||
When I run jekyll build --safe
|
||||
Then the _site directory should exist
|
||||
And I should see "Whatever" in "_site/index.html"
|
||||
And the "_site/test.txt" file should exist
|
||||
And I should see "this is a test" in "_site/test.txt"
|
||||
And I should see "FOO" in "_site/index.html"
|
||||
And I should not see " " in "_site/index.html"
|
||||
|
||||
@@ -8,7 +8,7 @@ def file_content_from_hash(input_hash)
|
||||
input_hash['content']
|
||||
end
|
||||
|
||||
<<EOF
|
||||
<<-EOF
|
||||
---
|
||||
#{matter}
|
||||
---
|
||||
@@ -22,11 +22,15 @@ Before do
|
||||
end
|
||||
|
||||
After do
|
||||
FileUtils.rm_rf(TEST_DIR) if File.exists?(TEST_DIR)
|
||||
FileUtils.rm(JEKYLL_COMMAND_OUTPUT_FILE) if File.exists?(JEKYLL_COMMAND_OUTPUT_FILE)
|
||||
FileUtils.rm_rf(TEST_DIR) if File.exist?(TEST_DIR)
|
||||
FileUtils.rm(JEKYLL_COMMAND_OUTPUT_FILE) if File.exist?(JEKYLL_COMMAND_OUTPUT_FILE)
|
||||
FileUtils.rm(JEKYLL_COMMAND_STATUS_FILE) if File.exist?(JEKYLL_COMMAND_STATUS_FILE)
|
||||
Dir.chdir(File.dirname(TEST_DIR))
|
||||
end
|
||||
|
||||
World(Test::Unit::Assertions)
|
||||
World do
|
||||
MinitestWorld.new
|
||||
end
|
||||
|
||||
Given /^I have a blank site in "(.*)"$/ do |path|
|
||||
FileUtils.mkdir_p(path) unless File.exist?(path)
|
||||
@@ -39,7 +43,7 @@ end
|
||||
# Like "I have a foo file" but gives a yaml front matter so jekyll actually processes it
|
||||
Given /^I have an? "(.*)" page(?: with (.*) "(.*)")? that contains "(.*)"$/ do |file, key, value, text|
|
||||
File.open(file, 'w') do |f|
|
||||
f.write <<EOF
|
||||
f.write <<-EOF
|
||||
---
|
||||
#{key || 'layout'}: #{value || 'nil'}
|
||||
---
|
||||
@@ -83,7 +87,7 @@ end
|
||||
Given /^I have the following (draft|page|post)s?(?: (in|under) "([^"]+)")?:$/ do |status, direction, folder, table|
|
||||
table.hashes.each do |input_hash|
|
||||
title = slug(input_hash['title'])
|
||||
ext = input_hash['type'] || 'textile'
|
||||
ext = input_hash['type'] || 'markdown'
|
||||
before, after = location(folder, direction)
|
||||
|
||||
case status
|
||||
@@ -133,6 +137,10 @@ Given /^I have fixture collections$/ do
|
||||
FileUtils.cp_r File.join(JEKYLL_SOURCE_DIR, "test", "source", "_methods"), source_dir
|
||||
end
|
||||
|
||||
Given /^I wait (\d+) second(s?)$/ do |time, plural|
|
||||
sleep(time.to_f)
|
||||
end
|
||||
|
||||
##################
|
||||
#
|
||||
# Changing stuff
|
||||
@@ -146,6 +154,13 @@ When /^I run jekyll(.*)$/ do |args|
|
||||
end
|
||||
end
|
||||
|
||||
When /^I run bundle(.*)$/ do |args|
|
||||
status = run_bundle(args)
|
||||
if args.include?("--verbose") || ENV['DEBUG']
|
||||
puts jekyll_run_output
|
||||
end
|
||||
end
|
||||
|
||||
When /^I change "(.*)" to contain "(.*)"$/ do |file, text|
|
||||
File.open(file, 'a') do |f|
|
||||
f.write(text)
|
||||
@@ -156,6 +171,12 @@ When /^I delete the file "(.*)"$/ do |file|
|
||||
File.delete(file)
|
||||
end
|
||||
|
||||
##################
|
||||
#
|
||||
# Checking stuff
|
||||
#
|
||||
##################
|
||||
|
||||
Then /^the (.*) directory should +exist$/ do |dir|
|
||||
assert File.directory?(dir), "The directory \"#{dir}\" does not exist"
|
||||
end
|
||||
@@ -173,7 +194,7 @@ Then /^I should see exactly "(.*)" in "(.*)"$/ do |text, file|
|
||||
end
|
||||
|
||||
Then /^I should not see "(.*)" in "(.*)"$/ do |text, file|
|
||||
assert_no_match Regexp.new(text, Regexp::MULTILINE), file_contents(file)
|
||||
refute_match Regexp.new(text, Regexp::MULTILINE), file_contents(file)
|
||||
end
|
||||
|
||||
Then /^I should see escaped "(.*)" in "(.*)"$/ do |text, file|
|
||||
@@ -181,7 +202,15 @@ Then /^I should see escaped "(.*)" in "(.*)"$/ do |text, file|
|
||||
end
|
||||
|
||||
Then /^the "(.*)" file should +exist$/ do |file|
|
||||
assert File.file?(file), "The file \"#{file}\" does not exist"
|
||||
file_does_exist = File.file?(file)
|
||||
unless file_does_exist
|
||||
all_steps_to_path(file).each do |dir|
|
||||
STDERR.puts ""
|
||||
STDERR.puts "Dir #{dir}:"
|
||||
STDERR.puts Dir["#{dir}/**/*"]
|
||||
end
|
||||
end
|
||||
assert file_does_exist, "The file \"#{file}\" does not exist.\n"
|
||||
end
|
||||
|
||||
Then /^the "(.*)" file should not exist$/ do |file|
|
||||
@@ -199,3 +228,7 @@ end
|
||||
Then /^I should see "(.*)" in the build output$/ do |text|
|
||||
assert_match Regexp.new(text), jekyll_run_output
|
||||
end
|
||||
|
||||
Then /^I should get a non-zero exit(?:\-| )status$/ do
|
||||
assert jekyll_run_status > 0
|
||||
end
|
||||
|
||||
@@ -1,27 +1,78 @@
|
||||
require 'fileutils'
|
||||
require 'rr'
|
||||
require 'test/unit'
|
||||
require 'posix-spawn'
|
||||
require 'minitest/spec'
|
||||
require 'time'
|
||||
|
||||
class MinitestWorld
|
||||
extend Minitest::Assertions
|
||||
attr_accessor :assertions
|
||||
|
||||
def initialize
|
||||
self.assertions = 0
|
||||
end
|
||||
end
|
||||
|
||||
JEKYLL_SOURCE_DIR = File.dirname(File.dirname(File.dirname(__FILE__)))
|
||||
TEST_DIR = File.expand_path(File.join('..', '..', 'tmp', 'jekyll'), File.dirname(__FILE__))
|
||||
JEKYLL_PATH = File.join(File.dirname(__FILE__), '..', '..', 'bin', 'jekyll')
|
||||
JEKYLL_PATH = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'bin', 'jekyll'))
|
||||
JEKYLL_COMMAND_OUTPUT_FILE = File.join(File.dirname(TEST_DIR), 'jekyll_output.txt')
|
||||
JEKYLL_COMMAND_STATUS_FILE = File.join(File.dirname(TEST_DIR), 'jekyll_status.txt')
|
||||
|
||||
def source_dir(*files)
|
||||
File.join(TEST_DIR, *files)
|
||||
end
|
||||
|
||||
def all_steps_to_path(path)
|
||||
source = Pathname.new(source_dir('_site')).expand_path
|
||||
dest = Pathname.new(path).expand_path
|
||||
paths = []
|
||||
dest.ascend do |f|
|
||||
break if f.eql? source
|
||||
paths.unshift f.to_s
|
||||
end
|
||||
paths
|
||||
end
|
||||
|
||||
def jekyll_output_file
|
||||
JEKYLL_COMMAND_OUTPUT_FILE
|
||||
end
|
||||
|
||||
def jekyll_status_file
|
||||
JEKYLL_COMMAND_STATUS_FILE
|
||||
end
|
||||
|
||||
def jekyll_run_output
|
||||
File.read(jekyll_output_file)
|
||||
File.read(jekyll_output_file) if File.file?(jekyll_output_file)
|
||||
end
|
||||
|
||||
def jekyll_run_status
|
||||
(File.read(jekyll_status_file) rescue 0).to_i
|
||||
end
|
||||
|
||||
def run_bundle(args)
|
||||
run_in_shell('bundle', *args.strip.split(' '))
|
||||
end
|
||||
|
||||
def run_jekyll(args)
|
||||
system "#{JEKYLL_PATH} #{args} --trace > #{jekyll_output_file} 2>&1"
|
||||
child = run_in_shell(JEKYLL_PATH, *args.strip.split(' '), "--trace")
|
||||
child.status.exitstatus == 0
|
||||
end
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# XXX: POSIX::Spawn::Child does not write output when the exit status is > 0
|
||||
# for example when doing [:out, :err] => [file, "w"] it will skip
|
||||
# writing the file entirely, we sould switch to Open.
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
def run_in_shell(*args)
|
||||
spawned = POSIX::Spawn::Child.new(*args)
|
||||
status = spawned.status.exitstatus
|
||||
File.write(JEKYLL_COMMAND_STATUS_FILE, status)
|
||||
File.open(JEKYLL_COMMAND_OUTPUT_FILE, "w+") do |file|
|
||||
status == 0 ? file.write(spawned.out) : file.write(spawned.err)
|
||||
end
|
||||
|
||||
spawned
|
||||
end
|
||||
|
||||
def slug(title)
|
||||
|
||||
147
features/support/overview.rb
Normal file
147
features/support/overview.rb
Normal file
@@ -0,0 +1,147 @@
|
||||
require 'fileutils'
|
||||
require 'colorator'
|
||||
require 'cucumber/formatter/console'
|
||||
require 'cucumber/formatter/io'
|
||||
require 'gherkin/formatter/escaping'
|
||||
|
||||
module Features
|
||||
module Support
|
||||
# The formatter used for <tt>--format pretty</tt> (the default formatter).
|
||||
#
|
||||
# This formatter prints features to plain text - exactly how they were parsed,
|
||||
# just prettier. That means with proper indentation and alignment of table columns.
|
||||
#
|
||||
# If the output is STDOUT (and not a file), there are bright colours to watch too.
|
||||
#
|
||||
class Overview
|
||||
include FileUtils
|
||||
include Cucumber::Formatter::Console
|
||||
include Cucumber::Formatter::Io
|
||||
include Gherkin::Formatter::Escaping
|
||||
attr_writer :indent
|
||||
attr_reader :runtime
|
||||
|
||||
def initialize(runtime, path_or_io, options)
|
||||
@runtime, @io, @options = runtime, ensure_io(path_or_io, "pretty"), options
|
||||
@exceptions = []
|
||||
@indent = 0
|
||||
@prefixes = options[:prefixes] || {}
|
||||
@delayed_messages = []
|
||||
end
|
||||
|
||||
def before_features(features)
|
||||
print_profile_information
|
||||
end
|
||||
|
||||
def after_features(features)
|
||||
@io.puts
|
||||
print_summary(features)
|
||||
end
|
||||
|
||||
def before_feature(feature)
|
||||
@exceptions = []
|
||||
@indent = 0
|
||||
end
|
||||
|
||||
def comment_line(comment_line)
|
||||
end
|
||||
|
||||
def after_tags(tags)
|
||||
end
|
||||
|
||||
def tag_name(tag_name)
|
||||
end
|
||||
|
||||
def before_feature_element(feature_element)
|
||||
@indent = 2
|
||||
@scenario_indent = 2
|
||||
end
|
||||
|
||||
def after_feature_element(feature_element)
|
||||
end
|
||||
|
||||
def before_background(background)
|
||||
@indent = 2
|
||||
@scenario_indent = 2
|
||||
@in_background = true
|
||||
end
|
||||
|
||||
def after_background(background)
|
||||
@in_background = nil
|
||||
end
|
||||
|
||||
def background_name(keyword, name, file_colon_line, source_indent)
|
||||
print_feature_element_name(keyword, name, file_colon_line, source_indent)
|
||||
end
|
||||
|
||||
def scenario_name(keyword, name, file_colon_line, source_indent)
|
||||
print_feature_element_name(keyword, name, file_colon_line, source_indent)
|
||||
end
|
||||
|
||||
def before_step(step)
|
||||
@current_step = step
|
||||
end
|
||||
|
||||
def before_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background, file_colon_line)
|
||||
@hide_this_step = false
|
||||
if exception
|
||||
if @exceptions.include?(exception)
|
||||
@hide_this_step = true
|
||||
return
|
||||
end
|
||||
@exceptions << exception
|
||||
end
|
||||
if status != :failed && @in_background ^ background
|
||||
@hide_this_step = true
|
||||
return
|
||||
end
|
||||
@status = status
|
||||
end
|
||||
|
||||
CHARS = {
|
||||
:failed => "x".red,
|
||||
:pending => "?".yellow,
|
||||
:undefined => "x".red,
|
||||
:passed => ".".green,
|
||||
:skipped => "-".blue
|
||||
}
|
||||
|
||||
def step_name(keyword, step_match, status, source_indent, background, file_colon_line)
|
||||
@io.print CHARS[status]
|
||||
end
|
||||
|
||||
def exception(exception, status)
|
||||
return if @hide_this_step
|
||||
@io.puts
|
||||
print_exception(exception, status, @indent)
|
||||
@io.flush
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def print_feature_element_name(keyword, name, file_colon_line, source_indent)
|
||||
@io.puts
|
||||
names = name.empty? ? [name] : name.split("\n")
|
||||
line = " #{keyword}: #{names[0]}"
|
||||
if @options[:source]
|
||||
line_comment = "#{file_colon_line}"
|
||||
@io.print(line_comment)
|
||||
end
|
||||
@io.print(line)
|
||||
@io.print " "
|
||||
@io.flush
|
||||
end
|
||||
|
||||
def cell_prefix(status)
|
||||
@prefixes[status]
|
||||
end
|
||||
|
||||
def print_summary(features)
|
||||
@io.puts
|
||||
print_stats(features, @options)
|
||||
print_snippets(@options)
|
||||
print_passing_wip(@options)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -5,59 +5,35 @@ require 'jekyll/version'
|
||||
|
||||
Gem::Specification.new do |s|
|
||||
s.specification_version = 2 if s.respond_to? :specification_version=
|
||||
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
||||
s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to? :required_rubygems_version=
|
||||
s.rubygems_version = '2.2.2'
|
||||
s.required_ruby_version = '>= 1.9.3'
|
||||
s.required_ruby_version = '>= 2.0.0'
|
||||
|
||||
s.name = 'jekyll'
|
||||
s.version = Jekyll::VERSION
|
||||
s.license = 'MIT'
|
||||
s.name = 'jekyll'
|
||||
s.version = Jekyll::VERSION
|
||||
s.license = 'MIT'
|
||||
|
||||
s.summary = "A simple, blog aware, static site generator."
|
||||
s.description = "Jekyll is a simple, blog aware, static site generator."
|
||||
s.summary = 'A simple, blog aware, static site generator.'
|
||||
s.description = 'Jekyll is a simple, blog aware, static site generator.'
|
||||
|
||||
s.authors = ["Tom Preston-Werner"]
|
||||
s.email = 'tom@mojombo.com'
|
||||
s.homepage = 'https://github.com/jekyll/jekyll'
|
||||
s.authors = ['Tom Preston-Werner']
|
||||
s.email = 'tom@mojombo.com'
|
||||
s.homepage = 'https://github.com/jekyll/jekyll'
|
||||
|
||||
s.files = `git ls-files`.split($/)
|
||||
s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
||||
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
||||
s.require_paths = ["lib"]
|
||||
all_files = `git ls-files -z`.split("\x0")
|
||||
s.files = all_files.grep(%r{^(bin|lib)/})
|
||||
s.executables = all_files.grep(%r{^bin/}) { |f| File.basename(f) }
|
||||
s.require_paths = ['lib']
|
||||
|
||||
s.rdoc_options = ["--charset=UTF-8"]
|
||||
s.rdoc_options = ['--charset=UTF-8']
|
||||
s.extra_rdoc_files = %w[README.markdown LICENSE]
|
||||
|
||||
s.add_runtime_dependency('liquid', "~> 2.6.1")
|
||||
s.add_runtime_dependency('classifier', "~> 1.3")
|
||||
s.add_runtime_dependency('listen', [">= 2.7.6", "< 3.0.0"])
|
||||
s.add_runtime_dependency('kramdown', "~> 1.3")
|
||||
s.add_runtime_dependency('pygments.rb', "~> 0.6.0")
|
||||
s.add_runtime_dependency('mercenary', "~> 0.3.3")
|
||||
s.add_runtime_dependency('safe_yaml', "~> 1.0")
|
||||
s.add_runtime_dependency('colorator', "~> 0.1")
|
||||
s.add_runtime_dependency('redcarpet', "~> 3.1")
|
||||
s.add_runtime_dependency('toml', '~> 0.1.0')
|
||||
s.add_runtime_dependency('jekyll-paginate', '~> 1.0')
|
||||
s.add_runtime_dependency('jekyll-gist', '~> 1.0')
|
||||
s.add_runtime_dependency('jekyll-coffeescript', '~> 1.0')
|
||||
s.add_runtime_dependency('liquid', '~> 3.0')
|
||||
s.add_runtime_dependency('kramdown', '~> 1.3')
|
||||
s.add_runtime_dependency('mercenary', '~> 0.3.3')
|
||||
s.add_runtime_dependency('safe_yaml', '~> 1.0')
|
||||
s.add_runtime_dependency('colorator', '~> 0.1')
|
||||
s.add_runtime_dependency('rouge', '~> 1.7')
|
||||
s.add_runtime_dependency('jekyll-sass-converter', '~> 1.0')
|
||||
|
||||
s.add_development_dependency('rake', "~> 10.1")
|
||||
s.add_development_dependency('rdoc', "~> 3.11")
|
||||
s.add_development_dependency('redgreen', "~> 1.2")
|
||||
s.add_development_dependency('shoulda', "~> 3.5")
|
||||
s.add_development_dependency('rr', "~> 1.1")
|
||||
s.add_development_dependency('cucumber', "1.3.11")
|
||||
s.add_development_dependency('RedCloth', "~> 4.2")
|
||||
s.add_development_dependency('maruku', "0.7.0")
|
||||
s.add_development_dependency('rdiscount', "~> 1.6")
|
||||
s.add_development_dependency('launchy', "~> 2.3")
|
||||
s.add_development_dependency('simplecov', "~> 0.7")
|
||||
s.add_development_dependency('simplecov-gem-adapter', "~> 1.0.1")
|
||||
s.add_development_dependency('mime-types', "~> 1.5")
|
||||
s.add_development_dependency('activesupport', '~> 3.2.13')
|
||||
s.add_development_dependency('jekyll_test_plugin')
|
||||
s.add_development_dependency('jekyll_test_plugin_malicious')
|
||||
s.add_development_dependency('rouge', '~> 1.3')
|
||||
s.add_runtime_dependency('jekyll-watch', '~> 1.1')
|
||||
end
|
||||
|
||||
247
lib/jekyll.rb
247
lib/jekyll.rb
@@ -18,52 +18,156 @@ require 'rubygems'
|
||||
# stdlib
|
||||
require 'fileutils'
|
||||
require 'time'
|
||||
require 'safe_yaml/load'
|
||||
require 'English'
|
||||
require 'pathname'
|
||||
require 'logger'
|
||||
require 'set'
|
||||
|
||||
# 3rd party
|
||||
require 'safe_yaml/load'
|
||||
require 'liquid'
|
||||
require 'kramdown'
|
||||
require 'colorator'
|
||||
require 'toml'
|
||||
|
||||
# internal requires
|
||||
require 'jekyll/version'
|
||||
require 'jekyll/utils'
|
||||
require 'jekyll/log_adapter'
|
||||
require 'jekyll/stevenson'
|
||||
require 'jekyll/deprecator'
|
||||
require 'jekyll/configuration'
|
||||
require 'jekyll/document'
|
||||
require 'jekyll/collection'
|
||||
require 'jekyll/plugin_manager'
|
||||
require 'jekyll/frontmatter_defaults'
|
||||
require 'jekyll/site'
|
||||
require 'jekyll/convertible'
|
||||
require 'jekyll/url'
|
||||
require 'jekyll/layout'
|
||||
require 'jekyll/page'
|
||||
require 'jekyll/post'
|
||||
require 'jekyll/excerpt'
|
||||
require 'jekyll/draft'
|
||||
require 'jekyll/filters'
|
||||
require 'jekyll/static_file'
|
||||
require 'jekyll/errors'
|
||||
require 'jekyll/related_posts'
|
||||
require 'jekyll/cleaner'
|
||||
require 'jekyll/entry_filter'
|
||||
require 'jekyll/layout_reader'
|
||||
require 'jekyll/publisher'
|
||||
require 'jekyll/renderer'
|
||||
SafeYAML::OPTIONS[:suppress_warnings] = true
|
||||
|
||||
# extensions
|
||||
require 'jekyll/plugin'
|
||||
require 'jekyll/converter'
|
||||
require 'jekyll/generator'
|
||||
require 'jekyll/command'
|
||||
require 'jekyll/liquid_extensions'
|
||||
module Jekyll
|
||||
|
||||
# internal requires
|
||||
autoload :Cleaner, 'jekyll/cleaner'
|
||||
autoload :Collection, 'jekyll/collection'
|
||||
autoload :Configuration, 'jekyll/configuration'
|
||||
autoload :Convertible, 'jekyll/convertible'
|
||||
autoload :Deprecator, 'jekyll/deprecator'
|
||||
autoload :Document, 'jekyll/document'
|
||||
autoload :Draft, 'jekyll/draft'
|
||||
autoload :EntryFilter, 'jekyll/entry_filter'
|
||||
autoload :Errors, 'jekyll/errors'
|
||||
autoload :Excerpt, 'jekyll/excerpt'
|
||||
autoload :External, 'jekyll/external'
|
||||
autoload :Filters, 'jekyll/filters'
|
||||
autoload :FrontmatterDefaults, 'jekyll/frontmatter_defaults'
|
||||
autoload :Hooks, 'jekyll/hooks'
|
||||
autoload :Layout, 'jekyll/layout'
|
||||
autoload :CollectionReader, 'jekyll/readers/collection_reader'
|
||||
autoload :DataReader, 'jekyll/readers/data_reader'
|
||||
autoload :LayoutReader, 'jekyll/readers/layout_reader'
|
||||
autoload :PostReader, 'jekyll/readers/post_reader'
|
||||
autoload :PageReader, 'jekyll/readers/page_reader'
|
||||
autoload :StaticFileReader, 'jekyll/readers/static_file_reader'
|
||||
autoload :LogAdapter, 'jekyll/log_adapter'
|
||||
autoload :Page, 'jekyll/page'
|
||||
autoload :PluginManager, 'jekyll/plugin_manager'
|
||||
autoload :Publisher, 'jekyll/publisher'
|
||||
autoload :Reader, 'jekyll/reader'
|
||||
autoload :Regenerator, 'jekyll/regenerator'
|
||||
autoload :RelatedPosts, 'jekyll/related_posts'
|
||||
autoload :Renderer, 'jekyll/renderer'
|
||||
autoload :LiquidRenderer, 'jekyll/liquid_renderer'
|
||||
autoload :Site, 'jekyll/site'
|
||||
autoload :StaticFile, 'jekyll/static_file'
|
||||
autoload :Stevenson, 'jekyll/stevenson'
|
||||
autoload :URL, 'jekyll/url'
|
||||
autoload :Utils, 'jekyll/utils'
|
||||
autoload :VERSION, 'jekyll/version'
|
||||
|
||||
# extensions
|
||||
require 'jekyll/plugin'
|
||||
require 'jekyll/converter'
|
||||
require 'jekyll/generator'
|
||||
require 'jekyll/command'
|
||||
require 'jekyll/liquid_extensions'
|
||||
|
||||
class << self
|
||||
# Public: Tells you which Jekyll environment you are building in so you can skip tasks
|
||||
# if you need to. This is useful when doing expensive compression tasks on css and
|
||||
# images and allows you to skip that when working in development.
|
||||
|
||||
def env
|
||||
ENV["JEKYLL_ENV"] || "development"
|
||||
end
|
||||
|
||||
# Public: Generate a Jekyll configuration Hash by merging the default
|
||||
# options with anything in _config.yml, and adding the given options on top.
|
||||
#
|
||||
# override - A Hash of config directives that override any options in both
|
||||
# the defaults and the config file. See Jekyll::Configuration::DEFAULTS for a
|
||||
# list of option names and their defaults.
|
||||
#
|
||||
# Returns the final configuration Hash.
|
||||
def configuration(override = Hash.new)
|
||||
config = Configuration[Configuration::DEFAULTS]
|
||||
override = Configuration[override].stringify_keys
|
||||
unless override.delete('skip_config_files')
|
||||
config = config.read_config_files(config.config_files(override))
|
||||
end
|
||||
|
||||
# Merge DEFAULTS < _config.yml < override
|
||||
config = Utils.deep_merge_hashes(config, override).stringify_keys
|
||||
set_timezone(config['timezone']) if config['timezone']
|
||||
|
||||
config
|
||||
end
|
||||
|
||||
# Public: Set the TZ environment variable to use the timezone specified
|
||||
#
|
||||
# timezone - the IANA Time Zone
|
||||
#
|
||||
# Returns nothing
|
||||
def set_timezone(timezone)
|
||||
ENV['TZ'] = timezone
|
||||
end
|
||||
|
||||
# Public: Fetch the logger instance for this Jekyll process.
|
||||
#
|
||||
# Returns the LogAdapter instance.
|
||||
def logger
|
||||
@logger ||= LogAdapter.new(Stevenson.new, (ENV["JEKYLL_LOG_LEVEL"] || :info).to_sym)
|
||||
end
|
||||
|
||||
# Public: Set the log writer.
|
||||
# New log writer must respond to the same methods
|
||||
# as Ruby's interal Logger.
|
||||
#
|
||||
# writer - the new Logger-compatible log transport
|
||||
#
|
||||
# Returns the new logger.
|
||||
def logger=(writer)
|
||||
@logger = LogAdapter.new(writer, (ENV["JEKYLL_LOG_LEVEL"] || :info).to_sym)
|
||||
end
|
||||
|
||||
# Public: An array of sites
|
||||
#
|
||||
# Returns the Jekyll sites created.
|
||||
def sites
|
||||
@sites ||= []
|
||||
end
|
||||
|
||||
# Public: Ensures the questionable path is prefixed with the base directory
|
||||
# and prepends the questionable path with the base directory if false.
|
||||
#
|
||||
# base_directory - the directory with which to prefix the questionable path
|
||||
# questionable_path - the path we're unsure about, and want prefixed
|
||||
#
|
||||
# Returns the sanitized path.
|
||||
def sanitized_path(base_directory, questionable_path)
|
||||
return base_directory if base_directory.eql?(questionable_path)
|
||||
|
||||
clean_path = File.expand_path(questionable_path, "/")
|
||||
clean_path = clean_path.sub(/\A\w\:\//, '/')
|
||||
|
||||
unless clean_path.start_with?(base_directory.sub(/\A\w\:\//, '/'))
|
||||
File.join(base_directory, clean_path)
|
||||
else
|
||||
clean_path
|
||||
end
|
||||
end
|
||||
|
||||
# Conditional optimizations
|
||||
Jekyll::External.require_if_present('liquid-c')
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
require_all 'jekyll/commands'
|
||||
require_all 'jekyll/converters'
|
||||
@@ -71,75 +175,4 @@ require_all 'jekyll/converters/markdown'
|
||||
require_all 'jekyll/generators'
|
||||
require_all 'jekyll/tags'
|
||||
|
||||
# plugins
|
||||
require 'jekyll-coffeescript'
|
||||
require 'jekyll-sass-converter'
|
||||
require 'jekyll-paginate'
|
||||
require 'jekyll-gist'
|
||||
|
||||
SafeYAML::OPTIONS[:suppress_warnings] = true
|
||||
|
||||
module Jekyll
|
||||
|
||||
# Public: Tells you which Jekyll environment you are building in so you can skip tasks
|
||||
# if you need to. This is useful when doing expensive compression tasks on css and
|
||||
# images and allows you to skip that when working in development.
|
||||
|
||||
def self.env
|
||||
ENV["JEKYLL_ENV"] || "development"
|
||||
end
|
||||
|
||||
# Public: Generate a Jekyll configuration Hash by merging the default
|
||||
# options with anything in _config.yml, and adding the given options on top.
|
||||
#
|
||||
# override - A Hash of config directives that override any options in both
|
||||
# the defaults and the config file. See Jekyll::Configuration::DEFAULTS for a
|
||||
# list of option names and their defaults.
|
||||
#
|
||||
# Returns the final configuration Hash.
|
||||
def self.configuration(override)
|
||||
config = Configuration[Configuration::DEFAULTS]
|
||||
override = Configuration[override].stringify_keys
|
||||
config = config.read_config_files(config.config_files(override))
|
||||
|
||||
# Merge DEFAULTS < _config.yml < override
|
||||
config = Utils.deep_merge_hashes(config, override).stringify_keys
|
||||
set_timezone(config['timezone']) if config['timezone']
|
||||
|
||||
config
|
||||
end
|
||||
|
||||
# Static: Set the TZ environment variable to use the timezone specified
|
||||
#
|
||||
# timezone - the IANA Time Zone
|
||||
#
|
||||
# Returns nothing
|
||||
def self.set_timezone(timezone)
|
||||
ENV['TZ'] = timezone
|
||||
end
|
||||
|
||||
def self.logger
|
||||
@logger ||= LogAdapter.new(Stevenson.new)
|
||||
end
|
||||
|
||||
def self.logger=(writer)
|
||||
@logger = LogAdapter.new(writer)
|
||||
end
|
||||
|
||||
# Public: File system root
|
||||
#
|
||||
# Returns the root of the filesystem as a Pathname
|
||||
def self.fs_root
|
||||
@fs_root ||= "/"
|
||||
end
|
||||
|
||||
def self.sanitized_path(base_directory, questionable_path)
|
||||
clean_path = File.expand_path(questionable_path, fs_root)
|
||||
clean_path.gsub!(/\A\w\:\//, '/')
|
||||
unless clean_path.start_with?(base_directory)
|
||||
File.join(base_directory, clean_path)
|
||||
else
|
||||
clean_path
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,95 +1,105 @@
|
||||
require 'set'
|
||||
|
||||
module Jekyll
|
||||
class Site
|
||||
# Handles the cleanup of a site's destination before it is built.
|
||||
class Cleaner
|
||||
attr_reader :site
|
||||
# Handles the cleanup of a site's destination before it is built.
|
||||
class Cleaner
|
||||
HIDDEN_FILE_REGEX = /\/\.{1,2}$/
|
||||
attr_reader :site
|
||||
|
||||
def initialize(site)
|
||||
@site = site
|
||||
def initialize(site)
|
||||
@site = site
|
||||
end
|
||||
|
||||
# Cleans up the site's destination directory
|
||||
def cleanup!
|
||||
FileUtils.rm_rf(obsolete_files)
|
||||
FileUtils.rm_rf(metadata_file) if !@site.incremental?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Private: The list of files and directories to be deleted during cleanup process
|
||||
#
|
||||
# Returns an Array of the file and directory paths
|
||||
def obsolete_files
|
||||
(existing_files - new_files - new_dirs + replaced_files).to_a
|
||||
end
|
||||
|
||||
# Private: The metadata file storing dependency tree and build history
|
||||
#
|
||||
# Returns an Array with the metdata file as the only item
|
||||
def metadata_file
|
||||
[site.regenerator.metadata_file]
|
||||
end
|
||||
|
||||
# Private: The list of existing files, apart from those included in keep_files and hidden files.
|
||||
#
|
||||
# Returns a Set with the file paths
|
||||
def existing_files
|
||||
files = Set.new
|
||||
regex = keep_file_regex
|
||||
dirs = keep_dirs
|
||||
|
||||
Dir.glob(site.in_dest_dir("**", "*"), File::FNM_DOTMATCH) do |file|
|
||||
next if file =~ HIDDEN_FILE_REGEX || file =~ regex || dirs.include?(file)
|
||||
files << file
|
||||
end
|
||||
|
||||
# Cleans up the site's destination directory
|
||||
def cleanup!
|
||||
FileUtils.rm_rf(obsolete_files)
|
||||
end
|
||||
files
|
||||
end
|
||||
|
||||
private
|
||||
# Private: The list of files to be created when site is built.
|
||||
#
|
||||
# Returns a Set with the file paths
|
||||
def new_files
|
||||
files = Set.new
|
||||
site.each_site_file { |item| files << item.destination(site.dest) }
|
||||
files
|
||||
end
|
||||
|
||||
# Private: The list of files and directories to be deleted during cleanup process
|
||||
#
|
||||
# Returns an Array of the file and directory paths
|
||||
def obsolete_files
|
||||
(existing_files - new_files - new_dirs + replaced_files).to_a
|
||||
end
|
||||
# Private: The list of directories to be created when site is built.
|
||||
# These are the parent directories of the files in #new_files.
|
||||
#
|
||||
# Returns a Set with the directory paths
|
||||
def new_dirs
|
||||
new_files.map { |file| parent_dirs(file) }.flatten.to_set
|
||||
end
|
||||
|
||||
# Private: The list of existing files, apart from those included in keep_files and hidden files.
|
||||
#
|
||||
# Returns a Set with the file paths
|
||||
def existing_files
|
||||
files = Set.new
|
||||
Dir.glob(File.join(site.dest, "**", "*"), File::FNM_DOTMATCH) do |file|
|
||||
files << file unless file =~ /\/\.{1,2}$/ || file =~ keep_file_regex || keep_dirs.include?(file)
|
||||
end
|
||||
files
|
||||
# Private: The list of parent directories of a given file
|
||||
#
|
||||
# Returns an Array with the directory paths
|
||||
def parent_dirs(file)
|
||||
parent_dir = File.dirname(file)
|
||||
if parent_dir == site.dest
|
||||
[]
|
||||
else
|
||||
[parent_dir] + parent_dirs(parent_dir)
|
||||
end
|
||||
end
|
||||
|
||||
# Private: The list of files to be created when site is built.
|
||||
#
|
||||
# Returns a Set with the file paths
|
||||
def new_files
|
||||
files = Set.new
|
||||
site.each_site_file { |item| files << item.destination(site.dest) }
|
||||
files
|
||||
end
|
||||
# Private: The list of existing files that will be replaced by a directory during build
|
||||
#
|
||||
# Returns a Set with the file paths
|
||||
def replaced_files
|
||||
new_dirs.select { |dir| File.file?(dir) }.to_set
|
||||
end
|
||||
|
||||
# Private: The list of directories to be created when site is built.
|
||||
# These are the parent directories of the files in #new_files.
|
||||
#
|
||||
# Returns a Set with the directory paths
|
||||
def new_dirs
|
||||
new_files.map { |file| parent_dirs(file) }.flatten.to_set
|
||||
end
|
||||
# Private: The list of directories that need to be kept because they are parent directories
|
||||
# of files specified in keep_files
|
||||
#
|
||||
# Returns a Set with the directory paths
|
||||
def keep_dirs
|
||||
site.keep_files.map { |file| parent_dirs(site.in_dest_dir(file)) }.flatten.to_set
|
||||
end
|
||||
|
||||
# Private: The list of parent directories of a given file
|
||||
#
|
||||
# Returns an Array with the directory paths
|
||||
def parent_dirs(file)
|
||||
parent_dir = File.dirname(file)
|
||||
if parent_dir == site.dest
|
||||
[]
|
||||
else
|
||||
[parent_dir] + parent_dirs(parent_dir)
|
||||
end
|
||||
end
|
||||
|
||||
# Private: The list of existing files that will be replaced by a directory during build
|
||||
#
|
||||
# Returns a Set with the file paths
|
||||
def replaced_files
|
||||
new_dirs.select { |dir| File.file?(dir) }.to_set
|
||||
end
|
||||
|
||||
# Private: The list of directories that need to be kept because they are parent directories
|
||||
# of files specified in keep_files
|
||||
#
|
||||
# Returns a Set with the directory paths
|
||||
def keep_dirs
|
||||
site.keep_files.map{|file| parent_dirs(File.join(site.dest, file))}.flatten.to_set
|
||||
end
|
||||
|
||||
# Private: Creates a regular expression from the config's keep_files array
|
||||
#
|
||||
# Examples
|
||||
# ['.git','.svn'] creates the following regex: /\/(\.git|\/.svn)/
|
||||
#
|
||||
# Returns the regular expression
|
||||
def keep_file_regex
|
||||
or_list = site.keep_files.join("|")
|
||||
pattern = "\/(#{or_list.gsub(".", "\.")})"
|
||||
Regexp.new pattern
|
||||
end
|
||||
# Private: Creates a regular expression from the config's keep_files array
|
||||
#
|
||||
# Examples
|
||||
# ['.git','.svn'] creates the following regex: /\/(\.git|\/.svn)/
|
||||
#
|
||||
# Returns the regular expression
|
||||
def keep_file_regex
|
||||
Regexp.union(site.keep_files)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
module Jekyll
|
||||
class Collection
|
||||
attr_reader :site, :label, :metadata
|
||||
attr_writer :docs
|
||||
|
||||
# Create a new Collection.
|
||||
#
|
||||
@@ -22,14 +23,46 @@ module Jekyll
|
||||
@docs ||= []
|
||||
end
|
||||
|
||||
# Override of normal respond_to? to match method_missing's logic for
|
||||
# looking in @data.
|
||||
def respond_to?(method, include_private = false)
|
||||
docs.respond_to?(method.to_sym, include_private) || super
|
||||
end
|
||||
|
||||
# Override of method_missing to check in @data for the key.
|
||||
def method_missing(method, *args, &blck)
|
||||
if docs.respond_to?(method.to_sym)
|
||||
Jekyll.logger.warn "Deprecation:", "Collection##{method} should be called on the #docs array directly."
|
||||
Jekyll.logger.warn "", "Called by #{caller.first}."
|
||||
docs.public_send(method.to_sym, *args, &blck)
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
# Fetch the static files in this collection.
|
||||
# Defaults to an empty array if no static files have been read in.
|
||||
#
|
||||
# Returns an array of Jekyll::StaticFile objects.
|
||||
def files
|
||||
@files ||= []
|
||||
end
|
||||
|
||||
# Read the allowed documents into the collection's array of docs.
|
||||
#
|
||||
# Returns the sorted array of docs.
|
||||
def read
|
||||
filtered_entries.each do |file_path|
|
||||
doc = Jekyll::Document.new(Jekyll.sanitized_path(directory, file_path), { site: site, collection: self })
|
||||
doc.read
|
||||
docs << doc
|
||||
full_path = collection_dir(file_path)
|
||||
next if File.directory?(full_path)
|
||||
if Utils.has_yaml_header? full_path
|
||||
doc = Jekyll::Document.new(full_path, { site: site, collection: self })
|
||||
doc.read
|
||||
docs << doc if site.publisher.publish?(doc) || !write?
|
||||
else
|
||||
relative_dir = Jekyll.sanitized_path(relative_directory, File.dirname(file_path)).chomp("/.")
|
||||
files << StaticFile.new(site, site.source, relative_dir, File.basename(full_path), self)
|
||||
end
|
||||
end
|
||||
docs.sort!
|
||||
end
|
||||
@@ -40,9 +73,10 @@ module Jekyll
|
||||
# relative to the collection's directory
|
||||
def entries
|
||||
return Array.new unless exists?
|
||||
Dir.glob(File.join(directory, "**", "*.*")).map do |entry|
|
||||
entry[File.join(directory, "")] = ''; entry
|
||||
end
|
||||
@entries ||=
|
||||
Dir.glob(collection_dir("**", "*.*")).map do |entry|
|
||||
entry["#{collection_dir}/"] = ''; entry
|
||||
end
|
||||
end
|
||||
|
||||
# Filtered version of the entries in this collection.
|
||||
@@ -51,9 +85,13 @@ module Jekyll
|
||||
# Returns a list of filtered entry paths.
|
||||
def filtered_entries
|
||||
return Array.new unless exists?
|
||||
Dir.chdir(directory) do
|
||||
entry_filter.filter(entries)
|
||||
end
|
||||
@filtered_entries ||=
|
||||
Dir.chdir(directory) do
|
||||
entry_filter.filter(entries).reject do |f|
|
||||
path = collection_dir(f)
|
||||
File.directory?(path) || (File.symlink?(f) && site.safe)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# The directory for this Collection, relative to the site source.
|
||||
@@ -61,15 +99,28 @@ module Jekyll
|
||||
# Returns a String containing the directory name where the collection
|
||||
# is stored on the filesystem.
|
||||
def relative_directory
|
||||
"_#{label}"
|
||||
@relative_directory ||= "_#{label}"
|
||||
end
|
||||
|
||||
# The full path to the directory containing the
|
||||
# The full path to the directory containing the collection.
|
||||
#
|
||||
# Returns a String containing th directory name where the collection
|
||||
# is stored on the filesystem.
|
||||
def directory
|
||||
Jekyll.sanitized_path(site.source, relative_directory)
|
||||
@directory ||= site.in_source_dir(relative_directory)
|
||||
end
|
||||
|
||||
# The full path to the directory containing the collection, with
|
||||
# optional subpaths.
|
||||
#
|
||||
# *files - (optional) any other path pieces relative to the
|
||||
# directory to append to the path
|
||||
#
|
||||
# Returns a String containing th directory name where the collection
|
||||
# is stored on the filesystem.
|
||||
def collection_dir(*files)
|
||||
return directory if files.empty?
|
||||
site.in_source_dir(relative_directory, *files)
|
||||
end
|
||||
|
||||
# Checks whether the directory "exists" for this collection.
|
||||
@@ -105,7 +156,7 @@ module Jekyll
|
||||
#
|
||||
# Returns a sanitized version of the label.
|
||||
def sanitize_label(label)
|
||||
label.gsub(/[^a-z0-9_\-]/i, '')
|
||||
label.gsub(/[^a-z0-9_\-\.]/i, '')
|
||||
end
|
||||
|
||||
# Produce a representation of this Collection for use in Liquid.
|
||||
@@ -118,6 +169,7 @@ module Jekyll
|
||||
metadata.merge({
|
||||
"label" => label,
|
||||
"docs" => docs,
|
||||
"files" => files,
|
||||
"directory" => directory,
|
||||
"output" => write?,
|
||||
"relative_directory" => relative_directory
|
||||
@@ -129,14 +181,16 @@ module Jekyll
|
||||
#
|
||||
# Returns true if the 'write' metadata is true, false otherwise.
|
||||
def write?
|
||||
!!metadata['output']
|
||||
!!metadata.fetch('output', false)
|
||||
end
|
||||
|
||||
# The URL template to render collection's documents at.
|
||||
#
|
||||
# Returns the URL template to render collection's documents at.
|
||||
def url_template
|
||||
metadata.fetch('permalink', "/:collection/:path:output_ext")
|
||||
metadata.fetch('permalink') do
|
||||
Utils.add_permalink_suffix("/:collection/:path", site.permalink_style)
|
||||
end
|
||||
end
|
||||
|
||||
# Extract options for this collection from the site configuration.
|
||||
@@ -149,6 +203,5 @@ module Jekyll
|
||||
{}
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -19,31 +19,6 @@ module Jekyll
|
||||
super(base)
|
||||
end
|
||||
|
||||
# Paths to ignore for the watch option
|
||||
#
|
||||
# options - A Hash of options passed to the command
|
||||
#
|
||||
# Returns a list of relative paths from source that should be ignored
|
||||
def ignore_paths(options)
|
||||
source = options['source']
|
||||
destination = options['destination']
|
||||
config_files = Configuration[options].config_files(options)
|
||||
paths = config_files + Array(destination)
|
||||
ignored = []
|
||||
|
||||
source_abs = Pathname.new(source).expand_path
|
||||
paths.each do |p|
|
||||
path_abs = Pathname.new(p).expand_path
|
||||
begin
|
||||
rel_path = path_abs.relative_path_from(source_abs).to_s
|
||||
ignored << Regexp.new(Regexp.escape(rel_path)) unless rel_path.start_with?('../')
|
||||
rescue ArgumentError
|
||||
# Could not find a relative path
|
||||
end
|
||||
end
|
||||
ignored
|
||||
end
|
||||
|
||||
# Run Site#process and catch errors
|
||||
#
|
||||
# site - the Jekyll::Site object
|
||||
@@ -51,7 +26,7 @@ module Jekyll
|
||||
# Returns nothing
|
||||
def process_site(site)
|
||||
site.process
|
||||
rescue Jekyll::FatalException => e
|
||||
rescue Jekyll::Errors::FatalException => e
|
||||
Jekyll.logger.error "ERROR:", "YOUR SITE COULD NOT BE BUILT:"
|
||||
Jekyll.logger.error "", "------------------------------------"
|
||||
Jekyll.logger.error "", e.message
|
||||
@@ -74,15 +49,18 @@ module Jekyll
|
||||
# Returns nothing
|
||||
def add_build_options(c)
|
||||
c.option 'config', '--config CONFIG_FILE[,CONFIG_FILE2,...]', Array, 'Custom configuration file'
|
||||
c.option 'destination', '-d', '--destination DESTINATION', 'The current folder will be generated into DESTINATION'
|
||||
c.option 'source', '-s', '--source SOURCE', 'Custom source directory'
|
||||
c.option 'future', '--future', 'Publishes posts with a future date'
|
||||
c.option 'limit_posts', '--limit_posts MAX_POSTS', Integer, 'Limits the number of posts to parse and publish'
|
||||
c.option 'watch', '-w', '--watch', 'Watch for changes and rebuild'
|
||||
c.option 'watch', '-w', '--[no-]watch', 'Watch for changes and rebuild'
|
||||
c.option 'force_polling', '--force_polling', 'Force watch to use polling'
|
||||
c.option 'lsi', '--lsi', 'Use LSI for improved related posts'
|
||||
c.option 'show_drafts', '-D', '--drafts', 'Render posts in the _drafts folder'
|
||||
c.option 'unpublished', '--unpublished', 'Render posts that were marked as unpublished'
|
||||
c.option 'quiet', '-q', '--quiet', 'Silence output.'
|
||||
c.option 'verbose', '-V', '--verbose', 'Print verbose output.'
|
||||
c.option 'incremental', '-I', '--incremental', 'Enable incremental rebuild.'
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -9,6 +9,7 @@ module Jekyll
|
||||
prog.command(:build) do |c|
|
||||
c.syntax 'build [options]'
|
||||
c.description 'Build your site'
|
||||
c.alias :b
|
||||
|
||||
add_build_options(c)
|
||||
|
||||
@@ -22,7 +23,8 @@ module Jekyll
|
||||
# Build your jekyll site
|
||||
# Continuously watch if `watch` is set to true in the config.
|
||||
def process(options)
|
||||
Jekyll.logger.log_level = :error if options['quiet']
|
||||
# Adjust verbosity quickly
|
||||
Jekyll.logger.adjust_verbosity(options)
|
||||
|
||||
options = configuration_from_options(options)
|
||||
site = Jekyll::Site.new(options)
|
||||
@@ -32,23 +34,31 @@ module Jekyll
|
||||
else
|
||||
build(site, options)
|
||||
end
|
||||
watch(site, options) if options['watch']
|
||||
|
||||
if options.fetch('watch', false)
|
||||
watch(site, options)
|
||||
else
|
||||
Jekyll.logger.info "Auto-regeneration:", "disabled. Use --watch to enable."
|
||||
end
|
||||
end
|
||||
|
||||
# Build your Jekyll site.
|
||||
#
|
||||
# site - the Jekyll::Site instance to build
|
||||
# options - the
|
||||
# options - A Hash of options passed to the command
|
||||
#
|
||||
# Returns nothing.
|
||||
def build(site, options)
|
||||
t = Time.now
|
||||
source = options['source']
|
||||
destination = options['destination']
|
||||
incremental = options['incremental']
|
||||
Jekyll.logger.info "Source:", source
|
||||
Jekyll.logger.info "Destination:", destination
|
||||
Jekyll.logger.info "Incremental build:", (incremental ? "enabled" : "disabled. Enable with --incremental")
|
||||
Jekyll.logger.info "Generating..."
|
||||
process_site(site)
|
||||
Jekyll.logger.info "", "done."
|
||||
Jekyll.logger.info "", "done in #{(Time.now - t).round(3)} seconds."
|
||||
end
|
||||
|
||||
# Private: Watch for file changes and rebuild the site.
|
||||
@@ -58,38 +68,8 @@ module Jekyll
|
||||
#
|
||||
# Returns nothing.
|
||||
def watch(site, options)
|
||||
require 'listen'
|
||||
|
||||
listener = Listen.to(
|
||||
options['source'],
|
||||
:ignore => ignore_paths(options),
|
||||
:force_polling => options['force_polling']
|
||||
) do |modified, added, removed|
|
||||
t = Time.now.strftime("%Y-%m-%d %H:%M:%S")
|
||||
n = modified.length + added.length + removed.length
|
||||
print Jekyll.logger.formatted_topic("Regenerating:") + "#{n} files at #{t} "
|
||||
begin
|
||||
process_site(site)
|
||||
puts "...done."
|
||||
rescue => e
|
||||
puts "...error:"
|
||||
Jekyll.logger.warn "Error:", e.message
|
||||
Jekyll.logger.warn "Error:", "Run jekyll build --trace for more information."
|
||||
end
|
||||
end
|
||||
listener.start
|
||||
|
||||
Jekyll.logger.info "Auto-regeneration:", "enabled for '#{source}'"
|
||||
|
||||
unless options['serving']
|
||||
trap("INT") do
|
||||
listener.stop
|
||||
puts " Halting auto-regeneration."
|
||||
exit 0
|
||||
end
|
||||
|
||||
loop { sleep 1000 }
|
||||
end
|
||||
External.require_with_graceful_fail 'jekyll-watch'
|
||||
Jekyll::Watcher.watch(options)
|
||||
end
|
||||
|
||||
end # end of class << self
|
||||
|
||||
44
lib/jekyll/commands/clean.rb
Normal file
44
lib/jekyll/commands/clean.rb
Normal file
@@ -0,0 +1,44 @@
|
||||
module Jekyll
|
||||
module Commands
|
||||
class Clean < Command
|
||||
class << self
|
||||
|
||||
def init_with_program(prog)
|
||||
prog.command(:clean) do |c|
|
||||
c.syntax 'clean [subcommand]'
|
||||
c.description 'Clean the site (removes site output and metadata file) without building.'
|
||||
|
||||
add_build_options(c)
|
||||
|
||||
c.action do |args, _|
|
||||
Jekyll::Commands::Clean.process({})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def process(options)
|
||||
options = configuration_from_options(options)
|
||||
destination = options['destination']
|
||||
metadata_file = File.join(options['source'], '.jekyll-metadata')
|
||||
|
||||
if File.directory? destination
|
||||
Jekyll.logger.info "Cleaning #{destination}..."
|
||||
FileUtils.rm_rf(destination)
|
||||
Jekyll.logger.info "", "done."
|
||||
else
|
||||
Jekyll.logger.info "Nothing to do for #{destination}."
|
||||
end
|
||||
|
||||
if File.file? metadata_file
|
||||
Jekyll.logger.info "Removing #{metadata_file}..."
|
||||
FileUtils.rm_rf(metadata_file)
|
||||
Jekyll.logger.info "", "done."
|
||||
else
|
||||
Jekyll.logger.info "Nothing to do for #{metadata_file}."
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,30 +0,0 @@
|
||||
module Jekyll
|
||||
module Commands
|
||||
class Docs < Command
|
||||
|
||||
class << self
|
||||
|
||||
def init_with_program(prog)
|
||||
prog.command(:docs) do |c|
|
||||
c.syntax 'docs'
|
||||
c.description "Launch local server with docs for Jekyll v#{Jekyll::VERSION}"
|
||||
|
||||
c.option 'port', '-P', '--port [PORT]', 'Port to listen on'
|
||||
c.option 'host', '-H', '--host [HOST]', 'Host to bind to'
|
||||
|
||||
c.action do |args, options|
|
||||
options.merge!({
|
||||
'source' => File.expand_path("../../../site", File.dirname(__FILE__)),
|
||||
'destination' => File.expand_path("../../../site/_site", File.dirname(__FILE__))
|
||||
})
|
||||
Jekyll::Commands::Build.process(options)
|
||||
Jekyll::Commands::Serve.process(options)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -30,29 +30,26 @@ module Jekyll
|
||||
|
||||
def healthy?(site)
|
||||
[
|
||||
fsnotify_buggy?(site),
|
||||
!deprecated_relative_permalinks(site),
|
||||
!conflicting_urls(site)
|
||||
].all?
|
||||
end
|
||||
|
||||
def deprecated_relative_permalinks(site)
|
||||
contains_deprecated_pages = false
|
||||
site.pages.each do |page|
|
||||
if page.uses_relative_permalinks
|
||||
Jekyll.logger.warn "Deprecation:", "'#{page.path}' uses relative" +
|
||||
" permalinks which will be deprecated in" +
|
||||
" Jekyll v2.0.0 and beyond."
|
||||
contains_deprecated_pages = true
|
||||
end
|
||||
if site.config['relative_permalinks']
|
||||
Jekyll::Deprecator.deprecation_message "Your site still uses relative" +
|
||||
" permalinks, which was removed in" +
|
||||
" Jekyll v3.0.0."
|
||||
return true
|
||||
end
|
||||
contains_deprecated_pages
|
||||
end
|
||||
|
||||
def conflicting_urls(site)
|
||||
conflicting_urls = false
|
||||
urls = {}
|
||||
urls = collect_urls(urls, site.pages, site.dest)
|
||||
urls = collect_urls(urls, site.posts, site.dest)
|
||||
urls = collect_urls(urls, site.posts.docs, site.dest)
|
||||
urls.each do |url, paths|
|
||||
if paths.size > 1
|
||||
conflicting_urls = true
|
||||
@@ -63,8 +60,23 @@ module Jekyll
|
||||
conflicting_urls
|
||||
end
|
||||
|
||||
private
|
||||
def fsnotify_buggy?(site)
|
||||
return true if !Utils::Platforms.osx?
|
||||
if Dir.pwd != `pwd`.strip
|
||||
Jekyll.logger.error " " + <<-STR.strip.gsub(/\n\s+/, "\n ")
|
||||
We have detected that there might be trouble using fsevent on your
|
||||
operating system, you can read https://github.com/thibaudgg/rb-fsevent/wiki/no-fsevents-fired-(OSX-bug)
|
||||
for possible work arounds or you can work around it immediately
|
||||
with `--force-polling`.
|
||||
STR
|
||||
|
||||
false
|
||||
end
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
private
|
||||
def collect_urls(urls, things, destination)
|
||||
things.each do |thing|
|
||||
dest = thing.destination(destination)
|
||||
|
||||
33
lib/jekyll/commands/help.rb
Normal file
33
lib/jekyll/commands/help.rb
Normal file
@@ -0,0 +1,33 @@
|
||||
module Jekyll
|
||||
module Commands
|
||||
class Help < Command
|
||||
class << self
|
||||
|
||||
def init_with_program(prog)
|
||||
prog.command(:help) do |c|
|
||||
c.syntax 'help [subcommand]'
|
||||
c.description 'Show the help message, optionally for a given subcommand.'
|
||||
|
||||
c.action do |args, _|
|
||||
cmd = (args.first || "").to_sym
|
||||
if args.empty?
|
||||
puts prog
|
||||
elsif prog.has_command? cmd
|
||||
puts prog.commands[cmd]
|
||||
else
|
||||
invalid_command(prog, cmd)
|
||||
abort
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def invalid_command(prog, cmd)
|
||||
Jekyll.logger.error "Error:", "Hmm... we don't know what the '#{cmd}' command is."
|
||||
Jekyll.logger.info "Valid commands:", prog.commands.keys.join(", ")
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -3,77 +3,79 @@ require 'erb'
|
||||
module Jekyll
|
||||
module Commands
|
||||
class New < Command
|
||||
def self.init_with_program(prog)
|
||||
prog.command(:new) do |c|
|
||||
c.syntax 'new PATH'
|
||||
c.description 'Creates a new Jekyll site scaffold in PATH'
|
||||
class << self
|
||||
def init_with_program(prog)
|
||||
prog.command(:new) do |c|
|
||||
c.syntax 'new PATH'
|
||||
c.description 'Creates a new Jekyll site scaffold in PATH'
|
||||
|
||||
c.option 'force', '--force', 'Force creation even if PATH already exists'
|
||||
c.option 'blank', '--blank', 'Creates scaffolding but with empty files'
|
||||
c.option 'force', '--force', 'Force creation even if PATH already exists'
|
||||
c.option 'blank', '--blank', 'Creates scaffolding but with empty files'
|
||||
|
||||
c.action do |args, options|
|
||||
Jekyll::Commands::New.process(args, options)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.process(args, options = {})
|
||||
raise ArgumentError.new('You must specify a path.') if args.empty?
|
||||
|
||||
new_blog_path = File.expand_path(args.join(" "), Dir.pwd)
|
||||
FileUtils.mkdir_p new_blog_path
|
||||
if preserve_source_location?(new_blog_path, options)
|
||||
Jekyll.logger.abort_with "Conflict:", "#{new_blog_path} exists and is not empty."
|
||||
end
|
||||
|
||||
if options["blank"]
|
||||
create_blank_site new_blog_path
|
||||
else
|
||||
create_sample_files new_blog_path
|
||||
|
||||
File.open(File.expand_path(initialized_post_name, new_blog_path), "w") do |f|
|
||||
f.write(scaffold_post_content)
|
||||
c.action do |args, options|
|
||||
Jekyll::Commands::New.process(args, options)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Jekyll.logger.info "New jekyll site installed in #{new_blog_path}."
|
||||
end
|
||||
def process(args, options = {})
|
||||
raise ArgumentError.new('You must specify a path.') if args.empty?
|
||||
|
||||
def self.create_blank_site(path)
|
||||
Dir.chdir(path) do
|
||||
FileUtils.mkdir(%w(_layouts _posts _drafts))
|
||||
FileUtils.touch("index.html")
|
||||
new_blog_path = File.expand_path(args.join(" "), Dir.pwd)
|
||||
FileUtils.mkdir_p new_blog_path
|
||||
if preserve_source_location?(new_blog_path, options)
|
||||
Jekyll.logger.abort_with "Conflict:", "#{new_blog_path} exists and is not empty."
|
||||
end
|
||||
|
||||
if options["blank"]
|
||||
create_blank_site new_blog_path
|
||||
else
|
||||
create_sample_files new_blog_path
|
||||
|
||||
File.open(File.expand_path(initialized_post_name, new_blog_path), "w") do |f|
|
||||
f.write(scaffold_post_content)
|
||||
end
|
||||
end
|
||||
|
||||
Jekyll.logger.info "New jekyll site installed in #{new_blog_path}."
|
||||
end
|
||||
end
|
||||
|
||||
def self.scaffold_post_content
|
||||
ERB.new(File.read(File.expand_path(scaffold_path, site_template))).result
|
||||
end
|
||||
def create_blank_site(path)
|
||||
Dir.chdir(path) do
|
||||
FileUtils.mkdir(%w(_layouts _posts _drafts))
|
||||
FileUtils.touch("index.html")
|
||||
end
|
||||
end
|
||||
|
||||
# Internal: Gets the filename of the sample post to be created
|
||||
#
|
||||
# Returns the filename of the sample post, as a String
|
||||
def self.initialized_post_name
|
||||
"_posts/#{Time.now.strftime('%Y-%m-%d')}-welcome-to-jekyll.markdown"
|
||||
end
|
||||
def scaffold_post_content
|
||||
ERB.new(File.read(File.expand_path(scaffold_path, site_template))).result
|
||||
end
|
||||
|
||||
private
|
||||
# Internal: Gets the filename of the sample post to be created
|
||||
#
|
||||
# Returns the filename of the sample post, as a String
|
||||
def initialized_post_name
|
||||
"_posts/#{Time.now.strftime('%Y-%m-%d')}-welcome-to-jekyll.markdown"
|
||||
end
|
||||
|
||||
def self.preserve_source_location?(path, options)
|
||||
!options["force"] && !Dir["#{path}/**/*"].empty?
|
||||
end
|
||||
private
|
||||
|
||||
def self.create_sample_files(path)
|
||||
FileUtils.cp_r site_template + '/.', path
|
||||
FileUtils.rm File.expand_path(scaffold_path, path)
|
||||
end
|
||||
def preserve_source_location?(path, options)
|
||||
!options["force"] && !Dir["#{path}/**/*"].empty?
|
||||
end
|
||||
|
||||
def self.site_template
|
||||
File.expand_path("../../site_template", File.dirname(__FILE__))
|
||||
end
|
||||
def create_sample_files(path)
|
||||
FileUtils.cp_r site_template + '/.', path
|
||||
FileUtils.rm File.expand_path(scaffold_path, path)
|
||||
end
|
||||
|
||||
def self.scaffold_path
|
||||
"_posts/0000-00-00-welcome-to-jekyll.markdown.erb"
|
||||
def site_template
|
||||
File.expand_path("../../site_template", File.dirname(__FILE__))
|
||||
end
|
||||
|
||||
def scaffold_path
|
||||
"_posts/0000-00-00-welcome-to-jekyll.markdown.erb"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -10,6 +10,7 @@ module Jekyll
|
||||
c.syntax 'serve [options]'
|
||||
c.description 'Serve your site locally'
|
||||
c.alias :server
|
||||
c.alias :s
|
||||
|
||||
add_build_options(c)
|
||||
|
||||
@@ -20,7 +21,8 @@ module Jekyll
|
||||
c.option 'skip_initial_build', '--skip-initial-build', 'Skips the initial site build which occurs before the server is started.'
|
||||
|
||||
c.action do |args, options|
|
||||
options["serving"] ||= true
|
||||
options["serving"] = true
|
||||
options["watch"] = true unless options.key?("watch")
|
||||
Jekyll::Commands::Build.process(options)
|
||||
Jekyll::Commands::Serve.process(options)
|
||||
end
|
||||
@@ -38,7 +40,7 @@ module Jekyll
|
||||
|
||||
s.mount(
|
||||
options['baseurl'],
|
||||
WEBrick::HTTPServlet::FileHandler,
|
||||
custom_file_handler,
|
||||
destination,
|
||||
file_handler_options
|
||||
)
|
||||
@@ -48,7 +50,7 @@ module Jekyll
|
||||
if options['detach'] # detach the server
|
||||
pid = Process.fork { s.start }
|
||||
Process.detach(pid)
|
||||
Jekyll.logger.info "Server detached with pid '#{pid}'.", "Run `kill -9 #{pid}' to stop the server."
|
||||
Jekyll.logger.info "Server detached with pid '#{pid}'.", "Run `pkill -f jekyll' or `kill -9 #{pid}' to stop the server."
|
||||
else # create a new server thread, then join it with current terminal
|
||||
t = Thread.new { s.start }
|
||||
trap("INT") { s.shutdown }
|
||||
@@ -74,16 +76,20 @@ module Jekyll
|
||||
|
||||
def webrick_options(config)
|
||||
opts = {
|
||||
:DocumentRoot => config['destination'],
|
||||
:Port => config['port'],
|
||||
:BindAddress => config['host'],
|
||||
:MimeTypes => mime_types,
|
||||
:DirectoryIndex => %w(index.html index.htm index.cgi index.rhtml index.xml),
|
||||
:DocumentRoot => config['destination'],
|
||||
:DoNotReverseLookup => true,
|
||||
:StartCallback => start_callback(config['detach']),
|
||||
:DirectoryIndex => %w(index.html index.htm index.cgi index.rhtml index.xml)
|
||||
:MimeTypes => mime_types,
|
||||
:Port => config['port'],
|
||||
:StartCallback => start_callback(config['detach'])
|
||||
}
|
||||
|
||||
if !config['verbose']
|
||||
if config['verbose']
|
||||
opts.merge!({
|
||||
:Logger => WEBrick::Log.new($stdout, WEBrick::Log::DEBUG)
|
||||
})
|
||||
else
|
||||
opts.merge!({
|
||||
:AccessLog => [],
|
||||
:Logger => WEBrick::Log.new([], WEBrick::Log::WARN)
|
||||
@@ -93,6 +99,21 @@ module Jekyll
|
||||
opts
|
||||
end
|
||||
|
||||
# Custom WEBrick FileHandler servlet for serving "/file.html" at "/file"
|
||||
# when no exact match is found. This mirrors the behavior of GitHub
|
||||
# Pages and many static web server configs.
|
||||
def custom_file_handler
|
||||
Class.new WEBrick::HTTPServlet::FileHandler do
|
||||
def search_file(req, res, basename)
|
||||
if file = super
|
||||
file
|
||||
else
|
||||
super(req, res, "#{basename}.html")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def start_callback(detached)
|
||||
unless detached
|
||||
Proc.new { Jekyll.logger.info "Server running...", "press ctrl-c to stop." }
|
||||
@@ -117,9 +138,10 @@ module Jekyll
|
||||
|
||||
# recreate NondisclosureName under utf-8 circumstance
|
||||
def file_handler_options
|
||||
fh_option = WEBrick::Config::FileHandler
|
||||
fh_option[:NondisclosureName] = ['.ht*','~*']
|
||||
fh_option
|
||||
WEBrick::Config::FileHandler.merge({
|
||||
:FancyIndexing => true,
|
||||
:NondisclosureName => ['.ht*','~*']
|
||||
})
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -5,56 +5,55 @@ module Jekyll
|
||||
|
||||
# Default options. Overridden by values in _config.yml.
|
||||
# Strings rather than symbols are used for compatibility with YAML.
|
||||
DEFAULTS = {
|
||||
DEFAULTS = Configuration[{
|
||||
# Where things are
|
||||
'source' => Dir.pwd,
|
||||
'destination' => File.join(Dir.pwd, '_site'),
|
||||
'plugins' => '_plugins',
|
||||
'layouts' => '_layouts',
|
||||
'data_source' => '_data',
|
||||
'keep_files' => ['.git','.svn'],
|
||||
'gems' => [],
|
||||
'collections' => nil,
|
||||
|
||||
'timezone' => nil, # use the local timezone
|
||||
|
||||
'encoding' => 'utf-8', # always use utf-8 encoding. NEVER FORGET
|
||||
'plugins_dir' => '_plugins',
|
||||
'layouts_dir' => '_layouts',
|
||||
'data_dir' => '_data',
|
||||
'includes_dir' => '_includes',
|
||||
'collections' => {},
|
||||
|
||||
# Handling Reading
|
||||
'safe' => false,
|
||||
'detach' => false, # default to not detaching the server
|
||||
'show_drafts' => nil,
|
||||
'limit_posts' => 0,
|
||||
'lsi' => false,
|
||||
'future' => true, # remove and make true just default
|
||||
'unpublished' => false,
|
||||
|
||||
'relative_permalinks' => false,
|
||||
|
||||
'markdown' => 'kramdown',
|
||||
'highlighter' => 'pygments',
|
||||
'permalink' => 'date',
|
||||
'baseurl' => '',
|
||||
'include' => ['.htaccess'],
|
||||
'exclude' => [],
|
||||
'paginate_path' => '/page:num',
|
||||
|
||||
'keep_files' => ['.git','.svn'],
|
||||
'encoding' => 'utf-8',
|
||||
'markdown_ext' => 'markdown,mkdown,mkdn,mkd,md',
|
||||
'textile_ext' => 'textile',
|
||||
|
||||
'port' => '4000',
|
||||
'host' => '0.0.0.0',
|
||||
# Filtering Content
|
||||
'show_drafts' => nil,
|
||||
'limit_posts' => 0,
|
||||
'future' => false,
|
||||
'unpublished' => false,
|
||||
|
||||
# Plugins
|
||||
'whitelist' => [],
|
||||
'gems' => [],
|
||||
|
||||
# Conversion
|
||||
'markdown' => 'kramdown',
|
||||
'highlighter' => 'rouge',
|
||||
'lsi' => false,
|
||||
'excerpt_separator' => "\n\n",
|
||||
'incremental' => false,
|
||||
|
||||
'defaults' => [],
|
||||
# Serving
|
||||
'detach' => false, # default to not detaching the server
|
||||
'port' => '4000',
|
||||
'host' => '127.0.0.1',
|
||||
'baseurl' => '',
|
||||
|
||||
'maruku' => {
|
||||
'use_tex' => false,
|
||||
'use_divs' => false,
|
||||
'png_engine' => 'blahtex',
|
||||
'png_dir' => 'images/latex',
|
||||
'png_url' => '/images/latex',
|
||||
'fenced_code_blocks' => true
|
||||
},
|
||||
# Output Configuration
|
||||
'permalink' => 'date',
|
||||
'paginate_path' => '/page:num',
|
||||
'timezone' => nil, # use the local timezone
|
||||
|
||||
'quiet' => false,
|
||||
'verbose' => false,
|
||||
'defaults' => [],
|
||||
|
||||
'rdiscount' => {
|
||||
'extensions' => []
|
||||
@@ -65,12 +64,12 @@ module Jekyll
|
||||
},
|
||||
|
||||
'kramdown' => {
|
||||
'auto_ids' => true,
|
||||
'footnote_nr' => 1,
|
||||
'entity_output' => 'as_char',
|
||||
'toc_levels' => '1..6',
|
||||
'smart_quotes' => 'lsquo,rsquo,ldquo,rdquo',
|
||||
'use_coderay' => false,
|
||||
'auto_ids' => true,
|
||||
'footnote_nr' => 1,
|
||||
'entity_output' => 'as_char',
|
||||
'toc_levels' => '1..6',
|
||||
'smart_quotes' => 'lsquo,rsquo,ldquo,rdquo',
|
||||
'enable_coderay' => false,
|
||||
|
||||
'coderay' => {
|
||||
'coderay_wrap' => 'div',
|
||||
@@ -80,12 +79,8 @@ module Jekyll
|
||||
'coderay_bold_every' => 10,
|
||||
'coderay_css' => 'style'
|
||||
}
|
||||
},
|
||||
|
||||
'redcloth' => {
|
||||
'hard_breaks' => true
|
||||
}
|
||||
}
|
||||
}]
|
||||
|
||||
# Public: Turn all keys into string
|
||||
#
|
||||
@@ -94,20 +89,35 @@ module Jekyll
|
||||
reduce({}) { |hsh,(k,v)| hsh.merge(k.to_s => v) }
|
||||
end
|
||||
|
||||
def get_config_value_with_override(config_key, override)
|
||||
override[config_key] || self[config_key] || DEFAULTS[config_key]
|
||||
end
|
||||
|
||||
# Public: Directory of the Jekyll source folder
|
||||
#
|
||||
# override - the command-line options hash
|
||||
#
|
||||
# Returns the path to the Jekyll source directory
|
||||
def source(override)
|
||||
override['source'] || self['source'] || DEFAULTS['source']
|
||||
get_config_value_with_override('source', override)
|
||||
end
|
||||
|
||||
def quiet(override = {})
|
||||
get_config_value_with_override('quiet', override)
|
||||
end
|
||||
alias_method :quiet?, :quiet
|
||||
|
||||
def verbose(override = {})
|
||||
get_config_value_with_override('verbose', override)
|
||||
end
|
||||
alias_method :verbose?, :verbose
|
||||
|
||||
def safe_load_file(filename)
|
||||
case File.extname(filename)
|
||||
when '.toml'
|
||||
when /\.toml/i
|
||||
Jekyll::External.require_with_graceful_fail('toml') unless defined?(TOML)
|
||||
TOML.load_file(filename)
|
||||
when /\.y(a)?ml/
|
||||
when /\.ya?ml/i
|
||||
SafeYAML.load_file(filename)
|
||||
else
|
||||
raise ArgumentError, "No parser for '#{filename}' is available. Use a .toml or .y(a)ml file instead."
|
||||
@@ -120,11 +130,14 @@ module Jekyll
|
||||
#
|
||||
# Returns an Array of config files
|
||||
def config_files(override)
|
||||
# Adjust verbosity quickly
|
||||
Jekyll.logger.adjust_verbosity(:quiet => quiet?(override), :verbose => verbose?(override))
|
||||
|
||||
# Get configuration from <source>/_config.yml or <source>/<config_file>
|
||||
config_files = override.delete('config')
|
||||
if config_files.to_s.empty?
|
||||
default = %w[yml yaml].find(Proc.new { 'yml' }) do |ext|
|
||||
File.exists? Jekyll.sanitized_path(source(override), "_config.#{ext}")
|
||||
File.exist?(Jekyll.sanitized_path(source(override), "_config.#{ext}"))
|
||||
end
|
||||
config_files = Jekyll.sanitized_path(source(override), "_config.#{default}")
|
||||
@default_config_file = true
|
||||
@@ -173,7 +186,7 @@ module Jekyll
|
||||
$stderr.puts "#{err}"
|
||||
end
|
||||
|
||||
configuration.fix_common_issues.backwards_compatibilize
|
||||
configuration.fix_common_issues.backwards_compatibilize.add_default_collections
|
||||
end
|
||||
|
||||
# Public: Split a CSV string into an array containing its values
|
||||
@@ -192,32 +205,28 @@ module Jekyll
|
||||
def backwards_compatibilize
|
||||
config = clone
|
||||
# Provide backwards-compatibility
|
||||
if config.has_key?('auto') || config.has_key?('watch')
|
||||
Jekyll.logger.warn "Deprecation:", "Auto-regeneration can no longer" +
|
||||
if config.key?('auto') || config.key?('watch')
|
||||
Jekyll::Deprecator.deprecation_message "Auto-regeneration can no longer" +
|
||||
" be set from your configuration file(s). Use the"+
|
||||
" --watch/-w command-line option instead."
|
||||
" --[no-]watch/-w command-line option instead."
|
||||
config.delete('auto')
|
||||
config.delete('watch')
|
||||
end
|
||||
|
||||
if config.has_key? 'server'
|
||||
Jekyll.logger.warn "Deprecation:", "The 'server' configuration option" +
|
||||
if config.key? 'server'
|
||||
Jekyll::Deprecator.deprecation_message "The 'server' configuration option" +
|
||||
" is no longer accepted. Use the 'jekyll serve'" +
|
||||
" subcommand to serve your site with WEBrick."
|
||||
config.delete('server')
|
||||
end
|
||||
|
||||
if config.has_key? 'server_port'
|
||||
Jekyll.logger.warn "Deprecation:", "The 'server_port' configuration option" +
|
||||
" has been renamed to 'port'. Please update your config" +
|
||||
" file accordingly."
|
||||
# copy but don't overwrite:
|
||||
config['port'] = config['server_port'] unless config.has_key?('port')
|
||||
config.delete('server_port')
|
||||
end
|
||||
renamed_key 'server_port', 'port', config
|
||||
renamed_key 'plugins', 'plugins_dir', config
|
||||
renamed_key 'layouts', 'layouts_dir', config
|
||||
renamed_key 'data_source', 'data_dir', config
|
||||
|
||||
if config.has_key? 'pygments'
|
||||
Jekyll.logger.warn "Deprecation:", "The 'pygments' configuration option" +
|
||||
if config.key? 'pygments'
|
||||
Jekyll::Deprecator.deprecation_message "The 'pygments' configuration option" +
|
||||
" has been renamed to 'highlighter'. Please update your" +
|
||||
" config file accordingly. The allowed values are 'rouge', " +
|
||||
"'pygments' or null."
|
||||
@@ -228,26 +237,36 @@ module Jekyll
|
||||
|
||||
%w[include exclude].each do |option|
|
||||
if config.fetch(option, []).is_a?(String)
|
||||
Jekyll.logger.warn "Deprecation:", "The '#{option}' configuration option" +
|
||||
Jekyll::Deprecator.deprecation_message "The '#{option}' configuration option" +
|
||||
" must now be specified as an array, but you specified" +
|
||||
" a string. For now, we've treated the string you provided" +
|
||||
" as a list of comma-separated values."
|
||||
config[option] = csv_to_array(config[option])
|
||||
end
|
||||
config[option].map!(&:to_s)
|
||||
end
|
||||
|
||||
if (config['kramdown'] || {}).key?('use_coderay')
|
||||
Jekyll::Deprecator.deprecation_message "Please change 'use_coderay'" +
|
||||
" to 'enable_coderay' in your configuration file."
|
||||
config['kramdown']['use_coderay'] = config['kramdown'].delete('enable_coderay')
|
||||
end
|
||||
|
||||
if config.fetch('markdown', 'kramdown').to_s.downcase.eql?("maruku")
|
||||
Jekyll::Deprecator.deprecation_message "You're using the 'maruku' " +
|
||||
"Markdown processor. Maruku support has been deprecated and will " +
|
||||
"be removed in 3.0.0. We recommend you switch to Kramdown."
|
||||
Jekyll.logger.abort_with "Error:", "You're using the 'maruku' " +
|
||||
"Markdown processor, which has been removed as of 3.0.0. " +
|
||||
"We recommend you switch to Kramdown. To do this, replace " +
|
||||
"`markdown: maruku` with `markdown: kramdown` in your " +
|
||||
"`_config.yml` file."
|
||||
end
|
||||
|
||||
config
|
||||
end
|
||||
|
||||
def fix_common_issues
|
||||
config = clone
|
||||
|
||||
if config.has_key?('paginate') && (!config['paginate'].is_a?(Integer) || config['paginate'] < 1)
|
||||
if config.key?('paginate') && (!config['paginate'].is_a?(Integer) || config['paginate'] < 1)
|
||||
Jekyll.logger.warn "Config Warning:", "The `paginate` key must be a" +
|
||||
" positive integer or nil. It's currently set to '#{config['paginate'].inspect}'."
|
||||
config['paginate'] = nil
|
||||
@@ -255,5 +274,45 @@ module Jekyll
|
||||
|
||||
config
|
||||
end
|
||||
|
||||
def add_default_collections
|
||||
config = clone
|
||||
|
||||
return config if config['collections'].nil?
|
||||
|
||||
if config['collections'].is_a?(Array)
|
||||
config['collections'] = Hash[config['collections'].map{|c| [c, {}]}]
|
||||
end
|
||||
config['collections']['posts'] ||= {}
|
||||
config['collections']['posts']['output'] = true
|
||||
config['collections']['posts']['permalink'] = style_to_permalink(config['permalink'])
|
||||
|
||||
config
|
||||
end
|
||||
|
||||
def renamed_key(old, new, config, allowed_values = nil)
|
||||
if config.key?(old)
|
||||
Jekyll::Deprecator.deprecation_message "The '#{old}' configuration" +
|
||||
"option has been renamed to '#{new}'. Please update your config " +
|
||||
"file accordingly."
|
||||
config[new] = config.delete(old)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def style_to_permalink(permalink_style)
|
||||
case permalink_style.to_sym
|
||||
when :pretty
|
||||
"/:categories/:year/:month/:day/:title/"
|
||||
when :none
|
||||
"/:categories/:title.html"
|
||||
when :date
|
||||
"/:categories/:year/:month/:day/:title.html"
|
||||
when :ordinal
|
||||
"/:categories/:year/:y_day/:title.html"
|
||||
else
|
||||
permalink_style.to_s
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -11,25 +11,44 @@ module Jekyll
|
||||
@parser =
|
||||
case @config['markdown'].downcase
|
||||
when 'redcarpet' then RedcarpetParser.new(@config)
|
||||
when 'kramdown' then KramdownParser.new(@config)
|
||||
when 'kramdown' then KramdownParser.new(@config)
|
||||
when 'rdiscount' then RDiscountParser.new(@config)
|
||||
when 'maruku' then MarukuParser.new(@config)
|
||||
else
|
||||
# So they can't try some tricky bullshit or go down the ancestor chain, I hope.
|
||||
if allowed_custom_class?(@config['markdown'])
|
||||
self.class.const_get(@config['markdown']).new(@config)
|
||||
else
|
||||
Jekyll.logger.error "Invalid Markdown Processor:", "#{@config['markdown']}"
|
||||
Jekyll.logger.error "", "Valid options are [ maruku | rdiscount | kramdown | redcarpet ]"
|
||||
raise FatalException, "Invalid Markdown Processor: #{@config['markdown']}"
|
||||
Jekyll.logger.error "", "Valid options are [ #{valid_processors.join(" | ")} ]"
|
||||
raise Errors::FatalException, "Invalid Markdown Processor: #{@config['markdown']}"
|
||||
end
|
||||
end
|
||||
@setup = true
|
||||
end
|
||||
|
||||
def valid_processors
|
||||
%w[
|
||||
rdiscount
|
||||
kramdown
|
||||
redcarpet
|
||||
] + third_party_processors
|
||||
end
|
||||
|
||||
def third_party_processors
|
||||
self.class.constants - %w[
|
||||
KramdownParser
|
||||
RDiscountParser
|
||||
RedcarpetParser
|
||||
PRIORITIES
|
||||
].map(&:to_sym)
|
||||
end
|
||||
|
||||
def extname_list
|
||||
@extname_list ||= @config['markdown_ext'].split(',').map { |e| ".#{e.downcase}" }
|
||||
end
|
||||
|
||||
def matches(ext)
|
||||
rgx = '^\.(' + @config['markdown_ext'].gsub(',','|') +')$'
|
||||
ext =~ Regexp.new(rgx, Regexp::IGNORECASE)
|
||||
extname_list.include? ext.downcase
|
||||
end
|
||||
|
||||
def output_ext(ext)
|
||||
|
||||
@@ -5,22 +5,27 @@ module Jekyll
|
||||
def initialize(config)
|
||||
require 'kramdown'
|
||||
@config = config
|
||||
# If kramdown supported highlighter enabled, use that
|
||||
highlighter = @config['highlighter']
|
||||
if highlighter == 'rouge' || highlighter == 'coderay'
|
||||
@config['kramdown']['syntax_highlighter'] ||= highlighter
|
||||
end
|
||||
rescue LoadError
|
||||
STDERR.puts 'You are missing a library required for Markdown. Please run:'
|
||||
STDERR.puts ' $ [sudo] gem install kramdown'
|
||||
raise FatalException.new("Missing dependency: kramdown")
|
||||
raise Errors::FatalException.new("Missing dependency: kramdown")
|
||||
end
|
||||
|
||||
def convert(content)
|
||||
# Check for use of coderay
|
||||
if @config['kramdown']['use_coderay']
|
||||
if @config['kramdown']['enable_coderay']
|
||||
%w[wrap line_numbers line_numbers_start tab_width bold_every css default_lang].each do |opt|
|
||||
key = "coderay_#{opt}"
|
||||
@config['kramdown'][key] = @config['kramdown']['coderay'][key] unless @config['kramdown'].has_key?(key)
|
||||
@config['kramdown'][key] = @config['kramdown']['coderay'][key] unless @config['kramdown'].key?(key)
|
||||
end
|
||||
end
|
||||
|
||||
Kramdown::Document.new(content, Utils.symbolize_hash_keys(@config["kramdown"])).to_html
|
||||
Kramdown::Document.new(content, Utils.symbolize_hash_keys(@config['kramdown'])).to_html
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
module Jekyll
|
||||
module Converters
|
||||
class Markdown
|
||||
class MarukuParser
|
||||
def initialize(config)
|
||||
require 'maruku'
|
||||
@config = config
|
||||
@errors = []
|
||||
load_divs_library if @config['maruku']['use_divs']
|
||||
load_blahtext_library if @config['maruku']['use_tex']
|
||||
|
||||
# allow fenced code blocks (new in Maruku 0.7.0)
|
||||
MaRuKu::Globals[:fenced_code_blocks] = !!@config['maruku']['fenced_code_blocks']
|
||||
|
||||
rescue LoadError
|
||||
STDERR.puts 'You are missing a library required for Markdown. Please run:'
|
||||
STDERR.puts ' $ [sudo] gem install maruku'
|
||||
raise FatalException.new("Missing dependency: maruku")
|
||||
end
|
||||
|
||||
def load_divs_library
|
||||
require 'maruku/ext/div'
|
||||
STDERR.puts 'Maruku: Using extended syntax for div elements.'
|
||||
end
|
||||
|
||||
def load_blahtext_library
|
||||
require 'maruku/ext/math'
|
||||
STDERR.puts "Maruku: Using LaTeX extension. Images in `#{@config['maruku']['png_dir']}`."
|
||||
|
||||
# Switch off MathML output
|
||||
MaRuKu::Globals[:html_math_output_mathml] = false
|
||||
MaRuKu::Globals[:html_math_engine] = 'none'
|
||||
|
||||
# Turn on math to PNG support with blahtex
|
||||
# Resulting PNGs stored in `images/latex`
|
||||
MaRuKu::Globals[:html_math_output_png] = true
|
||||
MaRuKu::Globals[:html_png_engine] = @config['maruku']['png_engine']
|
||||
MaRuKu::Globals[:html_png_dir] = @config['maruku']['png_dir']
|
||||
MaRuKu::Globals[:html_png_url] = @config['maruku']['png_url']
|
||||
end
|
||||
|
||||
def print_errors_and_fail
|
||||
print @errors.join
|
||||
raise MaRuKu::Exception, "MaRuKu encountered problem(s) while converting your markup."
|
||||
end
|
||||
|
||||
def convert(content)
|
||||
converted = Maruku.new(content, :error_stream => @errors).to_html.strip
|
||||
print_errors_and_fail unless @errors.empty?
|
||||
converted
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -3,13 +3,9 @@ module Jekyll
|
||||
class Markdown
|
||||
class RDiscountParser
|
||||
def initialize(config)
|
||||
require 'rdiscount'
|
||||
Jekyll::External.require_with_graceful_fail "rdiscount"
|
||||
@config = config
|
||||
@rdiscount_extensions = @config['rdiscount']['extensions'].map { |e| e.to_sym }
|
||||
rescue LoadError
|
||||
STDERR.puts 'You are missing a library required for Markdown. Please run:'
|
||||
STDERR.puts ' $ [sudo] gem install rdiscount'
|
||||
raise FatalException.new("Missing dependency: rdiscount")
|
||||
end
|
||||
|
||||
def convert(content)
|
||||
|
||||
@@ -14,7 +14,7 @@ module Jekyll
|
||||
module WithPygments
|
||||
include CommonMethods
|
||||
def block_code(code, lang)
|
||||
require 'pygments'
|
||||
Jekyll::External.require_with_graceful_fail("pygments")
|
||||
lang = lang && lang.split.first || "text"
|
||||
add_code_tags(
|
||||
Pygments.highlight(code, :lexer => lang, :options => { :encoding => 'utf-8' }),
|
||||
@@ -29,7 +29,7 @@ module Jekyll
|
||||
include CommonMethods
|
||||
|
||||
def code_wrap(code)
|
||||
"<div class=\"highlight\"><pre>#{CGI::escapeHTML(code)}</pre></div>"
|
||||
"<figure class=\"highlight\"><pre>#{CGI::escapeHTML(code)}</pre></figure>"
|
||||
end
|
||||
|
||||
def block_code(code, lang)
|
||||
@@ -48,52 +48,47 @@ module Jekyll
|
||||
end
|
||||
|
||||
protected
|
||||
def rouge_formatter(opts = {})
|
||||
Rouge::Formatters::HTML.new(opts.merge(wrap: false))
|
||||
def rouge_formatter(lexer)
|
||||
Rouge::Formatters::HTML.new(:wrap => false)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def initialize(config)
|
||||
require 'redcarpet'
|
||||
External.require_with_graceful_fail("redcarpet")
|
||||
@config = config
|
||||
@redcarpet_extensions = {}
|
||||
@config['redcarpet']['extensions'].each { |e| @redcarpet_extensions[e.to_sym] = true }
|
||||
|
||||
@renderer ||= case @config['highlighter']
|
||||
when 'pygments'
|
||||
Class.new(Redcarpet::Render::HTML) do
|
||||
include WithPygments
|
||||
end
|
||||
when 'rouge'
|
||||
Class.new(Redcarpet::Render::HTML) do
|
||||
begin
|
||||
require 'rouge'
|
||||
require 'rouge/plugins/redcarpet'
|
||||
rescue LoadError => e
|
||||
Jekyll.logger.error "You are missing the 'rouge' gem. Please run:"
|
||||
Jekyll.logger.error " $ [sudo] gem install rouge"
|
||||
Jekyll.logger.error "Or add 'rouge' to your Gemfile."
|
||||
raise FatalException.new("Missing dependency: rouge")
|
||||
end
|
||||
@renderer ||= class_with_proper_highlighter(@config['highlighter'])
|
||||
end
|
||||
|
||||
if Rouge.version < '1.3.0'
|
||||
abort "Please install Rouge 1.3.0 or greater and try running Jekyll again."
|
||||
end
|
||||
def class_with_proper_highlighter(highlighter)
|
||||
case highlighter
|
||||
when "pygments"
|
||||
Class.new(Redcarpet::Render::HTML) do
|
||||
include WithPygments
|
||||
end
|
||||
when "rouge"
|
||||
Class.new(Redcarpet::Render::HTML) do
|
||||
Jekyll::External.require_with_graceful_fail(%w[
|
||||
rouge
|
||||
rouge/plugins/redcarpet
|
||||
])
|
||||
|
||||
include Rouge::Plugins::Redcarpet
|
||||
include CommonMethods
|
||||
include WithRouge
|
||||
end
|
||||
else
|
||||
Class.new(Redcarpet::Render::HTML) do
|
||||
include WithoutHighlighting
|
||||
end
|
||||
end
|
||||
rescue LoadError
|
||||
STDERR.puts 'You are missing a library required for Markdown. Please run:'
|
||||
STDERR.puts ' $ [sudo] gem install redcarpet'
|
||||
raise FatalException.new("Missing dependency: redcarpet")
|
||||
unless Gem::Version.new(Rouge.version) > Gem::Version.new("1.3.0")
|
||||
abort "Please install Rouge 1.3.0 or greater and try running Jekyll again."
|
||||
end
|
||||
|
||||
include Rouge::Plugins::Redcarpet
|
||||
include CommonMethods
|
||||
include WithRouge
|
||||
end
|
||||
else
|
||||
Class.new(Redcarpet::Render::HTML) do
|
||||
include WithoutHighlighting
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def convert(content)
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
module Jekyll
|
||||
module Converters
|
||||
class Textile < Converter
|
||||
safe true
|
||||
|
||||
highlighter_prefix '<notextile>'
|
||||
highlighter_suffix '</notextile>'
|
||||
|
||||
def setup
|
||||
return if @setup
|
||||
require 'redcloth'
|
||||
@setup = true
|
||||
rescue LoadError
|
||||
STDERR.puts 'You are missing a library required for Textile. Please run:'
|
||||
STDERR.puts ' $ [sudo] gem install RedCloth'
|
||||
raise FatalException.new("Missing dependency: RedCloth")
|
||||
end
|
||||
|
||||
def matches(ext)
|
||||
rgx = '(' + @config['textile_ext'].gsub(',','|') +')'
|
||||
ext =~ Regexp.new(rgx, Regexp::IGNORECASE)
|
||||
end
|
||||
|
||||
def output_ext(ext)
|
||||
".html"
|
||||
end
|
||||
|
||||
def convert(content)
|
||||
setup
|
||||
|
||||
# Shortcut if config doesn't contain RedCloth section
|
||||
return RedCloth.new(content).to_html if @config['redcloth'].nil?
|
||||
|
||||
# List of attributes defined on RedCloth
|
||||
# (from http://redcloth.rubyforge.org/classes/RedCloth/TextileDoc.html)
|
||||
attrs = ['filter_classes', 'filter_html', 'filter_ids', 'filter_styles',
|
||||
'hard_breaks', 'lite_mode', 'no_span_caps', 'sanitize_html']
|
||||
|
||||
r = RedCloth.new(content)
|
||||
|
||||
# Set attributes in r if they are NOT nil in the config
|
||||
attrs.each do |attr|
|
||||
r.instance_variable_set("@#{attr}".to_sym, @config['redcloth'][attr]) unless @config['redcloth'][attr].nil?
|
||||
end
|
||||
|
||||
r.to_html
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -25,7 +25,7 @@ module Jekyll
|
||||
|
||||
# Whether the file is published or not, as indicated in YAML front-matter
|
||||
def published?
|
||||
!(data.has_key?('published') && data['published'] == false)
|
||||
!(data.key?('published') && data['published'] == false)
|
||||
end
|
||||
|
||||
# Returns merged option hash for File.read of self.site (if exists)
|
||||
@@ -43,7 +43,7 @@ module Jekyll
|
||||
# Returns nothing.
|
||||
def read_yaml(base, name, opts = {})
|
||||
begin
|
||||
self.content = File.read(File.join(base, name),
|
||||
self.content = File.read(site.in_source_dir(base, name),
|
||||
merged_file_read_opts(opts))
|
||||
if content =~ /\A(---\s*\n.*?\n?)^((---|\.\.\.)\s*$\n?)/m
|
||||
self.content = $POSTMATCH
|
||||
@@ -56,17 +56,27 @@ module Jekyll
|
||||
end
|
||||
|
||||
self.data ||= {}
|
||||
|
||||
unless self.data.is_a?(Hash)
|
||||
Jekyll.logger.abort_with "Fatal:", "Invalid YAML front matter in #{File.join(base, name)}"
|
||||
end
|
||||
|
||||
self.data
|
||||
end
|
||||
|
||||
# Transform the contents based on the content type.
|
||||
#
|
||||
# Returns nothing.
|
||||
# Returns the transformed contents.
|
||||
def transform
|
||||
self.content = converter.convert(content)
|
||||
rescue => e
|
||||
Jekyll.logger.error "Conversion error:", "There was an error converting" +
|
||||
" '#{path}'."
|
||||
raise e
|
||||
converters.reduce(content) do |output, converter|
|
||||
begin
|
||||
converter.convert output
|
||||
rescue => e
|
||||
Jekyll.logger.error "Conversion error:", "#{converter.class} encountered an error while converting '#{path}':"
|
||||
Jekyll.logger.error("", e.to_s)
|
||||
raise e
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Determine the extension depending on content_type.
|
||||
@@ -74,15 +84,21 @@ module Jekyll
|
||||
# Returns the String extension for the output file.
|
||||
# e.g. ".html" for an HTML output file.
|
||||
def output_ext
|
||||
converter.output_ext(ext)
|
||||
if converters.all? { |c| c.is_a?(Jekyll::Converters::Identity) }
|
||||
ext
|
||||
else
|
||||
converters.map { |c|
|
||||
c.output_ext(ext) unless c.is_a?(Jekyll::Converters::Identity)
|
||||
}.compact.last
|
||||
end
|
||||
end
|
||||
|
||||
# Determine which converter to use based on this convertible's
|
||||
# extension.
|
||||
#
|
||||
# Returns the Converter instance.
|
||||
def converter
|
||||
@converter ||= site.converters.find { |c| c.matches(ext) }
|
||||
def converters
|
||||
@converters ||= site.converters.select { |c| c.matches(ext) }.sort
|
||||
end
|
||||
|
||||
# Render Liquid in the content
|
||||
@@ -92,8 +108,8 @@ module Jekyll
|
||||
# info - the info for Liquid
|
||||
#
|
||||
# Returns the converted content
|
||||
def render_liquid(content, payload, info, path = nil)
|
||||
Liquid::Template.parse(content).render!(payload, info)
|
||||
def render_liquid(content, payload, info, path)
|
||||
site.liquid_renderer.file(path).parse(content).render!(payload, info)
|
||||
rescue Tags::IncludeTagError => e
|
||||
Jekyll.logger.error "Liquid Exception:", "#{e.message} in #{e.path}, included in #{path || self.path}"
|
||||
raise e
|
||||
@@ -119,12 +135,15 @@ module Jekyll
|
||||
#
|
||||
# Returns the type of self.
|
||||
def type
|
||||
if is_a?(Post)
|
||||
:post
|
||||
elsif is_a?(Page)
|
||||
:page
|
||||
elsif is_a?(Draft)
|
||||
:draft
|
||||
if is_a?(Page)
|
||||
:pages
|
||||
end
|
||||
end
|
||||
|
||||
# returns the owner symbol for hook triggering
|
||||
def hook_owner
|
||||
if is_a?(Page)
|
||||
:pages
|
||||
end
|
||||
end
|
||||
|
||||
@@ -134,25 +153,46 @@ module Jekyll
|
||||
# Returns true if the extname belongs to the set of extensions
|
||||
# that asset files use.
|
||||
def asset_file?
|
||||
%w[.sass .scss .coffee].include?(ext)
|
||||
sass_file? || coffeescript_file?
|
||||
end
|
||||
|
||||
# Determine whether the document is a Sass file.
|
||||
#
|
||||
# Returns true if extname == .sass or .scss, false otherwise.
|
||||
def sass_file?
|
||||
%w[.sass .scss].include?(ext)
|
||||
end
|
||||
|
||||
# Determine whether the document is a CoffeeScript file.
|
||||
#
|
||||
# Returns true if extname == .coffee, false otherwise.
|
||||
def coffeescript_file?
|
||||
'.coffee'.eql?(ext)
|
||||
end
|
||||
|
||||
# Determine whether the file should be rendered with Liquid.
|
||||
#
|
||||
# Returns false if the document is either an asset file or a yaml file,
|
||||
# true otherwise.
|
||||
# Always returns true.
|
||||
def render_with_liquid?
|
||||
!asset_file?
|
||||
true
|
||||
end
|
||||
|
||||
# Determine whether the file should be placed into layouts.
|
||||
#
|
||||
# Returns false if the document is either an asset file or a yaml file,
|
||||
# true otherwise.
|
||||
# Returns false if the document is an asset file.
|
||||
def place_in_layout?
|
||||
!asset_file?
|
||||
end
|
||||
|
||||
# Checks if the layout specified in the document actually exists
|
||||
#
|
||||
# layout - the layout to check
|
||||
#
|
||||
# Returns true if the layout is invalid, false if otherwise
|
||||
def invalid_layout?(layout)
|
||||
!data["layout"].nil? && layout.nil? && !(self.is_a? Jekyll::Excerpt)
|
||||
end
|
||||
|
||||
# Recursively render layouts
|
||||
#
|
||||
# layouts - a list of the layouts
|
||||
@@ -163,15 +203,25 @@ module Jekyll
|
||||
def render_all_layouts(layouts, payload, info)
|
||||
# recursively render layouts
|
||||
layout = layouts[data["layout"]]
|
||||
|
||||
Jekyll.logger.warn("Build Warning:", "Layout '#{data["layout"]}' requested in #{path} does not exist.") if invalid_layout? layout
|
||||
|
||||
used = Set.new([layout])
|
||||
|
||||
while layout
|
||||
Jekyll.logger.debug "Rendering Layout:", path
|
||||
payload = Utils.deep_merge_hashes(payload, {"content" => output, "page" => layout.data})
|
||||
|
||||
self.output = render_liquid(layout.content,
|
||||
payload,
|
||||
info,
|
||||
File.join(site.config['layouts'], layout.name))
|
||||
File.join(site.config['layouts_dir'], layout.name))
|
||||
|
||||
# Add layout to dependency tree
|
||||
site.regenerator.add_dependency(
|
||||
site.in_source_dir(path),
|
||||
site.in_source_dir(layout.path)
|
||||
)
|
||||
|
||||
if layout = layouts[layout.data["layout"]]
|
||||
if used.include?(layout)
|
||||
@@ -190,19 +240,29 @@ module Jekyll
|
||||
#
|
||||
# Returns nothing.
|
||||
def do_layout(payload, layouts)
|
||||
Jekyll.logger.debug "Rendering:", self.relative_path
|
||||
|
||||
Jekyll.logger.debug "Pre-Render Hooks:", self.relative_path
|
||||
Jekyll::Hooks.trigger hook_owner, :pre_render, self, payload
|
||||
info = { :filters => [Jekyll::Filters], :registers => { :site => site, :page => payload['page'] } }
|
||||
|
||||
# render and transform content (this becomes the final content of the object)
|
||||
payload["highlighter_prefix"] = converter.highlighter_prefix
|
||||
payload["highlighter_suffix"] = converter.highlighter_suffix
|
||||
payload["highlighter_prefix"] = converters.first.highlighter_prefix
|
||||
payload["highlighter_suffix"] = converters.first.highlighter_suffix
|
||||
|
||||
self.content = render_liquid(content, payload, info) if render_with_liquid?
|
||||
transform
|
||||
if render_with_liquid?
|
||||
Jekyll.logger.debug "Rendering Liquid:", self.relative_path
|
||||
self.content = render_liquid(content, payload, info, path)
|
||||
end
|
||||
Jekyll.logger.debug "Rendering Markup:", self.relative_path
|
||||
self.content = transform
|
||||
|
||||
# output keeps track of what will finally be written
|
||||
self.output = content
|
||||
|
||||
render_all_layouts(layouts, payload, info) if place_in_layout?
|
||||
Jekyll.logger.debug "Post-Render Hooks:", self.relative_path
|
||||
Jekyll::Hooks.trigger hook_owner, :post_render, self
|
||||
end
|
||||
|
||||
# Write the generated page file to the destination directory.
|
||||
@@ -216,6 +276,7 @@ module Jekyll
|
||||
File.open(path, 'wb') do |f|
|
||||
f.write(output)
|
||||
end
|
||||
Jekyll::Hooks.trigger hook_owner, :post_write, self
|
||||
end
|
||||
|
||||
# Accessor for data properties by Liquid.
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
module Jekyll
|
||||
class Deprecator
|
||||
def self.process(args)
|
||||
no_subcommand(args)
|
||||
module Deprecator
|
||||
extend self
|
||||
|
||||
def process(args)
|
||||
arg_is_present? args, "--server", "The --server command has been replaced by the \
|
||||
'serve' subcommand."
|
||||
arg_is_present? args, "--serve", "The --server command has been replaced by the \
|
||||
'serve' subcommand."
|
||||
arg_is_present? args, "--no-server", "To build Jekyll without launching a server, \
|
||||
use the 'build' subcommand."
|
||||
arg_is_present? args, "--auto", "The switch '--auto' has been replaced with '--watch'."
|
||||
@@ -14,23 +17,30 @@ module Jekyll
|
||||
arg_is_present? args, "--paginate", "The 'paginate' setting can only be set in your \
|
||||
config files."
|
||||
arg_is_present? args, "--url", "The 'url' setting can only be set in your config files."
|
||||
no_subcommand(args)
|
||||
end
|
||||
|
||||
def self.no_subcommand(args)
|
||||
def no_subcommand(args)
|
||||
if args.size > 0 && args.first =~ /^--/ && !%w[--help --version].include?(args.first)
|
||||
Jekyll.logger.error "Deprecation:", "Jekyll now uses subcommands instead of just \
|
||||
switches. Run `jekyll --help' to find out more."
|
||||
deprecation_message "Jekyll now uses subcommands instead of just switches. Run `jekyll --help` to find out more."
|
||||
abort
|
||||
end
|
||||
end
|
||||
|
||||
def self.arg_is_present?(args, deprecated_argument, message)
|
||||
def arg_is_present?(args, deprecated_argument, message)
|
||||
if args.include?(deprecated_argument)
|
||||
deprecation_message(message)
|
||||
end
|
||||
end
|
||||
|
||||
def self.deprecation_message(message)
|
||||
def deprecation_message(message)
|
||||
Jekyll.logger.error "Deprecation:", message
|
||||
end
|
||||
|
||||
def defaults_deprecate_type(old, current)
|
||||
Jekyll.logger.warn "Defaults:", "The '#{old}' type has become '#{current}'."
|
||||
Jekyll.logger.warn "Defaults:", "Please update your front-matter defaults to use 'type: #{current}'."
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
module Jekyll
|
||||
class Document
|
||||
include Comparable
|
||||
|
||||
attr_reader :path, :site
|
||||
attr_accessor :content, :collection, :output
|
||||
attr_reader :path, :site, :extname, :output_ext, :content, :output, :collection
|
||||
|
||||
YAML_FRONT_MATTER_REGEXP = /\A(---\s*\n.*?\n?)^((---|\.\.\.)\s*$\n?)/m
|
||||
DATELESS_FILENAME_MATCHER = /^(.*)(\.[^.]+)$/
|
||||
DATE_FILENAME_MATCHER = /^(.+\/)*(\d+-\d+-\d+)-(.*)(\.[^.]+)$/
|
||||
|
||||
# Create a new Document.
|
||||
#
|
||||
@@ -14,7 +19,32 @@ module Jekyll
|
||||
def initialize(path, relations)
|
||||
@site = relations[:site]
|
||||
@path = path
|
||||
@extname = File.extname(path)
|
||||
@output_ext = Jekyll::Renderer.new(site, self).output_ext
|
||||
@collection = relations[:collection]
|
||||
@has_yaml_header = nil
|
||||
|
||||
if draft?
|
||||
categories_from_path("_drafts")
|
||||
else
|
||||
categories_from_path(collection.relative_directory)
|
||||
end
|
||||
|
||||
data.default_proc = proc do |hash, key|
|
||||
site.frontmatter_defaults.find(relative_path, collection.label, key)
|
||||
end
|
||||
|
||||
trigger_hooks(:post_init)
|
||||
end
|
||||
|
||||
def output=(output)
|
||||
@to_liquid = nil
|
||||
@output = output
|
||||
end
|
||||
|
||||
def content=(content)
|
||||
@to_liquid = nil
|
||||
@content = content
|
||||
end
|
||||
|
||||
# Fetch the Document's data.
|
||||
@@ -25,28 +55,56 @@ module Jekyll
|
||||
@data ||= Hash.new
|
||||
end
|
||||
|
||||
# Merge some data in with this document's data.
|
||||
#
|
||||
# Returns the merged data.
|
||||
def merge_data!(other)
|
||||
if other.key?('categories') && !other['categories'].nil?
|
||||
if other['categories'].is_a?(String)
|
||||
other['categories'] = other['categories'].split(" ").map(&:strip)
|
||||
end
|
||||
other['categories'] = (data['categories'] || []) | other['categories']
|
||||
end
|
||||
Utils.deep_merge_hashes!(data, other)
|
||||
if data.key?('date') && !data['date'].is_a?(Time)
|
||||
data['date'] = Utils.parse_date(data['date'].to_s, "Document '#{relative_path}' does not have a valid date in the YAML front matter.")
|
||||
end
|
||||
data
|
||||
end
|
||||
|
||||
def date
|
||||
data['date'] ||= site.time
|
||||
end
|
||||
|
||||
# Returns whether the document is a draft. This is only the case if
|
||||
# the document is in the 'posts' collection but in a different
|
||||
# directory than '_posts'.
|
||||
#
|
||||
# Returns whether the document is a draft.
|
||||
def draft?
|
||||
data['draft'] ||= relative_path.index(collection.relative_directory).nil? && collection.label == "posts"
|
||||
end
|
||||
|
||||
# The path to the document, relative to the site source.
|
||||
#
|
||||
# Returns a String path which represents the relative path
|
||||
# from the site source to this document
|
||||
def relative_path
|
||||
Pathname.new(path).relative_path_from(Pathname.new(site.source)).to_s
|
||||
@relative_path ||= Pathname.new(path).relative_path_from(Pathname.new(site.source)).to_s
|
||||
end
|
||||
|
||||
# The base filename of the document, without the file extname.
|
||||
#
|
||||
# Returns the basename without the file extname.
|
||||
def basename_without_ext
|
||||
@basename_without_ext ||= File.basename(path, '.*')
|
||||
end
|
||||
|
||||
# The base filename of the document.
|
||||
#
|
||||
# suffix - (optional) the suffix to be removed from the end of the filename
|
||||
#
|
||||
# Returns the base filename of the document.
|
||||
def basename(suffix = "")
|
||||
File.basename(path, suffix)
|
||||
end
|
||||
|
||||
# The extension name of the document.
|
||||
#
|
||||
# Returns the extension name of the document.
|
||||
def extname
|
||||
File.extname(path)
|
||||
def basename
|
||||
@basename ||= File.basename(path)
|
||||
end
|
||||
|
||||
# Produces a "cleaned" relative path.
|
||||
@@ -61,7 +119,8 @@ module Jekyll
|
||||
#
|
||||
# Returns the cleaned relative path of the document.
|
||||
def cleaned_relative_path
|
||||
relative_path[0 .. -extname.length - 1].sub(collection.relative_directory, "")
|
||||
@cleaned_relative_path ||=
|
||||
relative_path[0 .. -extname.length - 1].sub(collection.relative_directory, "")
|
||||
end
|
||||
|
||||
# Determine whether the document is a YAML file.
|
||||
@@ -77,7 +136,21 @@ module Jekyll
|
||||
# Returns true if the extname belongs to the set of extensions
|
||||
# that asset files use.
|
||||
def asset_file?
|
||||
%w[.sass .scss .coffee].include?(extname)
|
||||
sass_file? || coffeescript_file?
|
||||
end
|
||||
|
||||
# Determine whether the document is a Sass file.
|
||||
#
|
||||
# Returns true if extname == .sass or .scss, false otherwise.
|
||||
def sass_file?
|
||||
%w[.sass .scss].include?(extname)
|
||||
end
|
||||
|
||||
# Determine whether the document is a CoffeeScript file.
|
||||
#
|
||||
# Returns true if extname == .coffee, false otherwise.
|
||||
def coffeescript_file?
|
||||
'.coffee'.eql?(extname)
|
||||
end
|
||||
|
||||
# Determine whether the file should be rendered with Liquid.
|
||||
@@ -85,7 +158,7 @@ module Jekyll
|
||||
# Returns false if the document is either an asset file or a yaml file,
|
||||
# true otherwise.
|
||||
def render_with_liquid?
|
||||
!(asset_file? || yaml_file?)
|
||||
!(coffeescript_file? || yaml_file?)
|
||||
end
|
||||
|
||||
# Determine whether the file should be placed into layouts.
|
||||
@@ -109,9 +182,25 @@ module Jekyll
|
||||
# Returns the Hash of key-value pairs for replacement in the URL.
|
||||
def url_placeholders
|
||||
{
|
||||
collection: collection.label,
|
||||
path: cleaned_relative_path,
|
||||
output_ext: Jekyll::Renderer.new(site, self).output_ext
|
||||
collection: collection.label,
|
||||
path: cleaned_relative_path,
|
||||
output_ext: output_ext,
|
||||
name: Utils.slugify(basename_without_ext),
|
||||
title: Utils.slugify(data['slug'], mode: "pretty", cased: true) || Utils
|
||||
.slugify(basename_without_ext, mode: "pretty", cased: true),
|
||||
slug: Utils.slugify(data['slug']) || Utils.slugify(basename_without_ext),
|
||||
year: date.strftime("%Y"),
|
||||
month: date.strftime("%m"),
|
||||
day: date.strftime("%d"),
|
||||
hour: date.strftime("%H"),
|
||||
minute: date.strftime("%M"),
|
||||
second: date.strftime("%S"),
|
||||
i_day: date.strftime("%-d"),
|
||||
i_month: date.strftime("%-m"),
|
||||
categories: (data['categories'] || []).map { |c| c.to_s.downcase }.uniq.join('/'),
|
||||
short_month: date.strftime("%b"),
|
||||
short_year: date.strftime("%y"),
|
||||
y_day: date.strftime("%j"),
|
||||
}
|
||||
end
|
||||
|
||||
@@ -127,21 +216,27 @@ module Jekyll
|
||||
#
|
||||
# Returns the computed URL for the document.
|
||||
def url
|
||||
@url ||= URL.new({
|
||||
@url = URL.new({
|
||||
template: url_template,
|
||||
placeholders: url_placeholders,
|
||||
permalink: permalink
|
||||
}).to_s
|
||||
end
|
||||
|
||||
def [](key)
|
||||
data[key]
|
||||
end
|
||||
|
||||
# The full path to the output file.
|
||||
#
|
||||
# base_directory - the base path of the output directory
|
||||
#
|
||||
# Returns the full path to the output file of this document.
|
||||
def destination(base_directory)
|
||||
path = Jekyll.sanitized_path(base_directory, url)
|
||||
path = File.join(path, "index.html") if url =~ /\/$/
|
||||
dest = site.in_dest_dir(base_directory)
|
||||
path = site.in_dest_dir(dest, URL.unescape_path(url))
|
||||
path = File.join(path, "index.html") if url.end_with?("/")
|
||||
path << output_ext unless path.end_with?(output_ext)
|
||||
path
|
||||
end
|
||||
|
||||
@@ -156,6 +251,8 @@ module Jekyll
|
||||
File.open(path, 'wb') do |f|
|
||||
f.write(output)
|
||||
end
|
||||
|
||||
trigger_hooks(:post_write)
|
||||
end
|
||||
|
||||
# Returns merged option hash for File.read of self.site (if exists)
|
||||
@@ -172,7 +269,7 @@ module Jekyll
|
||||
#
|
||||
# Returns true if the 'published' key is specified in the YAML front-matter and not `false`.
|
||||
def published?
|
||||
!(data.has_key?('published') && data['published'] == false)
|
||||
!(data.key?('published') && data['published'] == false)
|
||||
end
|
||||
|
||||
# Read in the file and assign the content and data based on the file contents.
|
||||
@@ -181,22 +278,25 @@ module Jekyll
|
||||
#
|
||||
# Returns nothing.
|
||||
def read(opts = {})
|
||||
@to_liquid = nil
|
||||
|
||||
Jekyll.logger.debug "Reading:", relative_path
|
||||
|
||||
if yaml_file?
|
||||
@data = SafeYAML.load_file(path)
|
||||
else
|
||||
begin
|
||||
defaults = @site.frontmatter_defaults.all(url, collection.label.to_sym)
|
||||
unless defaults.empty?
|
||||
@data = defaults
|
||||
end
|
||||
@content = File.read(path, merged_file_read_opts(opts))
|
||||
if content =~ /\A(---\s*\n.*?\n?)^(---\s*$\n?)/m
|
||||
@content = $POSTMATCH
|
||||
merge_data!(defaults) unless defaults.empty?
|
||||
|
||||
self.content = File.read(path, merged_file_read_opts(opts))
|
||||
if content =~ YAML_FRONT_MATTER_REGEXP
|
||||
self.content = $POSTMATCH
|
||||
data_file = SafeYAML.load($1)
|
||||
unless data_file.nil?
|
||||
@data = Utils.deep_merge_hashes(defaults, data_file)
|
||||
end
|
||||
merge_data!(data_file) if data_file
|
||||
end
|
||||
|
||||
post_read
|
||||
rescue SyntaxError => e
|
||||
puts "YAML Exception reading #{path}: #{e.message}"
|
||||
rescue Exception => e
|
||||
@@ -205,19 +305,66 @@ module Jekyll
|
||||
end
|
||||
end
|
||||
|
||||
def post_read
|
||||
if DATE_FILENAME_MATCHER =~ relative_path
|
||||
m, cats, date, slug, ext = *relative_path.match(DATE_FILENAME_MATCHER)
|
||||
merge_data!({
|
||||
"slug" => slug,
|
||||
"ext" => ext
|
||||
})
|
||||
merge_data!({"date" => date}) if data['date'].nil? || data['date'].to_i == site.time.to_i
|
||||
data['title'] ||= slug.split('-').select {|w| w.capitalize! || w }.join(' ')
|
||||
end
|
||||
populate_categories
|
||||
populate_tags
|
||||
|
||||
if generate_excerpt?
|
||||
data['excerpt'] ||= Jekyll::Excerpt.new(self)
|
||||
end
|
||||
end
|
||||
|
||||
# Add superdirectories of the special_dir to categories.
|
||||
# In the case of es/_posts, 'es' is added as a category.
|
||||
# In the case of _posts/es, 'es' is NOT added as a category.
|
||||
#
|
||||
# Returns nothing.
|
||||
def categories_from_path(special_dir)
|
||||
superdirs = relative_path.sub(/#{special_dir}(.*)/, '').split(File::SEPARATOR).reject do |c|
|
||||
c.empty? || c.eql?(special_dir) || c.eql?(basename)
|
||||
end
|
||||
merge_data!({ 'categories' => superdirs })
|
||||
end
|
||||
|
||||
def populate_categories
|
||||
merge_data!({
|
||||
'categories' => (
|
||||
Array(data['categories']) + Utils.pluralized_array_from_hash(data, 'category', 'categories')
|
||||
).map { |c| c.to_s }.flatten.uniq
|
||||
})
|
||||
end
|
||||
|
||||
def populate_tags
|
||||
merge_data!({
|
||||
"tags" => Utils.pluralized_array_from_hash(data, "tag", "tags").flatten
|
||||
})
|
||||
end
|
||||
|
||||
# Create a Liquid-understandable version of this Document.
|
||||
#
|
||||
# Returns a Hash representing this Document's data.
|
||||
def to_liquid
|
||||
if data.is_a?(Hash)
|
||||
Utils.deep_merge_hashes data, {
|
||||
@to_liquid ||= if data.is_a?(Hash)
|
||||
Utils.deep_merge_hashes Utils.deep_merge_hashes({
|
||||
"output" => output,
|
||||
"content" => content,
|
||||
"path" => path,
|
||||
"relative_path" => relative_path,
|
||||
"path" => relative_path,
|
||||
"url" => url,
|
||||
"collection" => collection.label
|
||||
}
|
||||
"collection" => collection.label,
|
||||
"next" => next_doc,
|
||||
"previous" => previous_doc,
|
||||
"id" => id,
|
||||
}, data), { 'excerpt' => data['excerpt'].to_s }
|
||||
else
|
||||
data
|
||||
end
|
||||
@@ -235,7 +382,7 @@ module Jekyll
|
||||
#
|
||||
# Returns the content of the document
|
||||
def to_s
|
||||
output || content
|
||||
output || content || 'NO CONTENT'
|
||||
end
|
||||
|
||||
# Compare this document against another document.
|
||||
@@ -243,8 +390,11 @@ module Jekyll
|
||||
#
|
||||
# Returns -1, 0, +1 or nil depending on whether this doc's path is less than,
|
||||
# equal or greater than the other doc's path. See String#<=> for more details.
|
||||
def <=>(anotherDocument)
|
||||
path <=> anotherDocument.path
|
||||
def <=>(other)
|
||||
return nil if !other.respond_to?(:data)
|
||||
cmp = data['date'] <=> other.data['date']
|
||||
cmp = path <=> other.path if cmp == 0
|
||||
cmp
|
||||
end
|
||||
|
||||
# Determine whether this document should be written.
|
||||
@@ -256,5 +406,70 @@ module Jekyll
|
||||
collection && collection.write?
|
||||
end
|
||||
|
||||
# The Document excerpt_separator, from the YAML Front-Matter or site
|
||||
# default excerpt_separator value
|
||||
#
|
||||
# Returns the document excerpt_separator
|
||||
def excerpt_separator
|
||||
(data['excerpt_separator'] || site.config['excerpt_separator']).to_s
|
||||
end
|
||||
|
||||
# Whether to generate an excerpt
|
||||
#
|
||||
# Returns true if the excerpt separator is configured.
|
||||
def generate_excerpt?
|
||||
!excerpt_separator.empty?
|
||||
end
|
||||
|
||||
def next_doc
|
||||
pos = collection.docs.index {|post| post.equal?(self) }
|
||||
if pos && pos < collection.docs.length - 1
|
||||
collection.docs[pos + 1]
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def previous_doc
|
||||
pos = collection.docs.index {|post| post.equal?(self) }
|
||||
if pos && pos > 0
|
||||
collection.docs[pos - 1]
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def trigger_hooks(hook_name, *args)
|
||||
Jekyll::Hooks.trigger collection.label.to_sym, hook_name, self, *args if collection
|
||||
Jekyll::Hooks.trigger :documents, hook_name, self, *args
|
||||
end
|
||||
|
||||
def id
|
||||
@id ||= File.join(File.dirname(url), (data['slug'] || basename_without_ext).to_s)
|
||||
end
|
||||
|
||||
# Calculate related posts.
|
||||
#
|
||||
# Returns an Array of related Posts.
|
||||
def related_posts
|
||||
Jekyll::RelatedPosts.new(self).build
|
||||
end
|
||||
|
||||
# Override of normal respond_to? to match method_missing's logic for
|
||||
# looking in @data.
|
||||
def respond_to?(method, include_private = false)
|
||||
data.key?(method.to_s) || super
|
||||
end
|
||||
|
||||
# Override of method_missing to check in @data for the key.
|
||||
def method_missing(method, *args, &blck)
|
||||
if data.key?(method.to_s)
|
||||
Jekyll.logger.warn "Deprecation:", "Document##{method} is now a key in the #data hash."
|
||||
Jekyll.logger.warn "", "Called by #{caller.first}."
|
||||
data[method.to_s]
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
module Jekyll
|
||||
|
||||
class Draft < Post
|
||||
|
||||
# Valid post name regex (no date)
|
||||
MATCHER = /^(.*)(\.[^.]+)$/
|
||||
|
||||
# Draft name validator. Draft filenames must be like:
|
||||
# my-awesome-post.textile
|
||||
#
|
||||
# Returns true if valid, false if not.
|
||||
def self.valid?(name)
|
||||
name =~ MATCHER
|
||||
end
|
||||
|
||||
# Get the full path to the directory containing the draft files
|
||||
def containing_dir(source, dir)
|
||||
File.join(source, dir, '_drafts')
|
||||
end
|
||||
|
||||
# The path to the draft source file, relative to the site source
|
||||
def relative_path
|
||||
File.join(@dir, '_drafts', @name)
|
||||
end
|
||||
|
||||
# Extract information from the post filename.
|
||||
#
|
||||
# name - The String filename of the post file.
|
||||
#
|
||||
# Returns nothing.
|
||||
def process(name)
|
||||
m, slug, ext = *name.match(MATCHER)
|
||||
self.date = File.mtime(File.join(@base, name))
|
||||
self.slug = slug
|
||||
self.ext = ext
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
@@ -47,7 +47,7 @@ module Jekyll
|
||||
|
||||
def excluded?(entry)
|
||||
excluded = glob_include?(site.exclude, relative_to_source(entry))
|
||||
Jekyll.logger.debug "excluded?(#{relative_to_source(entry)}) ==> #{excluded}"
|
||||
Jekyll.logger.debug "EntryFilter:", "excluded?(#{relative_to_source(entry)}) ==> #{excluded}"
|
||||
excluded
|
||||
end
|
||||
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
module Jekyll
|
||||
class FatalException < StandardError
|
||||
module Errors
|
||||
class FatalException < RuntimeError
|
||||
end
|
||||
|
||||
class MissingDependencyException < FatalException
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,48 +1,44 @@
|
||||
require 'jekyll/convertible'
|
||||
require 'forwardable'
|
||||
|
||||
module Jekyll
|
||||
class Excerpt
|
||||
include Convertible
|
||||
extend Forwardable
|
||||
|
||||
attr_accessor :post
|
||||
attr_accessor :content, :output, :ext
|
||||
attr_accessor :doc
|
||||
attr_accessor :content, :ext
|
||||
attr_writer :output
|
||||
|
||||
def_delegator :@post, :site, :site
|
||||
def_delegator :@post, :name, :name
|
||||
def_delegator :@post, :ext, :ext
|
||||
def_delegators :@doc, :site, :name, :ext, :relative_path, :extname,
|
||||
:render_with_liquid?, :collection, :related_posts
|
||||
|
||||
# Initialize this Post instance.
|
||||
# Initialize this Excerpt instance.
|
||||
#
|
||||
# site - The Site.
|
||||
# base - The String path to the dir containing the post file.
|
||||
# name - The String filename of the post file.
|
||||
# doc - The Document.
|
||||
#
|
||||
# Returns the new Post.
|
||||
def initialize(post)
|
||||
self.post = post
|
||||
self.content = extract_excerpt(post.content)
|
||||
# Returns the new Excerpt.
|
||||
def initialize(doc)
|
||||
self.doc = doc
|
||||
self.content = extract_excerpt(doc.content)
|
||||
end
|
||||
|
||||
def to_liquid
|
||||
post.to_liquid(post.class::EXCERPT_ATTRIBUTES_FOR_LIQUID)
|
||||
end
|
||||
|
||||
# Fetch YAML front-matter data from related post, without layout key
|
||||
# Fetch YAML front-matter data from related doc, without layout key
|
||||
#
|
||||
# Returns Hash of post data
|
||||
# Returns Hash of doc data
|
||||
def data
|
||||
@data ||= post.data.dup
|
||||
@data ||= doc.data.dup
|
||||
@data.delete("layout")
|
||||
@data.delete("excerpt")
|
||||
@data
|
||||
end
|
||||
|
||||
def trigger_hooks(*)
|
||||
end
|
||||
|
||||
# 'Path' of the excerpt.
|
||||
#
|
||||
# Returns the path for the post this excerpt belongs to with #excerpt appended
|
||||
# Returns the path for the doc this excerpt belongs to with #excerpt appended
|
||||
def path
|
||||
File.join(post.path, "#excerpt")
|
||||
File.join(doc.path, "#excerpt")
|
||||
end
|
||||
|
||||
# Check if excerpt includes a string
|
||||
@@ -52,28 +48,43 @@ module Jekyll
|
||||
(output && output.include?(something)) || content.include?(something)
|
||||
end
|
||||
|
||||
# The UID for this post (useful in feeds).
|
||||
# e.g. /2008/11/05/my-awesome-post
|
||||
# The UID for this doc (useful in feeds).
|
||||
# e.g. /2008/11/05/my-awesome-doc
|
||||
#
|
||||
# Returns the String UID.
|
||||
def id
|
||||
File.join(post.dir, post.slug, "#excerpt")
|
||||
"#{doc.id}#excerpt"
|
||||
end
|
||||
|
||||
def to_s
|
||||
output || content
|
||||
end
|
||||
|
||||
# Returns the shorthand String identifier of this Post.
|
||||
def to_liquid
|
||||
doc.data['excerpt'] = nil
|
||||
@to_liquid ||= doc.to_liquid
|
||||
doc.data['excerpt'] = self
|
||||
@to_liquid
|
||||
end
|
||||
|
||||
# Returns the shorthand String identifier of this doc.
|
||||
def inspect
|
||||
"<Excerpt: #{self.id}>"
|
||||
end
|
||||
|
||||
def output
|
||||
@output ||= Renderer.new(doc.site, self, site.site_payload).run
|
||||
end
|
||||
|
||||
def place_in_layout?
|
||||
false
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# Internal: Extract excerpt from the content
|
||||
#
|
||||
# By default excerpt is your first paragraph of a post: everything before
|
||||
# By default excerpt is your first paragraph of a doc: everything before
|
||||
# the first two new lines:
|
||||
#
|
||||
# ---
|
||||
@@ -87,16 +98,16 @@ module Jekyll
|
||||
# [1]: http://example.com/
|
||||
#
|
||||
# This is fairly good option for Markdown and Textile files. But might cause
|
||||
# problems for HTML posts (which is quite unusual for Jekyll). If default
|
||||
# problems for HTML docs (which is quite unusual for Jekyll). If default
|
||||
# excerpt delimiter is not good for you, you might want to set your own via
|
||||
# configuration option `excerpt_separator`. For example, following is a good
|
||||
# alternative for HTML posts:
|
||||
# alternative for HTML docs:
|
||||
#
|
||||
# # file: _config.yml
|
||||
# excerpt_separator: "<!-- more -->"
|
||||
#
|
||||
# Notice that all markdown-style link references will be appended to the
|
||||
# excerpt. So the example post above will have this excerpt source:
|
||||
# excerpt. So the example doc above will have this excerpt source:
|
||||
#
|
||||
# First paragraph with [link][1].
|
||||
#
|
||||
@@ -105,11 +116,14 @@ module Jekyll
|
||||
# Excerpts are rendered same time as content is rendered.
|
||||
#
|
||||
# Returns excerpt String
|
||||
def extract_excerpt(post_content)
|
||||
separator = site.config['excerpt_separator']
|
||||
head, _, tail = post_content.partition(separator)
|
||||
def extract_excerpt(doc_content)
|
||||
head, _, tail = doc_content.to_s.partition(doc.excerpt_separator)
|
||||
|
||||
"" << head << "\n\n" << tail.scan(/^\[[^\]]+\]:.+$/).join("\n")
|
||||
if tail.empty?
|
||||
head
|
||||
else
|
||||
"" << head << "\n\n" << tail.scan(/^\[[^\]]+\]:.+$/).join("\n")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
59
lib/jekyll/external.rb
Normal file
59
lib/jekyll/external.rb
Normal file
@@ -0,0 +1,59 @@
|
||||
module Jekyll
|
||||
module External
|
||||
class << self
|
||||
|
||||
#
|
||||
# Gems that, if installed, should be loaded.
|
||||
# Usually contain subcommands.
|
||||
#
|
||||
def blessed_gems
|
||||
%w{
|
||||
jekyll-docs
|
||||
jekyll-import
|
||||
}
|
||||
end
|
||||
|
||||
#
|
||||
# Require a gem or file if it's present, otherwise silently fail.
|
||||
#
|
||||
# names - a string gem name or array of gem names
|
||||
#
|
||||
def require_if_present(names)
|
||||
Array(names).each do |name|
|
||||
begin
|
||||
require name
|
||||
rescue LoadError
|
||||
Jekyll.logger.debug "Couldn't load #{name}. Skipping."
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Require a gem or gems. If it's not present, show a very nice error
|
||||
# message that explains everything and is much more helpful than the
|
||||
# normal LoadError.
|
||||
#
|
||||
# names - a string gem name or array of gem names
|
||||
#
|
||||
def require_with_graceful_fail(names)
|
||||
Array(names).each do |name|
|
||||
begin
|
||||
require name
|
||||
rescue LoadError => e
|
||||
Jekyll.logger.error "Dependency Error:", <<-MSG
|
||||
Yikes! It looks like you don't have #{name} or one of its dependencies installed.
|
||||
In order to use Jekyll as currently configured, you'll need to install this gem.
|
||||
|
||||
The full error message from Ruby is: '#{e.message}'
|
||||
|
||||
If you run into trouble, you can find helpful resources at http://jekyllrb.com/help/!
|
||||
MSG
|
||||
raise Jekyll::Errors::MissingDependencyException.new(name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,19 +1,9 @@
|
||||
require 'uri'
|
||||
require 'json'
|
||||
require 'date'
|
||||
|
||||
module Jekyll
|
||||
module Filters
|
||||
# Convert a Textile string into HTML output.
|
||||
#
|
||||
# input - The Textile String to convert.
|
||||
#
|
||||
# Returns the HTML formatted String.
|
||||
def textilize(input)
|
||||
site = @context.registers[:site]
|
||||
converter = site.getConverterImpl(Jekyll::Converters::Textile)
|
||||
converter.convert(input)
|
||||
end
|
||||
|
||||
# Convert a Markdown string into HTML output.
|
||||
#
|
||||
# input - The Markdown String to convert.
|
||||
@@ -21,10 +11,43 @@ module Jekyll
|
||||
# Returns the HTML formatted String.
|
||||
def markdownify(input)
|
||||
site = @context.registers[:site]
|
||||
converter = site.getConverterImpl(Jekyll::Converters::Markdown)
|
||||
converter = site.find_converter_instance(Jekyll::Converters::Markdown)
|
||||
converter.convert(input)
|
||||
end
|
||||
|
||||
# Convert a Sass string into CSS output.
|
||||
#
|
||||
# input - The Sass String to convert.
|
||||
#
|
||||
# Returns the CSS formatted String.
|
||||
def sassify(input)
|
||||
site = @context.registers[:site]
|
||||
converter = site.find_converter_instance(Jekyll::Converters::Sass)
|
||||
converter.convert(input)
|
||||
end
|
||||
|
||||
# Convert a Scss string into CSS output.
|
||||
#
|
||||
# input - The Scss String to convert.
|
||||
#
|
||||
# Returns the CSS formatted String.
|
||||
def scssify(input)
|
||||
site = @context.registers[:site]
|
||||
converter = site.find_converter_instance(Jekyll::Converters::Scss)
|
||||
converter.convert(input)
|
||||
end
|
||||
|
||||
# Slugify a filename or title.
|
||||
#
|
||||
# input - The filename or title to slugify.
|
||||
# mode - how string is slugified
|
||||
#
|
||||
# Returns the given filename or title as a lowercase URL String.
|
||||
# See Utils.slugify for more detail.
|
||||
def slugify(input, mode=nil)
|
||||
Utils.slugify(input, mode: mode)
|
||||
end
|
||||
|
||||
# Format a date in short format e.g. "27 Jan 2011".
|
||||
#
|
||||
# date - the Time to format.
|
||||
@@ -155,7 +178,7 @@ module Jekyll
|
||||
#
|
||||
# Returns the converted json string
|
||||
def jsonify(input)
|
||||
input.to_json
|
||||
as_liquid(input).to_json
|
||||
end
|
||||
|
||||
# Group an array of items by a property
|
||||
@@ -181,13 +204,14 @@ module Jekyll
|
||||
# Filter an array of objects
|
||||
#
|
||||
# input - the object array
|
||||
# key - key within each object to filter by
|
||||
# property - property within each object to filter by
|
||||
# value - desired value
|
||||
#
|
||||
# Returns the filtered array of objects
|
||||
def where(input, property, value)
|
||||
return input unless input.is_a?(Array)
|
||||
input.select { |object| item_property(object, property) == value }
|
||||
return input unless input.is_a?(Enumerable)
|
||||
input = input.values if input.is_a?(Hash)
|
||||
input.select { |object| item_property(object, property).to_s == value.to_s }
|
||||
end
|
||||
|
||||
# Sort an array of objects
|
||||
@@ -198,6 +222,9 @@ module Jekyll
|
||||
#
|
||||
# Returns the filtered array of objects
|
||||
def sort(input, property = nil, nils = "first")
|
||||
if input.nil?
|
||||
raise ArgumentError.new("Cannot sort a null object.")
|
||||
end
|
||||
if property.nil?
|
||||
input.sort
|
||||
else
|
||||
@@ -226,11 +253,50 @@ module Jekyll
|
||||
end
|
||||
end
|
||||
|
||||
def pop(array, input = 1)
|
||||
return array unless array.is_a?(Array)
|
||||
new_ary = array.dup
|
||||
new_ary.pop(input.to_i || 1)
|
||||
new_ary
|
||||
end
|
||||
|
||||
def push(array, input)
|
||||
return array unless array.is_a?(Array)
|
||||
new_ary = array.dup
|
||||
new_ary.push(input)
|
||||
new_ary
|
||||
end
|
||||
|
||||
def shift(array, input = 1)
|
||||
return array unless array.is_a?(Array)
|
||||
new_ary = array.dup
|
||||
new_ary.shift(input.to_i || 1)
|
||||
new_ary
|
||||
end
|
||||
|
||||
def unshift(array, input)
|
||||
return array unless array.is_a?(Array)
|
||||
new_ary = array.dup
|
||||
new_ary.unshift(input)
|
||||
new_ary
|
||||
end
|
||||
|
||||
# Convert an object into its String representation for debugging
|
||||
#
|
||||
# input - The Object to be converted
|
||||
#
|
||||
# Returns a String representation of the object.
|
||||
def inspect(input)
|
||||
CGI.escapeHTML(input.inspect)
|
||||
end
|
||||
|
||||
private
|
||||
def time(input)
|
||||
case input
|
||||
when Time
|
||||
input
|
||||
when Date
|
||||
input.to_time
|
||||
when String
|
||||
Time.parse(input) rescue Time.at(input.to_i)
|
||||
when Numeric
|
||||
@@ -238,7 +304,7 @@ module Jekyll
|
||||
else
|
||||
Jekyll.logger.error "Invalid Date:", "'#{input}' is not a valid datetime."
|
||||
exit(1)
|
||||
end
|
||||
end.localtime
|
||||
end
|
||||
|
||||
def groupable?(element)
|
||||
@@ -254,5 +320,27 @@ module Jekyll
|
||||
item[property.to_s]
|
||||
end
|
||||
end
|
||||
|
||||
def as_liquid(item)
|
||||
case item
|
||||
when Hash
|
||||
pairs = item.map { |k, v| as_liquid([k, v]) }
|
||||
Hash[pairs]
|
||||
when Array
|
||||
item.map{ |i| as_liquid(i) }
|
||||
else
|
||||
if item.respond_to?(:to_liquid)
|
||||
liquidated = item.to_liquid
|
||||
# prevent infinite recursion for simple types (which return `self`)
|
||||
if liquidated == item
|
||||
item
|
||||
else
|
||||
as_liquid(liquidated)
|
||||
end
|
||||
else
|
||||
item
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,148 +1,180 @@
|
||||
module Jekyll
|
||||
class Configuration
|
||||
# This class handles custom defaults for YAML frontmatter settings.
|
||||
# These are set in _config.yml and apply both to internal use (e.g. layout)
|
||||
# and the data available to liquid.
|
||||
# This class handles custom defaults for YAML frontmatter settings.
|
||||
# These are set in _config.yml and apply both to internal use (e.g. layout)
|
||||
# and the data available to liquid.
|
||||
#
|
||||
# It is exposed via the frontmatter_defaults method on the site class.
|
||||
class FrontmatterDefaults
|
||||
# Initializes a new instance.
|
||||
def initialize(site)
|
||||
@site = site
|
||||
end
|
||||
|
||||
def update_deprecated_types(set)
|
||||
return set unless set.key?('scope') && set['scope'].key?('type')
|
||||
|
||||
set['scope']['type'] = case set['scope']['type']
|
||||
when 'page'
|
||||
Deprecator.defaults_deprecate_type('page', 'pages')
|
||||
'pages'
|
||||
when 'post'
|
||||
Deprecator.defaults_deprecate_type('post', 'posts')
|
||||
'posts'
|
||||
when 'draft'
|
||||
Deprecator.defaults_deprecate_type('draft', 'drafts')
|
||||
'drafts'
|
||||
else
|
||||
set['scope']['type']
|
||||
end
|
||||
|
||||
set
|
||||
end
|
||||
|
||||
# Finds a default value for a given setting, filtered by path and type
|
||||
#
|
||||
# It is exposed via the frontmatter_defaults method on the site class.
|
||||
class FrontmatterDefaults
|
||||
# Initializes a new instance.
|
||||
def initialize(site)
|
||||
@site = site
|
||||
end
|
||||
# path - the path (relative to the source) of the page, post or :draft the default is used in
|
||||
# type - a symbol indicating whether a :page, a :post or a :draft calls this method
|
||||
#
|
||||
# Returns the default value or nil if none was found
|
||||
def find(path, type, setting)
|
||||
value = nil
|
||||
old_scope = nil
|
||||
|
||||
# Finds a default value for a given setting, filtered by path and type
|
||||
#
|
||||
# path - the path (relative to the source) of the page, post or :draft the default is used in
|
||||
# type - a symbol indicating whether a :page, a :post or a :draft calls this method
|
||||
#
|
||||
# Returns the default value or nil if none was found
|
||||
def find(path, type, setting)
|
||||
value = nil
|
||||
old_scope = nil
|
||||
|
||||
matching_sets(path, type).each do |set|
|
||||
if set['values'].has_key?(setting) && has_precedence?(old_scope, set['scope'])
|
||||
value = set['values'][setting]
|
||||
old_scope = set['scope']
|
||||
end
|
||||
end
|
||||
value
|
||||
end
|
||||
|
||||
# Collects a hash with all default values for a page or post
|
||||
#
|
||||
# path - the relative path of the page or post
|
||||
# type - a symbol indicating the type (:post, :page or :draft)
|
||||
#
|
||||
# Returns a hash with all default values (an empty hash if there are none)
|
||||
def all(path, type)
|
||||
defaults = {}
|
||||
old_scope = nil
|
||||
matching_sets(path, type).each do |set|
|
||||
if has_precedence?(old_scope, set['scope'])
|
||||
defaults.merge! set['values']
|
||||
old_scope = set['scope']
|
||||
else
|
||||
defaults = set['values'].merge(defaults)
|
||||
end
|
||||
end
|
||||
defaults
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Checks if a given default setting scope matches the given path and type
|
||||
#
|
||||
# scope - the hash indicating the scope, as defined in _config.yml
|
||||
# path - the path to check for
|
||||
# type - the type (:post, :page or :draft) to check for
|
||||
#
|
||||
# Returns true if the scope applies to the given path and type
|
||||
def applies?(scope, path, type)
|
||||
applies_path?(scope, path) && applies_type?(scope, type)
|
||||
end
|
||||
|
||||
def applies_path?(scope, path)
|
||||
return true if scope['path'].empty?
|
||||
|
||||
scope_path = Pathname.new(scope['path'])
|
||||
Pathname.new(sanitize_path(path)).ascend do |path|
|
||||
if path == scope_path
|
||||
return true
|
||||
end
|
||||
matching_sets(path, type).each do |set|
|
||||
if set['values'].key?(setting) && has_precedence?(old_scope, set['scope'])
|
||||
value = set['values'][setting]
|
||||
old_scope = set['scope']
|
||||
end
|
||||
end
|
||||
value
|
||||
end
|
||||
|
||||
def applies_type?(scope, type)
|
||||
!scope.has_key?('type') || scope['type'] == type.to_s
|
||||
end
|
||||
|
||||
# Checks if a given set of default values is valid
|
||||
#
|
||||
# set - the default value hash, as defined in _config.yml
|
||||
#
|
||||
# Returns true if the set is valid and can be used in this class
|
||||
def valid?(set)
|
||||
set.is_a?(Hash) && set['scope'].is_a?(Hash) && set['scope']['path'].is_a?(String) && set['values'].is_a?(Hash)
|
||||
end
|
||||
|
||||
# Determines if a new scope has precedence over an old one
|
||||
#
|
||||
# old_scope - the old scope hash, or nil if there's none
|
||||
# new_scope - the new scope hash
|
||||
#
|
||||
# Returns true if the new scope has precedence over the older
|
||||
def has_precedence?(old_scope, new_scope)
|
||||
return true if old_scope.nil?
|
||||
|
||||
new_path = sanitize_path(new_scope['path'])
|
||||
old_path = sanitize_path(old_scope['path'])
|
||||
|
||||
if new_path.length != old_path.length
|
||||
new_path.length >= old_path.length
|
||||
elsif new_scope.has_key? 'type'
|
||||
true
|
||||
# Collects a hash with all default values for a page or post
|
||||
#
|
||||
# path - the relative path of the page or post
|
||||
# type - a symbol indicating the type (:post, :page or :draft)
|
||||
#
|
||||
# Returns a hash with all default values (an empty hash if there are none)
|
||||
def all(path, type)
|
||||
defaults = {}
|
||||
old_scope = nil
|
||||
matching_sets(path, type).each do |set|
|
||||
if has_precedence?(old_scope, set['scope'])
|
||||
defaults = Utils.deep_merge_hashes(defaults, set['values'])
|
||||
old_scope = set['scope']
|
||||
else
|
||||
!old_scope.has_key? 'type'
|
||||
defaults = Utils.deep_merge_hashes(set['values'], defaults)
|
||||
end
|
||||
end
|
||||
defaults
|
||||
end
|
||||
|
||||
# Collects a list of sets that match the given path and type
|
||||
#
|
||||
# Returns an array of hashes
|
||||
def matching_sets(path, type)
|
||||
valid_sets.select do |set|
|
||||
applies?(set['scope'], path, type)
|
||||
end
|
||||
end
|
||||
private
|
||||
|
||||
# Returns a list of valid sets
|
||||
#
|
||||
# This is not cached to allow plugins to modify the configuration
|
||||
# and have their changes take effect
|
||||
#
|
||||
# Returns an array of hashes
|
||||
def valid_sets
|
||||
sets = @site.config['defaults']
|
||||
return [] unless sets.is_a?(Array)
|
||||
# Checks if a given default setting scope matches the given path and type
|
||||
#
|
||||
# scope - the hash indicating the scope, as defined in _config.yml
|
||||
# path - the path to check for
|
||||
# type - the type (:post, :page or :draft) to check for
|
||||
#
|
||||
# Returns true if the scope applies to the given path and type
|
||||
def applies?(scope, path, type)
|
||||
applies_path?(scope, path) && applies_type?(scope, type)
|
||||
end
|
||||
|
||||
sets.select do |set|
|
||||
unless valid?(set)
|
||||
Jekyll.logger.warn "Default:", "An invalid default set was found"
|
||||
end
|
||||
valid?(set)
|
||||
end
|
||||
end
|
||||
def applies_path?(scope, path)
|
||||
return true if !scope.has_key?('path') || scope['path'].empty?
|
||||
|
||||
# Sanitizes the given path by removing a leading and addding a trailing slash
|
||||
def sanitize_path(path)
|
||||
if path.nil? || path.empty?
|
||||
""
|
||||
else
|
||||
path.gsub(/\A\//, '').gsub(/([^\/])\z/, '\1/')
|
||||
scope_path = Pathname.new(scope['path'])
|
||||
Pathname.new(sanitize_path(path)).ascend do |path|
|
||||
if path.to_s == scope_path.to_s
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Determines whether the scope applies to type.
|
||||
# The scope applies to the type if:
|
||||
# 1. no 'type' is specified
|
||||
# 2. the 'type' in the scope is the same as the type asked about
|
||||
#
|
||||
# scope - the Hash defaults set being asked about application
|
||||
# type - the type of the document being processed / asked about
|
||||
# its defaults.
|
||||
#
|
||||
# Returns true if either of the above conditions are satisfied,
|
||||
# otherwise returns false
|
||||
def applies_type?(scope, type)
|
||||
!scope.key?('type') || scope['type'].eql?(type.to_s)
|
||||
end
|
||||
|
||||
# Checks if a given set of default values is valid
|
||||
#
|
||||
# set - the default value hash, as defined in _config.yml
|
||||
#
|
||||
# Returns true if the set is valid and can be used in this class
|
||||
def valid?(set)
|
||||
set.is_a?(Hash) && set['values'].is_a?(Hash)
|
||||
end
|
||||
|
||||
# Determines if a new scope has precedence over an old one
|
||||
#
|
||||
# old_scope - the old scope hash, or nil if there's none
|
||||
# new_scope - the new scope hash
|
||||
#
|
||||
# Returns true if the new scope has precedence over the older
|
||||
def has_precedence?(old_scope, new_scope)
|
||||
return true if old_scope.nil?
|
||||
|
||||
new_path = sanitize_path(new_scope['path'])
|
||||
old_path = sanitize_path(old_scope['path'])
|
||||
|
||||
if new_path.length != old_path.length
|
||||
new_path.length >= old_path.length
|
||||
elsif new_scope.key? 'type'
|
||||
true
|
||||
else
|
||||
!old_scope.key? 'type'
|
||||
end
|
||||
end
|
||||
|
||||
# Collects a list of sets that match the given path and type
|
||||
#
|
||||
# Returns an array of hashes
|
||||
def matching_sets(path, type)
|
||||
valid_sets.select do |set|
|
||||
!set.has_key?('scope') || applies?(set['scope'], path, type)
|
||||
end
|
||||
end
|
||||
|
||||
# Returns a list of valid sets
|
||||
#
|
||||
# This is not cached to allow plugins to modify the configuration
|
||||
# and have their changes take effect
|
||||
#
|
||||
# Returns an array of hashes
|
||||
def valid_sets
|
||||
sets = @site.config['defaults']
|
||||
return [] unless sets.is_a?(Array)
|
||||
|
||||
sets.map do |set|
|
||||
if valid?(set)
|
||||
update_deprecated_types(set)
|
||||
else
|
||||
Jekyll.logger.warn "Defaults:", "An invalid front-matter default set was found:"
|
||||
Jekyll.logger.warn "#{set}"
|
||||
nil
|
||||
end
|
||||
end.compact
|
||||
end
|
||||
|
||||
# Sanitizes the given path by removing a leading and adding a trailing slash
|
||||
def sanitize_path(path)
|
||||
if path.nil? || path.empty?
|
||||
""
|
||||
else
|
||||
path.gsub(/\A\//, '').gsub(/([^\/])\z/, '\1')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
101
lib/jekyll/hooks.rb
Normal file
101
lib/jekyll/hooks.rb
Normal file
@@ -0,0 +1,101 @@
|
||||
module Jekyll
|
||||
module Hooks
|
||||
DEFAULT_PRIORITY = 20
|
||||
|
||||
# compatibility layer for octopress-hooks users
|
||||
PRIORITY_MAP = {
|
||||
low: 10,
|
||||
normal: 20,
|
||||
high: 30,
|
||||
}.freeze
|
||||
|
||||
# initial empty hooks
|
||||
@registry = {
|
||||
:site => {
|
||||
after_reset: [],
|
||||
post_read: [],
|
||||
pre_render: [],
|
||||
post_render: [],
|
||||
post_write: [],
|
||||
},
|
||||
:pages => {
|
||||
post_init: [],
|
||||
pre_render: [],
|
||||
post_render: [],
|
||||
post_write: [],
|
||||
},
|
||||
:posts => {
|
||||
post_init: [],
|
||||
pre_render: [],
|
||||
post_render: [],
|
||||
post_write: [],
|
||||
},
|
||||
:documents => {
|
||||
post_init: [],
|
||||
pre_render: [],
|
||||
post_render: [],
|
||||
post_write: [],
|
||||
},
|
||||
}
|
||||
|
||||
# map of all hooks and their priorities
|
||||
@hook_priority = {}
|
||||
|
||||
NotAvailable = Class.new(RuntimeError)
|
||||
Uncallable = Class.new(RuntimeError)
|
||||
|
||||
# register hook(s) to be called later, public API
|
||||
def self.register(owners, event, priority: DEFAULT_PRIORITY, &block)
|
||||
Array(owners).each do |owner|
|
||||
register_one(owner, event, priority_value(priority), &block)
|
||||
end
|
||||
end
|
||||
|
||||
# Ensure the priority is a Fixnum
|
||||
def self.priority_value(priority)
|
||||
return priority if priority.is_a?(Fixnum)
|
||||
PRIORITY_MAP[priority] || DEFAULT_PRIORITY
|
||||
end
|
||||
|
||||
# register a single hook to be called later, internal API
|
||||
def self.register_one(owner, event, priority, &block)
|
||||
@registry[owner] ||={
|
||||
post_init: [],
|
||||
pre_render: [],
|
||||
post_render: [],
|
||||
post_write: [],
|
||||
}
|
||||
|
||||
unless @registry[owner][event]
|
||||
raise NotAvailable, "Invalid hook. #{owner} supports only the " <<
|
||||
"following hooks #{@registry[owner].keys.inspect}"
|
||||
end
|
||||
|
||||
unless block.respond_to? :call
|
||||
raise Uncallable, "Hooks must respond to :call"
|
||||
end
|
||||
|
||||
insert_hook owner, event, priority, &block
|
||||
end
|
||||
|
||||
def self.insert_hook(owner, event, priority, &block)
|
||||
@hook_priority[block] = "#{priority}.#{@hook_priority.size}".to_f
|
||||
@registry[owner][event] << block
|
||||
end
|
||||
|
||||
# interface for Jekyll core components to trigger hooks
|
||||
def self.trigger(owner, event, *args)
|
||||
# proceed only if there are hooks to call
|
||||
return unless @registry[owner]
|
||||
return unless @registry[owner][event]
|
||||
|
||||
# hooks to call for this owner and event
|
||||
hooks = @registry[owner][event]
|
||||
|
||||
# sort and call hooks according to priority and load order
|
||||
hooks.sort_by { |h| @hook_priority[h] }.each do |hook|
|
||||
hook.call(*args)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -8,6 +8,9 @@ module Jekyll
|
||||
# Gets the name of this layout.
|
||||
attr_reader :name
|
||||
|
||||
# Gets the path to this layout.
|
||||
attr_reader :path
|
||||
|
||||
# Gets/Sets the extension of this layout.
|
||||
attr_accessor :ext
|
||||
|
||||
@@ -26,6 +29,7 @@ module Jekyll
|
||||
@site = site
|
||||
@base = base
|
||||
@name = name
|
||||
@path = site.in_source_dir(base, name)
|
||||
|
||||
self.data = {}
|
||||
|
||||
|
||||
39
lib/jekyll/liquid_renderer.rb
Normal file
39
lib/jekyll/liquid_renderer.rb
Normal file
@@ -0,0 +1,39 @@
|
||||
require 'jekyll/liquid_renderer/file'
|
||||
require 'jekyll/liquid_renderer/table'
|
||||
|
||||
module Jekyll
|
||||
class LiquidRenderer
|
||||
def initialize(site)
|
||||
@site = site
|
||||
reset
|
||||
end
|
||||
|
||||
def reset
|
||||
@stats = {}
|
||||
end
|
||||
|
||||
def file(filename)
|
||||
filename = @site.in_source_dir(filename).sub(/\A#{Regexp.escape(@site.source)}\//, '')
|
||||
|
||||
LiquidRenderer::File.new(self, filename).tap do |file|
|
||||
@stats[filename] ||= {}
|
||||
@stats[filename][:count] ||= 0
|
||||
@stats[filename][:count] += 1
|
||||
end
|
||||
end
|
||||
|
||||
def increment_bytes(filename, bytes)
|
||||
@stats[filename][:bytes] ||= 0
|
||||
@stats[filename][:bytes] += bytes
|
||||
end
|
||||
|
||||
def increment_time(filename, time)
|
||||
@stats[filename][:time] ||= 0.0
|
||||
@stats[filename][:time] += time
|
||||
end
|
||||
|
||||
def stats_table(n = 50)
|
||||
LiquidRenderer::Table.new(@stats).to_s(n)
|
||||
end
|
||||
end
|
||||
end
|
||||
50
lib/jekyll/liquid_renderer/file.rb
Normal file
50
lib/jekyll/liquid_renderer/file.rb
Normal file
@@ -0,0 +1,50 @@
|
||||
module Jekyll
|
||||
class LiquidRenderer
|
||||
class File
|
||||
def initialize(renderer, filename)
|
||||
@renderer = renderer
|
||||
@filename = filename
|
||||
end
|
||||
|
||||
def parse(content)
|
||||
measure_time do
|
||||
@template = Liquid::Template.parse(content)
|
||||
end
|
||||
|
||||
self
|
||||
end
|
||||
|
||||
def render(*args)
|
||||
measure_time do
|
||||
measure_bytes do
|
||||
@template.render(*args)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def render!(*args)
|
||||
measure_time do
|
||||
measure_bytes do
|
||||
@template.render!(*args)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def measure_bytes
|
||||
yield.tap do |str|
|
||||
@renderer.increment_bytes(@filename, str.bytesize)
|
||||
end
|
||||
end
|
||||
|
||||
def measure_time
|
||||
before = Time.now
|
||||
yield
|
||||
ensure
|
||||
after = Time.now
|
||||
@renderer.increment_time(@filename, after - before)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
94
lib/jekyll/liquid_renderer/table.rb
Normal file
94
lib/jekyll/liquid_renderer/table.rb
Normal file
@@ -0,0 +1,94 @@
|
||||
module Jekyll
|
||||
class LiquidRenderer::Table
|
||||
def initialize(stats)
|
||||
@stats = stats
|
||||
end
|
||||
|
||||
def to_s(n = 50)
|
||||
data = data_for_table(n)
|
||||
widths = table_widths(data)
|
||||
generate_table(data, widths)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def generate_table(data, widths)
|
||||
str = "\n"
|
||||
|
||||
table_head = data.shift
|
||||
str << generate_row(table_head, widths)
|
||||
str << generate_table_head_border(table_head, widths)
|
||||
|
||||
data.each do |row_data|
|
||||
str << generate_row(row_data, widths)
|
||||
end
|
||||
|
||||
str << "\n"
|
||||
str
|
||||
end
|
||||
|
||||
def generate_table_head_border(row_data, widths)
|
||||
str = ""
|
||||
|
||||
row_data.each_index do |cell_index|
|
||||
str << '-' * widths[cell_index]
|
||||
str << '-+-' unless cell_index == row_data.length-1
|
||||
end
|
||||
|
||||
str << "\n"
|
||||
str
|
||||
end
|
||||
|
||||
def generate_row(row_data, widths)
|
||||
str = ''
|
||||
|
||||
row_data.each_with_index do |cell_data, cell_index|
|
||||
if cell_index == 0
|
||||
str << cell_data.ljust(widths[cell_index], ' ')
|
||||
else
|
||||
str << cell_data.rjust(widths[cell_index], ' ')
|
||||
end
|
||||
|
||||
str << ' | ' unless cell_index == row_data.length-1
|
||||
end
|
||||
|
||||
str << "\n"
|
||||
str
|
||||
end
|
||||
|
||||
def table_widths(data)
|
||||
widths = []
|
||||
|
||||
data.each do |row|
|
||||
row.each_with_index do |cell, index|
|
||||
widths[index] = [ cell.length, widths[index] ].compact.max
|
||||
end
|
||||
end
|
||||
|
||||
widths
|
||||
end
|
||||
|
||||
def data_for_table(n)
|
||||
sorted = @stats.sort_by{ |filename, file_stats| -file_stats[:time] }
|
||||
sorted = sorted.slice(0, n)
|
||||
|
||||
table = [[ 'Filename', 'Count', 'Bytes', 'Time' ]]
|
||||
|
||||
sorted.each do |filename, file_stats|
|
||||
row = []
|
||||
row << filename
|
||||
row << file_stats[:count].to_s
|
||||
row << format_bytes(file_stats[:bytes])
|
||||
row << "%.3f" % file_stats[:time]
|
||||
table << row
|
||||
end
|
||||
|
||||
table
|
||||
end
|
||||
|
||||
def format_bytes(bytes)
|
||||
bytes /= 1024.0
|
||||
"%.2fK" % bytes
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,6 +1,6 @@
|
||||
module Jekyll
|
||||
class LogAdapter
|
||||
attr_reader :writer
|
||||
attr_reader :writer, :messages
|
||||
|
||||
LOG_LEVELS = {
|
||||
:debug => ::Logger::DEBUG,
|
||||
@@ -9,13 +9,14 @@ module Jekyll
|
||||
:error => ::Logger::ERROR
|
||||
}
|
||||
|
||||
# Public: Create a new instance of Jekyll's log writer
|
||||
# Public: Create a new instance of a log writer
|
||||
#
|
||||
# writer - Logger compatible instance
|
||||
# log_level - (optional, symbol) the log level
|
||||
#
|
||||
# Returns nothing
|
||||
def initialize(writer, level = :info)
|
||||
@messages = []
|
||||
@writer = writer
|
||||
self.log_level = level
|
||||
end
|
||||
@@ -29,7 +30,17 @@ module Jekyll
|
||||
writer.level = LOG_LEVELS.fetch(level)
|
||||
end
|
||||
|
||||
# Public: Print a jekyll debug message
|
||||
def adjust_verbosity(options = {})
|
||||
# Quiet always wins.
|
||||
if options[:quiet]
|
||||
self.log_level = :error
|
||||
elsif options[:verbose]
|
||||
self.log_level = :debug
|
||||
end
|
||||
debug "Logging at level:", LOG_LEVELS.key(writer.level).to_s
|
||||
end
|
||||
|
||||
# Public: Print a debug message
|
||||
#
|
||||
# topic - the topic of the message, e.g. "Configuration file", "Deprecation", etc.
|
||||
# message - the message detail
|
||||
@@ -39,7 +50,7 @@ module Jekyll
|
||||
writer.debug(message(topic, message))
|
||||
end
|
||||
|
||||
# Public: Print a jekyll message
|
||||
# Public: Print a message
|
||||
#
|
||||
# topic - the topic of the message, e.g. "Configuration file", "Deprecation", etc.
|
||||
# message - the message detail
|
||||
@@ -49,7 +60,7 @@ module Jekyll
|
||||
writer.info(message(topic, message))
|
||||
end
|
||||
|
||||
# Public: Print a jekyll message
|
||||
# Public: Print a message
|
||||
#
|
||||
# topic - the topic of the message, e.g. "Configuration file", "Deprecation", etc.
|
||||
# message - the message detail
|
||||
@@ -59,7 +70,7 @@ module Jekyll
|
||||
writer.warn(message(topic, message))
|
||||
end
|
||||
|
||||
# Public: Print a jekyll error message
|
||||
# Public: Print an error message
|
||||
#
|
||||
# topic - the topic of the message, e.g. "Configuration file", "Deprecation", etc.
|
||||
# message - the message detail
|
||||
@@ -69,7 +80,7 @@ module Jekyll
|
||||
writer.error(message(topic, message))
|
||||
end
|
||||
|
||||
# Public: Print a Jekyll error message and immediately abort the process
|
||||
# Public: Print an error message and immediately abort the process
|
||||
#
|
||||
# topic - the topic of the message, e.g. "Configuration file", "Deprecation", etc.
|
||||
# message - the message detail (can be omitted)
|
||||
@@ -80,14 +91,16 @@ module Jekyll
|
||||
abort
|
||||
end
|
||||
|
||||
# Internal: Build a Jekyll topic method
|
||||
# Internal: Build a topic method
|
||||
#
|
||||
# topic - the topic of the message, e.g. "Configuration file", "Deprecation", etc.
|
||||
# message - the message detail
|
||||
#
|
||||
# Returns the formatted message
|
||||
def message(topic, message)
|
||||
formatted_topic(topic) + message.to_s.gsub(/\s+/, ' ')
|
||||
msg = formatted_topic(topic) + message.to_s.gsub(/\s+/, ' ')
|
||||
messages << msg
|
||||
msg
|
||||
end
|
||||
|
||||
# Internal: Format the topic
|
||||
|
||||
@@ -1,95 +1,800 @@
|
||||
-# These are the same MIME types that GitHub Pages uses as of 26 January 2014
|
||||
# Woah there. Do not edit this file directly.
|
||||
# This file is generated automatically by script/vendor-mimes.
|
||||
|
||||
text/html html htm shtml
|
||||
text/css css
|
||||
text/xml xml rss xsl xsd
|
||||
image/gif gif
|
||||
image/jpeg jpeg jpg
|
||||
application/x-javascript js
|
||||
application/atom+xml atom
|
||||
application/json json geojson topojson
|
||||
|
||||
text/mathml mml
|
||||
text/plain txt
|
||||
text/vnd.sun.j2me.app-descriptor jad
|
||||
text/vnd.wap.wml wml
|
||||
text/x-component htc
|
||||
text/cache-manifest manifest appcache
|
||||
text/coffeescript coffee
|
||||
text/plain pde
|
||||
text/plain md markdown
|
||||
text/vcard vcf vcard
|
||||
|
||||
image/png png
|
||||
image/svg+xml svg
|
||||
image/svg+xml svgz
|
||||
image/tiff tif tiff
|
||||
image/vnd.wap.wbmp wbmp
|
||||
image/x-icon ico
|
||||
image/x-jng jng
|
||||
image/x-ms-bmp bmp
|
||||
|
||||
application/vnd.ms-fontobject eot
|
||||
application/x-font-ttf ttf
|
||||
application/x-font-woff woff
|
||||
font/opentype otf
|
||||
|
||||
application/java-archive jar ear
|
||||
application/mac-binhex40 hqx
|
||||
application/msword doc
|
||||
application/pdf pdf
|
||||
application/postscript ps eps ai
|
||||
application/rdf+xml rdf
|
||||
application/rtf rtf
|
||||
application/vnd.apple.pkpass pkpass
|
||||
application/vnd.ms-excel xls
|
||||
application/vnd.ms-powerpoint ppt
|
||||
application/vnd.wap.wmlc wmlc
|
||||
application/xhtml+xml xhtml
|
||||
application/x-cocoa cco
|
||||
application/x-chrome-extension crx
|
||||
application/x-java-archive-diff jardiff
|
||||
application/x-java-jnlp-file jnlp
|
||||
application/x-makeself run
|
||||
application/x-ms-application application
|
||||
application/x-ms-manifest manifest
|
||||
application/x-ms-vsto vsto
|
||||
application/x-ns-proxy-autoconfig pac
|
||||
application/x-perl pl pm
|
||||
application/x-pilot prc pdb
|
||||
application/x-rar-compressed rar
|
||||
application/x-redhat-package-manager rpm
|
||||
application/x-sea sea
|
||||
application/x-shockwave-flash swf
|
||||
application/x-stuffit sit
|
||||
application/x-tcl tcl tk
|
||||
application/x-web-app-manifest+json webapp
|
||||
application/x-x509-ca-cert der pem crt
|
||||
application/x-xpinstall xpi
|
||||
application/x-zip war
|
||||
application/zip zip
|
||||
|
||||
application/octet-stream bin exe dll
|
||||
application/octet-stream deb
|
||||
application/octet-stream deploy
|
||||
application/octet-stream dmg
|
||||
application/octet-stream iso img
|
||||
application/octet-stream msi msp msm
|
||||
|
||||
audio/midi mid midi kar
|
||||
audio/mpeg mp3
|
||||
audio/x-realaudio ra
|
||||
audio/ogg ogg
|
||||
|
||||
video/3gpp 3gpp 3gp
|
||||
video/m4v m4v
|
||||
video/mp4 mp4
|
||||
video/mpeg mpeg mpg
|
||||
video/ogg ogg ogv
|
||||
video/quicktime mov
|
||||
video/webm webm
|
||||
video/x-flv flv
|
||||
video/x-mng mng
|
||||
video/x-ms-asf asx asf
|
||||
video/x-ms-wmv wmv
|
||||
video/x-msvideo avi
|
||||
application/andrew-inset ez
|
||||
application/applixware aw
|
||||
application/atom+xml atom
|
||||
application/atomcat+xml atomcat
|
||||
application/atomsvc+xml atomsvc
|
||||
application/bdoc bdoc
|
||||
application/ccxml+xml ccxml
|
||||
application/cdmi-capability cdmia
|
||||
application/cdmi-container cdmic
|
||||
application/cdmi-domain cdmid
|
||||
application/cdmi-object cdmio
|
||||
application/cdmi-queue cdmiq
|
||||
application/cu-seeme cu
|
||||
application/dash+xml mdp
|
||||
application/davmount+xml davmount
|
||||
application/docbook+xml dbk
|
||||
application/dssc+der dssc
|
||||
application/dssc+xml xdssc
|
||||
application/ecmascript ecma
|
||||
application/emma+xml emma
|
||||
application/epub+zip epub
|
||||
application/exi exi
|
||||
application/font-tdpfr pfr
|
||||
application/font-woff woff
|
||||
application/font-woff2 woff2
|
||||
application/gml+xml gml
|
||||
application/gpx+xml gpx
|
||||
application/gxf gxf
|
||||
application/hyperstudio stk
|
||||
application/inkml+xml ink inkml
|
||||
application/ipfix ipfix
|
||||
application/java-archive jar war ear
|
||||
application/java-serialized-object ser
|
||||
application/java-vm class
|
||||
application/javascript js
|
||||
application/json json map
|
||||
application/json5 json5
|
||||
application/jsonml+json jsonml
|
||||
application/ld+json jsonld
|
||||
application/lost+xml lostxml
|
||||
application/mac-binhex40 hqx
|
||||
application/mac-compactpro cpt
|
||||
application/mads+xml mads
|
||||
application/manifest+json webmanifest
|
||||
application/marc mrc
|
||||
application/marcxml+xml mrcx
|
||||
application/mathematica ma nb mb
|
||||
application/mathml+xml mathml
|
||||
application/mbox mbox
|
||||
application/mediaservercontrol+xml mscml
|
||||
application/metalink+xml metalink
|
||||
application/metalink4+xml meta4
|
||||
application/mets+xml mets
|
||||
application/mods+xml mods
|
||||
application/mp21 m21 mp21
|
||||
application/mp4 mp4s m4p
|
||||
application/msword doc dot
|
||||
application/mxf mxf
|
||||
application/octet-stream bin dms lrf mar so dist distz pkg bpk dump elc deploy exe dll deb dmg iso img msi msp msm buffer
|
||||
application/oda oda
|
||||
application/oebps-package+xml opf
|
||||
application/ogg ogx
|
||||
application/omdoc+xml omdoc
|
||||
application/onenote onetoc onetoc2 onetmp onepkg
|
||||
application/oxps oxps
|
||||
application/patch-ops-error+xml xer
|
||||
application/pdf pdf
|
||||
application/pgp-encrypted pgp
|
||||
application/pgp-signature asc sig
|
||||
application/pics-rules prf
|
||||
application/pkcs10 p10
|
||||
application/pkcs7-mime p7m p7c
|
||||
application/pkcs7-signature p7s
|
||||
application/pkcs8 p8
|
||||
application/pkix-attr-cert ac
|
||||
application/pkix-cert cer
|
||||
application/pkix-crl crl
|
||||
application/pkix-pkipath pkipath
|
||||
application/pkixcmp pki
|
||||
application/pls+xml pls
|
||||
application/postscript ai eps ps
|
||||
application/prs.cww cww
|
||||
application/pskc+xml pskcxml
|
||||
application/rdf+xml rdf
|
||||
application/reginfo+xml rif
|
||||
application/relax-ng-compact-syntax rnc
|
||||
application/resource-lists+xml rl
|
||||
application/resource-lists-diff+xml rld
|
||||
application/rls-services+xml rs
|
||||
application/rpki-ghostbusters gbr
|
||||
application/rpki-manifest mft
|
||||
application/rpki-roa roa
|
||||
application/rsd+xml rsd
|
||||
application/rss+xml rss
|
||||
application/rtf rtf
|
||||
application/sbml+xml sbml
|
||||
application/scvp-cv-request scq
|
||||
application/scvp-cv-response scs
|
||||
application/scvp-vp-request spq
|
||||
application/scvp-vp-response spp
|
||||
application/sdp sdp
|
||||
application/set-payment-initiation setpay
|
||||
application/set-registration-initiation setreg
|
||||
application/shf+xml shf
|
||||
application/smil+xml smi smil
|
||||
application/sparql-query rq
|
||||
application/sparql-results+xml srx
|
||||
application/srgs gram
|
||||
application/srgs+xml grxml
|
||||
application/sru+xml sru
|
||||
application/ssdl+xml ssdl
|
||||
application/ssml+xml ssml
|
||||
application/tei+xml tei teicorpus
|
||||
application/thraud+xml tfi
|
||||
application/timestamped-data tsd
|
||||
application/vnd.3gpp.pic-bw-large plb
|
||||
application/vnd.3gpp.pic-bw-small psb
|
||||
application/vnd.3gpp.pic-bw-var pvb
|
||||
application/vnd.3gpp2.tcap tcap
|
||||
application/vnd.3m.post-it-notes pwn
|
||||
application/vnd.accpac.simply.aso aso
|
||||
application/vnd.accpac.simply.imp imp
|
||||
application/vnd.acucobol acu
|
||||
application/vnd.acucorp atc acutc
|
||||
application/vnd.adobe.air-application-installer-package+zip air
|
||||
application/vnd.adobe.formscentral.fcdt fcdt
|
||||
application/vnd.adobe.fxp fxp fxpl
|
||||
application/vnd.adobe.xdp+xml xdp
|
||||
application/vnd.adobe.xfdf xfdf
|
||||
application/vnd.ahead.space ahead
|
||||
application/vnd.airzip.filesecure.azf azf
|
||||
application/vnd.airzip.filesecure.azs azs
|
||||
application/vnd.amazon.ebook azw
|
||||
application/vnd.americandynamics.acc acc
|
||||
application/vnd.amiga.ami ami
|
||||
application/vnd.android.package-archive apk
|
||||
application/vnd.anser-web-certificate-issue-initiation cii
|
||||
application/vnd.anser-web-funds-transfer-initiation fti
|
||||
application/vnd.antix.game-component atx
|
||||
application/vnd.apple.installer+xml mpkg
|
||||
application/vnd.apple.mpegurl m3u8
|
||||
application/vnd.aristanetworks.swi swi
|
||||
application/vnd.astraea-software.iota iota
|
||||
application/vnd.audiograph aep
|
||||
application/vnd.blueice.multipass mpm
|
||||
application/vnd.bmi bmi
|
||||
application/vnd.businessobjects rep
|
||||
application/vnd.chemdraw+xml cdxml
|
||||
application/vnd.chipnuts.karaoke-mmd mmd
|
||||
application/vnd.cinderella cdy
|
||||
application/vnd.claymore cla
|
||||
application/vnd.cloanto.rp9 rp9
|
||||
application/vnd.clonk.c4group c4g c4d c4f c4p c4u
|
||||
application/vnd.cluetrust.cartomobile-config c11amc
|
||||
application/vnd.cluetrust.cartomobile-config-pkg c11amz
|
||||
application/vnd.commonspace csp
|
||||
application/vnd.contact.cmsg cdbcmsg
|
||||
application/vnd.cosmocaller cmc
|
||||
application/vnd.crick.clicker clkx
|
||||
application/vnd.crick.clicker.keyboard clkk
|
||||
application/vnd.crick.clicker.palette clkp
|
||||
application/vnd.crick.clicker.template clkt
|
||||
application/vnd.crick.clicker.wordbank clkw
|
||||
application/vnd.criticaltools.wbs+xml wbs
|
||||
application/vnd.ctc-posml pml
|
||||
application/vnd.cups-ppd ppd
|
||||
application/vnd.curl.car car
|
||||
application/vnd.curl.pcurl pcurl
|
||||
application/vnd.dart dart
|
||||
application/vnd.data-vision.rdz rdz
|
||||
application/vnd.dece.data uvf uvvf uvd uvvd
|
||||
application/vnd.dece.ttml+xml uvt uvvt
|
||||
application/vnd.dece.unspecified uvx uvvx
|
||||
application/vnd.dece.zip uvz uvvz
|
||||
application/vnd.denovo.fcselayout-link fe_launch
|
||||
application/vnd.dna dna
|
||||
application/vnd.dolby.mlp mlp
|
||||
application/vnd.dpgraph dpg
|
||||
application/vnd.dreamfactory dfac
|
||||
application/vnd.ds-keypoint kpxx
|
||||
application/vnd.dvb.ait ait
|
||||
application/vnd.dvb.service svc
|
||||
application/vnd.dynageo geo
|
||||
application/vnd.ecowin.chart mag
|
||||
application/vnd.enliven nml
|
||||
application/vnd.epson.esf esf
|
||||
application/vnd.epson.msf msf
|
||||
application/vnd.epson.quickanime qam
|
||||
application/vnd.epson.salt slt
|
||||
application/vnd.epson.ssf ssf
|
||||
application/vnd.eszigno3+xml es3 et3
|
||||
application/vnd.ezpix-album ez2
|
||||
application/vnd.ezpix-package ez3
|
||||
application/vnd.fdf fdf
|
||||
application/vnd.fdsn.mseed mseed
|
||||
application/vnd.fdsn.seed seed dataless
|
||||
application/vnd.flographit gph
|
||||
application/vnd.fluxtime.clip ftc
|
||||
application/vnd.framemaker fm frame maker book
|
||||
application/vnd.frogans.fnc fnc
|
||||
application/vnd.frogans.ltf ltf
|
||||
application/vnd.fsc.weblaunch fsc
|
||||
application/vnd.fujitsu.oasys oas
|
||||
application/vnd.fujitsu.oasys2 oa2
|
||||
application/vnd.fujitsu.oasys3 oa3
|
||||
application/vnd.fujitsu.oasysgp fg5
|
||||
application/vnd.fujitsu.oasysprs bh2
|
||||
application/vnd.fujixerox.ddd ddd
|
||||
application/vnd.fujixerox.docuworks xdw
|
||||
application/vnd.fujixerox.docuworks.binder xbd
|
||||
application/vnd.fuzzysheet fzs
|
||||
application/vnd.genomatix.tuxedo txd
|
||||
application/vnd.geogebra.file ggb
|
||||
application/vnd.geogebra.tool ggt
|
||||
application/vnd.geometry-explorer gex gre
|
||||
application/vnd.geonext gxt
|
||||
application/vnd.geoplan g2w
|
||||
application/vnd.geospace g3w
|
||||
application/vnd.gmx gmx
|
||||
application/vnd.google-earth.kml+xml kml
|
||||
application/vnd.google-earth.kmz kmz
|
||||
application/vnd.grafeq gqf gqs
|
||||
application/vnd.groove-account gac
|
||||
application/vnd.groove-help ghf
|
||||
application/vnd.groove-identity-message gim
|
||||
application/vnd.groove-injector grv
|
||||
application/vnd.groove-tool-message gtm
|
||||
application/vnd.groove-tool-template tpl
|
||||
application/vnd.groove-vcard vcg
|
||||
application/vnd.hal+xml hal
|
||||
application/vnd.handheld-entertainment+xml zmm
|
||||
application/vnd.hbci hbci
|
||||
application/vnd.hhe.lesson-player les
|
||||
application/vnd.hp-hpgl hpgl
|
||||
application/vnd.hp-hpid hpid
|
||||
application/vnd.hp-hps hps
|
||||
application/vnd.hp-jlyt jlt
|
||||
application/vnd.hp-pcl pcl
|
||||
application/vnd.hp-pclxl pclxl
|
||||
application/vnd.hydrostatix.sof-data sfd-hdstx
|
||||
application/vnd.ibm.minipay mpy
|
||||
application/vnd.ibm.modcap afp listafp list3820
|
||||
application/vnd.ibm.rights-management irm
|
||||
application/vnd.ibm.secure-container sc
|
||||
application/vnd.iccprofile icc icm
|
||||
application/vnd.igloader igl
|
||||
application/vnd.immervision-ivp ivp
|
||||
application/vnd.immervision-ivu ivu
|
||||
application/vnd.insors.igm igm
|
||||
application/vnd.intercon.formnet xpw xpx
|
||||
application/vnd.intergeo i2g
|
||||
application/vnd.intu.qbo qbo
|
||||
application/vnd.intu.qfx qfx
|
||||
application/vnd.ipunplugged.rcprofile rcprofile
|
||||
application/vnd.irepository.package+xml irp
|
||||
application/vnd.is-xpr xpr
|
||||
application/vnd.isac.fcs fcs
|
||||
application/vnd.jam jam
|
||||
application/vnd.jcp.javame.midlet-rms rms
|
||||
application/vnd.jisp jisp
|
||||
application/vnd.joost.joda-archive joda
|
||||
application/vnd.kahootz ktz ktr
|
||||
application/vnd.kde.karbon karbon
|
||||
application/vnd.kde.kchart chrt
|
||||
application/vnd.kde.kformula kfo
|
||||
application/vnd.kde.kivio flw
|
||||
application/vnd.kde.kontour kon
|
||||
application/vnd.kde.kpresenter kpr kpt
|
||||
application/vnd.kde.kspread ksp
|
||||
application/vnd.kde.kword kwd kwt
|
||||
application/vnd.kenameaapp htke
|
||||
application/vnd.kidspiration kia
|
||||
application/vnd.kinar kne knp
|
||||
application/vnd.koan skp skd skt skm
|
||||
application/vnd.kodak-descriptor sse
|
||||
application/vnd.las.las+xml lasxml
|
||||
application/vnd.llamagraphics.life-balance.desktop lbd
|
||||
application/vnd.llamagraphics.life-balance.exchange+xml lbe
|
||||
application/vnd.lotus-1-2-3 123
|
||||
application/vnd.lotus-approach apr
|
||||
application/vnd.lotus-freelance pre
|
||||
application/vnd.lotus-notes nsf
|
||||
application/vnd.lotus-organizer org
|
||||
application/vnd.lotus-screencam scm
|
||||
application/vnd.lotus-wordpro lwp
|
||||
application/vnd.macports.portpkg portpkg
|
||||
application/vnd.mcd mcd
|
||||
application/vnd.medcalcdata mc1
|
||||
application/vnd.mediastation.cdkey cdkey
|
||||
application/vnd.mfer mwf
|
||||
application/vnd.mfmp mfm
|
||||
application/vnd.micrografx.flo flo
|
||||
application/vnd.micrografx.igx igx
|
||||
application/vnd.mif mif
|
||||
application/vnd.mobius.daf daf
|
||||
application/vnd.mobius.dis dis
|
||||
application/vnd.mobius.mbk mbk
|
||||
application/vnd.mobius.mqy mqy
|
||||
application/vnd.mobius.msl msl
|
||||
application/vnd.mobius.plc plc
|
||||
application/vnd.mobius.txf txf
|
||||
application/vnd.mophun.application mpn
|
||||
application/vnd.mophun.certificate mpc
|
||||
application/vnd.mozilla.xul+xml xul
|
||||
application/vnd.ms-artgalry cil
|
||||
application/vnd.ms-cab-compressed cab
|
||||
application/vnd.ms-excel xls xlm xla xlc xlt xlw
|
||||
application/vnd.ms-excel.addin.macroenabled.12 xlam
|
||||
application/vnd.ms-excel.sheet.binary.macroenabled.12 xlsb
|
||||
application/vnd.ms-excel.sheet.macroenabled.12 xlsm
|
||||
application/vnd.ms-excel.template.macroenabled.12 xltm
|
||||
application/vnd.ms-fontobject eot
|
||||
application/vnd.ms-htmlhelp chm
|
||||
application/vnd.ms-ims ims
|
||||
application/vnd.ms-lrm lrm
|
||||
application/vnd.ms-officetheme thmx
|
||||
application/vnd.ms-pki.seccat cat
|
||||
application/vnd.ms-pki.stl stl
|
||||
application/vnd.ms-powerpoint ppt pps pot
|
||||
application/vnd.ms-powerpoint.addin.macroenabled.12 ppam
|
||||
application/vnd.ms-powerpoint.presentation.macroenabled.12 pptm
|
||||
application/vnd.ms-powerpoint.slide.macroenabled.12 sldm
|
||||
application/vnd.ms-powerpoint.slideshow.macroenabled.12 ppsm
|
||||
application/vnd.ms-powerpoint.template.macroenabled.12 potm
|
||||
application/vnd.ms-project mpp mpt
|
||||
application/vnd.ms-word.document.macroenabled.12 docm
|
||||
application/vnd.ms-word.template.macroenabled.12 dotm
|
||||
application/vnd.ms-works wps wks wcm wdb
|
||||
application/vnd.ms-wpl wpl
|
||||
application/vnd.ms-xpsdocument xps
|
||||
application/vnd.mseq mseq
|
||||
application/vnd.musician mus
|
||||
application/vnd.muvee.style msty
|
||||
application/vnd.mynfc taglet
|
||||
application/vnd.neurolanguage.nlu nlu
|
||||
application/vnd.nitf ntf nitf
|
||||
application/vnd.noblenet-directory nnd
|
||||
application/vnd.noblenet-sealer nns
|
||||
application/vnd.noblenet-web nnw
|
||||
application/vnd.nokia.n-gage.data ngdat
|
||||
application/vnd.nokia.n-gage.symbian.install n-gage
|
||||
application/vnd.nokia.radio-preset rpst
|
||||
application/vnd.nokia.radio-presets rpss
|
||||
application/vnd.novadigm.edm edm
|
||||
application/vnd.novadigm.edx edx
|
||||
application/vnd.novadigm.ext ext
|
||||
application/vnd.oasis.opendocument.chart odc
|
||||
application/vnd.oasis.opendocument.chart-template otc
|
||||
application/vnd.oasis.opendocument.database odb
|
||||
application/vnd.oasis.opendocument.formula odf
|
||||
application/vnd.oasis.opendocument.formula-template odft
|
||||
application/vnd.oasis.opendocument.graphics odg
|
||||
application/vnd.oasis.opendocument.graphics-template otg
|
||||
application/vnd.oasis.opendocument.image odi
|
||||
application/vnd.oasis.opendocument.image-template oti
|
||||
application/vnd.oasis.opendocument.presentation odp
|
||||
application/vnd.oasis.opendocument.presentation-template otp
|
||||
application/vnd.oasis.opendocument.spreadsheet ods
|
||||
application/vnd.oasis.opendocument.spreadsheet-template ots
|
||||
application/vnd.oasis.opendocument.text odt
|
||||
application/vnd.oasis.opendocument.text-master odm
|
||||
application/vnd.oasis.opendocument.text-template ott
|
||||
application/vnd.oasis.opendocument.text-web oth
|
||||
application/vnd.olpc-sugar xo
|
||||
application/vnd.oma.dd2+xml dd2
|
||||
application/vnd.openofficeorg.extension oxt
|
||||
application/vnd.openxmlformats-officedocument.presentationml.presentation pptx
|
||||
application/vnd.openxmlformats-officedocument.presentationml.slide sldx
|
||||
application/vnd.openxmlformats-officedocument.presentationml.slideshow ppsx
|
||||
application/vnd.openxmlformats-officedocument.presentationml.template potx
|
||||
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx
|
||||
application/vnd.openxmlformats-officedocument.spreadsheetml.template xltx
|
||||
application/vnd.openxmlformats-officedocument.wordprocessingml.document docx
|
||||
application/vnd.openxmlformats-officedocument.wordprocessingml.template dotx
|
||||
application/vnd.osgeo.mapguide.package mgp
|
||||
application/vnd.osgi.dp dp
|
||||
application/vnd.osgi.subsystem esa
|
||||
application/vnd.palm pdb pqa oprc
|
||||
application/vnd.pawaafile paw
|
||||
application/vnd.pg.format str
|
||||
application/vnd.pg.osasli ei6
|
||||
application/vnd.picsel efif
|
||||
application/vnd.pmi.widget wg
|
||||
application/vnd.pocketlearn plf
|
||||
application/vnd.powerbuilder6 pbd
|
||||
application/vnd.previewsystems.box box
|
||||
application/vnd.proteus.magazine mgz
|
||||
application/vnd.publishare-delta-tree qps
|
||||
application/vnd.pvi.ptid1 ptid
|
||||
application/vnd.quark.quarkxpress qxd qxt qwd qwt qxl qxb
|
||||
application/vnd.realvnc.bed bed
|
||||
application/vnd.recordare.musicxml mxl
|
||||
application/vnd.recordare.musicxml+xml musicxml
|
||||
application/vnd.rig.cryptonote cryptonote
|
||||
application/vnd.rim.cod cod
|
||||
application/vnd.rn-realmedia rm
|
||||
application/vnd.rn-realmedia-vbr rmvb
|
||||
application/vnd.route66.link66+xml link66
|
||||
application/vnd.sailingtracker.track st
|
||||
application/vnd.seemail see
|
||||
application/vnd.sema sema
|
||||
application/vnd.semd semd
|
||||
application/vnd.semf semf
|
||||
application/vnd.shana.informed.formdata ifm
|
||||
application/vnd.shana.informed.formtemplate itp
|
||||
application/vnd.shana.informed.interchange iif
|
||||
application/vnd.shana.informed.package ipk
|
||||
application/vnd.simtech-mindmapper twd twds
|
||||
application/vnd.smaf mmf
|
||||
application/vnd.smart.teacher teacher
|
||||
application/vnd.solent.sdkm+xml sdkm sdkd
|
||||
application/vnd.spotfire.dxp dxp
|
||||
application/vnd.spotfire.sfs sfs
|
||||
application/vnd.stardivision.calc sdc
|
||||
application/vnd.stardivision.draw sda
|
||||
application/vnd.stardivision.impress sdd
|
||||
application/vnd.stardivision.math smf
|
||||
application/vnd.stardivision.writer sdw vor
|
||||
application/vnd.stardivision.writer-global sgl
|
||||
application/vnd.stepmania.package smzip
|
||||
application/vnd.stepmania.stepchart sm
|
||||
application/vnd.sun.xml.calc sxc
|
||||
application/vnd.sun.xml.calc.template stc
|
||||
application/vnd.sun.xml.draw sxd
|
||||
application/vnd.sun.xml.draw.template std
|
||||
application/vnd.sun.xml.impress sxi
|
||||
application/vnd.sun.xml.impress.template sti
|
||||
application/vnd.sun.xml.math sxm
|
||||
application/vnd.sun.xml.writer sxw
|
||||
application/vnd.sun.xml.writer.global sxg
|
||||
application/vnd.sun.xml.writer.template stw
|
||||
application/vnd.sus-calendar sus susp
|
||||
application/vnd.svd svd
|
||||
application/vnd.symbian.install sis sisx
|
||||
application/vnd.syncml+xml xsm
|
||||
application/vnd.syncml.dm+wbxml bdm
|
||||
application/vnd.syncml.dm+xml xdm
|
||||
application/vnd.tao.intent-module-archive tao
|
||||
application/vnd.tcpdump.pcap pcap cap dmp
|
||||
application/vnd.tmobile-livetv tmo
|
||||
application/vnd.trid.tpt tpt
|
||||
application/vnd.triscape.mxs mxs
|
||||
application/vnd.trueapp tra
|
||||
application/vnd.ufdl ufd ufdl
|
||||
application/vnd.uiq.theme utz
|
||||
application/vnd.umajin umj
|
||||
application/vnd.unity unityweb
|
||||
application/vnd.uoml+xml uoml
|
||||
application/vnd.vcx vcx
|
||||
application/vnd.visio vsd vst vss vsw
|
||||
application/vnd.visionary vis
|
||||
application/vnd.vsf vsf
|
||||
application/vnd.wap.wbxml wbxml
|
||||
application/vnd.wap.wmlc wmlc
|
||||
application/vnd.wap.wmlscriptc wmlsc
|
||||
application/vnd.webturbo wtb
|
||||
application/vnd.wolfram.player nbp
|
||||
application/vnd.wordperfect wpd
|
||||
application/vnd.wqd wqd
|
||||
application/vnd.wt.stf stf
|
||||
application/vnd.xara xar
|
||||
application/vnd.xfdl xfdl
|
||||
application/vnd.yamaha.hv-dic hvd
|
||||
application/vnd.yamaha.hv-script hvs
|
||||
application/vnd.yamaha.hv-voice hvp
|
||||
application/vnd.yamaha.openscoreformat osf
|
||||
application/vnd.yamaha.openscoreformat.osfpvg+xml osfpvg
|
||||
application/vnd.yamaha.smaf-audio saf
|
||||
application/vnd.yamaha.smaf-phrase spf
|
||||
application/vnd.yellowriver-custom-menu cmp
|
||||
application/vnd.zul zir zirz
|
||||
application/vnd.zzazz.deck+xml zaz
|
||||
application/voicexml+xml vxml
|
||||
application/widget wgt
|
||||
application/winhlp hlp
|
||||
application/wsdl+xml wsdl
|
||||
application/wspolicy+xml wspolicy
|
||||
application/x-7z-compressed 7z
|
||||
application/x-abiword abw
|
||||
application/x-ace-compressed ace
|
||||
application/x-authorware-bin aab x32 u32 vox
|
||||
application/x-authorware-map aam
|
||||
application/x-authorware-seg aas
|
||||
application/x-bcpio bcpio
|
||||
application/x-bittorrent torrent
|
||||
application/x-blorb blb blorb
|
||||
application/x-bzip bz
|
||||
application/x-bzip2 bz2 boz
|
||||
application/x-cbr cbr cba cbt cbz cb7
|
||||
application/x-cdlink vcd
|
||||
application/x-cfs-compressed cfs
|
||||
application/x-chat chat
|
||||
application/x-chess-pgn pgn
|
||||
application/x-chrome-extension crx
|
||||
application/x-cocoa cco
|
||||
application/x-conference nsc
|
||||
application/x-cpio cpio
|
||||
application/x-csh csh
|
||||
application/x-debian-package udeb
|
||||
application/x-dgc-compressed dgc
|
||||
application/x-director dir dcr dxr cst cct cxt w3d fgd swa
|
||||
application/x-doom wad
|
||||
application/x-dtbncx+xml ncx
|
||||
application/x-dtbook+xml dtb
|
||||
application/x-dtbresource+xml res
|
||||
application/x-dvi dvi
|
||||
application/x-envoy evy
|
||||
application/x-eva eva
|
||||
application/x-font-bdf bdf
|
||||
application/x-font-ghostscript gsf
|
||||
application/x-font-linux-psf psf
|
||||
application/x-font-otf otf
|
||||
application/x-font-pcf pcf
|
||||
application/x-font-snf snf
|
||||
application/x-font-ttf ttf ttc
|
||||
application/x-font-type1 pfa pfb pfm afm
|
||||
application/x-freearc arc
|
||||
application/x-futuresplash spl
|
||||
application/x-gca-compressed gca
|
||||
application/x-glulx ulx
|
||||
application/x-gnumeric gnumeric
|
||||
application/x-gramps-xml gramps
|
||||
application/x-gtar gtar
|
||||
application/x-hdf hdf
|
||||
application/x-httpd-php php
|
||||
application/x-install-instructions install
|
||||
application/x-java-archive-diff jardiff
|
||||
application/x-java-jnlp-file jnlp
|
||||
application/x-latex latex
|
||||
application/x-lua-bytecode luac
|
||||
application/x-lzh-compressed lzh lha
|
||||
application/x-makeself run
|
||||
application/x-mie mie
|
||||
application/x-mobipocket-ebook prc mobi
|
||||
application/x-ms-application application
|
||||
application/x-ms-shortcut lnk
|
||||
application/x-ms-wmd wmd
|
||||
application/x-ms-wmz wmz
|
||||
application/x-ms-xbap xbap
|
||||
application/x-msaccess mdb
|
||||
application/x-msbinder obd
|
||||
application/x-mscardfile crd
|
||||
application/x-msclip clp
|
||||
application/x-msdownload com bat
|
||||
application/x-msmediaview mvb m13 m14
|
||||
application/x-msmetafile wmf emf emz
|
||||
application/x-msmoney mny
|
||||
application/x-mspublisher pub
|
||||
application/x-msschedule scd
|
||||
application/x-msterminal trm
|
||||
application/x-mswrite wri
|
||||
application/x-netcdf nc cdf
|
||||
application/x-ns-proxy-autoconfig pac
|
||||
application/x-nzb nzb
|
||||
application/x-perl pl pm
|
||||
application/x-pkcs12 p12 pfx
|
||||
application/x-pkcs7-certificates p7b spc
|
||||
application/x-pkcs7-certreqresp p7r
|
||||
application/x-rar-compressed rar
|
||||
application/x-redhat-package-manager rpm
|
||||
application/x-research-info-systems ris
|
||||
application/x-sea sea
|
||||
application/x-sh sh
|
||||
application/x-shar shar
|
||||
application/x-shockwave-flash swf
|
||||
application/x-silverlight-app xap
|
||||
application/x-sql sql
|
||||
application/x-stuffit sit
|
||||
application/x-stuffitx sitx
|
||||
application/x-subrip srt
|
||||
application/x-sv4cpio sv4cpio
|
||||
application/x-sv4crc sv4crc
|
||||
application/x-t3vm-image t3
|
||||
application/x-tads gam
|
||||
application/x-tar tar
|
||||
application/x-tcl tcl tk
|
||||
application/x-tex tex
|
||||
application/x-tex-tfm tfm
|
||||
application/x-texinfo texinfo texi
|
||||
application/x-tgif obj
|
||||
application/x-ustar ustar
|
||||
application/x-wais-source src
|
||||
application/x-web-app-manifest+json webapp
|
||||
application/x-x509-ca-cert der crt pem
|
||||
application/x-xfig fig
|
||||
application/x-xliff+xml xlf
|
||||
application/x-xpinstall xpi
|
||||
application/x-xz xz
|
||||
application/x-zmachine z1 z2 z3 z4 z5 z6 z7 z8
|
||||
application/xaml+xml xaml
|
||||
application/xcap-diff+xml xdf
|
||||
application/xenc+xml xenc
|
||||
application/xhtml+xml xhtml xht
|
||||
application/xml xml xsl xsd
|
||||
application/xml-dtd dtd
|
||||
application/xop+xml xop
|
||||
application/xproc+xml xpl
|
||||
application/xslt+xml xslt
|
||||
application/xspf+xml xspf
|
||||
application/xv+xml mxml xhvml xvml xvm
|
||||
application/yang yang
|
||||
application/yin+xml yin
|
||||
application/zip zip
|
||||
audio/adpcm adp
|
||||
audio/basic au snd
|
||||
audio/midi mid midi kar rmi
|
||||
audio/mp4 mp4a m4a
|
||||
audio/mpeg mpga mp2 mp2a mp3 m2a m3a
|
||||
audio/ogg oga ogg spx
|
||||
audio/s3m s3m
|
||||
audio/silk sil
|
||||
audio/vnd.dece.audio uva uvva
|
||||
audio/vnd.digital-winds eol
|
||||
audio/vnd.dra dra
|
||||
audio/vnd.dts dts
|
||||
audio/vnd.dts.hd dtshd
|
||||
audio/vnd.lucent.voice lvp
|
||||
audio/vnd.ms-playready.media.pya pya
|
||||
audio/vnd.nuera.ecelp4800 ecelp4800
|
||||
audio/vnd.nuera.ecelp7470 ecelp7470
|
||||
audio/vnd.nuera.ecelp9600 ecelp9600
|
||||
audio/vnd.rip rip
|
||||
audio/wav wav
|
||||
audio/webm weba
|
||||
audio/x-aac aac
|
||||
audio/x-aiff aif aiff aifc
|
||||
audio/x-caf caf
|
||||
audio/x-flac flac
|
||||
audio/x-matroska mka
|
||||
audio/x-mpegurl m3u
|
||||
audio/x-ms-wax wax
|
||||
audio/x-ms-wma wma
|
||||
audio/x-pn-realaudio ram ra
|
||||
audio/x-pn-realaudio-plugin rmp
|
||||
audio/xm xm
|
||||
chemical/x-cdx cdx
|
||||
chemical/x-cif cif
|
||||
chemical/x-cmdf cmdf
|
||||
chemical/x-cml cml
|
||||
chemical/x-csml csml
|
||||
chemical/x-xyz xyz
|
||||
image/bmp bmp
|
||||
image/cgm cgm
|
||||
image/g3fax g3
|
||||
image/gif gif
|
||||
image/ief ief
|
||||
image/jpeg jpeg jpg jpe
|
||||
image/ktx ktx
|
||||
image/png png
|
||||
image/prs.btif btif
|
||||
image/sgi sgi
|
||||
image/svg+xml svg svgz
|
||||
image/tiff tiff tif
|
||||
image/vnd.adobe.photoshop psd
|
||||
image/vnd.dece.graphic uvi uvvi uvg uvvg
|
||||
image/vnd.djvu djvu djv
|
||||
image/vnd.dvb.subtitle sub
|
||||
image/vnd.dwg dwg
|
||||
image/vnd.dxf dxf
|
||||
image/vnd.fastbidsheet fbs
|
||||
image/vnd.fpx fpx
|
||||
image/vnd.fst fst
|
||||
image/vnd.fujixerox.edmics-mmr mmr
|
||||
image/vnd.fujixerox.edmics-rlc rlc
|
||||
image/vnd.ms-modi mdi
|
||||
image/vnd.ms-photo wdp
|
||||
image/vnd.net-fpx npx
|
||||
image/vnd.wap.wbmp wbmp
|
||||
image/vnd.xiff xif
|
||||
image/webp webp
|
||||
image/x-3ds 3ds
|
||||
image/x-cmu-raster ras
|
||||
image/x-cmx cmx
|
||||
image/x-freehand fh fhc fh4 fh5 fh7
|
||||
image/x-icon ico
|
||||
image/x-jng jng
|
||||
image/x-mrsid-image sid
|
||||
image/x-pcx pcx
|
||||
image/x-pict pic pct
|
||||
image/x-portable-anymap pnm
|
||||
image/x-portable-bitmap pbm
|
||||
image/x-portable-graymap pgm
|
||||
image/x-portable-pixmap ppm
|
||||
image/x-rgb rgb
|
||||
image/x-tga tga
|
||||
image/x-xbitmap xbm
|
||||
image/x-xpixmap xpm
|
||||
image/x-xwindowdump xwd
|
||||
message/rfc822 eml mime
|
||||
model/iges igs iges
|
||||
model/mesh msh mesh silo
|
||||
model/vnd.collada+xml dae
|
||||
model/vnd.dwf dwf
|
||||
model/vnd.gdl gdl
|
||||
model/vnd.gtw gtw
|
||||
model/vnd.mts mts
|
||||
model/vnd.vtu vtu
|
||||
model/vrml wrl vrml
|
||||
model/x3d+binary x3db x3dbz
|
||||
model/x3d+vrml x3dv x3dvz
|
||||
model/x3d+xml x3d x3dz
|
||||
text/cache-manifest appcache manifest
|
||||
text/calendar ics ifb
|
||||
text/coffeescript coffee litcoffee
|
||||
text/css css
|
||||
text/csv csv
|
||||
text/hjson hjson
|
||||
text/html html htm shtml
|
||||
text/jade jade
|
||||
text/jsx jsx
|
||||
text/less less
|
||||
text/mathml mml
|
||||
text/n3 n3
|
||||
text/plain txt text conf def list log in ini
|
||||
text/prs.lines.tag dsc
|
||||
text/richtext rtx
|
||||
text/sgml sgml sgm
|
||||
text/stylus stylus styl
|
||||
text/tab-separated-values tsv
|
||||
text/troff t tr roff man me ms
|
||||
text/turtle ttl
|
||||
text/uri-list uri uris urls
|
||||
text/vcard vcard
|
||||
text/vnd.curl curl
|
||||
text/vnd.curl.dcurl dcurl
|
||||
text/vnd.curl.mcurl mcurl
|
||||
text/vnd.curl.scurl scurl
|
||||
text/vnd.fly fly
|
||||
text/vnd.fmi.flexstor flx
|
||||
text/vnd.graphviz gv
|
||||
text/vnd.in3d.3dml 3dml
|
||||
text/vnd.in3d.spot spot
|
||||
text/vnd.sun.j2me.app-descriptor jad
|
||||
text/vnd.wap.wml wml
|
||||
text/vnd.wap.wmlscript wmls
|
||||
text/vtt vtt
|
||||
text/x-asm s asm
|
||||
text/x-c c cc cxx cpp h hh dic
|
||||
text/x-component htc
|
||||
text/x-fortran f for f77 f90
|
||||
text/x-handlebars-template hbs
|
||||
text/x-java-source java
|
||||
text/x-lua lua
|
||||
text/x-markdown markdown md mkd
|
||||
text/x-nfo nfo
|
||||
text/x-opml opml
|
||||
text/x-pascal p pas
|
||||
text/x-processing pde
|
||||
text/x-sass sass
|
||||
text/x-scss scss
|
||||
text/x-setext etx
|
||||
text/x-sfv sfv
|
||||
text/x-uuencode uu
|
||||
text/x-vcalendar vcs
|
||||
text/x-vcard vcf
|
||||
text/yaml yaml yml
|
||||
video/3gpp 3gp 3gpp
|
||||
video/3gpp2 3g2
|
||||
video/h261 h261
|
||||
video/h263 h263
|
||||
video/h264 h264
|
||||
video/jpeg jpgv
|
||||
video/jpm jpm jpgm
|
||||
video/mj2 mj2 mjp2
|
||||
video/mp2t ts
|
||||
video/mp4 mp4 mp4v mpg4
|
||||
video/mpeg mpeg mpg mpe m1v m2v
|
||||
video/ogg ogv
|
||||
video/quicktime qt mov
|
||||
video/vnd.dece.hd uvh uvvh
|
||||
video/vnd.dece.mobile uvm uvvm
|
||||
video/vnd.dece.pd uvp uvvp
|
||||
video/vnd.dece.sd uvs uvvs
|
||||
video/vnd.dece.video uvv uvvv
|
||||
video/vnd.dvb.file dvb
|
||||
video/vnd.fvt fvt
|
||||
video/vnd.mpegurl mxu m4u
|
||||
video/vnd.ms-playready.media.pyv pyv
|
||||
video/vnd.uvvu.mp4 uvu uvvu
|
||||
video/vnd.vivo viv
|
||||
video/webm webm
|
||||
video/x-f4v f4v
|
||||
video/x-fli fli
|
||||
video/x-flv flv
|
||||
video/x-m4v m4v
|
||||
video/x-matroska mkv mk3d mks
|
||||
video/x-mng mng
|
||||
video/x-ms-asf asf asx
|
||||
video/x-ms-vob vob
|
||||
video/x-ms-wm wm
|
||||
video/x-ms-wmv wmv
|
||||
video/x-ms-wmx wmx
|
||||
video/x-ms-wvx wvx
|
||||
video/x-msvideo avi
|
||||
video/x-sgi-movie movie
|
||||
video/x-smv smv
|
||||
x-conference/x-cooltalk ice
|
||||
@@ -35,6 +35,8 @@ module Jekyll
|
||||
data.default_proc = proc do |hash, key|
|
||||
site.frontmatter_defaults.find(File.join(dir, name), type, key)
|
||||
end
|
||||
|
||||
Jekyll::Hooks.trigger :pages, :post_init, self
|
||||
end
|
||||
|
||||
# The generated directory into which the page will be placed
|
||||
@@ -52,27 +54,19 @@ module Jekyll
|
||||
# Returns the String permalink or nil if none has been set.
|
||||
def permalink
|
||||
return nil if data.nil? || data['permalink'].nil?
|
||||
if site.config['relative_permalinks']
|
||||
File.join(@dir, data['permalink'])
|
||||
else
|
||||
data['permalink']
|
||||
end
|
||||
data['permalink']
|
||||
end
|
||||
|
||||
# The template of the permalink.
|
||||
#
|
||||
# Returns the template String.
|
||||
def template
|
||||
if site.permalink_style == :pretty
|
||||
if index? && html?
|
||||
"/:path/"
|
||||
elsif html?
|
||||
"/:path/:basename/"
|
||||
else
|
||||
"/:path/:basename:output_ext"
|
||||
end
|
||||
else
|
||||
if !html?
|
||||
"/:path/:basename:output_ext"
|
||||
elsif index?
|
||||
"/:path/"
|
||||
else
|
||||
Utils.add_permalink_suffix("/:path/:basename", site.permalink_style)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -126,7 +120,7 @@ module Jekyll
|
||||
#
|
||||
# Returns the path to the source file
|
||||
def path
|
||||
data.fetch('path', relative_path.sub(/\A\//, ''))
|
||||
data.fetch('path') { relative_path.sub(/\A\//, '') }
|
||||
end
|
||||
|
||||
# The path to the page source file, relative to the site source
|
||||
@@ -140,8 +134,9 @@ module Jekyll
|
||||
#
|
||||
# Returns the destination file path String.
|
||||
def destination(dest)
|
||||
path = Jekyll.sanitized_path(dest, URL.unescape_path(url))
|
||||
path = File.join(path, "index.html") if url =~ /\/$/
|
||||
path = site.in_dest_dir(dest, URL.unescape_path(url))
|
||||
path = File.join(path, "index.html") if url.end_with?("/")
|
||||
path << output_ext unless path.end_with?(output_ext)
|
||||
path
|
||||
end
|
||||
|
||||
@@ -159,9 +154,5 @@ module Jekyll
|
||||
def index?
|
||||
basename == 'index'
|
||||
end
|
||||
|
||||
def uses_relative_permalinks
|
||||
permalink && !@dir.empty? && site.config['relative_permalinks']
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -27,7 +27,7 @@ module Jekyll
|
||||
# Returns the Symbol priority.
|
||||
def self.priority(priority = nil)
|
||||
@priority ||= nil
|
||||
if priority && PRIORITIES.has_key?(priority)
|
||||
if priority && PRIORITIES.key?(priority)
|
||||
@priority = priority
|
||||
end
|
||||
@priority || :normal
|
||||
@@ -56,6 +56,15 @@ module Jekyll
|
||||
PRIORITIES[other.priority] <=> PRIORITIES[self.priority]
|
||||
end
|
||||
|
||||
# Spaceship is priority [higher -> lower]
|
||||
#
|
||||
# other - The class to be compared.
|
||||
#
|
||||
# Returns -1, 0, 1.
|
||||
def <=>(other)
|
||||
self.class <=> other.class
|
||||
end
|
||||
|
||||
# Initialize a new plugin. This should be overridden by the subclass.
|
||||
#
|
||||
# config - The Hash of configuration options.
|
||||
|
||||
@@ -17,6 +17,7 @@ module Jekyll
|
||||
def conscientious_require
|
||||
require_plugin_files
|
||||
require_gems
|
||||
deprecation_checks
|
||||
end
|
||||
|
||||
# Require each of the gem plugins specified.
|
||||
@@ -25,11 +26,27 @@ module Jekyll
|
||||
def require_gems
|
||||
site.gems.each do |gem|
|
||||
if plugin_allowed?(gem)
|
||||
Jekyll.logger.debug("PluginManager:", "Requiring #{gem}")
|
||||
require gem
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.require_from_bundler
|
||||
if !ENV["JEKYLL_NO_BUNDLER_REQUIRE"] && File.file?("Gemfile")
|
||||
require "bundler"
|
||||
Bundler.setup # puts all groups on the load path
|
||||
required_gems = Bundler.require(:jekyll_plugins) # requires the gems in this group only
|
||||
Jekyll.logger.debug("PluginManager:", "Required #{required_gems.map(&:name).join(', ')}")
|
||||
ENV["JEKYLL_NO_BUNDLER_REQUIRE"] = "true"
|
||||
true
|
||||
else
|
||||
false
|
||||
end
|
||||
rescue LoadError, Bundler::GemfileNotFound
|
||||
false
|
||||
end
|
||||
|
||||
# Check whether a gem plugin is allowed to be used during this build.
|
||||
#
|
||||
# gem_name - the name of the gem
|
||||
@@ -65,10 +82,19 @@ module Jekyll
|
||||
#
|
||||
# Returns an Array of plugin search paths
|
||||
def plugins_path
|
||||
if (site.config['plugins'] == Jekyll::Configuration::DEFAULTS['plugins'])
|
||||
[Jekyll.sanitized_path(site.source, site.config['plugins'])]
|
||||
if (site.config['plugins_dir'] == Jekyll::Configuration::DEFAULTS['plugins_dir'])
|
||||
[site.in_source_dir(site.config['plugins_dir'])]
|
||||
else
|
||||
Array(site.config['plugins']).map { |d| File.expand_path(d) }
|
||||
Array(site.config['plugins_dir']).map { |d| File.expand_path(d) }
|
||||
end
|
||||
end
|
||||
|
||||
def deprecation_checks
|
||||
pagination_included = (site.config['gems'] || []).include?('jekyll-paginate') || defined?(Jekyll::Paginate)
|
||||
if site.config['paginate'] && !pagination_included
|
||||
Jekyll::Deprecator.deprecation_message "You appear to have pagination " +
|
||||
"turned on, but you haven't included the `jekyll-paginate` gem. " +
|
||||
"Ensure you have `gems: [jekyll-paginate]` in your configuration file."
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,317 +0,0 @@
|
||||
module Jekyll
|
||||
class Post
|
||||
include Comparable
|
||||
include Convertible
|
||||
|
||||
# Valid post name regex.
|
||||
MATCHER = /^(.+\/)*(\d+-\d+-\d+)-(.*)(\.[^.]+)$/
|
||||
|
||||
EXCERPT_ATTRIBUTES_FOR_LIQUID = %w[
|
||||
title
|
||||
url
|
||||
dir
|
||||
date
|
||||
id
|
||||
categories
|
||||
next
|
||||
previous
|
||||
tags
|
||||
path
|
||||
]
|
||||
|
||||
# Attributes for Liquid templates
|
||||
ATTRIBUTES_FOR_LIQUID = EXCERPT_ATTRIBUTES_FOR_LIQUID + %w[
|
||||
content
|
||||
excerpt
|
||||
]
|
||||
|
||||
# Post name validator. Post filenames must be like:
|
||||
# 2008-11-05-my-awesome-post.textile
|
||||
#
|
||||
# Returns true if valid, false if not.
|
||||
def self.valid?(name)
|
||||
name =~ MATCHER
|
||||
end
|
||||
|
||||
attr_accessor :site
|
||||
attr_accessor :data, :extracted_excerpt, :content, :output, :ext
|
||||
attr_accessor :date, :slug, :tags, :categories
|
||||
|
||||
attr_reader :name
|
||||
|
||||
# Initialize this Post instance.
|
||||
#
|
||||
# site - The Site.
|
||||
# base - The String path to the dir containing the post file.
|
||||
# name - The String filename of the post file.
|
||||
#
|
||||
# Returns the new Post.
|
||||
def initialize(site, source, dir, name)
|
||||
@site = site
|
||||
@dir = dir
|
||||
@base = containing_dir(source, dir)
|
||||
@name = name
|
||||
|
||||
self.categories = dir.downcase.split('/').reject { |x| x.empty? }
|
||||
process(name)
|
||||
read_yaml(@base, name)
|
||||
|
||||
data.default_proc = proc do |hash, key|
|
||||
site.frontmatter_defaults.find(File.join(dir, name), type, key)
|
||||
end
|
||||
|
||||
if data.has_key?('date')
|
||||
self.date = Time.parse(data["date"].to_s)
|
||||
end
|
||||
|
||||
populate_categories
|
||||
populate_tags
|
||||
end
|
||||
|
||||
def published?
|
||||
if data.has_key?('published') && data['published'] == false
|
||||
false
|
||||
else
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
def populate_categories
|
||||
categories_from_data = Utils.pluralized_array_from_hash(data, 'category', 'categories')
|
||||
self.categories = (Array(categories) + categories_from_data).map {|c| c.to_s.downcase}
|
||||
categories.flatten!
|
||||
end
|
||||
|
||||
def populate_tags
|
||||
self.tags = Utils.pluralized_array_from_hash(data, "tag", "tags").flatten
|
||||
end
|
||||
|
||||
# Get the full path to the directory containing the post files
|
||||
def containing_dir(source, dir)
|
||||
return File.join(source, dir, '_posts')
|
||||
end
|
||||
|
||||
# Read the YAML frontmatter.
|
||||
#
|
||||
# base - The String path to the dir containing the file.
|
||||
# name - The String filename of the file.
|
||||
#
|
||||
# Returns nothing.
|
||||
def read_yaml(base, name)
|
||||
super(base, name)
|
||||
self.extracted_excerpt = extract_excerpt
|
||||
end
|
||||
|
||||
# The post excerpt. This is either a custom excerpt
|
||||
# set in YAML front matter or the result of extract_excerpt.
|
||||
#
|
||||
# Returns excerpt string.
|
||||
def excerpt
|
||||
data.fetch('excerpt', extracted_excerpt.to_s)
|
||||
end
|
||||
|
||||
# Public: the Post title, from the YAML Front-Matter or from the slug
|
||||
#
|
||||
# Returns the post title
|
||||
def title
|
||||
data.fetch("title", titleized_slug)
|
||||
end
|
||||
|
||||
# Turns the post slug into a suitable title
|
||||
def titleized_slug
|
||||
slug.split('-').select {|w| w.capitalize! || w }.join(' ')
|
||||
end
|
||||
|
||||
# Public: the path to the post relative to the site source,
|
||||
# from the YAML Front-Matter or from a combination of
|
||||
# the directory it's in, "_posts", and the name of the
|
||||
# post file
|
||||
#
|
||||
# Returns the path to the file relative to the site source
|
||||
def path
|
||||
data.fetch('path', relative_path.sub(/\A\//, ''))
|
||||
end
|
||||
|
||||
# The path to the post source file, relative to the site source
|
||||
def relative_path
|
||||
File.join(*[@dir, "_posts", @name].map(&:to_s).reject(&:empty?))
|
||||
end
|
||||
|
||||
# Compares Post objects. First compares the Post date. If the dates are
|
||||
# equal, it compares the Post slugs.
|
||||
#
|
||||
# other - The other Post we are comparing to.
|
||||
#
|
||||
# Returns -1, 0, 1
|
||||
def <=>(other)
|
||||
cmp = self.date <=> other.date
|
||||
if 0 == cmp
|
||||
cmp = self.slug <=> other.slug
|
||||
end
|
||||
return cmp
|
||||
end
|
||||
|
||||
# Extract information from the post filename.
|
||||
#
|
||||
# name - The String filename of the post file.
|
||||
#
|
||||
# Returns nothing.
|
||||
def process(name)
|
||||
m, cats, date, slug, ext = *name.match(MATCHER)
|
||||
self.date = Time.parse(date)
|
||||
self.slug = slug
|
||||
self.ext = ext
|
||||
rescue ArgumentError
|
||||
path = File.join(@dir || "", name)
|
||||
msg = "Post '#{path}' does not have a valid date.\n"
|
||||
msg << "Fix the date, or exclude the file or directory from being processed"
|
||||
raise FatalException.new(msg)
|
||||
end
|
||||
|
||||
# The generated directory into which the post will be placed
|
||||
# upon generation. This is derived from the permalink or, if
|
||||
# permalink is absent, set to the default date
|
||||
# e.g. "/2008/11/05/" if the permalink style is :date, otherwise nothing.
|
||||
#
|
||||
# Returns the String directory.
|
||||
def dir
|
||||
File.dirname(url)
|
||||
end
|
||||
|
||||
# The full path and filename of the post. Defined in the YAML of the post
|
||||
# body (optional).
|
||||
#
|
||||
# Returns the String permalink.
|
||||
def permalink
|
||||
data && data['permalink']
|
||||
end
|
||||
|
||||
def template
|
||||
case site.permalink_style
|
||||
when :pretty
|
||||
"/:categories/:year/:month/:day/:title/"
|
||||
when :none
|
||||
"/:categories/:title.html"
|
||||
when :date
|
||||
"/:categories/:year/:month/:day/:title.html"
|
||||
when :ordinal
|
||||
"/:categories/:year/:y_day/:title.html"
|
||||
else
|
||||
site.permalink_style.to_s
|
||||
end
|
||||
end
|
||||
|
||||
# The generated relative url of this post.
|
||||
#
|
||||
# Returns the String url.
|
||||
def url
|
||||
@url ||= URL.new({
|
||||
:template => template,
|
||||
:placeholders => url_placeholders,
|
||||
:permalink => permalink
|
||||
}).to_s
|
||||
end
|
||||
|
||||
# Returns a hash of URL placeholder names (as symbols) mapping to the
|
||||
# desired placeholder replacements. For details see "url.rb"
|
||||
def url_placeholders
|
||||
{
|
||||
:year => date.strftime("%Y"),
|
||||
:month => date.strftime("%m"),
|
||||
:day => date.strftime("%d"),
|
||||
:title => slug,
|
||||
:i_day => date.strftime("%d").to_i.to_s,
|
||||
:i_month => date.strftime("%m").to_i.to_s,
|
||||
:categories => (categories || []).map { |c| c.to_s }.join('/'),
|
||||
:short_month => date.strftime("%b"),
|
||||
:short_year => date.strftime("%y"),
|
||||
:y_day => date.strftime("%j"),
|
||||
:output_ext => output_ext
|
||||
}
|
||||
end
|
||||
|
||||
# The UID for this post (useful in feeds).
|
||||
# e.g. /2008/11/05/my-awesome-post
|
||||
#
|
||||
# Returns the String UID.
|
||||
def id
|
||||
File.join(dir, slug)
|
||||
end
|
||||
|
||||
# Calculate related posts.
|
||||
#
|
||||
# Returns an Array of related Posts.
|
||||
def related_posts(posts)
|
||||
Jekyll::RelatedPosts.new(self).build
|
||||
end
|
||||
|
||||
# Add any necessary layouts to this post.
|
||||
#
|
||||
# layouts - A Hash of {"name" => "layout"}.
|
||||
# site_payload - The site payload hash.
|
||||
#
|
||||
# Returns nothing.
|
||||
def render(layouts, site_payload)
|
||||
# construct payload
|
||||
payload = Utils.deep_merge_hashes({
|
||||
"site" => { "related_posts" => related_posts(site_payload["site"]["posts"]) },
|
||||
"page" => to_liquid(self.class::EXCERPT_ATTRIBUTES_FOR_LIQUID)
|
||||
}, site_payload)
|
||||
|
||||
if generate_excerpt?
|
||||
extracted_excerpt.do_layout(payload, {})
|
||||
end
|
||||
|
||||
do_layout(payload.merge({"page" => to_liquid}), layouts)
|
||||
end
|
||||
|
||||
# Obtain destination path.
|
||||
#
|
||||
# dest - The String path to the destination dir.
|
||||
#
|
||||
# Returns destination file path String.
|
||||
def destination(dest)
|
||||
# The url needs to be unescaped in order to preserve the correct filename
|
||||
path = Jekyll.sanitized_path(dest, URL.unescape_path(url))
|
||||
path = File.join(path, "index.html") if path[/\.html$/].nil?
|
||||
path
|
||||
end
|
||||
|
||||
# Returns the shorthand String identifier of this Post.
|
||||
def inspect
|
||||
"<Post: #{id}>"
|
||||
end
|
||||
|
||||
def next
|
||||
pos = site.posts.index {|post| post.equal?(self) }
|
||||
if pos && pos < site.posts.length - 1
|
||||
site.posts[pos + 1]
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def previous
|
||||
pos = site.posts.index {|post| post.equal?(self) }
|
||||
if pos && pos > 0
|
||||
site.posts[pos - 1]
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def extract_excerpt
|
||||
if generate_excerpt?
|
||||
Jekyll::Excerpt.new(self)
|
||||
else
|
||||
""
|
||||
end
|
||||
end
|
||||
|
||||
def generate_excerpt?
|
||||
!(site.config['excerpt_separator'].to_s.empty?)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -15,7 +15,7 @@ module Jekyll
|
||||
end
|
||||
|
||||
def hidden_in_the_future?(thing)
|
||||
thing.is_a?(Post) && !@site.future && thing.date > @site.time
|
||||
thing.respond_to?(:date) && !@site.future && thing.date.to_i > @site.time.to_i
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
126
lib/jekyll/reader.rb
Normal file
126
lib/jekyll/reader.rb
Normal file
@@ -0,0 +1,126 @@
|
||||
# encoding: UTF-8
|
||||
require 'csv'
|
||||
|
||||
module Jekyll
|
||||
class Reader
|
||||
attr_reader :site
|
||||
|
||||
def initialize(site)
|
||||
@site = site
|
||||
end
|
||||
|
||||
# Read Site data from disk and load it into internal data structures.
|
||||
#
|
||||
# Returns nothing.
|
||||
def read
|
||||
@site.layouts = LayoutReader.new(site).read
|
||||
read_directories
|
||||
sort_files!
|
||||
@site.data = DataReader.new(site).read(site.config['data_dir'])
|
||||
CollectionReader.new(site).read
|
||||
end
|
||||
|
||||
# Sorts posts, pages, and static files.
|
||||
def sort_files!
|
||||
site.collections.values.each{|c| c.docs.sort!}
|
||||
site.pages.sort_by!(&:name)
|
||||
site.static_files.sort_by!(&:relative_path)
|
||||
end
|
||||
|
||||
# Recursively traverse directories to find pages and static files
|
||||
# that will become part of the site according to the rules in
|
||||
# filter_entries.
|
||||
#
|
||||
# dir - The String relative path of the directory to read. Default: ''.
|
||||
#
|
||||
# Returns nothing.
|
||||
def read_directories(dir = '')
|
||||
base = site.in_source_dir(dir)
|
||||
|
||||
dot = Dir.chdir(base) { filter_entries(Dir.entries('.'), base) }
|
||||
dot_dirs = dot.select{ |file| File.directory?(@site.in_source_dir(base,file)) }
|
||||
dot_files = (dot - dot_dirs)
|
||||
dot_pages = dot_files.select{ |file| Utils.has_yaml_header?(@site.in_source_dir(base,file)) }
|
||||
dot_static_files = dot_files - dot_pages
|
||||
|
||||
retrieve_posts(dir)
|
||||
retrieve_dirs(base, dir, dot_dirs)
|
||||
retrieve_pages(dir, dot_pages)
|
||||
retrieve_static_files(dir, dot_static_files)
|
||||
end
|
||||
|
||||
# Retrieves all the posts(posts/drafts) from the given directory
|
||||
# and add them to the site and sort them.
|
||||
#
|
||||
# dir - The String representing the directory to retrieve the posts from.
|
||||
#
|
||||
# Returns nothing.
|
||||
def retrieve_posts(dir)
|
||||
site.posts.docs.concat(PostReader.new(site).read_posts(dir))
|
||||
site.posts.docs.concat(PostReader.new(site).read_drafts(dir)) if site.show_drafts
|
||||
end
|
||||
|
||||
# Recursively traverse directories with the read_directories function.
|
||||
#
|
||||
# base - The String representing the site's base directory.
|
||||
# dir - The String representing the directory to traverse down.
|
||||
# dot_dirs - The Array of subdirectories in the dir.
|
||||
#
|
||||
# Returns nothing.
|
||||
def retrieve_dirs(base, dir, dot_dirs)
|
||||
dot_dirs.map { |file|
|
||||
dir_path = site.in_source_dir(dir,file)
|
||||
rel_path = File.join(dir, file)
|
||||
@site.reader.read_directories(rel_path) unless @site.dest.sub(/\/$/, '') == dir_path
|
||||
}
|
||||
end
|
||||
|
||||
# Retrieve all the pages from the current directory,
|
||||
# add them to the site and sort them.
|
||||
#
|
||||
# dir - The String representing the directory retrieve the pages from.
|
||||
# dot_pages - The Array of pages in the dir.
|
||||
#
|
||||
# Returns nothing.
|
||||
def retrieve_pages(dir, dot_pages)
|
||||
site.pages.concat(PageReader.new(site, dir).read(dot_pages))
|
||||
end
|
||||
|
||||
# Retrieve all the static files from the current directory,
|
||||
# add them to the site and sort them.
|
||||
#
|
||||
# dir - The directory retrieve the static files from.
|
||||
# dot_static_files - The static files in the dir.
|
||||
#
|
||||
# Returns nothing.
|
||||
def retrieve_static_files(dir, dot_static_files)
|
||||
site.static_files.concat(StaticFileReader.new(site, dir).read(dot_static_files))
|
||||
end
|
||||
|
||||
# Filter out any files/directories that are hidden or backup files (start
|
||||
# with "." or "#" or end with "~"), or contain site content (start with "_"),
|
||||
# or are excluded in the site configuration, unless they are web server
|
||||
# files such as '.htaccess'.
|
||||
#
|
||||
# entries - The Array of String file/directory entries to filter.
|
||||
# base_directory - The string representing the optional base directory.
|
||||
#
|
||||
# Returns the Array of filtered entries.
|
||||
def filter_entries(entries, base_directory = nil)
|
||||
EntryFilter.new(site, base_directory).filter(entries)
|
||||
end
|
||||
|
||||
# Read the entries from a particular directory for processing
|
||||
#
|
||||
# dir - The String representing the relative path of the directory to read.
|
||||
# subfolder - The String representing the directory to read.
|
||||
#
|
||||
# Returns the list of entries to process
|
||||
def get_entries(dir, subfolder)
|
||||
base = site.in_source_dir(dir, subfolder)
|
||||
return [] unless File.exist?(base)
|
||||
entries = Dir.chdir(base) { filter_entries(Dir['**/*'], base) }
|
||||
entries.delete_if { |e| File.directory?(site.in_source_dir(base, e)) }
|
||||
end
|
||||
end
|
||||
end
|
||||
21
lib/jekyll/readers/collection_reader.rb
Normal file
21
lib/jekyll/readers/collection_reader.rb
Normal file
@@ -0,0 +1,21 @@
|
||||
module Jekyll
|
||||
class CollectionReader
|
||||
SPECIAL_COLLECTIONS = %w{posts data}.freeze
|
||||
|
||||
attr_reader :site, :content
|
||||
def initialize(site)
|
||||
@site = site
|
||||
@content = {}
|
||||
end
|
||||
|
||||
# Read in all collections specified in the configuration
|
||||
#
|
||||
# Returns nothing.
|
||||
def read
|
||||
site.collections.each do |_, collection|
|
||||
collection.read unless SPECIAL_COLLECTIONS.include?(collection.label)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
69
lib/jekyll/readers/data_reader.rb
Normal file
69
lib/jekyll/readers/data_reader.rb
Normal file
@@ -0,0 +1,69 @@
|
||||
module Jekyll
|
||||
class DataReader
|
||||
attr_reader :site, :content
|
||||
def initialize(site)
|
||||
@site = site
|
||||
@content = {}
|
||||
end
|
||||
|
||||
# Read all the files in <source>/<dir>/_drafts and create a new Draft
|
||||
# object with each one.
|
||||
#
|
||||
# dir - The String relative path of the directory to read.
|
||||
#
|
||||
# Returns nothing.
|
||||
def read(dir)
|
||||
base = site.in_source_dir(dir)
|
||||
read_data_to(base, @content)
|
||||
@content
|
||||
end
|
||||
|
||||
# Read and parse all yaml files under <dir> and add them to the
|
||||
# <data> variable.
|
||||
#
|
||||
# dir - The string absolute path of the directory to read.
|
||||
# data - The variable to which data will be added.
|
||||
#
|
||||
# Returns nothing
|
||||
def read_data_to(dir, data)
|
||||
return unless File.directory?(dir) && (!site.safe || !File.symlink?(dir))
|
||||
|
||||
entries = Dir.chdir(dir) do
|
||||
Dir['*.{yaml,yml,json,csv}'] + Dir['*'].select { |fn| File.directory?(fn) }
|
||||
end
|
||||
|
||||
entries.each do |entry|
|
||||
path = @site.in_source_dir(dir, entry)
|
||||
next if File.symlink?(path) && site.safe
|
||||
|
||||
key = sanitize_filename(File.basename(entry, '.*'))
|
||||
if File.directory?(path)
|
||||
read_data_to(path, data[key] = {})
|
||||
else
|
||||
data[key] = read_data_file(path)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Determines how to read a data file.
|
||||
#
|
||||
# Returns the contents of the data file.
|
||||
def read_data_file(path)
|
||||
case File.extname(path).downcase
|
||||
when '.csv'
|
||||
CSV.read(path, {
|
||||
:headers => true,
|
||||
:encoding => site.config['encoding']
|
||||
}).map(&:to_hash)
|
||||
else
|
||||
SafeYAML.load_file(path)
|
||||
end
|
||||
end
|
||||
|
||||
def sanitize_filename(name)
|
||||
name.gsub!(/[^\w\s-]+/, '')
|
||||
name.gsub!(/(^|\b\s)\s+($|\s?\b)/, '\\1\\2')
|
||||
name.gsub(/\s+/, '_')
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -38,12 +38,12 @@ module Jekyll
|
||||
end
|
||||
|
||||
def layout_directory_inside_source
|
||||
Jekyll.sanitized_path(site.source, site.config['layouts'])
|
||||
site.in_source_dir(site.config['layouts_dir'])
|
||||
end
|
||||
|
||||
def layout_directory_in_cwd
|
||||
dir = Jekyll.sanitized_path(Dir.pwd, site.config['layouts'])
|
||||
if File.directory?(dir)
|
||||
dir = Jekyll.sanitized_path(Dir.pwd, site.config['layouts_dir'])
|
||||
if File.directory?(dir) && !site.safe
|
||||
dir
|
||||
else
|
||||
nil
|
||||
21
lib/jekyll/readers/page_reader.rb
Normal file
21
lib/jekyll/readers/page_reader.rb
Normal file
@@ -0,0 +1,21 @@
|
||||
module Jekyll
|
||||
class PageReader
|
||||
attr_reader :site, :dir, :unfiltered_content
|
||||
def initialize(site, dir)
|
||||
@site = site
|
||||
@dir = dir
|
||||
@unfiltered_content = Array.new
|
||||
end
|
||||
|
||||
# Read all the files in <source>/<dir>/ for Yaml header and create a new Page
|
||||
# object for each file.
|
||||
#
|
||||
# dir - The String relative path of the directory to read.
|
||||
#
|
||||
# Returns an array of static pages.
|
||||
def read(files)
|
||||
files.map{ |page| @unfiltered_content << Page.new(@site, @site.source, @dir, page) }
|
||||
@unfiltered_content.select{ |page| site.publisher.publish?(page) }
|
||||
end
|
||||
end
|
||||
end
|
||||
62
lib/jekyll/readers/post_reader.rb
Normal file
62
lib/jekyll/readers/post_reader.rb
Normal file
@@ -0,0 +1,62 @@
|
||||
module Jekyll
|
||||
class PostReader
|
||||
attr_reader :site, :unfiltered_content
|
||||
def initialize(site)
|
||||
@site = site
|
||||
end
|
||||
|
||||
# Read all the files in <source>/<dir>/_drafts and create a new
|
||||
# Document object with each one.
|
||||
#
|
||||
# dir - The String relative path of the directory to read.
|
||||
#
|
||||
# Returns nothing.
|
||||
def read_drafts(dir)
|
||||
read_publishable(dir, '_drafts', Document::DATELESS_FILENAME_MATCHER)
|
||||
end
|
||||
|
||||
# Read all the files in <source>/<dir>/_posts and create a new Document
|
||||
# object with each one.
|
||||
#
|
||||
# dir - The String relative path of the directory to read.
|
||||
#
|
||||
# Returns nothing.
|
||||
def read_posts(dir)
|
||||
read_publishable(dir, '_posts', Document::DATE_FILENAME_MATCHER)
|
||||
end
|
||||
|
||||
# Read all the files in <source>/<dir>/<magic_dir> and create a new
|
||||
# Document object with each one insofar as it matches the regexp matcher.
|
||||
#
|
||||
# dir - The String relative path of the directory to read.
|
||||
#
|
||||
# Returns nothing.
|
||||
def read_publishable(dir, magic_dir, matcher)
|
||||
read_content(dir, magic_dir, matcher).tap do |docs|
|
||||
docs.each(&:read)
|
||||
end.select do |doc|
|
||||
site.publisher.publish?(doc)
|
||||
end
|
||||
end
|
||||
|
||||
# Read all the content files from <source>/<dir>/magic_dir
|
||||
# and return them with the type klass.
|
||||
#
|
||||
# dir - The String relative path of the directory to read.
|
||||
# magic_dir - The String relative directory to <dir>,
|
||||
# looks for content here.
|
||||
# klass - The return type of the content.
|
||||
#
|
||||
# Returns klass type of content files
|
||||
def read_content(dir, magic_dir, matcher)
|
||||
@site.reader.get_entries(dir, magic_dir).map do |entry|
|
||||
next unless entry =~ matcher
|
||||
path = @site.in_source_dir(File.join(dir, magic_dir, entry))
|
||||
Document.new(path, {
|
||||
site: @site,
|
||||
collection: @site.posts
|
||||
})
|
||||
end.reject(&:nil?)
|
||||
end
|
||||
end
|
||||
end
|
||||
21
lib/jekyll/readers/static_file_reader.rb
Normal file
21
lib/jekyll/readers/static_file_reader.rb
Normal file
@@ -0,0 +1,21 @@
|
||||
module Jekyll
|
||||
class StaticFileReader
|
||||
attr_reader :site, :dir, :unfiltered_content
|
||||
def initialize(site, dir)
|
||||
@site = site
|
||||
@dir = dir
|
||||
@unfiltered_content = Array.new
|
||||
end
|
||||
|
||||
# Read all the files in <source>/<dir>/ for Yaml header and create a new Page
|
||||
# object for each file.
|
||||
#
|
||||
# dir - The String relative path of the directory to read.
|
||||
#
|
||||
# Returns an array of static files.
|
||||
def read(files)
|
||||
files.map{ |file| @unfiltered_content << StaticFile.new(@site, @site.source, @dir, file)}
|
||||
@unfiltered_content
|
||||
end
|
||||
end
|
||||
end
|
||||
176
lib/jekyll/regenerator.rb
Normal file
176
lib/jekyll/regenerator.rb
Normal file
@@ -0,0 +1,176 @@
|
||||
module Jekyll
|
||||
class Regenerator
|
||||
attr_reader :site, :metadata, :cache
|
||||
|
||||
def initialize(site)
|
||||
@site = site
|
||||
|
||||
# Read metadata from file
|
||||
read_metadata
|
||||
|
||||
# Initialize cache to an empty hash
|
||||
clear_cache
|
||||
end
|
||||
|
||||
# Checks if a renderable object needs to be regenerated
|
||||
#
|
||||
# Returns a boolean.
|
||||
def regenerate?(document)
|
||||
case document
|
||||
when Page
|
||||
document.asset_file? || document.data['regenerate'] ||
|
||||
source_modified_or_dest_missing?(
|
||||
site.in_source_dir(document.relative_path), document.destination(@site.dest)
|
||||
)
|
||||
when Document
|
||||
!document.write? || document.data['regenerate'] ||
|
||||
source_modified_or_dest_missing?(
|
||||
document.path, document.destination(@site.dest)
|
||||
)
|
||||
else
|
||||
source_path = document.respond_to?(:path) ? document.path : nil
|
||||
dest_path = document.respond_to?(:destination) ? document.destination(@site.dest) : nil
|
||||
source_modified_or_dest_missing?(source_path, dest_path)
|
||||
end
|
||||
end
|
||||
|
||||
# Add a path to the metadata
|
||||
#
|
||||
# Returns true, also on failure.
|
||||
def add(path)
|
||||
return true unless File.exist?(path)
|
||||
|
||||
metadata[path] = {
|
||||
"mtime" => File.mtime(path),
|
||||
"deps" => []
|
||||
}
|
||||
cache[path] = true
|
||||
end
|
||||
|
||||
# Force a path to regenerate
|
||||
#
|
||||
# Returns true.
|
||||
def force(path)
|
||||
cache[path] = true
|
||||
end
|
||||
|
||||
# Clear the metadata and cache
|
||||
#
|
||||
# Returns nothing
|
||||
def clear
|
||||
@metadata = {}
|
||||
clear_cache
|
||||
end
|
||||
|
||||
|
||||
# Clear just the cache
|
||||
#
|
||||
# Returns nothing
|
||||
def clear_cache
|
||||
@cache = {}
|
||||
end
|
||||
|
||||
|
||||
# Checks if the source has been modified or the
|
||||
# destination is missing
|
||||
#
|
||||
# returns a boolean
|
||||
def source_modified_or_dest_missing?(source_path, dest_path)
|
||||
modified?(source_path) || (dest_path and !File.exist?(dest_path))
|
||||
end
|
||||
|
||||
# Checks if a path's (or one of its dependencies)
|
||||
# mtime has changed
|
||||
#
|
||||
# Returns a boolean.
|
||||
def modified?(path)
|
||||
return true if disabled?
|
||||
|
||||
# objects that don't have a path are always regenerated
|
||||
return true if path.nil?
|
||||
|
||||
# Check for path in cache
|
||||
if cache.has_key? path
|
||||
return cache[path]
|
||||
end
|
||||
|
||||
# Check path that exists in metadata
|
||||
data = metadata[path]
|
||||
if data
|
||||
data["deps"].each do |dependency|
|
||||
if modified?(dependency)
|
||||
return cache[dependency] = cache[path] = true
|
||||
end
|
||||
end
|
||||
if File.exist?(path) && data["mtime"].eql?(File.mtime(path))
|
||||
return cache[path] = false
|
||||
else
|
||||
return add(path)
|
||||
end
|
||||
end
|
||||
|
||||
# Path does not exist in metadata, add it
|
||||
return add(path)
|
||||
end
|
||||
|
||||
# Add a dependency of a path
|
||||
#
|
||||
# Returns nothing.
|
||||
def add_dependency(path, dependency)
|
||||
return if (metadata[path].nil? || @disabled)
|
||||
|
||||
if !metadata[path]["deps"].include? dependency
|
||||
metadata[path]["deps"] << dependency
|
||||
add(dependency) unless metadata.include?(dependency)
|
||||
end
|
||||
regenerate? dependency
|
||||
end
|
||||
|
||||
# Write the metadata to disk
|
||||
#
|
||||
# Returns nothing.
|
||||
def write_metadata
|
||||
unless disabled?
|
||||
File.binwrite(metadata_file, Marshal.dump(metadata))
|
||||
end
|
||||
end
|
||||
|
||||
# Produce the absolute path of the metadata file
|
||||
#
|
||||
# Returns the String path of the file.
|
||||
def metadata_file
|
||||
site.in_source_dir('.jekyll-metadata')
|
||||
end
|
||||
|
||||
# Check if metadata has been disabled
|
||||
#
|
||||
# Returns a Boolean (true for disabled, false for enabled).
|
||||
def disabled?
|
||||
@disabled = !site.incremental? if @disabled.nil?
|
||||
@disabled
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Read metadata from the metadata file, if no file is found,
|
||||
# initialize with an empty hash
|
||||
#
|
||||
# Returns the read metadata.
|
||||
def read_metadata
|
||||
@metadata = if !disabled? && File.file?(metadata_file)
|
||||
content = File.binread(metadata_file)
|
||||
|
||||
begin
|
||||
Marshal.load(content)
|
||||
rescue TypeError
|
||||
SafeYAML.load(content)
|
||||
rescue ArgumentError => e
|
||||
Jekyll.logger.warn("Failed to load #{metadata_file}: #{e}")
|
||||
{}
|
||||
end
|
||||
else
|
||||
{}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -10,11 +10,11 @@ module Jekyll
|
||||
def initialize(post)
|
||||
@post = post
|
||||
@site = post.site
|
||||
require 'classifier' if site.lsi
|
||||
Jekyll::External.require_with_graceful_fail('classifier-reborn') if site.lsi
|
||||
end
|
||||
|
||||
def build
|
||||
return [] unless site.posts.size > 1
|
||||
return [] unless site.posts.docs.size > 1
|
||||
|
||||
if site.lsi
|
||||
build_index
|
||||
@@ -27,10 +27,10 @@ module Jekyll
|
||||
|
||||
def build_index
|
||||
self.class.lsi ||= begin
|
||||
lsi = Classifier::LSI.new(:auto_rebuild => false)
|
||||
lsi = ClassifierReborn::LSI.new(:auto_rebuild => false)
|
||||
display("Populating LSI...")
|
||||
|
||||
site.posts.each do |x|
|
||||
site.posts.docs.each do |x|
|
||||
lsi.add_item(x)
|
||||
end
|
||||
|
||||
@@ -42,12 +42,11 @@ module Jekyll
|
||||
end
|
||||
|
||||
def lsi_related_posts
|
||||
self.class.lsi.find_related(post.content, 11) - [post]
|
||||
self.class.lsi.find_related(post, 11)
|
||||
end
|
||||
|
||||
def most_recent_posts
|
||||
recent_posts = site.posts.reverse - [post]
|
||||
recent_posts.first(10)
|
||||
@most_recent_posts ||= (site.posts.docs.reverse - [post]).first(10)
|
||||
end
|
||||
|
||||
def display(output)
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
module Jekyll
|
||||
class Renderer
|
||||
|
||||
attr_reader :document, :site
|
||||
attr_reader :document, :site, :site_payload
|
||||
|
||||
def initialize(site, document)
|
||||
@site = site
|
||||
@document = document
|
||||
def initialize(site, document, site_payload = nil)
|
||||
@site = site
|
||||
@document = document
|
||||
@site_payload = site_payload
|
||||
end
|
||||
|
||||
# Determine which converters to use based on this document's
|
||||
@@ -20,7 +23,7 @@ module Jekyll
|
||||
#
|
||||
# Returns the output extname including the leading period.
|
||||
def output_ext
|
||||
converters.first.output_ext(document.extname)
|
||||
@output_ext ||= converters.first.output_ext(document.extname)
|
||||
end
|
||||
|
||||
######################
|
||||
@@ -28,9 +31,18 @@ module Jekyll
|
||||
######################
|
||||
|
||||
def run
|
||||
Jekyll.logger.debug "Rendering:", document.relative_path
|
||||
|
||||
payload = Utils.deep_merge_hashes({
|
||||
"page" => document.to_liquid
|
||||
}, site.site_payload)
|
||||
}, site_payload || site.site_payload)
|
||||
|
||||
if document.collection.label == 'posts' && document.is_a?(Document)
|
||||
payload['site']['related_posts'] = document.related_posts
|
||||
end
|
||||
|
||||
Jekyll.logger.debug "Pre-Render Hooks:", document.relative_path
|
||||
document.trigger_hooks(:pre_render, payload)
|
||||
|
||||
info = {
|
||||
filters: [Jekyll::Filters],
|
||||
@@ -44,17 +56,23 @@ module Jekyll
|
||||
output = document.content
|
||||
|
||||
if document.render_with_liquid?
|
||||
output = render_liquid(output, payload, info)
|
||||
Jekyll.logger.debug "Rendering Liquid:", document.relative_path
|
||||
output = render_liquid(output, payload, info, document.path)
|
||||
end
|
||||
|
||||
Jekyll.logger.debug "Rendering Markup:", document.relative_path
|
||||
output = convert(output)
|
||||
document.content = output
|
||||
|
||||
if document.place_in_layout?
|
||||
Jekyll.logger.debug "Rendering Layout:", document.relative_path
|
||||
place_in_layouts(
|
||||
convert(output),
|
||||
output,
|
||||
payload,
|
||||
info
|
||||
)
|
||||
else
|
||||
convert(output)
|
||||
output
|
||||
end
|
||||
end
|
||||
|
||||
@@ -68,7 +86,8 @@ module Jekyll
|
||||
begin
|
||||
converter.convert output
|
||||
rescue => e
|
||||
Jekyll.logger.error "Conversion error:", "#{converter.class} encountered an error converting '#{document.relative_path}'."
|
||||
Jekyll.logger.error "Conversion error:", "#{converter.class} encountered an error while converting '#{document.relative_path}':"
|
||||
Jekyll.logger.error("", e.to_s)
|
||||
raise e
|
||||
end
|
||||
end
|
||||
@@ -83,7 +102,7 @@ module Jekyll
|
||||
#
|
||||
# Returns the content, rendered by Liquid.
|
||||
def render_liquid(content, payload, info, path = nil)
|
||||
Liquid::Template.parse(content).render!(payload, info)
|
||||
site.liquid_renderer.file(path).parse(content).render!(payload, info)
|
||||
rescue Tags::IncludeTagError => e
|
||||
Jekyll.logger.error "Liquid Exception:", "#{e.message} in #{e.path}, included in #{path || document.relative_path}"
|
||||
raise e
|
||||
@@ -92,6 +111,15 @@ module Jekyll
|
||||
raise e
|
||||
end
|
||||
|
||||
# Checks if the layout specified in the document actually exists
|
||||
#
|
||||
# layout - the layout to check
|
||||
#
|
||||
# Returns true if the layout is invalid, false if otherwise
|
||||
def invalid_layout?(layout)
|
||||
!document.data["layout"].nil? && layout.nil?
|
||||
end
|
||||
|
||||
# Render layouts and place given content inside.
|
||||
#
|
||||
# content - the content to be placed in the layout
|
||||
@@ -101,6 +129,9 @@ module Jekyll
|
||||
def place_in_layouts(content, payload, info)
|
||||
output = content.dup
|
||||
layout = site.layouts[document.data["layout"]]
|
||||
|
||||
Jekyll.logger.warn("Build Warning:", "Layout '#{document.data["layout"]}' requested in #{document.relative_path} does not exist.") if invalid_layout? layout
|
||||
|
||||
used = Set.new([layout])
|
||||
|
||||
while layout
|
||||
@@ -117,9 +148,15 @@ module Jekyll
|
||||
layout.content,
|
||||
payload,
|
||||
info,
|
||||
File.join(site.config['layouts'], layout.name)
|
||||
File.join(site.config['layouts_dir'], layout.name)
|
||||
)
|
||||
|
||||
# Add layout to dependency tree
|
||||
site.regenerator.add_dependency(
|
||||
site.in_source_dir(document.path),
|
||||
site.in_source_dir(layout.path)
|
||||
) if document.write?
|
||||
|
||||
if layout = site.layouts[layout.data["layout"]]
|
||||
if used.include?(layout)
|
||||
layout = nil # avoid recursive chain
|
||||
|
||||
@@ -1,27 +1,39 @@
|
||||
# encoding: UTF-8
|
||||
require 'csv'
|
||||
|
||||
module Jekyll
|
||||
class Site
|
||||
attr_accessor :config, :layouts, :posts, :pages, :static_files,
|
||||
:exclude, :include, :source, :dest, :lsi, :highlighter,
|
||||
:permalink_style, :time, :future, :unpublished, :safe, :plugins, :limit_posts,
|
||||
:show_drafts, :keep_files, :baseurl, :data, :file_read_opts, :gems,
|
||||
:plugin_manager
|
||||
attr_reader :source, :dest, :config
|
||||
attr_accessor :layouts, :pages, :static_files, :drafts,
|
||||
:exclude, :include, :lsi, :highlighter, :permalink_style,
|
||||
:time, :future, :unpublished, :safe, :plugins, :limit_posts,
|
||||
:show_drafts, :keep_files, :baseurl, :data, :file_read_opts,
|
||||
:gems, :plugin_manager
|
||||
|
||||
attr_accessor :converters, :generators
|
||||
attr_accessor :converters, :generators, :reader
|
||||
attr_reader :regenerator, :liquid_renderer
|
||||
|
||||
# Public: Initialize a new Site.
|
||||
#
|
||||
# config - A Hash containing site configuration details.
|
||||
def initialize(config)
|
||||
self.config = config.clone
|
||||
@config = config.clone
|
||||
|
||||
%w[safe lsi highlighter baseurl exclude include future unpublished
|
||||
show_drafts limit_posts keep_files gems].each do |opt|
|
||||
self.send("#{opt}=", config[opt])
|
||||
end
|
||||
|
||||
self.source = File.expand_path(config['source'])
|
||||
self.dest = File.expand_path(config['destination'])
|
||||
self.permalink_style = config['permalink'].to_sym
|
||||
# Source and destination may not be changed after the site has been created.
|
||||
@source = File.expand_path(config['source']).freeze
|
||||
@dest = File.expand_path(config['destination']).freeze
|
||||
|
||||
@reader = Jekyll::Reader.new(self)
|
||||
|
||||
# Initialize incremental regenerator
|
||||
@regenerator = Regenerator.new(self)
|
||||
|
||||
@liquid_renderer = LiquidRenderer.new(self)
|
||||
|
||||
self.plugin_manager = Jekyll::PluginManager.new(self)
|
||||
self.plugins = plugin_manager.plugins_path
|
||||
@@ -29,6 +41,10 @@ module Jekyll
|
||||
self.file_read_opts = {}
|
||||
self.file_read_opts[:encoding] = config['encoding'] if config['encoding']
|
||||
|
||||
self.permalink_style = config['permalink'].to_sym
|
||||
|
||||
Jekyll.sites << self
|
||||
|
||||
reset
|
||||
setup
|
||||
end
|
||||
@@ -43,23 +59,33 @@ module Jekyll
|
||||
render
|
||||
cleanup
|
||||
write
|
||||
print_stats
|
||||
end
|
||||
|
||||
def print_stats
|
||||
if @config['profile']
|
||||
puts @liquid_renderer.stats_table
|
||||
end
|
||||
end
|
||||
|
||||
# Reset Site details.
|
||||
#
|
||||
# Returns nothing
|
||||
def reset
|
||||
self.time = (config['time'] ? Time.parse(config['time'].to_s) : Time.now)
|
||||
self.time = (config['time'] ? Utils.parse_date(config['time'].to_s, "Invalid time in _config.yml.") : Time.now)
|
||||
self.layouts = {}
|
||||
self.posts = []
|
||||
self.pages = []
|
||||
self.static_files = []
|
||||
self.data = {}
|
||||
@collections = nil
|
||||
@regenerator.clear_cache
|
||||
@liquid_renderer.reset
|
||||
|
||||
if limit_posts < 0
|
||||
raise ArgumentError, "limit_posts must be a non-negative number"
|
||||
end
|
||||
|
||||
Jekyll::Hooks.trigger :site, :after_reset, self
|
||||
end
|
||||
|
||||
# Load necessary libraries, plugins, converters, and generators.
|
||||
@@ -80,7 +106,7 @@ module Jekyll
|
||||
dest_pathname = Pathname.new(dest)
|
||||
Pathname.new(source).ascend do |path|
|
||||
if path == dest_pathname
|
||||
raise FatalException.new "Destination directory cannot be or contain the Source directory."
|
||||
raise Errors::FatalException.new "Destination directory cannot be or contain the Source directory."
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -115,124 +141,9 @@ module Jekyll
|
||||
#
|
||||
# Returns nothing.
|
||||
def read
|
||||
self.layouts = LayoutReader.new(self).read
|
||||
read_directories
|
||||
read_data(config['data_source'])
|
||||
read_collections
|
||||
end
|
||||
|
||||
# Recursively traverse directories to find posts, pages and static files
|
||||
# that will become part of the site according to the rules in
|
||||
# filter_entries.
|
||||
#
|
||||
# dir - The String relative path of the directory to read. Default: ''.
|
||||
#
|
||||
# Returns nothing.
|
||||
def read_directories(dir = '')
|
||||
base = File.join(source, dir)
|
||||
entries = Dir.chdir(base) { filter_entries(Dir.entries('.'), base) }
|
||||
|
||||
read_posts(dir)
|
||||
read_drafts(dir) if show_drafts
|
||||
posts.sort!
|
||||
limit_posts! if limit_posts > 0 # limit the posts if :limit_posts option is set
|
||||
|
||||
entries.each do |f|
|
||||
f_abs = File.join(base, f)
|
||||
if File.directory?(f_abs)
|
||||
f_rel = File.join(dir, f)
|
||||
read_directories(f_rel) unless dest.sub(/\/$/, '') == f_abs
|
||||
elsif has_yaml_header?(f_abs)
|
||||
page = Page.new(self, source, dir, f)
|
||||
pages << page if publisher.publish?(page)
|
||||
else
|
||||
static_files << StaticFile.new(self, source, dir, f)
|
||||
end
|
||||
end
|
||||
|
||||
pages.sort_by!(&:name)
|
||||
end
|
||||
|
||||
# Read all the files in <source>/<dir>/_posts and create a new Post
|
||||
# object with each one.
|
||||
#
|
||||
# dir - The String relative path of the directory to read.
|
||||
#
|
||||
# Returns nothing.
|
||||
def read_posts(dir)
|
||||
posts = read_content(dir, '_posts', Post)
|
||||
|
||||
posts.each do |post|
|
||||
aggregate_post_info(post) if publisher.publish?(post)
|
||||
end
|
||||
end
|
||||
|
||||
# Read all the files in <source>/<dir>/_drafts and create a new Post
|
||||
# object with each one.
|
||||
#
|
||||
# dir - The String relative path of the directory to read.
|
||||
#
|
||||
# Returns nothing.
|
||||
def read_drafts(dir)
|
||||
drafts = read_content(dir, '_drafts', Draft)
|
||||
|
||||
drafts.each do |draft|
|
||||
if draft.published?
|
||||
aggregate_post_info(draft)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def read_content(dir, magic_dir, klass)
|
||||
get_entries(dir, magic_dir).map do |entry|
|
||||
klass.new(self, source, dir, entry) if klass.valid?(entry)
|
||||
end.reject do |entry|
|
||||
entry.nil?
|
||||
end
|
||||
end
|
||||
|
||||
# Read and parse all yaml files under <source>/<dir>
|
||||
#
|
||||
# Returns nothing
|
||||
def read_data(dir)
|
||||
base = File.join(source, dir)
|
||||
read_data_to(base, self.data)
|
||||
end
|
||||
|
||||
# Read and parse all yaml files under <dir> and add them to the
|
||||
# <data> variable.
|
||||
#
|
||||
# dir - The string absolute path of the directory to read.
|
||||
# data - The variable to which data will be added.
|
||||
#
|
||||
# Returns nothing
|
||||
def read_data_to(dir, data)
|
||||
return unless File.directory?(dir) && (!safe || !File.symlink?(dir))
|
||||
|
||||
entries = Dir.chdir(dir) do
|
||||
Dir['*.{yaml,yml,json}'] + Dir['*'].select { |fn| File.directory?(fn) }
|
||||
end
|
||||
|
||||
entries.each do |entry|
|
||||
path = File.join(dir, entry)
|
||||
next if File.symlink?(path) && safe
|
||||
|
||||
key = sanitize_filename(File.basename(entry, '.*'))
|
||||
if File.directory?(path)
|
||||
read_data_to(path, data[key] = {})
|
||||
else
|
||||
data[key] = SafeYAML.load_file(path)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Read in all collections specified in the configuration
|
||||
#
|
||||
# Returns nothing.
|
||||
def read_collections
|
||||
collections.each do |_, collection|
|
||||
collection.read unless collection.label.eql?("data")
|
||||
end
|
||||
reader.read
|
||||
limit_posts!
|
||||
Jekyll::Hooks.trigger :site, :post_read, self
|
||||
end
|
||||
|
||||
# Run each of the Generators.
|
||||
@@ -248,19 +159,29 @@ module Jekyll
|
||||
#
|
||||
# Returns nothing.
|
||||
def render
|
||||
relative_permalinks_deprecation_method
|
||||
relative_permalinks_are_deprecated
|
||||
|
||||
payload = site_payload
|
||||
|
||||
Jekyll::Hooks.trigger :site, :pre_render, self, payload
|
||||
|
||||
collections.each do |label, collection|
|
||||
collection.docs.each do |document|
|
||||
document.output = Jekyll::Renderer.new(self, document).run
|
||||
if regenerator.regenerate?(document)
|
||||
document.output = Jekyll::Renderer.new(self, document, payload).run
|
||||
document.trigger_hooks(:post_render)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
payload = site_payload
|
||||
[posts, pages].flatten.each do |page_or_post|
|
||||
page_or_post.render(layouts, payload)
|
||||
pages.flatten.each do |page|
|
||||
if regenerator.regenerate?(page)
|
||||
page.render(layouts, payload)
|
||||
end
|
||||
end
|
||||
rescue Errno::ENOENT => e
|
||||
|
||||
Jekyll::Hooks.trigger :site, :post_render, self, payload
|
||||
rescue Errno::ENOENT
|
||||
# ignore missing layout dir
|
||||
end
|
||||
|
||||
@@ -275,7 +196,15 @@ module Jekyll
|
||||
#
|
||||
# Returns nothing.
|
||||
def write
|
||||
each_site_file { |item| item.write(dest) }
|
||||
each_site_file { |item|
|
||||
item.write(dest) if regenerator.regenerate?(item)
|
||||
}
|
||||
regenerator.write_metadata
|
||||
Jekyll::Hooks.trigger :site, :post_write, self
|
||||
end
|
||||
|
||||
def posts
|
||||
collections['posts'] ||= Collection.new(self, 'posts')
|
||||
end
|
||||
|
||||
# Construct a Hash of Posts indexed by the specified Post attribute.
|
||||
@@ -295,7 +224,7 @@ module Jekyll
|
||||
# Build a hash map based on the specified post attribute ( post attr =>
|
||||
# array of posts ) then sort each array in reverse order.
|
||||
hash = Hash.new { |h, key| h[key] = [] }
|
||||
posts.each { |p| p.send(post_attr.to_sym).each { |t| hash[t] << p } }
|
||||
posts.docs.each { |p| p.data[post_attr].each { |t| hash[t] << p } }
|
||||
hash.values.each { |posts| posts.sort!.reverse! }
|
||||
hash
|
||||
end
|
||||
@@ -338,43 +267,26 @@ module Jekyll
|
||||
"site" => Utils.deep_merge_hashes(config,
|
||||
Utils.deep_merge_hashes(Hash[collections.map{|label, coll| [label, coll.docs]}], {
|
||||
"time" => time,
|
||||
"posts" => posts.sort { |a, b| b <=> a },
|
||||
"posts" => posts.docs.sort { |a, b| b <=> a },
|
||||
"pages" => pages,
|
||||
"static_files" => static_files.sort { |a, b| a.relative_path <=> b.relative_path },
|
||||
"static_files" => static_files,
|
||||
"html_pages" => pages.select { |page| page.html? || page.url.end_with?("/") },
|
||||
"categories" => post_attr_hash('categories'),
|
||||
"tags" => post_attr_hash('tags'),
|
||||
"collections" => collections,
|
||||
"collections" => collections.values.map(&:to_liquid),
|
||||
"documents" => documents,
|
||||
"data" => site_data
|
||||
}))
|
||||
}
|
||||
end
|
||||
|
||||
# Filter out any files/directories that are hidden or backup files (start
|
||||
# with "." or "#" or end with "~"), or contain site content (start with "_"),
|
||||
# or are excluded in the site configuration, unless they are web server
|
||||
# files such as '.htaccess'.
|
||||
#
|
||||
# entries - The Array of String file/directory entries to filter.
|
||||
#
|
||||
# Returns the Array of filtered entries.
|
||||
def filter_entries(entries, base_directory = nil)
|
||||
EntryFilter.new(self, base_directory).filter(entries)
|
||||
end
|
||||
|
||||
# Get the implementation class for the given Converter.
|
||||
#
|
||||
# klass - The Class of the Converter to fetch.
|
||||
#
|
||||
# Returns the Converter instance implementing the given Converter.
|
||||
def getConverterImpl(klass)
|
||||
matches = converters.select { |c| c.class == klass }
|
||||
if impl = matches.first
|
||||
impl
|
||||
else
|
||||
raise "Converter implementation not found for #{klass}"
|
||||
end
|
||||
def find_converter_instance(klass)
|
||||
converters.find { |c| c.class == klass } || proc { raise "No converter for #{klass}" }.call
|
||||
end
|
||||
|
||||
# Create array of instances of the subclasses of the class or module
|
||||
@@ -392,87 +304,109 @@ module Jekyll
|
||||
end
|
||||
end
|
||||
|
||||
# Read the entries from a particular directory for processing
|
||||
# Warns the user if permanent links are relative to the parent
|
||||
# directory. As this is a deprecated function of Jekyll.
|
||||
#
|
||||
# dir - The String relative path of the directory to read
|
||||
# subfolder - The String directory to read
|
||||
#
|
||||
# Returns the list of entries to process
|
||||
def get_entries(dir, subfolder)
|
||||
base = File.join(source, dir, subfolder)
|
||||
return [] unless File.exist?(base)
|
||||
entries = Dir.chdir(base) { filter_entries(Dir['**/*'], base) }
|
||||
entries.delete_if { |e| File.directory?(File.join(base, e)) }
|
||||
end
|
||||
|
||||
# Aggregate post information
|
||||
#
|
||||
# post - The Post object to aggregate information for
|
||||
#
|
||||
# Returns nothing
|
||||
def aggregate_post_info(post)
|
||||
posts << post
|
||||
end
|
||||
|
||||
def relative_permalinks_deprecation_method
|
||||
if config['relative_permalinks'] && has_relative_page?
|
||||
Jekyll.logger.warn "Deprecation:", "Starting in 2.0, permalinks for pages" +
|
||||
" in subfolders must be relative to the" +
|
||||
" site source directory, not the parent" +
|
||||
" directory. Check http://jekyllrb.com/docs/upgrading/"+
|
||||
" for more info."
|
||||
# Returns
|
||||
def relative_permalinks_are_deprecated
|
||||
if config['relative_permalinks']
|
||||
Jekyll.logger.abort_with "Since v3.0, permalinks for pages" +
|
||||
" in subfolders must be relative to the" +
|
||||
" site source directory, not the parent" +
|
||||
" directory. Check http://jekyllrb.com/docs/upgrading/"+
|
||||
" for more info."
|
||||
end
|
||||
end
|
||||
|
||||
# Get the to be written documents
|
||||
#
|
||||
# Returns an Array of Documents which should be written
|
||||
def docs_to_write
|
||||
documents.select(&:write?)
|
||||
end
|
||||
|
||||
# Get all the documents
|
||||
#
|
||||
# Returns an Array of all Documents
|
||||
def documents
|
||||
collections.reduce(Set.new) do |docs, (_, collection)|
|
||||
docs.merge(collection.docs)
|
||||
docs + collection.docs + collection.files
|
||||
end.to_a
|
||||
end
|
||||
|
||||
def each_site_file
|
||||
%w(posts pages static_files docs_to_write).each do |type|
|
||||
%w(pages static_files docs_to_write).each do |type|
|
||||
send(type).each do |item|
|
||||
yield item
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Returns the FrontmatterDefaults or creates a new FrontmatterDefaults
|
||||
# if it doesn't already exist.
|
||||
#
|
||||
# Returns The FrontmatterDefaults
|
||||
def frontmatter_defaults
|
||||
@frontmatter_defaults ||= Configuration::FrontmatterDefaults.new(self)
|
||||
@frontmatter_defaults ||= FrontmatterDefaults.new(self)
|
||||
end
|
||||
|
||||
# Whether to perform a full rebuild without incremental regeneration
|
||||
#
|
||||
# Returns a Boolean: true for a full rebuild, false for normal build
|
||||
def incremental?(override = {})
|
||||
override['incremental'] || config['incremental']
|
||||
end
|
||||
|
||||
# Returns the publisher or creates a new publisher if it doesn't
|
||||
# already exist.
|
||||
#
|
||||
# Returns The Publisher
|
||||
def publisher
|
||||
@publisher ||= Publisher.new(self)
|
||||
end
|
||||
|
||||
# Public: Prefix a given path with the source directory.
|
||||
#
|
||||
# paths - (optional) path elements to a file or directory within the
|
||||
# source directory
|
||||
#
|
||||
# Returns a path which is prefixed with the source directory.
|
||||
def in_source_dir(*paths)
|
||||
paths.reduce(source) do |base, path|
|
||||
Jekyll.sanitized_path(base, path)
|
||||
end
|
||||
end
|
||||
|
||||
# Public: Prefix a given path with the destination directory.
|
||||
#
|
||||
# paths - (optional) path elements to a file or directory within the
|
||||
# destination directory
|
||||
#
|
||||
# Returns a path which is prefixed with the destination directory.
|
||||
def in_dest_dir(*paths)
|
||||
paths.reduce(dest) do |base, path|
|
||||
Jekyll.sanitized_path(base, path)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def has_relative_page?
|
||||
pages.any? { |page| page.uses_relative_permalinks }
|
||||
end
|
||||
|
||||
def has_yaml_header?(file)
|
||||
!!(File.open(file, 'rb') { |f| f.read(5) } =~ /\A---\r?\n/)
|
||||
end
|
||||
|
||||
# Limits the current posts; removes the posts which exceed the limit_posts
|
||||
#
|
||||
# Returns nothing
|
||||
def limit_posts!
|
||||
limit = posts.length < limit_posts ? posts.length : limit_posts
|
||||
self.posts = posts[-limit, limit]
|
||||
if limit_posts > 0
|
||||
limit = posts.docs.length < limit_posts ? posts.docs.length : limit_posts
|
||||
self.posts.docs = posts.docs[-limit, limit]
|
||||
end
|
||||
end
|
||||
|
||||
# Returns the Cleaner or creates a new Cleaner if it doesn't
|
||||
# already exist.
|
||||
#
|
||||
# Returns The Cleaner
|
||||
def site_cleaner
|
||||
@site_cleaner ||= Cleaner.new(self)
|
||||
end
|
||||
|
||||
def sanitize_filename(name)
|
||||
name.gsub!(/[^\w\s_-]+/, '')
|
||||
name.gsub!(/(^|\b\s)\s+($|\s?\b)/, '\\1\\2')
|
||||
name.gsub(/\s+/, '_')
|
||||
end
|
||||
|
||||
def publisher
|
||||
@publisher ||= Publisher.new(self)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3,17 +3,22 @@ module Jekyll
|
||||
# The cache of last modification times [path] -> mtime.
|
||||
@@mtimes = Hash.new
|
||||
|
||||
attr_reader :relative_path, :extname
|
||||
|
||||
# Initialize a new StaticFile.
|
||||
#
|
||||
# site - The Site.
|
||||
# base - The String path to the <source>.
|
||||
# dir - The String path between <source> and the file.
|
||||
# name - The String filename of the file.
|
||||
def initialize(site, base, dir, name)
|
||||
def initialize(site, base, dir, name, collection = nil)
|
||||
@site = site
|
||||
@base = base
|
||||
@dir = dir
|
||||
@name = name
|
||||
@collection = collection
|
||||
@relative_path = File.join(*[@dir, @name].compact)
|
||||
@extname = File.extname(@name)
|
||||
end
|
||||
|
||||
# Returns source file path.
|
||||
@@ -21,23 +26,30 @@ module Jekyll
|
||||
File.join(*[@base, @dir, @name].compact)
|
||||
end
|
||||
|
||||
# Returns the source file path relative to the site source
|
||||
def relative_path
|
||||
@relative_path ||= path.sub(/\A#{@site.source}/, '')
|
||||
end
|
||||
|
||||
# Obtain destination path.
|
||||
#
|
||||
# dest - The String path to the destination dir.
|
||||
#
|
||||
# Returns destination file path.
|
||||
def destination(dest)
|
||||
File.join(*[dest, @dir, @name].compact)
|
||||
@site.in_dest_dir(*[dest, destination_rel_dir, @name].compact)
|
||||
end
|
||||
|
||||
def destination_rel_dir
|
||||
if @collection
|
||||
File.dirname(url)
|
||||
else
|
||||
@dir
|
||||
end
|
||||
end
|
||||
|
||||
def modified_time
|
||||
@modified_time ||= File.stat(path).mtime
|
||||
end
|
||||
|
||||
# Returns last modification time for this file.
|
||||
def mtime
|
||||
File.stat(path).mtime.to_i
|
||||
modified_time.to_i
|
||||
end
|
||||
|
||||
# Is source path modified?
|
||||
@@ -47,6 +59,14 @@ module Jekyll
|
||||
@@mtimes[path] != mtime
|
||||
end
|
||||
|
||||
# Whether to write the file to the filesystem
|
||||
#
|
||||
# Returns true unless the defaults for the destination path from
|
||||
# _config.yml contain `published: false`.
|
||||
def write?
|
||||
defaults.fetch('published', true)
|
||||
end
|
||||
|
||||
# Write the static file to the destination directory (if modified).
|
||||
#
|
||||
# dest - The String path to the destination dir.
|
||||
@@ -61,6 +81,7 @@ module Jekyll
|
||||
FileUtils.mkdir_p(File.dirname(dest_path))
|
||||
FileUtils.rm(dest_path) if File.exist?(dest_path)
|
||||
FileUtils.cp(path, dest_path)
|
||||
File.utime(@@mtimes[path], @@mtimes[path], dest_path)
|
||||
|
||||
true
|
||||
end
|
||||
@@ -75,10 +96,46 @@ module Jekyll
|
||||
|
||||
def to_liquid
|
||||
{
|
||||
"path" => relative_path,
|
||||
"modified_time" => mtime.to_s,
|
||||
"extname" => File.extname(relative_path)
|
||||
"extname" => extname,
|
||||
"modified_time" => modified_time,
|
||||
"path" => File.join("", relative_path)
|
||||
}
|
||||
end
|
||||
|
||||
def placeholders
|
||||
{
|
||||
collection: @collection.label,
|
||||
path: relative_path[
|
||||
@collection.relative_directory.size..relative_path.size],
|
||||
output_ext: '',
|
||||
name: '',
|
||||
title: '',
|
||||
}
|
||||
end
|
||||
|
||||
# Applies a similar URL-building technique as Jekyll::Document that takes
|
||||
# the collection's URL template into account. The default URL template can
|
||||
# be overriden in the collection's configuration in _config.yml.
|
||||
def url
|
||||
@url ||= if @collection.nil?
|
||||
relative_path
|
||||
else
|
||||
::Jekyll::URL.new({
|
||||
template: @collection.url_template,
|
||||
placeholders: placeholders,
|
||||
})
|
||||
end.to_s.gsub /\/$/, ''
|
||||
end
|
||||
|
||||
# Returns the type of the collection if present, nil otherwise.
|
||||
def type
|
||||
@type ||= @collection.nil? ? nil : @collection.label.to_sym
|
||||
end
|
||||
|
||||
# Returns the front matter defaults defined for the file's URL and/or type
|
||||
# as defined in _config.yml.
|
||||
def defaults
|
||||
@defaults ||= @site.frontmatter_defaults.all url, type
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,9 +4,11 @@ module Jekyll
|
||||
include Liquid::StandardFilters
|
||||
|
||||
# The regular expression syntax checker. Start with the language specifier.
|
||||
# Follow that by zero or more space separated options that take one of two
|
||||
# forms: name or name=value
|
||||
SYNTAX = /^([a-zA-Z0-9.+#-]+)((\s+\w+(=\w+)?)*)$/
|
||||
# Follow that by zero or more space separated options that take one of three
|
||||
# forms: name, name=value, or name="<quoted list>"
|
||||
#
|
||||
# <quoted list> is a space-separated list of numbers
|
||||
SYNTAX = /^([a-zA-Z0-9.+#-]+)((\s+\w+(=(\w+|"([0-9]+\s)*[0-9]+"))?)*)$/
|
||||
|
||||
def initialize(tag_name, markup, tokens)
|
||||
super
|
||||
@@ -14,8 +16,14 @@ module Jekyll
|
||||
@lang = $1.downcase
|
||||
@options = {}
|
||||
if defined?($2) && $2 != ''
|
||||
$2.split.each do |opt|
|
||||
# Split along 3 possible forms -- key="<quoted list>", key=value, or key
|
||||
$2.scan(/(?:\w="[^"]*"|\w=\w|\w)+/) do |opt|
|
||||
key, value = opt.split('=')
|
||||
# If a quoted list, convert to array
|
||||
if value && value.include?("\"")
|
||||
value.gsub!(/"/, "")
|
||||
value = value.split
|
||||
end
|
||||
@options[key.to_sym] = value || true
|
||||
end
|
||||
end
|
||||
@@ -34,26 +42,46 @@ eos
|
||||
def render(context)
|
||||
prefix = context["highlighter_prefix"] || ""
|
||||
suffix = context["highlighter_suffix"] || ""
|
||||
code = super.to_s.strip
|
||||
code = super.to_s.gsub(/\A(\n|\r)+|(\n|\r)+\z/, '')
|
||||
|
||||
output = case context.registers[:site].highlighter
|
||||
when 'pygments'
|
||||
render_pygments(code)
|
||||
when 'rouge'
|
||||
render_rouge(code)
|
||||
else
|
||||
render_codehighlighter(code)
|
||||
end
|
||||
is_safe = !!context.registers[:site].safe
|
||||
|
||||
output =
|
||||
case context.registers[:site].highlighter
|
||||
when 'pygments'
|
||||
render_pygments(code, is_safe)
|
||||
when 'rouge'
|
||||
render_rouge(code)
|
||||
else
|
||||
render_codehighlighter(code)
|
||||
end
|
||||
|
||||
rendered_output = add_code_tag(output)
|
||||
prefix + rendered_output + suffix
|
||||
end
|
||||
|
||||
def render_pygments(code)
|
||||
require 'pygments'
|
||||
@options[:encoding] = 'utf-8'
|
||||
def sanitized_opts(opts, is_safe)
|
||||
if is_safe
|
||||
Hash[[
|
||||
[:startinline, opts.fetch(:startinline, nil)],
|
||||
[:hl_lines, opts.fetch(:hl_lines, nil)],
|
||||
[:linenos, opts.fetch(:linenos, nil)],
|
||||
[:encoding, opts.fetch(:encoding, 'utf-8')],
|
||||
[:cssclass, opts.fetch(:cssclass, nil)]
|
||||
].reject {|f| f.last.nil? }]
|
||||
else
|
||||
opts
|
||||
end
|
||||
end
|
||||
|
||||
highlighted_code = Pygments.highlight(code, :lexer => @lang, :options => @options)
|
||||
def render_pygments(code, is_safe)
|
||||
Jekyll::External.require_with_graceful_fail('pygments')
|
||||
|
||||
highlighted_code = Pygments.highlight(
|
||||
code,
|
||||
:lexer => @lang,
|
||||
:options => sanitized_opts(@options, is_safe)
|
||||
)
|
||||
|
||||
if highlighted_code.nil?
|
||||
Jekyll.logger.error "There was an error highlighting your code:"
|
||||
@@ -66,26 +94,26 @@ eos
|
||||
raise ArgumentError.new("Pygments.rb returned an unacceptable value when attempting to highlight some code.")
|
||||
end
|
||||
|
||||
highlighted_code
|
||||
highlighted_code.sub('<div class="highlight"><pre>', '').sub('</pre></div>', '')
|
||||
end
|
||||
|
||||
def render_rouge(code)
|
||||
require 'rouge'
|
||||
Jekyll::External.require_with_graceful_fail('rouge')
|
||||
formatter = Rouge::Formatters::HTML.new(line_numbers: @options[:linenos], wrap: false)
|
||||
lexer = Rouge::Lexer.find_fancy(@lang, code) || Rouge::Lexers::PlainText
|
||||
code = formatter.format(lexer.lex(code))
|
||||
"<div class=\"highlight\"><pre>#{code}</pre></div>"
|
||||
formatter.format(lexer.lex(code))
|
||||
end
|
||||
|
||||
def render_codehighlighter(code)
|
||||
"<div class=\"highlight\"><pre>#{h(code).strip}</pre></div>"
|
||||
h(code).strip
|
||||
end
|
||||
|
||||
def add_code_tag(code)
|
||||
# Add nested <code> tags to code blocks
|
||||
code = code.sub(/<pre>\n*/,'<pre><code class="language-' + @lang.to_s.gsub("+", "-") + '" data-lang="' + @lang.to_s + '">')
|
||||
code = code.sub(/\n*<\/pre>/,"</code></pre>")
|
||||
code.strip
|
||||
code_attributes = [
|
||||
"class=\"language-#{@lang.to_s.gsub('+', '-')}\"",
|
||||
"data-lang=\"#{@lang.to_s}\""
|
||||
].join(" ")
|
||||
"<figure class=\"highlight\"><pre><code #{code_attributes}>#{code.chomp}</code></pre></figure>"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
module Jekyll
|
||||
module Tags
|
||||
class IncludeTagError < StandardError
|
||||
@@ -11,12 +13,10 @@ module Jekyll
|
||||
|
||||
class IncludeTag < Liquid::Tag
|
||||
|
||||
SYNTAX_EXAMPLE = "{% include file.ext param='value' param2='value' %}"
|
||||
attr_reader :includes_dir
|
||||
|
||||
VALID_SYNTAX = /([\w-]+)\s*=\s*(?:"([^"\\]*(?:\\.[^"\\]*)*)"|'([^'\\]*(?:\\.[^'\\]*)*)'|([\w\.-]+))/
|
||||
VARIABLE_SYNTAX = /(?<variable>\{\{\s*(?<name>[\w\-\.]+)\s*(\|.*)?\}\})(?<params>.*)/
|
||||
|
||||
INCLUDES_DIR = '_includes'
|
||||
VARIABLE_SYNTAX = /(?<variable>[^{]*\{\{\s*(?<name>[\w\-\.]+)\s*(\|.*)?\}\}[^\s}]*)(?<params>.*)/
|
||||
|
||||
def initialize(tag_name, markup, tokens)
|
||||
super
|
||||
@@ -28,6 +28,11 @@ module Jekyll
|
||||
@file, @params = markup.strip.split(' ', 2);
|
||||
end
|
||||
validate_params if @params
|
||||
@tag_name = tag_name
|
||||
end
|
||||
|
||||
def syntax_example
|
||||
"{% #{@tag_name} file.ext param='value' param2='value' %}"
|
||||
end
|
||||
|
||||
def parse_params(context)
|
||||
@@ -59,7 +64,7 @@ Invalid syntax for include tag. File contains invalid characters or sequences:
|
||||
|
||||
Valid syntax:
|
||||
|
||||
#{SYNTAX_EXAMPLE}
|
||||
#{syntax_example}
|
||||
|
||||
eos
|
||||
end
|
||||
@@ -75,7 +80,7 @@ Invalid syntax for include tag:
|
||||
|
||||
Valid syntax:
|
||||
|
||||
#{SYNTAX_EXAMPLE}
|
||||
#{syntax_example}
|
||||
|
||||
eos
|
||||
end
|
||||
@@ -89,32 +94,50 @@ eos
|
||||
# Render the variable if required
|
||||
def render_variable(context)
|
||||
if @file.match(VARIABLE_SYNTAX)
|
||||
partial = Liquid::Template.parse(@file)
|
||||
partial = context.registers[:site].liquid_renderer.file("(variable)").parse(@file)
|
||||
partial.render!(context)
|
||||
end
|
||||
end
|
||||
|
||||
def tag_includes_dir(context)
|
||||
context.registers[:site].config['includes_dir'].freeze
|
||||
end
|
||||
|
||||
def render(context)
|
||||
dir = File.join(File.realpath(context.registers[:site].source), INCLUDES_DIR)
|
||||
site = context.registers[:site]
|
||||
@includes_dir = tag_includes_dir(context)
|
||||
dir = resolved_includes_dir(context)
|
||||
|
||||
file = render_variable(context) || @file
|
||||
validate_file_name(file)
|
||||
|
||||
path = File.join(dir, file)
|
||||
validate_path(path, dir, context.registers[:site].safe)
|
||||
validate_path(path, dir, site.safe)
|
||||
|
||||
# Add include to dependency tree
|
||||
if context.registers[:page] and context.registers[:page].has_key? "path"
|
||||
site.regenerator.add_dependency(
|
||||
site.in_source_dir(context.registers[:page]["path"]),
|
||||
path
|
||||
)
|
||||
end
|
||||
|
||||
begin
|
||||
partial = Liquid::Template.parse(source(path, context))
|
||||
partial = site.liquid_renderer.file(path).parse(read_file(path, context))
|
||||
|
||||
context.stack do
|
||||
context['include'] = parse_params(context) if @params
|
||||
partial.render!(context)
|
||||
end
|
||||
rescue => e
|
||||
raise IncludeTagError.new e.message, File.join(INCLUDES_DIR, @file)
|
||||
raise IncludeTagError.new e.message, File.join(@includes_dir, @file)
|
||||
end
|
||||
end
|
||||
|
||||
def resolved_includes_dir(context)
|
||||
context.registers[:site].in_source_dir(@includes_dir)
|
||||
end
|
||||
|
||||
def validate_path(path, dir, safe)
|
||||
if safe && !realpath_prefixed_with?(path, dir)
|
||||
raise IOError.new "The included file '#{path}' should exist and should not be a symlink"
|
||||
@@ -124,23 +147,34 @@ eos
|
||||
end
|
||||
|
||||
def path_relative_to_source(dir, path)
|
||||
File.join(INCLUDES_DIR, path.sub(Regexp.new("^#{dir}"), ""))
|
||||
File.join(@includes_dir, path.sub(Regexp.new("^#{dir}"), ""))
|
||||
end
|
||||
|
||||
def realpath_prefixed_with?(path, dir)
|
||||
File.exist?(path) && File.realpath(path).start_with?(dir)
|
||||
end
|
||||
|
||||
def blank?
|
||||
false
|
||||
# This method allows to modify the file content by inheriting from the class.
|
||||
def read_file(file, context)
|
||||
File.read(file, file_read_opts(context))
|
||||
end
|
||||
end
|
||||
|
||||
class IncludeRelativeTag < IncludeTag
|
||||
def tag_includes_dir(context)
|
||||
'.'.freeze
|
||||
end
|
||||
|
||||
# This method allows to modify the file content by inheriting from the class.
|
||||
def source(file, context)
|
||||
File.read(file, file_read_opts(context))
|
||||
def page_path(context)
|
||||
context.registers[:page].nil? ? includes_dir : File.dirname(context.registers[:page]["path"])
|
||||
end
|
||||
|
||||
def resolved_includes_dir(context)
|
||||
context.registers[:site].in_source_dir(page_path(context))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Liquid::Template.register_tag('include', Jekyll::Tags::IncludeTag)
|
||||
Liquid::Template.register_tag('include_relative', Jekyll::Tags::IncludeRelativeTag)
|
||||
|
||||
@@ -3,16 +3,22 @@ module Jekyll
|
||||
class PostComparer
|
||||
MATCHER = /^(.+\/)*(\d+-\d+-\d+)-(.*)$/
|
||||
|
||||
attr_accessor :date, :slug
|
||||
attr_reader :path, :date, :slug, :name
|
||||
|
||||
def initialize(name)
|
||||
all, path, date, slug = *name.sub(/^\//, "").match(MATCHER)
|
||||
raise ArgumentError.new("'#{name}' does not contain valid date and/or title") unless all
|
||||
@slug = path ? path + slug : slug
|
||||
@date = Time.parse(date)
|
||||
@name = name
|
||||
all, @path, @date, @slug = *name.sub(/^\//, "").match(MATCHER)
|
||||
raise ArgumentError.new("'#{name}' does not contain valid date and/or title.") unless all
|
||||
|
||||
@name_regex = /^#{path}#{date}-#{slug}\.[^.]+/
|
||||
end
|
||||
|
||||
def ==(other)
|
||||
other.basename.match(@name_regex)
|
||||
end
|
||||
|
||||
def deprecated_equality(other)
|
||||
date = Utils.parse_date(name, "'#{name}' does not contain valid date and/or title.")
|
||||
slug == post_slug(other) &&
|
||||
date.year == other.date.year &&
|
||||
date.month == other.date.month &&
|
||||
@@ -26,11 +32,11 @@ module Jekyll
|
||||
#
|
||||
# Returns the post slug with the subdirectory (relative to _posts)
|
||||
def post_slug(other)
|
||||
path = other.name.split("/")[0...-1].join("/")
|
||||
path = other.basename.split("/")[0...-1].join("/")
|
||||
if path.nil? || path == ""
|
||||
other.slug
|
||||
other.data['slug']
|
||||
else
|
||||
path + '/' + other.slug
|
||||
path + '/' + other.data['slug']
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -53,12 +59,25 @@ eos
|
||||
def render(context)
|
||||
site = context.registers[:site]
|
||||
|
||||
site.posts.each do |p|
|
||||
site.posts.docs.each do |p|
|
||||
if @post == p
|
||||
return p.url
|
||||
end
|
||||
end
|
||||
|
||||
# New matching method did not match, fall back to old method
|
||||
# with deprecation warning if this matches
|
||||
|
||||
site.posts.docs.each do |p|
|
||||
if @post.deprecated_equality p
|
||||
Jekyll::Deprecator.deprecation_message "A call to '{{ post_url #{@post.name} }}' did not match " +
|
||||
"a post using the new matching method of checking name " +
|
||||
"(path-date-slug) equality. Please make sure that you " +
|
||||
"change this tag to match the post's name exactly."
|
||||
return p.url
|
||||
end
|
||||
end
|
||||
|
||||
raise ArgumentError.new <<-eos
|
||||
Could not find post "#{@orig_post}" in tag 'post_url'.
|
||||
|
||||
|
||||
@@ -37,33 +37,51 @@ module Jekyll
|
||||
#
|
||||
# Returns the String URL
|
||||
def to_s
|
||||
sanitize_url(@permalink || generate_url)
|
||||
sanitize_url(generated_permalink || generated_url)
|
||||
end
|
||||
|
||||
# Generates a URL from the permalink
|
||||
#
|
||||
# Returns the _unsanitized String URL
|
||||
def generated_permalink
|
||||
(@generated_permalink ||= generate_url(@permalink)) if @permalink
|
||||
end
|
||||
|
||||
# Generates a URL from the template
|
||||
#
|
||||
# Returns the unsanitized String URL
|
||||
def generated_url
|
||||
@generated_url ||= generate_url(@template)
|
||||
end
|
||||
|
||||
# Internal: Generate the URL by replacing all placeholders with their
|
||||
# respective values
|
||||
# respective values in the given template
|
||||
#
|
||||
# Returns the _unsanitizied_ String URL
|
||||
def generate_url
|
||||
@placeholders.inject(@template) do |result, token|
|
||||
result.gsub(/:#{token.first}/, self.class.escape_path(token.last))
|
||||
# Returns the unsanitized String URL
|
||||
def generate_url(template)
|
||||
@placeholders.inject(template) do |result, token|
|
||||
break result if result.index(':').nil?
|
||||
if token.last.nil?
|
||||
# Remove leading '/' to avoid generating urls with `//`
|
||||
result.gsub(/\/:#{token.first}/, '')
|
||||
else
|
||||
result.gsub(/:#{token.first}/, self.class.escape_path(token.last))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Returns a sanitized String URL
|
||||
def sanitize_url(in_url)
|
||||
|
||||
# Remove all double slashes
|
||||
url = in_url.gsub(/\/\//, "/")
|
||||
|
||||
# Remove every URL segment that consists solely of dots
|
||||
url = url.split('/').reject{ |part| part =~ /^\.+$/ }.join('/')
|
||||
url = in_url \
|
||||
# Remove all double slashes
|
||||
.gsub(/\/\//, '/') \
|
||||
# Remove every URL segment that consists solely of dots
|
||||
.split('/').reject{ |part| part =~ /^\.+$/ }.join('/') \
|
||||
# Always add a leading slash
|
||||
.gsub(/\A([^\/])/, '/\1')
|
||||
|
||||
# Append a trailing slash to the URL if the unsanitized URL had one
|
||||
url += "/" if in_url =~ /\/$/
|
||||
|
||||
# Always add a leading slash
|
||||
url.gsub!(/\A([^\/])/, '/\1')
|
||||
url << "/" if in_url.end_with?("/")
|
||||
|
||||
url
|
||||
end
|
||||
@@ -79,7 +97,7 @@ module Jekyll
|
||||
#
|
||||
# Returns the escaped path.
|
||||
def self.escape_path(path)
|
||||
# Because URI.escape doesn't escape '?', '[' and ']' by defaut,
|
||||
# Because URI.escape doesn't escape '?', '[' and ']' by default,
|
||||
# specify unsafe string (except unreserved, sub-delims, ":", "@" and "/").
|
||||
#
|
||||
# URI path segment is defined in RFC 3986 as follows:
|
||||
@@ -89,7 +107,7 @@ module Jekyll
|
||||
# pct-encoded = "%" HEXDIG HEXDIG
|
||||
# sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
|
||||
# / "*" / "+" / "," / ";" / "="
|
||||
URI.escape(path, /[^a-zA-Z\d\-._~!$&\'()*+,;=:@\/]/).encode('utf-8')
|
||||
URI.escape(path, /[^a-zA-Z\d\-._~!$&'()*+,;=:@\/]/).encode('utf-8')
|
||||
end
|
||||
|
||||
# Unescapes a URL path segment
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user