diff --git a/packages/code-du-travail-frontend/__tests__/__snapshots__/fiche-ministere-travail.test.js.snap b/packages/code-du-travail-frontend/__tests__/__snapshots__/fiche-ministere-travail.test.js.snap index 2df7e423c1..fb3df50caa 100644 --- a/packages/code-du-travail-frontend/__tests__/__snapshots__/fiche-ministere-travail.test.js.snap +++ b/packages/code-du-travail-frontend/__tests__/__snapshots__/fiche-ministere-travail.test.js.snap @@ -2346,7 +2346,9 @@ exports[` should render 1`] = `
-
+
lorem ipsum intro
diff --git a/packages/code-du-travail-frontend/__tests__/__snapshots__/glossaire-[slug].test.js.snap b/packages/code-du-travail-frontend/__tests__/__snapshots__/glossaire-[slug].test.js.snap index 23853cfb0a..a22b86c062 100644 --- a/packages/code-du-travail-frontend/__tests__/__snapshots__/glossaire-[slug].test.js.snap +++ b/packages/code-du-travail-frontend/__tests__/__snapshots__/glossaire-[slug].test.js.snap @@ -1384,7 +1384,9 @@ exports[` should render 1`] = ` Définition -
+

Accord collectif de travail conclu au niveau d'une entreprise.

diff --git a/packages/code-du-travail-frontend/__tests__/__snapshots__/modeles-de-courriers-[slug].test.js.snap b/packages/code-du-travail-frontend/__tests__/__snapshots__/modeles-de-courriers-[slug].test.js.snap index 84bcf06c67..aab6c41fb8 100644 --- a/packages/code-du-travail-frontend/__tests__/__snapshots__/modeles-de-courriers-[slug].test.js.snap +++ b/packages/code-du-travail-frontend/__tests__/__snapshots__/modeles-de-courriers-[slug].test.js.snap @@ -2435,7 +2435,9 @@ exports[` should render 1`] = `
-
+
un description
@@ -2508,7 +2510,9 @@ exports[` should render 1`] = `
-
+

youhou

