From b5c36927ad59623ac902fdf0ed80adb0cf49d3e8 Mon Sep 17 00:00:00 2001 From: Paris Oplopoios Date: Mon, 24 Oct 2022 14:12:44 +0300 Subject: [PATCH] a11y: Add check for tabs used for formatting MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Add accessibility check and relevant test for a document that uses tabs for formatting Useful to detect fake tables made of tabs Change-Id: Ief765f25c8dc67405d0671e257cf0ba7aec9f16c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/141732 Tested-by: Jenkins Reviewed-by: Tomaž Vajngerl Reviewed-on: https://gerrit.libreoffice.org/c/core/+/142575 Tested-by: Jenkins CollaboraOffice --- sw/inc/AccessibilityCheckStrings.hrc | 1 + .../accessibilitycheck/AccessibilityCheckTest.cxx | 14 +++++ sw/qa/core/accessibilitycheck/data/TabsTest.odt | Bin 0 -> 9333 bytes sw/source/core/access/AccessibilityCheck.cxx | 68 +++++++++++++++------ 4 files changed, 64 insertions(+), 19 deletions(-) create mode 100644 sw/qa/core/accessibilitycheck/data/TabsTest.odt diff --git a/sw/inc/AccessibilityCheckStrings.hrc b/sw/inc/AccessibilityCheckStrings.hrc index 7245a2b8d3e0..baa61cbcb8ba 100644 --- a/sw/inc/AccessibilityCheckStrings.hrc +++ b/sw/inc/AccessibilityCheckStrings.hrc @@ -27,6 +27,7 @@ #define STR_AVOID_BACKGROUND_IMAGES NC_("STR_AVOID_BACKGROUND_IMAGES", "Avoid background images.") #define STR_AVOID_NEWLINES_SPACE NC_("STR_AVOID_NEWLINES_SPACE", "Avoid newlines to create space.") #define STR_AVOID_SPACES_SPACE NC_("STR_AVOID_SPACES_SPACE", "Avoid spaces to create space.") +#define STR_AVOID_TABS_FORMATTING NC_("STR_AVOID_TABS_FORMATTING", "Avoid using tabs for formatting.") #define STR_HEADINGS_NOT_IN_ORDER NC_("STR_HEADINGS_NOT_IN_ORDER", "Headings not in order.") #define STR_TEXT_FORMATTING_CONVEYS_MEANING NC_("STR_TEXT_FORMATTING_CONVEYS_MEANING", "The text formatting conveys additional meaning.") #define STR_NON_INTERACTIVE_FORMS NC_("STR_NON_INTERACTIVE_FORMS", "An input form is not interactive.") diff --git a/sw/qa/core/accessibilitycheck/AccessibilityCheckTest.cxx b/sw/qa/core/accessibilitycheck/AccessibilityCheckTest.cxx index 122332931544..0059bdf2fa8f 100644 --- a/sw/qa/core/accessibilitycheck/AccessibilityCheckTest.cxx +++ b/sw/qa/core/accessibilitycheck/AccessibilityCheckTest.cxx @@ -152,6 +152,20 @@ CPPUNIT_TEST_FIXTURE(AccessibilityCheckTest, testCheckTableFormatting) CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TABLE_FORMATTING, aIssues[0]->m_eIssueID); } +CPPUNIT_TEST_FIXTURE(AccessibilityCheckTest, testCheckTabsFormatting) +{ + SwDoc* pDoc = createSwDoc(DATA_DIRECTORY, "TabsTest.odt"); + CPPUNIT_ASSERT(pDoc); + sw::AccessibilityCheck aCheck(pDoc); + aCheck.check(); + auto& aIssues = aCheck.getIssueCollection().getIssues(); + CPPUNIT_ASSERT_EQUAL(size_t(4), aIssues.size()); + CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TEXT_FORMATTING, aIssues[0]->m_eIssueID); + CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TEXT_FORMATTING, aIssues[1]->m_eIssueID); + CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TEXT_FORMATTING, aIssues[2]->m_eIssueID); + CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TEXT_FORMATTING, aIssues[3]->m_eIssueID); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/qa/core/accessibilitycheck/data/TabsTest.odt b/sw/qa/core/accessibilitycheck/data/TabsTest.odt new file mode 100644 index 0000000000000000000000000000000000000000..29b415df87a7c2d1e743e482654c9774a7e7e18a GIT binary patch literal 9333 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 literal 0 HcwPel00001 diff --git a/sw/source/core/access/AccessibilityCheck.cxx b/sw/source/core/access/AccessibilityCheck.cxx index d9d1c76e5b67..fc47ce8f39d0 100644 --- a/sw/source/core/access/AccessibilityCheck.cxx +++ b/sw/source/core/access/AccessibilityCheck.cxx @@ -771,33 +771,63 @@ public: const OUString& sParagraphText = pTextNode->GetText(); sal_Int32 nSpaceCount = 0; sal_Int32 nSpaceStart = 0; + sal_Int32 nTabCount = 0; bool bNonSpaceFound = false; + bool bPreviousWasChar = false; for (sal_Int32 i = 0; i < nParagraphLength; i++) { - if (sParagraphText[i] == ' ') + switch (sParagraphText[i]) { - if (bNonSpaceFound) + case ' ': { - nSpaceCount++; - if (nSpaceCount == 2) - nSpaceStart = i; + if (bNonSpaceFound) + { + nSpaceCount++; + if (nSpaceCount == 2) + nSpaceStart = i; + } + break; } - } - else - { - if (nSpaceCount >= 2) + case '\t': { - auto pIssue = lclAddIssue(m_rIssueCollection, SwResId(STR_AVOID_SPACES_SPACE), - sfx::AccessibilityIssueID::TEXT_FORMATTING); - pIssue->setIssueObject(IssueObject::TEXT); - pIssue->setNode(pTextNode); - SwDoc& rDocument = pTextNode->GetDoc(); - pIssue->setDoc(rDocument); - pIssue->setStart(nSpaceStart); - pIssue->setEnd(nSpaceStart + nSpaceCount - 1); + if (bPreviousWasChar) + { + ++nTabCount; + bPreviousWasChar = false; + if (nTabCount == 2) + { + auto pIssue = lclAddIssue(m_rIssueCollection, + SwResId(STR_AVOID_TABS_FORMATTING), + sfx::AccessibilityIssueID::TEXT_FORMATTING); + pIssue->setIssueObject(IssueObject::TEXT); + pIssue->setNode(pTextNode); + SwDoc& rDocument = pTextNode->GetDoc(); + pIssue->setDoc(rDocument); + pIssue->setStart(0); + pIssue->setEnd(nParagraphLength); + } + } + break; + } + default: + { + if (nSpaceCount >= 2) + { + auto pIssue + = lclAddIssue(m_rIssueCollection, SwResId(STR_AVOID_SPACES_SPACE), + sfx::AccessibilityIssueID::TEXT_FORMATTING); + pIssue->setIssueObject(IssueObject::TEXT); + pIssue->setNode(pTextNode); + SwDoc& rDocument = pTextNode->GetDoc(); + pIssue->setDoc(rDocument); + pIssue->setStart(nSpaceStart); + pIssue->setEnd(nSpaceStart + nSpaceCount - 1); + } + bNonSpaceFound = true; + bPreviousWasChar = true; + nSpaceCount = 0; + break; } - bNonSpaceFound = true; - nSpaceCount = 0; } } } -- 2.11.4.GIT