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

CaptainFact / captain-fact-frontend / 20007847013

07 Dec 2025 05:32PM UTC coverage: 2.876% (-2.5%) from 5.41%
20007847013

push

github

Betree
refact: Move everythin to GraphQL, remove redux

38 of 2339 branches covered (1.62%)

Branch coverage included in aggregate %.

0 of 906 new or added lines in 41 files covered. (0.0%)

31 existing lines in 7 files now uncovered.

125 of 3328 relevant lines covered (3.76%)

0.11 hits per line

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

0.0
/app/components/Help/HelpPageContent.jsx
1
/* eslint-disable jsx-a11y/anchor-has-content */
2
/* eslint-disable jsx-a11y/heading-has-content */
3
import PropTypes from 'prop-types'
4
import React, { useEffect, useState } from 'react'
5
import Markdown from 'react-markdown'
6
import { Link } from 'react-router-dom'
7
import remarkGfm from 'remark-gfm'
8

9
import { useUserPreferences } from '../../contexts/UserPreferencesContext'
10
import { isDownloadableFile, isExternal } from '../../lib/url_utils'
11
import { ErrorView } from '../Utils/ErrorView'
12
import ExternalLinkNewTab from '../Utils/ExternalLinkNewTab'
13
import { LoadingFrame } from '../Utils/LoadingFrame'
14

NEW
15
const ERROR_NOT_FOUND = 'not_found'
×
16

