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

mozilla / blurts-server / #12980

pending completion
#12980

push

circleci

Vinnl
Add redundant social media preview tags

Not all social media websites implement the same (or any) fallbacks
for preview cards, so we have to add them redundantly to make sure
they show up everywhere.

282 of 1595 branches covered (17.68%)

Branch coverage included in aggregate %.

959 of 4308 relevant lines covered (22.26%)

1.85 hits per line

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

0.0
/src/views/mainLayout.js
1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
 * License, v. 2.0. If a copy of the MPL was not distributed with this
3
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4

5
import AppConstants from '../app-constants.js'
6
import { getMessage, getLocale } from '../utils/fluent.js'
7

8
const mainLayout = data => `
×
9
<!doctype html>
10
<html lang=${getLocale()}>
11
  <head>
12
    <title>${getMessage('brand-fx-monitor')}</title>
13
    <style>html {display: none;}</style>
14

15
    <meta charset='utf-8'>
16
    <meta name='viewport' content='width=320, initial-scale=1'>
17
    <meta name='description' content='${getMessage('meta-desc')}'>
18
    <meta name='twitter:card' content='summary_large_image'>
19
    <meta name='twitter:title' content='${getMessage('brand-fx-monitor')}'>
20
    <meta name='twitter:description' content='${getMessage('meta-desc')}'>
21
    <meta name='twitter:image' content='${AppConstants.SERVER_URL}/images/og-image.webp'>
22
    <meta property='og:title' content='${getMessage('brand-fx-monitor')}'>
23
    <meta property='og:description' content='${getMessage('meta-desc')}'>
24
    <meta property='og:site_name' content='${getMessage('brand-fx-monitor')}'>
25
    <meta property='og:type' content='website'>
26
    <meta property='og:url' content='${AppConstants.SERVER_URL}'>
27
    <meta property='og:image' content='${AppConstants.SERVER_URL}/images/og-image.webp'>
28

29
    <link rel='preload' href='/fonts/Metropolis-Bold.woff2' as='font' type='font/woff2' crossorigin>
30
    <link rel='preload' href='/fonts/Inter-Regular-latin.woff2' as='font' type='font/woff2' crossorigin>
31
    <link rel='stylesheet' href='/css/index.css' type='text/css'>
32
    <link rel='stylesheet' href='/css/partials/${data.partial.name}.css' type='text/css'>
33
    <link rel='icon' href='/images/favicon-16.webp' sizes='16x16'>
34
    <link rel='icon' href='/images/favicon-32.webp' sizes='32x32'>
35
    <link rel='icon' href='/images/favicon-48.webp' sizes='48x48'>
36
    <link rel='icon' href='/images/favicon-96.webp' sizes='96x96'>
37
    <link rel='icon' href='/images/favicon-144.webp' sizes='144x144'>
38
    <link rel='icon' href='/images/favicon-256.webp' sizes='256x256'>
39
    <link rel='apple-touch-icon' href='/images/apple-touch-icon.webp' sizes='180x180'>
40

41
    <script src='/js/index.js' type='module'></script>
42

43
    <!-- Google tag (gtag.js) -->
44
    <script nonce='${data.nonce}' type='module'>
45
      if (navigator.doNotTrack !== '1') {
46
        (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
47
        new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
48
        j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
49
        'https://www.googletagmanager.com/gtag/js?id='+i+dl;var n=d.querySelector('[nonce]');
50
        n&&j.setAttribute('nonce',n.nonce||n.getAttribute('nonce'));f.parentNode.insertBefore(j,f);
51
        })(window,document,'script','dataLayer','${AppConstants.GA4_MEASUREMENT_ID}');
52
        function gtag(){dataLayer.push(arguments);}
53
        gtag('js', new Date()); gtag('config', '${AppConstants.GA4_MEASUREMENT_ID}');
54
        window.gtag = gtag
55
      } else {
56
        function gtag() {
57
          console.debug("Google Analytics disbled by DNT")
58
        }
59
        window.gtag = gtag
60
      }
61
      </script>
62
    <!-- End Google tag (gtag.js) -->
63
  </head>
64
  <body>
65
    <header>
66
      <a href='/user/breaches'>
67
        <img class='monitor-logo' srcset='/images/monitor-logo-transparent.webp 213w, /images/monitor-logo-transparent@2x.webp 425w' width='213' height='33' alt='${getMessage('brand-fx-monitor')}'>
68
      </a>
69
      <div class='nav-wrapper'>
70
        <button class='nav-toggle'>
71
          <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 8' width='20'>
72
            <path d='M1 1h8M1 4h8M1 7h8' stroke='#000' stroke-width='1' stroke-linecap='round'/>
73
          </svg>
74
        </button>
75
        ${userMenu(data)}
76
      </div>
77
    </header>
78

79
    <nav class='site-nav'>
80
      <div class='pages-nav'>
81
        <a href='/user/breaches' class='nav-item ${data.partial.name === 'breaches' ? 'current' : ''}'>
×
82
          <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
83
            <path fill-rule="evenodd" clip-rule="evenodd" d="M10.5942 20.049C9.87439 21.3816 10.8394 22.9996 12.3539 22.9996H19.657C21.1692 22.9996 22.1344 21.3862 21.4193 20.0538L17.7796 13.2724C17.0264 11.8689 15.0148 11.8662 14.2577 13.2676L10.5942 20.049Z" fill="white" stroke="currentcolor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
84
            <path fill-rule="evenodd" clip-rule="evenodd" d="M16 21C16.5523 21 17 20.5523 17 20C17 19.4477 16.5523 19 16 19C15.4477 19 15 19.4477 15 20C15 20.5523 15.4477 21 16 21Z" fill="currentcolor"/>
85
            <path d="M16 17V16" stroke="currentcolor" stroke-width="2" stroke-linecap="round"/>
86
            <path d="M7 22H5C3.89543 22 3 21.1046 3 20V11C3 9.89543 3.89543 9 5 9H19C20.1046 9 21 9.89543 21 11V13" stroke="currentcolor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
87
            <path d="M7 9V7C7 4.23858 9.23858 2 12 2C14.7614 2 17 4.23858 17 7V9" stroke="currentcolor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
88
          </svg>
89
          ${getMessage('site-nav-breaches-link')}
90
        </a>
91
      </div>
92
      <div class='meta-nav'>
93
        <a href='/user/settings' class='nav-item ${data.partial.name === 'settings' ? 'current' : ''}'>
×
94
          ${getMessage('site-nav-settings-link')}
95
        </a>
96
        <a target="_blank" href='https://support.mozilla.org/kb/firefox-monitor' class='nav-item'>
97
          ${getMessage('site-nav-help-link')}
98
        </a>
99
      </div>
100
      <div class='callouts'>
101
        <p>${getMessage('site-nav-ad-callout')}</p>
102
        <a href='https://relay.firefox.com/?utm_medium=mozilla-websites&utm_source=monitor&utm_campaign=&utm_content=nav-bar-global' target='_blank'><img src='/images/logo-relay.svg' width='416' height='92' alt='${getMessage('brand-relay')}'></a>
103
        <a href='https://www.mozilla.org/products/vpn?utm_medium=mozilla-websites&utm_source=monitor&utm_campaign=&utm_content=nav-bar-global' target='_blank'><img src='/images/logo-vpn.svg' width='232' height='48' alt='${getMessage('brand-mozilla-vpn')}'></a>
104
      </div>
105
    </nav>
106

107
    <main data-partial='${data.partial.name}'>
108
      ${data.partial(data)}
109
    </main>
110
    <footer>
111
      <a href='https://www.mozilla.org' target='_blank'>
112
        <img src='/images/moz-logo-1color-white-rgb-01.svg' width='100' height='29' loading='lazy' alt='${getMessage('mozilla')}'>
113
      </a>
114
      <menu>
115
        <li><a href='/breaches'>${getMessage('footer-nav-all-breaches')}</a></li>
116
        <li><a href='https://support.mozilla.org/kb/firefox-monitor-faq' target='_blank'>FAQ</a></li>
117
        <li><a href='https://www.mozilla.org/privacy/firefox-monitor' target='_blank'>${getMessage('terms-and-privacy')}</a></li>
118
        <li><a href='https://github.com/mozilla/blurts-server' target='_blank'>${getMessage('github')}</a></li>
119
      </menu>
120
    </footer>
121
  </body>
122
</html>
123
`
124

