Skip to content

Commit ed20b8c

Browse files
committed
[CM2] model.match(),create() rootContext and fixes
Some ideas in this one: Match & Create ============== Each model has a method named 'match' which returns whether or not a node satisfies the model's fsNode requirements. And they have a 'create' method to turn a node into a content-model. So, e.g., a collection calls category.match(node) in a node traversal, and then calls category.create(node) if the former returns true. Each model configures its matchers mostly based on the settings it receives. Benefits: - Prevents the duplicaiton of functions like 'isPost', 'isPostIndexFile' etc. - Models look similar in shape to each other and to root (countdown to class Model {}) - Post index files can now be named with the entryAlias. e.g. demo.md, episode.md, article.md - Same goes for categories. Whatever alias works. Root context ============ ContentModel2 has now a context object which is passed down throughout the tree, just like a collection context. Benefits: - No more reliance on settings.out and settings.permalinkPrefix in models. So, permalinks and outputPaths are computed completely by a cascade of contexts. - This inspires a further improvement of automating that computation by introducing a context depth-level. Each model would rely on the context that is closest to itself, without necessarily recognizing where it comes from. But to not complicate the templates, some magic should follow it either in rendering phase or in the form of template helpers. {{context.category.permalink}} is too tasty to give up on. - It also means simpler/less settings for initializing models. Some fixes ========== - Category index - Tags
1 parent 0b6c9ac commit ed20b8c

File tree

11 files changed

+503
-415
lines changed

11 files changed

+503
-415
lines changed

src/compiler/contentModel2/index.js

+44-75
Original file line numberDiff line numberDiff line change
@@ -8,48 +8,6 @@ const models = {
88
asset: require('./models/asset')
99
}
1010