diff --git a/packages/code-du-travail-frontend/package.json b/packages/code-du-travail-frontend/package.json index 56093b32c9..df84e6a73b 100644 --- a/packages/code-du-travail-frontend/package.json +++ b/packages/code-du-travail-frontend/package.json @@ -39,6 +39,7 @@ "@socialgouv/reference-article": "^1.0.1", "@ungap/url-search-params": "^0.2.2", "@zeit/next-source-maps": "^0.0.3", + "cheerio": "^1.0.0-rc.10", "date-fns": "^2.22.1", "debounce-promise": "^3.1.2", "final-form": "^4.20.2", @@ -73,7 +74,8 @@ "styled-components": "^5.3.0", "typescript": "^4.3.5", "unified": "^9.2.2", - "uuid": "^8.3.2" + "uuid": "^8.3.2", + "xss": "^1.0.10" }, "devDependencies": { "@babel/core": "^7.14.8", diff --git a/packages/code-du-travail-frontend/pages/_app.js b/packages/code-du-travail-frontend/pages/_app.js index 8e64b57623..89db6524e4 100644 --- a/packages/code-du-travail-frontend/pages/_app.js +++ b/packages/code-du-travail-frontend/pages/_app.js @@ -2,6 +2,7 @@ import "katex/dist/katex.min.css"; // eslint-disable-next-line import/no-extraneous-dependencies import "react-image-lightbox/style.css"; +import "../public/static/modeles.css"; import * as Sentry from "@sentry/nextjs"; import { GlobalStyles, ThemeProvider } from "@socialgouv/cdtn-ui"; diff --git a/packages/code-du-travail-frontend/public/static/modeles.css b/packages/code-du-travail-frontend/public/static/modeles.css new file mode 100644 index 0000000000..48878aaa86 --- /dev/null +++ b/packages/code-du-travail-frontend/public/static/modeles.css @@ -0,0 +1,8 @@ +.courrier-expediteur {display: flex; align-items: flex-start; flex-direction:column;} +.courrier-destinataire {display: flex; align-items: flex-end; flex-direction:column;} +.courrier-signature {display: flex; flex-direction:column; align-items: flex-end;} +.title-center {display: flex; align-items: center; flex-direction:column; font-size: 1.8rem; font-weight:bold} +.center {display: flex; align-items: center; flex-direction:column; } +.checklist { list-style-image: url(data:image/svg+xml;,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%221rem%22%20height%3D%221rem%22%20viewBox%3D%220%200%2011%2011%22%3E%3Cpath%20fill%3D%22currentColor%22%20d%3D%22M2%202h10v10H2z%22%2F%3E%3Cpath%20fill%3D%22%23fff%22%20stroke%3D%22currentColor%22%20stroke-width%3D%22.5%22%20d%3D%22M1%201h9v9H1z%22%2F%3E%3C%2Fsvg%3E);} +.editable {color: var(--color-secondary)} +.options {font-style: italic; color: var(--color-altText)} \ No newline at end of file diff --git a/packages/code-du-travail-frontend/src/common/Html.js b/packages/code-du-travail-frontend/src/common/Html.js deleted file mode 100644 index 4888e78272..0000000000 --- a/packages/code-du-travail-frontend/src/common/Html.js +++ /dev/null @@ -1,16 +0,0 @@ -import React from "react"; -import styled from "styled-components"; - -const Html = ({ children, inline = false, ...props }) => { - return inline ? ( - - ) : ( -
- ); -}; - -export default Html; - -const InlineBlockDiv = styled.div` - display: inline-block; -`; diff --git a/packages/code-du-travail-frontend/src/common/Html.tsx b/packages/code-du-travail-frontend/src/common/Html.tsx new file mode 100644 index 0000000000..88ffe6a655 --- /dev/null +++ b/packages/code-du-travail-frontend/src/common/Html.tsx @@ -0,0 +1,54 @@ +import React from "react"; +import styled from "styled-components"; +import xss, { escapeAttrValue } from "xss"; + +import { htmlParser } from "../lib/html"; + +type Props = { + children: string; + inline?: boolean; +}; + +/** + * List of tags that are allowed in the HTML + * @type {string[]} + * webcomponent-tooltip is used as an overlay for the definition of the words + */ +const whiteListTags = ["webcomponent-tooltip", "webcomponent-tooltip-cc"]; + +/** + * List of attributes that are allowed for the tags scan in the HTML + * @type {string[]} + * class is used for modeles-de-courrier + */ +const whiteListAttr = ["class", "rel", "href", "target"]; + +const Html = ({ children, inline = false, ...props }: Props): JSX.Element => { + return ( +
whiteTag === tag)) { + return html; + } + }, + onTagAttr: function (_tag, name, value, _isWhiteAttr) { + if (whiteListAttr.some((whiteAttr) => whiteAttr === name)) { + return name + '="' + escapeAttrValue(value) + '"'; + } + }, + }), + }} + /> + ); +}; + +export default Html; + +const Div = styled.div` + ${({ isInline }: { isInline: boolean }) => + isInline && "display: inline-block;"}; +`; diff --git a/packages/code-du-travail-frontend/src/common/__tests__/__snapshots__/Answer.test.js.snap b/packages/code-du-travail-frontend/src/common/__tests__/__snapshots__/Answer.test.js.snap index 7e2f1a1f38..dbec33107c 100644 --- a/packages/code-du-travail-frontend/src/common/__tests__/__snapshots__/Answer.test.js.snap +++ b/packages/code-du-travail-frontend/src/common/__tests__/__snapshots__/Answer.test.js.snap @@ -877,11 +877,15 @@ exports[` should renders 1`] = `
-
+
intro de l'article
-
+

@@ -2185,11 +2189,15 @@ exports[` should renders a breadcrumbs 1`] = `

-
+
intro de l'article
-
+

@@ -3243,11 +3251,15 @@ exports[` should renders back to results link 1`] = `

-
+
intro de l'article
-
+

@@ -4414,11 +4426,15 @@ exports[` should renders related content 1`] = `

-
+
intro de l'article
-
+

@@ -5631,11 +5647,15 @@ exports[` should renders tooltip 1`] = `

-
+
intro de l'article
-
+

@@ -6690,11 +6710,15 @@ exports[` should renders tooltip for words with diacritics without bre

-
+
intro de l'article
-
+

@@ -7749,11 +7773,15 @@ exports[` should renders tooltip without breaking a tag 1`] = `

-
+
intro de l'article
-
+

@@ -8809,11 +8837,15 @@ exports[` should renders tooltip without breaking previous word 1`] =

-
+
intro de l'article
-
+

diff --git a/packages/code-du-travail-frontend/src/common/__tests__/__snapshots__/Html.test.js.snap b/packages/code-du-travail-frontend/src/common/__tests__/__snapshots__/Html.test.js.snap index f1f699e3da..f47f40589d 100644 --- a/packages/code-du-travail-frontend/src/common/__tests__/__snapshots__/Html.test.js.snap +++ b/packages/code-du-travail-frontend/src/common/__tests__/__snapshots__/Html.test.js.snap @@ -2,7 +2,9 @@ exports[` should render 1`] = `

-
+
Hello diff --git a/packages/code-du-travail-frontend/src/conventions/Convention/__tests__/__snapshots__/index.test.js.snap b/packages/code-du-travail-frontend/src/conventions/Convention/__tests__/__snapshots__/index.test.js.snap index beffff49de..31c2e0436b 100644 --- a/packages/code-du-travail-frontend/src/conventions/Convention/__tests__/__snapshots__/index.test.js.snap +++ b/packages/code-du-travail-frontend/src/conventions/Convention/__tests__/__snapshots__/index.test.js.snap @@ -1037,7 +1037,9 @@ exports[` renders 1`] = `
-
+

Les jours fériés légaux sont payés dans les conditions prévues par la loi pour le 1er Mai, y compris lorsque les jours fériés tombent pendant une période de chômage-intempéries ou pendant le congé payé.

@@ -1168,7 +1170,9 @@ exports[` renders 1`] = `
-
+

Les salariées ont droit à un maintien de salaire à 100 % du dernier salaire mensuel, après déduction des indemnités de la sécurité sociale ou de tout autre régime de prévoyance, pendant une durée maximale de 6 semaines avant la date présumée de l'accouchement et de 10 semaines après.

@@ -1365,7 +1369,9 @@ exports[` renders 1`] = `
-
+

Les salariés ont droit à des congés exceptionnels avec maintien de la rémunération, pour les événements familiaux suivants :

@@ -1599,7 +1605,9 @@ exports[` renders 1`] = `
-
+

En cas de licenciement, la durée du préavis est égale à :

@@ -1778,7 +1786,9 @@ exports[` renders 1`] = `
-
+

En cas de démission, la durée du préavis est égale à :

@@ -1915,7 +1925,9 @@ exports[` renders 1`] = `
-
+

En cas de départ à la retraite du salarié, la durée du préavis est égale à 2 mois.

@@ -2063,7 +2075,9 @@ exports[` renders 1`] = `
-
+

En cas de mise à la retraite du salarié, la durée du préavis est égale à 2 mois.

@@ -2211,7 +2225,9 @@ exports[` renders 1`] = `
-
+

Si l'employeur ou le salarié ne respecte pas le préavis de licenciement ou de démission, l'autre partie peut obtenir le paiement d'une indemnité égale au salaire correspondant à la durée du préavis restant à courir.

@@ -2332,7 +2348,9 @@ exports[` renders 1`] = `
-
+

Pendant le préavis, l'ouvrier licencié ou démissionnaire est autorisé, s'il en fait la demande, à s'absenter pour rechercher un nouvel emploi, pendant :

@@ -2561,7 +2579,9 @@ exports[` renders 1`] = `
-
+

La durée de la période d'essai a été fixée par une convention collective conclue avant le 26 juin 2008.

@@ -2690,7 +2710,9 @@ exports[` renders 1`] = `
-
+

L'ancienneté du salarié tient compte de :

@@ -2890,7 +2912,9 @@ exports[` renders 1`] = `
-
+

L'employeur doit remettre au salarié, dans les 8 jours qui suivent son embauche, un document écrit (contrat de travail ou lettre d'engagement, ...) précisant :

@@ -3082,7 +3106,9 @@ exports[` renders 1`] = `
-
+

L'employeur doit remettre au salarié, dans les 8 jours qui suivent son embauche, un document écrit (contrat de travail ou lettre d'engagement, ...) précisant les conditions du poste. Ce document doit être accepté et signé par l'employeur et le salarié.

@@ -3203,7 +3229,9 @@ exports[` renders 1`] = `
-
+

La convention collective ne prévoit pas le recours au contrat d'usage.

@@ -3293,7 +3321,9 @@ exports[` renders 1`] = `
-
+

Le salarié doit s'engager dans le contrat de travail à ne pas avoir d'activité professionnelle susceptible de concurrencer celle de son employeur ou qui dépasserait le nombre d'heures de travail maximum prévu par le code du travail.

@@ -3481,7 +3511,9 @@ exports[` renders 1`] = `
-
+

La convention collective ne prévoit pas de prime pour travaux dangereux ni de prime pour travaux insalubres.

@@ -3562,7 +3594,9 @@ exports[` renders 1`] = `
-
+

La convention collective prévoit une @@ -3707,7 +3741,9 @@ exports[` renders 1`] = `

-
+

La convention collective ne prévoit pas de prime d'ancienneté.

@@ -3921,7 +3957,9 @@ exports[` renders 1`] = `
-
+

Le salarié a droit à un maintien de salaire pendant l'arrêt maladie dans les conditions suivantes.

@@ -4434,7 +4472,9 @@ exports[` renders 1`] = `
-
+

En cas d'accident du travail ou de maladie professionnelle, le code du travail s'applique.

diff --git a/packages/code-du-travail-frontend/src/lib/html.ts b/packages/code-du-travail-frontend/src/lib/html.ts new file mode 100644 index 0000000000..781de40af0 --- /dev/null +++ b/packages/code-du-travail-frontend/src/lib/html.ts @@ -0,0 +1,22 @@ +import cheerio from "cheerio"; + +export const htmlParser = (html: string): string => { + const $ = cheerio.load(html, null, false); + + // FIXME: Remove style from docx converter + $("style").remove(); + + $("dl").replaceWith(function () { + const src = $(this).find("source").attr("srcset"); + return src + ? `` + : $(this).html(); + }); + + $("a").each(() => { + const content = decodeURIComponent($(this).text()); + $(this).text(content); + }); + + return $.html(); +}; diff --git a/packages/code-du-travail-frontend/src/lib/index.ts b/packages/code-du-travail-frontend/src/lib/index.ts index 5ae023ffe3..dc8ff10669 100644 --- a/packages/code-du-travail-frontend/src/lib/index.ts +++ b/packages/code-du-travail-frontend/src/lib/index.ts @@ -1,2 +1,3 @@ +export * from "./html"; export * from "./tracking"; export * from "./url"; diff --git a/packages/code-du-travail-frontend/src/outils/ConventionCollective/enterprise/EnterpriseButton.tsx b/packages/code-du-travail-frontend/src/outils/ConventionCollective/enterprise/EnterpriseButton.tsx index 1c232db5db..838ad4e589 100644 --- a/packages/code-du-travail-frontend/src/outils/ConventionCollective/enterprise/EnterpriseButton.tsx +++ b/packages/code-du-travail-frontend/src/outils/ConventionCollective/enterprise/EnterpriseButton.tsx @@ -4,6 +4,7 @@ import Link from "next/link"; import React from "react"; import styled from "styled-components"; +import Html from "../../../common/Html"; import { Enterprise } from "../../../conventions/Search/api/enterprises.service"; import { ScreenType } from "../common/NavContext"; import { ResultItem } from "../common/ResultList"; @@ -52,22 +53,17 @@ export function EnterpriseButton({ > {showTitleWithHighlight ? ( - + <Title as="div" fontSize="hsmall" fontWeight="600"> + {highlightLabel} + ) : ( <> {simpleLabel} - + + {highlightLabel} + )} {activitePrincipale && ( @@ -96,12 +92,12 @@ const ItemButton = styled(ResultItem)` } `; -const Title = styled(Text)` +const Title = styled(Html)` padding-bottom: ${spacings.xsmall}; & b { font-weight: 700; } `; -const Subtitle = styled(Text)` +const Subtitle = styled(Html)` padding-bottom: ${spacings.xsmall}; `; diff --git a/yarn.lock b/yarn.lock index 9132cfa5bb..8aa92972d0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7735,6 +7735,11 @@ cssesc@^3.0.0: resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== +cssfilter@0.0.10: + version "0.0.10" + resolved "https://registry.yarnpkg.com/cssfilter/-/cssfilter-0.0.10.tgz#c6d2672632a2e5c83e013e6864a42ce8defd20ae" + integrity sha1-xtJnJjKi5cg+AT5oZKQs6N79IK4= + cssnano-preset-simple@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/cssnano-preset-simple/-/cssnano-preset-simple-3.0.0.tgz#e95d0012699ca2c741306e9a3b8eeb495a348dbe" @@ -21577,6 +21582,14 @@ xpath-builder@0.0.7: resolved "https://registry.yarnpkg.com/xpath-builder/-/xpath-builder-0.0.7.tgz#67d6bbc3f6a320ec317e3e6368c5706b6111deec" integrity sha1-Z9a7w/ajIOwxfj5jaMVwa2ER3uw= +xss@^1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/xss/-/xss-1.0.10.tgz#5cd63a9b147a755a14cb0455c7db8866120eb4d2" + integrity sha512-qmoqrRksmzqSKvgqzN0055UFWY7OKx1/9JWeRswwEVX9fCG5jcYRxa/A2DHcmZX6VJvjzHRQ2STeeVcQkrmLSw== + dependencies: + commander "^2.20.3" + cssfilter "0.0.10" + "xtend@>=4.0.0 <4.1.0-0", xtend@^4.0.0, xtend@^4.0.1, xtend@^4.0.2, xtend@~4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"