NEW
17
const HelpPageContent = ({ page, onLinkClick }) => {
×
NEW
18
  const { locale } = useUserPreferences()
×
NEW
19
  const [markdownContent, setMarkdownContent] = useState('')
×
NEW
20
  const [isLoading, setIsLoading] = useState(false)
×
NEW
21
  const [error, setError] = useState(null)
×
22

NEW
23
  useEffect(() => {
×
NEW
24
    const fetchHelpPage = async () => {
×
NEW
25
      setIsLoading(true)
×
NEW
26
      setError(null)
×
27

NEW
28
      try {
×
NEW
29
        const response = await fetch(`/assets/help/${locale}/${page}.md`)
×
NEW
30
        const contentType = response.headers.get('Content-Type')
×
31
        
NEW
32
        if (contentType && !contentType.includes('markdown')) {
×
NEW
33
          throw ERROR_NOT_FOUND
×
34
        }
35
        
NEW
36
        if (response.status === 200 || response.status === 304) {
×
NEW
37
          const text = await response.text()
×
NEW
38
          setMarkdownContent(text)
×
NEW
39
          setIsLoading(false)
×
NEW
40
        } else if (response.status === 404) {
×
NEW
41
          setError(ERROR_NOT_FOUND)
×
NEW
42
          setIsLoading(false)
×
43
        } else {
NEW
44
          throw new Error('Cannot fetch help page')
×
45
        }
46
      } catch (err) {
NEW
47
        setError(err)
×
NEW
48
        setIsLoading(false)
×
49
      }
50
    }
51

NEW
52
    fetchHelpPage()
×
53
  }, [locale, page])
54

NEW
55
  if (isLoading) {
×
NEW
56
    return <LoadingFrame />
×
57
  }
58
  
NEW
59
  if (error) {
×
NEW
60
    return <ErrorView canGoBack={false} error={error} />
×
61
  }
62
  
NEW
63
  return (
×
64
    <Markdown
65
      className="content"
66
      remarkPlugins={[remarkGfm]}
67
      components={{
68
        h1: (props) => (
NEW
69
          <h1
×
70
            className="text-4xl mb-8 mt-12 text-gray-800 dark:text-foreground font-bold"
71
            {...props}
72
          />
73
        ),
74
        h2: (props) => (
NEW
75
          <h2
×
76
            className="text-3xl font-bold mt-8 mb-6 text-gray-700 dark:text-foreground"
77
            {...props}
78
          />
79
        ),
80
        h3: (props) => (
NEW
81
          <h3
×
82
            className="text-2xl font-bold mb-4 mt-6 text-gray-600 dark:text-foreground"
83
            {...props}
84
          />
85
        ),
86
        h4: (props) => (
NEW
87
          <h4
×
88
            className="text-xl mb-4 mt-6 text-gray-600 dark:text-foreground font-semibold"
89
            {...props}
90
          />
91
        ),
92
        p: (props) => (
NEW
93
          <p
×
94
            className="text-lg leading-relaxed text-gray-600 dark:text-foreground my-6"
95
            {...props}
96
          />
97
        ),
98
        ul: (props) => (
NEW
99
          <ul
×
100
            className="list-disc list-outside ml-6 mb-6 space-y-2 text-gray-600 dark:text-foreground"
101
            {...props}
102
          />
103
        ),
104
        ol: (props) => (
NEW
105
          <ol
×
106
            className="list-decimal list-outside ml-6 mb-6 space-y-2 text-gray-600 dark:text-foreground"
107
            {...props}
108
          />
109
        ),
110
        // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
NEW
111
        li: ({ node, ...props }) => <li className="leading-relaxed mb-2" {...props} />,
×
112
        // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
113
        blockquote: ({ node, ...props }) => (
NEW
114
          <blockquote
×
115
            className="border-l-4 border-blue-400 dark:border-blue-500 bg-blue-50 dark:bg-blue-950/30 text-gray-600 dark:text-foreground px-6 py-1 mb-6 rounded-r italic leading-relaxed"
116
            {...props}
117
          />
118
        ),
119
        // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
120
        code: ({ node, className, children, ...props }) => {
NEW
121
          return typeof children === 'string' && children.length < 30 ? (
×
122
            <code
123
              className="bg-gray-100 dark:bg-accent text-pink-600 dark:text-pink-400 px-2 py-0.5 rounded font-mono text-sm"
124
              {...props}
125
            >
126
              {children}
127
            </code>
128
          ) : (
129
            <blockquote
130
              className="border-l-4 border-blue-400 dark:border-blue-500 bg-blue-50 dark:bg-blue-950/30 text-gray-600 dark:text-foreground px-6 py-3 mb-6 rounded-r italic leading-relaxed"
131
              {...props}
132
            >
133
              {children}
134
            </blockquote>
135
          )
136
        },
137
        // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
138
        a: ({ node, href, ...props }) =>
NEW
139
          isExternal(window.location.href, href) || isDownloadableFile(href) ? (
×
140
            <ExternalLinkNewTab className="underline" href={href} {...props} />
141
          ) : (
142
            <Link className="underline" to={href} onClick={onLinkClick} {...props} />
143
          ),
144
        // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
145
        table: ({ node, ...props }) => (
NEW
146
          <div className="overflow-x-auto mb-6">
×
147
            <table
148
              className="min-w-full border-collapse bg-white dark:bg-background shadow-sm dark:shadow-md rounded-lg"
149
              {...props}
150
            />
151
          </div>
152
        ),
153
        // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
154
        thead: ({ node, ...props }) => (
NEW
155
          <thead
×
156
            className="bg-gray-50 dark:bg-accent border-b border-gray-200 dark:border-border"
157
            {...props}
158
          />
159
        ),
160
        // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
161
        tr: ({ node, ...props }) => (
NEW
162
          <tr
×
163
            className="border-b border-gray-100 dark:border-border hover:bg-gray-50 dark:hover:bg-accent transition-colors duration-150"
164
            {...props}
165
          />
166
        ),
167
        // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
168
        th: ({ node, ...props }) => (
NEW
169
          <th
×
170
            className="p-3 font-medium text-left text-gray-700 dark:text-foreground"
171
            {...props}
172
          />
173
        ),
174
        // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
175
        td: ({ node, ...props }) => (
NEW
176
          <td className="p-3 text-gray-600 dark:text-foreground" {...props} />
×
177
        ),
178
      }}
179
    >
180
      {markdownContent}
181
    </Markdown>
182
  )
183
}
184

185
HelpPageContent.propTypes = {
×
186
  page: PropTypes.string.isRequired,
187
  onLinkClick: PropTypes.func,
188
  locale: PropTypes.string.isRequired,
189
}
190

191
export default HelpPageContent
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