11-
const isHomepageFile = (node) => {
12-
return isTemplateFile(node) && node.name.match(/^(homepage|home|index)\..+$/)
13-
}
14-
15-
const isHomepageDirectory = (node) => {
16-
return node.children && node.name.match(/^(homepage|home)$/) && node.children.find(isHomepageFile)
17-
}
18-
19-
const isHomepage = (node) => {
20-
return isHomepageFile(node) || isHomepageDirectory(node)
21-
}
22-
23-
const isPagesDirectory = (node) => {
24-
return node.children && node.name.match(/^(subpages|pages)$/)
25-
}
26-
27-
const isSubpageIndexFile = (node) => {
28-
return isTemplateFile(node) && node.name.match(/^(page|index)\..+$/)
29-
}
30-
31-
const isSubpage = (node) => {
32-
return isTemplateFile(node) || node.children?.find(isSubpageIndexFile)
33-
}
34-
35-
const isCollectionIndexFile = (node) => {
36-
return isTemplateFile(node) && node.name.match(/^collection\..+$/)
37-
}
38-
39-
const isACollectionDirectory = (node) => {
40-
return node.children?.find(isCollectionIndexFile)
41-
}
42-
43-
const isAssetsDirectory = (node) => {
44-
return node.children && node.name.match(/^assets$/)
45-
}
46-
47-
const defaultHomepage = () => models.homepage({
48-
name: 'index',
49-
extension: 'md',
50-
content: ''
51-
})
52-
5311
const linkEntries = (contentModel) => {
5412
contentModel.collections.forEach(collection => {
5513
collection.posts.forEach(post => {
@@ -107,73 +65,84 @@ class ContentModel {
10765
...contentModelSettings
10866
}
10967

110-
this.collectionSettings = _.pick(
111-
this.settings,
112-
['permalinkPrefix', 'out', 'defaultCategoryName']
113-
)
114-
this.subpageSettings = _.pick(
115-
this.settings,
116-
['permalinkPrefix', 'out', 'pagesDirectory']
117-
)
118-
this.homepageSettings = _.pick(
119-
this.settings,
120-
['permalinkPrefix', 'out', 'homepageDirectory']
121-
)
122-
this.assetSettings = _.pick(
123-
this.settings,
124-
['permalinkPrefix', 'out', 'assetsDirectory']
125-
)
68+
this.models = {
69+
collection: models.collection({
70+
defaultCategoryName: this.settings.defaultCategoryName
71+
}),
72+
subpage: models.subpage({
73+
pagesDirectory: this.settings.pagesDirectory
74+
}),
75+
homepage: models.homepage({
76+
homepageDirectory: this.settings.homepageDirectory
77+
}),
78+
asset: models.asset({
79+
assetsDirectory: this.settings.assetsDirectory
80+
})
81+
}
12682
}
12783

12884
create(fileSystemTree) {
85+
const context = {
86+
outputPath: this.settings.out,
87+
permalink: this.settings.permalinkPrefix
88+
}
89+
12990
const contentModel = {
130-
homepage: defaultHomepage(),
91+
homepage: this.models.homepage.create({
92+
name: 'index',
93+
extension: 'md',
94+
content: ''
95+
}, { root: context }),
13196
subpages: [],
13297
collections: [],
13398
assets: []
13499
}
135100

136101
fileSystemTree.forEach(node => {
137-
if (isHomepage(node)) {
138-
contentModel.homepage = models.homepage(node, this.homepageSettings)
102+
if (this.models.homepage.match(node)) {
103+
contentModel.homepage = this.models.homepage.create(node, { root: context })
139104
return
140105
}
141106

142-
if (isSubpage(node)) {
107+
if (this.models.subpage.match(node)) {
143108
return contentModel.subpages.push(
144-
models.subpage(node, this.subpageSettings)
109+
this.models.subpage.create(node, { root: context })
145110
)
146111
}
147112

148-
if (isPagesDirectory(node)) {
113+
if (this.models.subpage.matchPagesDirectory(node)) {
149114
return node.children.forEach(childNode => {
150-
if (isSubpage(childNode)) {
115+
if (this.models.subpage.match(childNode)) {
151116
contentModel.subpages.push(
152-
models.subpage(childNode, this.subpageSettings)
117+
this.models.subpage.create(childNode, { root: context })
153118
)
154-
} else {
119+
} else if (this.models.asset.match(childNode)) {
155120
contentModel.assets.push(
156-
models.asset(childNode, this.assetSettings)
121+
this.models.asset.create(childNode, { root: context })
157122
)
158123
}
159124
})
160125
}
161126

162-
if (isACollectionDirectory(node)) {
127+
if (this.models.collection.match(node)) {
163128
return contentModel.collections.push(
164-
models.collection(node, this.collectionSettings)
129+
this.models.collection.create(node, { root: context })
165130
)
166131
}
167132

168-
if (isAssetsDirectory(node)) {
133+
if (this.models.asset.matchAssetsDirectory(node)) {
169134
return contentModel.assets.push(
170-
...node.children.map(n => models.asset(n, this.assetSettings))
135+
...node.children.map(childNode => {
136+
return this.models.asset.create(childNode, { root: context })
137+
})
171138
)
172139
}
173140

174-
contentModel.assets.push(
175-
models.asset(node, this.assetSettings)
176-
)
141+
if (this.models.asset.match(node)) {
142+
return contentModel.assets.push(
143+
this.models.asset.create(node, { root: context })
144+
)
145+
}
177146
})
178147

179148
linkEntries(contentModel)

src/compiler/contentModel2/models/_baseEntry.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,17 @@ function parseFolderedEntry(node, indexFileNameOptions) {
2222
indexFile: null,
2323
attachments: []
2424
}
25+
const subModels = {
26+
attachment: models.attachment()
27+
}
2528
node.children.forEach(childNode => {
2629
if (isIndexFile(childNode, indexFileNameOptions)) {
2730
tree.indexFile = childNode
2831
return
2932
}
30-
tree.attachments.push(models.attachment.bind(null, childNode))
33+
if (subModels.attachment.match(childNode)) {
34+
tree.attachments.push(subModels.attachment.create.bind(null, childNode))
35+
}
3136
})
3237
return tree
3338
}

src/compiler/contentModel2/models/asset.js

+32-18
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,42 @@
11
const { join, resolve } = require('path')
22

33
const defaultSettings = {
4-
permalinkPrefix: '/',
5-
out: resolve('.'),
64
assetsDirectory: 'assets'
75
}
8-
function asset(node, settings = defaultSettings) {
9-
const permalink = (
10-
settings.permalinkPrefix +
11-
[settings.assetsDirectory, node.name].join('/')
12-
)
6+
module.exports = function asset(settings = defaultSettings) {
7+
const assetsDirectoryNameOptions = [settings.assetsDirectory, 'assets']
138

14-
const outputPath = join(
15-
settings.out,
16-
settings.assetsDirectory,
17-
node.name
18-
)
9+
const isAssetsDirectory = (node) => {
10+
return (
11+
node.children &&
12+
node.name.match(
13+
new RegExp(`^(${assetsDirectoryNameOptions.join('|')})$`)
14+
)
15+
)
16+
}
1917

2018
return {
21-
...node,
22-
permalink,
23-
outputPath,
24-
date: new Date(node.stats.birthtime || Date.now())
19+
match: node => true,
20+
matchAssetsDirectory: isAssetsDirectory,
21+
create: (node, context) => {
22+
const permalink = (
23+
context.root.permalink +
24+
[settings.assetsDirectory, node.name].join('/')
25+
)
26+
27+
const outputPath = join(
28+
context.root.outputPath,
29+
settings.assetsDirectory,
30+
node.name
31+
)
32+
33+
return {
34+
...node,
35+
context,
36+
permalink,
37+
outputPath,
38+
date: new Date(node.stats.birthtime || Date.now())
39+
}
40+
}
2541
}
2642
}
27-
28-
module.exports = asset

src/compiler/contentModel2/models/attachment.js

+26-23
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,32 @@
11
const { join } = require('path')
22

3-
function attachment(node, context) {
4-
const permalink = [
5-
context.page?.permalink ||
6-
context.post?.permalink ||
7-
context.category?.permalink ||
8-
context.collection?.permalink,
9-
node.name
10-
].filter(Boolean).join('/')
3+
module.exports = function attachment() {
4+
return {
5+
match: node => true,
6+
create(node, context) {
7+
const permalink = [
8+
context.page?.permalink ||
9+
context.post?.permalink ||
10+
context.category?.permalink ||
11+
context.collection?.permalink,
12+
node.name
13+
].filter(Boolean).join('/')
1114

12-
const outputPath = join(...[
13-
context.page?.outputPath ||
14-
context.post?.outputPath ||
15-
context.category?.outputPath ||
16-
context.collection?.outputPath,
17-
node.name
18-
].filter(Boolean))
15+
const outputPath = join(...[
16+
context.page?.outputPath ||
17+
context.post?.outputPath ||
18+
context.category?.outputPath ||
19+
context.collection?.outputPath,
20+
node.name
21+
].filter(Boolean))
1922

20-
return {
21-
...node,
22-
context,
23-
permalink,
24-
outputPath,
25-
date: new Date(node.stats.birthtime || Date.now())
23+
return {
24+
...node,
25+
context,
26+
permalink,
27+
outputPath,
28+
date: new Date(node.stats.birthtime || Date.now())
29+
}
30+
}
2631
}
2732
}
28-
29-
module.exports = attachment

0 commit comments

Comments
 (0)