From c896836ce8dccca753b07672041ee36b0f1cc9c1 Mon Sep 17 00:00:00 2001 From: Nolan Lawson Date: Thu, 21 Mar 2019 14:38:37 -0700 Subject: [PATCH] fix: fix spaces in status aria-labels (#1111) fixes #1108 --- src/routes/_components/status/Status.html | 5 +++-- src/routes/_utils/htmlToPlainText.js | 13 ------------- src/routes/_utils/statusHtmlToPlainText.js | 14 +++++++++----- tests/spec/120-status-aria-label.js | 18 +++++++++++++++++- 4 files changed, 29 insertions(+), 21 deletions(-) delete mode 100644 src/routes/_utils/htmlToPlainText.js diff --git a/src/routes/_components/status/Status.html b/src/routes/_components/status/Status.html index d3f5834d..f9c5a1ca 100644 --- a/src/routes/_components/status/Status.html +++ b/src/routes/_components/status/Status.html @@ -129,7 +129,6 @@ import { getAccountAccessibleName } from '../../_a11y/getAccountAccessibleName' import { getAccessibleLabelForStatus } from '../../_a11y/getAccessibleLabelForStatus' import { formatTimeagoDate } from '../../_intl/formatTimeagoDate' - import { htmlToPlainText } from '../../_utils/htmlToPlainText' import { measureText } from '../../_utils/measureText' import { LONG_POST_LENGTH, LONG_POST_TEXT } from '../../_static/statuses' import { absoluteDateFormatter } from '../../_utils/formatters' @@ -137,6 +136,7 @@ import { applyFocusStylesToParent } from '../../_utils/events' import noop from 'lodash-es/noop' import { createStatusOrNotificationUuid } from '../../_utils/createStatusOrNotificationUuid' + import { statusHtmlToPlainText } from '../../_utils/statusHtmlToPlainText' const INPUT_TAGS = new Set(['a', 'button', 'input', 'textarea']) const isUserInputElement = node => INPUT_TAGS.has(node.localName) @@ -231,7 +231,8 @@ originalAccountId: ({ originalAccount }) => originalAccount.id, accountForShortcut: ({ originalAccount, notification }) => notification ? notification.account : originalAccount, visibility: ({ originalStatus }) => originalStatus.visibility, - plainTextContent: ({ content }) => htmlToPlainText(content), + mentions: ({ originalStatus }) => originalStatus.mentions || [], + plainTextContent: ({ content, mentions }) => statusHtmlToPlainText(content, mentions), plainTextContentLength: ({ plainTextContent }) => measureText(plainTextContent), plainTextContentOverLength: ({ plainTextContentLength }) => plainTextContentLength > LONG_POST_LENGTH, spoilerText: ({ originalStatus, plainTextContentOverLength }) => ( diff --git a/src/routes/_utils/htmlToPlainText.js b/src/routes/_utils/htmlToPlainText.js deleted file mode 100644 index 1b242ed1..00000000 --- a/src/routes/_utils/htmlToPlainText.js +++ /dev/null @@ -1,13 +0,0 @@ -import { mark, stop } from './marks' - -let domParser = process.browser && new DOMParser() - -export function htmlToPlainText (html) { - if (!html) { - return '' - } - mark('htmlToPlainText') - let res = domParser.parseFromString(html, 'text/html').documentElement.textContent - stop('htmlToPlainText') - return res -} diff --git a/src/routes/_utils/statusHtmlToPlainText.js b/src/routes/_utils/statusHtmlToPlainText.js index 99117682..35b01b17 100644 --- a/src/routes/_utils/statusHtmlToPlainText.js +++ b/src/routes/_utils/statusHtmlToPlainText.js @@ -18,14 +18,18 @@ function massageMentions (doc, mentions) { // paragraphs should be separated by double newlines // single
s should become single newlines function innerTextRetainingNewlines (doc) { + let res = '' let paragraphs = doc.querySelectorAll('p') - return Array.from(paragraphs).map(paragraph => { + for (let i = 0; i < paragraphs.length; i++) { + let paragraph = paragraphs[i] let brs = paragraph.querySelectorAll('br') - Array.from(brs).forEach(br => { + for (let j = 0; j < brs.length; j++) { + let br = brs[j] br.parentNode.replaceChild(doc.createTextNode('\n'), br) - }) - return paragraph.textContent - }).join('\n\n') + } + res += (i > 0 ? '\n\n' : '') + paragraph.textContent + } + return res } export function statusHtmlToPlainText (html, mentions) { diff --git a/tests/spec/120-status-aria-label.js b/tests/spec/120-status-aria-label.js index 0c50f729..f4c03f3e 100644 --- a/tests/spec/120-status-aria-label.js +++ b/tests/spec/120-status-aria-label.js @@ -1,6 +1,6 @@ import { loginAsFoobar } from '../roles' import { getNthStatus } from '../utils' -import { postEmptyStatusWithMediaAs } from '../serverActions' +import { postAs, postEmptyStatusWithMediaAs } from '../serverActions' fixture`120-status-aria-label.js` .page`http://localhost:4002` @@ -14,3 +14,19 @@ test('aria-labels for statuses with no content text', async t => { /foobar, (.+ ago|just now), @foobar, Public/i ) }) + +test('aria-labels with links', async t => { + let content = 'Text here\n\nMore text\n\n' + + 'https://example.com/long/url/here/very/long/yes/so/long\n\n' + + '#woot #yolo' + + let expected = 'admin, Text here More text ' + + 'https://example.com/long/url/here/very/long/yes/so/long #woot #yolo,' + + await postAs('admin', content) + + await loginAsFoobar(t) + await t + .hover(getNthStatus(1)) + .expect(getNthStatus(1).getAttribute('aria-label')).contains(expected) +})