summaryrefslogtreecommitdiffstats
path: root/public/prism/prism-csp.js
blob: ed8c8523e7b78e8435391c63ed887bfaecdc4c1b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
/**
 * Original by Scott Helme.
 *
 * Reference: https://scotthelme.co.uk/csp-cheat-sheet/
 *
 * Supports the following:
 *  - https://www.w3.org/TR/CSP1/
 *  - https://www.w3.org/TR/CSP2/
 *  - https://www.w3.org/TR/CSP3/
 */

(function (Prism) {
  /**
   * @param {string} source
   * @returns {RegExp}
   */
  function value(source) {
    return RegExp(
      /([ \t])/.source + '(?:' + source + ')' + /(?=[\s;]|$)/.source,
      'i'
    );
  }

  Prism.languages.csp = {
    directive: {
      pattern:
        /(^|[\s;])(?:base-uri|block-all-mixed-content|(?:child|connect|default|font|frame|img|manifest|media|object|prefetch|script|style|worker)-src|disown-opener|form-action|frame-(?:ancestors|options)|input-protection(?:-(?:clip|selectors))?|navigate-to|plugin-types|policy-uri|referrer|reflected-xss|report-(?:to|uri)|require-sri-for|sandbox|(?:script|style)-src-(?:attr|elem)|upgrade-insecure-requests)(?=[\s;]|$)/i,
      lookbehind: true,
      alias: 'property',
    },
    scheme: {
      pattern: value(/[a-z][a-z0-9.+-]*:/.source),
      lookbehind: true,
    },
    none: {
      pattern: value(/'none'/.source),
      lookbehind: true,
      alias: 'keyword',
    },
    nonce: {
      pattern: value(/'nonce-[-+/\w=]+'/.source),
      lookbehind: true,
      alias: 'number',
    },
    hash: {
      pattern: value(/'sha(?:256|384|512)-[-+/\w=]+'/.source),
      lookbehind: true,
      alias: 'number',
    },
    host: {
      pattern: value(
        /[a-z][a-z0-9.+-]*:\/\/[^\s;,']*/.source +
          '|' +
          /\*[^\s;,']*/.source +
          '|' +
          /[a-z0-9-]+(?:\.[a-z0-9-]+)+(?::[\d*]+)?(?:\/[^\s;,']*)?/.source
      ),
      lookbehind: true,
      alias: 'url',
      inside: {
        important: /\*/,
      },
    },
    keyword: [
      {
        pattern: value(/'unsafe-[a-z-]+'/.source),
        lookbehind: true,
        alias: 'unsafe',
      },
      {
        pattern: value(/'[a-z-]+'/.source),
        lookbehind: true,
        alias: 'safe',
      },
    ],
    punctuation: /;/,
  };
})(Prism);
pics, thematics, title, } = post; const meta: ArticleMeta = { author, commentCount: commentCount || undefined, dates, readingTime: info.readingTime, thematics, wordsCount: info.wordsCount, }; const articleUrl = `${settings.url}${router.asPath}`; const webpageSchema: WebPage = { '@id': `${articleUrl}`, '@type': 'WebPage', breadcrumb: { '@id': `${settings.url}/#breadcrumb` }, lastReviewed: dates.update, name: seo.title, description: seo.metaDesc, reviewedBy: { '@id': `${settings.url}/#branding` }, url: `${articleUrl}`, isPartOf: { '@id': `${settings.url}`, }, }; const blogSchema: Blog = { '@id': `${settings.url}/#blog`, '@type': 'Blog', blogPost: { '@id': `${settings.url}/#article` }, isPartOf: { '@id': `${articleUrl}`, }, license: 'https://creativecommons.org/licenses/by-sa/4.0/deed.fr', }; const publicationDate = new Date(dates.publication); const updateDate = new Date(dates.update); const blogPostSchema: BlogPosting = { '@id': `${settings.url}/#article`, '@type': 'BlogPosting', name: title, description: intro, articleBody: content, author: { '@id': `${settings.url}/#branding` }, commentCount: commentCount || undefined, copyrightYear: publicationDate.getFullYear(), creator: { '@id': `${settings.url}/#branding` }, dateCreated: publicationDate.toISOString(), dateModified: updateDate.toISOString(), datePublished: publicationDate.toISOString(), discussionUrl: `${articleUrl}/#comments`, editor: { '@id': `${settings.url}/#branding` }, headline: title, image: featuredImage?.sourceUrl, inLanguage: settings.locales.defaultLocale, isPartOf: { '@id': `${settings.url}/blog`, }, license: 'https://creativecommons.org/licenses/by-sa/4.0/deed.fr', mainEntityOfPage: { '@id': `${articleUrl}` }, thumbnailUrl: featuredImage?.sourceUrl, }; const schemaJsonLd: Graph = { '@context': 'https://schema.org', '@graph': [webpageSchema, blogSchema, blogPostSchema], }; const copyText = intl.formatMessage({ defaultMessage: 'Copy', description: 'Prism: copy button text (no clicked)', id: '/ly3AC', }); const copiedText = intl.formatMessage({ defaultMessage: 'Copied!', description: 'Prism: copy button text (clicked)', id: 'OV9r1K', }); const errorText = intl.formatMessage({ defaultMessage: 'Use Ctrl+c to copy', description: 'Prism: error text', id: 'z9qkcQ', }); const darkTheme = intl.formatMessage({ defaultMessage: 'Dark Theme 🌙', description: 'Prism: toggle dark theme button text', id: 'nFMdWI', }); const lightTheme = intl.formatMessage({ defaultMessage: 'Light Theme 🌞', description: 'Prism: toggle light theme button text', id: 'Ua2g2p', }); return ( <> <Head> <title>{seo.title}</title> <meta name="description" content={seo.metaDesc} /> <meta property="og:url" content={`${articleUrl}`} /> <meta property="og:type" content="article" /> <meta property="og:title" content={title} /> <meta property="og:description" content={intro} /> <meta property="og:image" content={featuredImage?.sourceUrl} /> <meta property="og:image:alt" content={featuredImage?.altText} /> </Head> <Script id="schema-article" type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(schemaJsonLd) }} /> <article id="article" className={styles.article} data-prismjs-copy={copyText} data-prismjs-copy-success={copiedText} data-prismjs-copy-error={errorText} data-prismjs-color-scheme-dark={darkTheme} data-prismjs-color-scheme-light={lightTheme} > <PostHeader intro={intro} meta={meta} title={title} /> <Sidebar position="left" ariaLabel={intl.formatMessage({ defaultMessage: 'Table of Contents', description: 'ArticlePage: ToC sidebar aria-label', id: '9nhYRA', })} > <ToC /> </Sidebar> <div className={styles.body} dangerouslySetInnerHTML={{ __html: content }} ></div> <PostFooter topics={topics} /> <Sidebar position="right" ariaLabel={intl.formatMessage({ defaultMessage: 'Sidebar', description: 'ArticlePage: right sidebar aria-label', id: 'JeYOeA', })} > <Sharing title={title} excerpt={intro} /> </Sidebar> <section id="comments" className={styles.comments}> <CommentsList articleId={databaseId} comments={comments} /> <CommentForm articleId={databaseId} /> </section> </article> </> ); }; SingleArticle.getLayout = getLayout; interface PostParams extends ParsedUrlQuery { slug: string; } export const getStaticProps: GetStaticProps = async ( context: GetStaticPropsContext ) => { const { locale } = context; const translation = await loadTranslation(locale); const { slug } = context.params as PostParams; const post = await getPostBySlug(slug); const comments = await getCommentsByPostId(post.databaseId); const breadcrumbTitle = post.title; return { props: { breadcrumbTitle, comments, post, translation, }, }; }; export const getStaticPaths: GetStaticPaths = async () => { const allSlugs = await getAllPostsSlug(); const paths = getFormattedPaths(allSlugs); return { paths, fallback: true, }; }; export default SingleArticle;