125
const userMenu = data => `
×
126
<div class='user-menu-wrapper' tabindex='-1'>
127
  <button
128
    aria-expanded='false'
129
    aria-haspopup='true'
130
    class='user-menu-button'
131
    title='${getMessage('menu-button-title')}'
132
  >
133
    <img src='${data.fxaProfile?.avatar}' alt='${getMessage('menu-button-alt')}' />
134
  </button>
135
  <menu
136
    aria-label='${getMessage('menu-list-accessible-label')}'
137
    class='user-menu-container user-menu-popover'
138
    role='navigation'
139
    hidden
140
  >
141
    <li tabindex='1'>
142
      <a href='${AppConstants.FXA_SETTINGS_URL}' target='_blank' class='user-menu-header'>
143
        <b class='user-menu-email'>${data.fxaProfile?.email}</b>
144
        <div class='user-menu-subtitle'>
145
          ${getMessage('menu-item-fxa')}
146
          <img src='/images/icon-open-in.svg' />
147
        </div>
148
      </a>
149
    </li>
150
    <hr>
151
    <li>
152
      <a href='/user/settings' class='user-menu-link'>
153
        <img src='/images/icon-settings.svg' />
154
        ${getMessage('menu-item-settings')}
155
      </a>
156
    </li>
157
    <li>
158
      <a href='https://support.mozilla.org/kb/firefox-monitor' target='_blank' class='user-menu-link'>
159
        <img src='/images/icon-help.svg' />
160
        ${getMessage('menu-item-help')}
161
      </a>
162
    </li>
163
    <li>
164
      <a href='/user/logout' class='user-menu-link'>
165
        <img src='/images/icon-signout.svg' />
166
        ${getMessage('menu-item-logout')}
167
      </a>
168
    </li>
169
  </menu>
170
</div>
171
`
172

173
export { mainLayout }
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

© 2025 Coveralls, Inc