• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

scriptype / writ-cms / 19316730697

13 Nov 2025 12:49AM UTC coverage: 19.323% (+0.7%) from 18.626%
19316730697

push

github

scriptype
Introduce ContentModelNode

A ContentModelNode class is implemented by abstracting out the most
basic model: attachment.

So far models that extend ContentModelNode are: attachment, asset,
homepage, subpage.

_baseEntry's main functionality is extracted into small helpers in a new
helper module called parseTextEntry

ContentModel's helpers are duplicated into lib/ContentModelHelpers with
the idea of eventually nothing in contentModel needing to use those
helpers or something like that.

Next: post, category, collection, contentModel index

146 of 3405 branches covered (4.29%)

Branch coverage included in aggregate %.

119 of 189 new or added lines in 10 files covered. (62.96%)

10 existing lines in 2 files now uncovered.

916 of 2091 relevant lines covered (43.81%)

101.37 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

12.96
/src/compiler/contentModel/models/_baseEntry.js
1
const _ = require('lodash')
9✔
2
const frontMatter = require('front-matter')
9✔
3
const slug = require('slug')
9✔
4
const { templateExtensions, removeExtension, Markdown } = require('../helpers')
9✔
5

6
const models = {
9✔
7
  Attachment: require('./attachment')
8
}
9

10
const isIndexFile = (node, nameOptions) => {
9✔
11
  if (node.children) {
×
12
    return false
×
13
  }
14
  const names = nameOptions.join('|')
×
15
  const extensions = templateExtensions.join('|')
×
16
  const namePattern = new RegExp(`^(${names})(${extensions})$`, 'i')
×
17
  return node.name.match(namePattern)
×
18
}
19

20
function parseFolderedEntry(node, indexFileNameOptions, matchers) {
21
  const tree = {
×
22
    indexFile: null,
23
    __attachmentNodes: []
24
  }
25
  node.children.forEach(childNode => {
×
26
    if (isIndexFile(childNode, indexFileNameOptions)) {
×
27
      tree.indexFile = childNode
×
28
      return
×
29
    }
NEW
30
    if (matchers.attachment(childNode)) {
×
NEW
31
      tree.__attachmentNodes.push(childNode)
×
32
    }
33
  })
34
  return tree
×
35
}
36

37
function parseContent(node, content) {
UNCOV
38
  if (node.extension.match(/(html|htm|hbs|handlebars)/i)) {
×
39
    return content
×
40
  }
UNCOV
41
  return Markdown.parse(content)
×
42
}
43

44
function _baseEntry(node, indexFileNameOptions, matchers) {
UNCOV
45
  const folderedEntry = node.children ?
×
46
    parseFolderedEntry(node, indexFileNameOptions, matchers) :
47
    undefined
UNCOV
48
  const entryFile = folderedEntry?.indexFile || node
×
UNCOV
49
  const { attributes, body } = frontMatter(entryFile.content)
×
UNCOV
50
  const entryName = folderedEntry ? node.name : removeExtension(entryFile.name)
×
NEW
51
  const __attachmentNodes = folderedEntry?.__attachmentNodes || []
×
UNCOV
52
  const contentRaw = body || ''
×
UNCOV
53
  const content = parseContent(entryFile, contentRaw)
×
54

UNCOV
55
  return {
×
56
    ..._.omit(node, 'children'),
57
    ...attributes,
58
    hasIndex: !!folderedEntry,
59
    title: attributes.title || entryName,
×
60
    slug: attributes.slug || slug(entryName),
×
61
    contentRaw,
62
    content,
63
    __attachmentNodes
64
  }
65
}
66

67
module.exports = _baseEntry
9✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc