Просмотр исходного кода

Merge pull request #6523 from overleaf/jpa-translations-check-sanitize

[web] scripts/translations: add script for checking html sanitization

GitOrigin-RevId: d4b9c9a7eb1ed0ca9202b0cb6e4c33f3e73bd0e4
Timothée Alby 4 лет назад
Родитель
Сommit
58cf92620a

+ 42 - 0
services/web/scripts/translations/checkSanitizeOptions.js

@@ -0,0 +1,42 @@
+const Path = require('path')
+const fs = require('fs')
+const { sanitize } = require('./sanitize')
+
+async function main() {
+  let ok = true
+  const base = Path.join(__dirname, '/../../locales')
+  for (const name of await fs.promises.readdir(base)) {
+    if (name === 'README.md') continue
+    const blob = await fs.promises.readFile(
+      Path.join(__dirname, '/../../locales', name),
+      'utf-8'
+    )
+    const locales = JSON.parse(blob)
+
+    for (const key of Object.keys(locales)) {
+      const want = locales[key]
+      const got = sanitize(locales[key])
+      if (got !== want) {
+        if (want === 'Editor & PDF' && got === 'Editor & PDF') {
+          // Ignore this mismatch. React cannot handle escaped labels.
+          continue
+        }
+        ok = false
+        console.warn(`${name}: ${key}: want: ${want}`)
+        console.warn(`${name}: ${key}:  got: ${got}`)
+      }
+    }
+  }
+  if (!ok) {
+    throw new Error('Check the logs, some values changed.')
+  }
+}
+
+main()
+  .then(() => {
+    process.exit(0)
+  })
+  .catch(error => {
+    console.error(error)
+    process.exit(1)
+  })

+ 1 - 43
services/web/scripts/translations/download.js

@@ -1,7 +1,7 @@
 const path = require('path')
 const path = require('path')
 const { promises: fs } = require('fs')
 const { promises: fs } = require('fs')
 const oneSky = require('@brainly/onesky-utils')
 const oneSky = require('@brainly/onesky-utils')
-const sanitizeHtml = require('sanitize-html')
+const { sanitize } = require('./sanitize')
 const { withAuth } = require('./config')
 const { withAuth } = require('./config')
 
 
 async function run() {
 async function run() {
@@ -46,45 +46,3 @@ async function run() {
   }
   }
 }
 }
 run()
 run()
-
-/**
- * Sanitize a translation string to prevent injection attacks
- *
- * @param {string} input
- * @returns {string}
- */
-function sanitize(input) {
-  // Block Angular XSS
-  // Ticket: https://github.com/overleaf/issues/issues/4478
-  input = input.replace(/'/g, '’')
-  // Use left quote where (likely) appropriate.
-  input.replace(/ ’/g, ' ‘')
-
-  return sanitizeHtml(input, {
-    // Allow "replacement" tags (in the format <0>, <1>, <2>, etc) used by
-    // react-i18next to allow for HTML insertion via the Trans component.
-    // See: https://github.com/overleaf/developer-manual/blob/master/code/translations.md
-    // Unfortunately the sanitizeHtml library does not accept regexes or a
-    // function for the allowedTags option, so we are limited to a hard-coded
-    // number of "replacement" tags.
-    allowedTags: ['b', 'strong', 'a', 'code', ...range(10)],
-    allowedAttributes: {
-      a: ['href', 'class'],
-    },
-    textFilter(text) {
-      return text
-        .replace(/\{\{/, '&#123;&#123;')
-        .replace(/\}\}/, '&#125;&#125;')
-    },
-  })
-}
-
-/**
- * Generate a range of numbers as strings up to the given size
- *
- * @param {number} size Size of range
- * @returns {string[]}
- */
-function range(size) {
-  return Array.from(Array(size).keys()).map(n => n.toString())
-}

+ 45 - 0
services/web/scripts/translations/sanitize.js

@@ -0,0 +1,45 @@
+const sanitizeHtml = require('sanitize-html')
+
+/**
+ * Sanitize a translation string to prevent injection attacks
+ *
+ * @param {string} input
+ * @returns {string}
+ */
+function sanitize(input) {
+  // Block Angular XSS
+  // Ticket: https://github.com/overleaf/issues/issues/4478
+  input = input.replace(/'/g, '’')
+  // Use left quote where (likely) appropriate.
+  input.replace(/ ’/g, ' ‘')
+
+  return sanitizeHtml(input, {
+    // Allow "replacement" tags (in the format <0>, <1>, <2>, etc) used by
+    // react-i18next to allow for HTML insertion via the Trans component.
+    // See: https://github.com/overleaf/developer-manual/blob/master/code/translations.md
+    // Unfortunately the sanitizeHtml library does not accept regexes or a
+    // function for the allowedTags option, so we are limited to a hard-coded
+    // number of "replacement" tags.
+    allowedTags: ['b', 'strong', 'a', 'code', ...range(10)],
+    allowedAttributes: {
+      a: ['href', 'class'],
+    },
+    textFilter(text) {
+      return text
+        .replace(/\{\{/, '&#123;&#123;')
+        .replace(/\}\}/, '&#125;&#125;')
+    },
+  })
+}
+
+/**
+ * Generate a range of numbers as strings up to the given size
+ *
+ * @param {number} size Size of range
+ * @returns {string[]}
+ */
+function range(size) {
+  return Array.from(Array(size).keys()).map(n => n.toString())
+}
+
+module.exports = { sanitize }