Skip to content

Commit

Permalink
Update to cope with the RCE in native browser fullscreen (#126)
Browse files Browse the repository at this point in the history
* Update to cope with the RCE in native browser fullscreen

The primary change is to checker.js where it forwards the mountNode
prop to the Tray. This gets the a11y checker on top of the RCE
while in fullscreen.
Adjacent to that we position the indicator so it's correct and
visible whether in fullscreen or not.

Also fixed a bug where adjust() kept tracking indicators even
after they were removed from the DOM, and throttled the work
adjust does to just once every 10ms.

Moved the es build output from lib/modules to es and added
jest.config.js to ignore anything in either directory.

Updated the yarn "test" script so you can now execute
yarn test path/to/test/file.js
and jest will execute just the given file.

Added a yarn "test:debug" to facilitate debugging specs.

Updated the version number and changelog in preparation for
publishing the updates.

closes MAT-1115

* Update to cope with the RCE in native browser fullscreen

The primary change is to checker.js where it forwards the mountNode
prop to the Tray. This gets the a11y checker on top of the RCE
while in fullscreen.
Adjacent to that we position the indicator so it's correct and
visible whether in fullscreen or not.

Also fixed a bug where adjust() kept tracking indicators even
after they were removed from the DOM, and throttled the work
adjust does to just once every 10ms.

Moved the es build output from lib/modules to es and added
jest.config.js to ignore anything in either directory.

Updated the yarn "test" script so you can now execute
yarn test path/to/test/file.js
and jest will execute just the given file.

Added a yarn "test:debug" to facilitate debugging specs.

Updated the version number and changelog in preparation for
publishing the updates.

closes MAT-1115

* Update to cope with the RCE in native browser fullscreen

The primary change is to checker.js where it forwards the mountNode
prop to the Tray. This gets the a11y checker on top of the RCE
while in fullscreen.
Adjacent to that we position the indicator so it's correct and
visible whether in fullscreen or not.

Also fixed a bug where adjust() kept tracking indicators even
after they were removed from the DOM, and throttled the work
adjust does to just once every 10ms.

Moved the es build output from lib/modules to es and added
jest.config.js to ignore anything in either directory.

Updated the yarn "test" script so you can now execute
yarn test path/to/test/file.js
and jest will execute just the given file.

Added a yarn "test:debug" to facilitate debugging specs.

Updated the version number and changelog in preparation for
publishing the updates.

closes MAT-1115
  • Loading branch information
eschiebel authored Dec 1, 2022
1 parent e5eede9 commit aa69a93
Show file tree
Hide file tree
Showing 12 changed files with 728 additions and 875 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
node_modules
lib
es
src/translations.json
coverage
cypress/videos
Expand Down
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,44 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [4.1.2] - 2022-11-30

- Changes to cope with the RCE being put in browser-native fullscreen
- Fixed a bug that over aggressively kept track of the blue box that shows
the element in violation.

## [4.1.1] - 2022-08-10

### Changed

- Updated dependency versions

## [4.1.0] - 2022-08-09

### Added

- A new configurable rule that informs users to not use H1 headings

## [4.0.0] - 2022-08-02

### Added

- A changelog to make changes clear

### Changed

- `checkAccessibility` command's paramater `additional_rules` has been renamed `additionalRules`

### Fixed

- Bug that caused inconsistent checking behavior between `checkAccessibility` and `openAccessibilityChecker` when using a non-default configuration

### Removed

- TinyMCE v4 support
7 changes: 3 additions & 4 deletions jest-setup.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
const Enzyme = require("enzyme")
const Adapter = require("enzyme-adapter-react-16")
require("@instructure/ui-themes")
import Enzyme from "enzyme"
import Adapter from "enzyme-adapter-react-16"

Enzyme.configure({ adapter: new Adapter() })

Expand All @@ -9,6 +8,6 @@ document.documentElement.setAttribute("dir", "ltr")
// set up mocks for native APIs
if (!("MutationObserver" in window)) {
Object.defineProperty(window, "MutationObserver", {
value: require("mutation-observer")
value: require("mutation-observer"),
})
}
29 changes: 29 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright (C) 2022 - present Instructure, Inc.
*
* This file is part of Canvas.
*
* Canvas is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License as published by the Free
* Software Foundation, version 3 of the License.
*
* Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/

module.exports = {
setupFiles: ["<rootDir>/jest-setup.js"],
snapshotSerializers: ["enzyme-to-json/serializer"],
testPathIgnorePatterns: [
"<rootDir>/node_modules",
"<rootDir>/es",
"<rootDir>/lib",
],
modulePathIgnorePatterns: ["<rootDir>/.*/__mocks__"],
testMatch: ["**/__tests__/*.[jt]s?(x)"],
}
50 changes: 26 additions & 24 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
{
"name": "tinymce-a11y-checker",
"version": "4.1.1",
"version": "4.1.2",
"description": "An accessibility checker plugin for TinyMCE.",
"main": "lib/plugin.js",
"module": "lib/modules/plugin.js",
"module": "es/plugin.js",
"scripts": {
"test": "jest src",
"test": "jest --color --runInBand",
"test:all": "npm run test && npm run cypress:run",
"test:coverage": "jest src --coverage",
"test-watch": "jest --watch src",
"test:watch": "jest --watch",
"test:debug": "node --inspect-brk node_modules/.bin/jest --runInBand",
"cypress:ci": "start-server-and-test start http://localhost:8080 cypress:run",
"cypress:open": "cypress open",
"cypress:run": "cypress run",
Expand All @@ -17,6 +18,7 @@
"fmt": "prettier --no-semi --write \"src/**/*.js\"",
"fmt-check": "prettier --no-semi -l \"src/**/*.js\"",
"build": "scripts/build",
"build:watch": "babel --out-dir es/ --ignore __*/* --copy-files src",
"build:demo": "webpack",
"prepublish": "npm run build"
},
Expand Down Expand Up @@ -60,25 +62,25 @@
"webpack-dev-server": "^3"
},
"dependencies": {
"@instructure/canvas-theme": "^7.6.0",
"@instructure/ui-a11y-content": "^7.6.0",
"@instructure/ui-alerts": "^7.6.0",
"@instructure/ui-buttons": "^7.6.0",
"@instructure/ui-checkbox": "^7.6.0",
"@instructure/ui-grid": "^7.6.0",
"@instructure/ui-heading": "^7.6.0",
"@instructure/ui-icons": "^7.6.0",
"@instructure/ui-link": "^7.6.0",
"@instructure/ui-popover": "^7.6.0",
"@instructure/ui-simple-select": "^7.6.0",
"@instructure/ui-spinner": "^7.6.0",
"@instructure/ui-text": "^7.6.0",
"@instructure/ui-text-area": "^7.6.0",
"@instructure/ui-text-input": "^7.6.0",
"@instructure/ui-themeable": "^7.6.0",
"@instructure/ui-themes": "^7.6.0",
"@instructure/ui-tray": "^7.6.0",
"@instructure/ui-view": "^7.6.0",
"@instructure/canvas-theme": "^7",
"@instructure/ui-a11y-content": "^7",
"@instructure/ui-alerts": "^7",
"@instructure/ui-buttons": "^7",
"@instructure/ui-checkbox": "^7",
"@instructure/ui-grid": "^7",
"@instructure/ui-heading": "^7",
"@instructure/ui-icons": "^7",
"@instructure/ui-link": "^7",
"@instructure/ui-popover": "^7",
"@instructure/ui-simple-select": "^7",
"@instructure/ui-spinner": "^7",
"@instructure/ui-text": "^7",
"@instructure/ui-text-area": "^7",
"@instructure/ui-text-input": "^7",
"@instructure/ui-themeable": "^7",
"@instructure/ui-themes": "^7",
"@instructure/ui-tray": "^7",
"@instructure/ui-view": "^7",
"bloody-offset": "^0.0.0",
"format-message": "^6",
"format-message-generate-id": "^6",
Expand Down Expand Up @@ -110,4 +112,4 @@
}
}
}
}
}
5 changes: 3 additions & 2 deletions scripts/build
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

set -e
rm -rf lib
rm -rf es

node scripts/build-translations.js --empty

Expand All @@ -13,7 +14,7 @@ echo "building pretranslated output in lib/translated $CPUS at a time ..."
ls locales/*.json | \
xargs basename -s .json | \
xargs -t -n 1 -P $CPUS -I % env \
BUILD_LOCALE=% $(npm bin)/babel --out-dir lib/%/modules --ignore __*/* --copy-files src
BUILD_LOCALE=% $(npm bin)/babel --out-dir es/% --ignore __*/* --copy-files src

ls locales/*.json | \
xargs basename -s .json | \
Expand All @@ -22,5 +23,5 @@ ls locales/*.json | \

node scripts/build-translations.js

$(npm bin)/babel --out-dir lib/modules --ignore __*/* --copy-files src
$(npm bin)/babel --out-dir es/ --ignore __*/* --copy-files src
TRANSPILE=true $(npm bin)/babel --out-dir lib/ --ignore __*/* --copy-files src
1 change: 1 addition & 0 deletions src/components/__tests__/__snapshots__/checker.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ exports[`render matches snapshot with errors 1`] = `
>
<Link
color="link"
forceButtonRole={true}
href="http://some-url"
iconPlacement="start"
isWithinText={true}
Expand Down
51 changes: 36 additions & 15 deletions src/components/checker.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ import checkNode from "../node-checker"
import formatMessage from "../format-message"
import { clearIndicators } from "../utils/indicate"

// safari still doesn't support the standard api
const FS_CHANGEEVENT = document.exitFullscreen
? "fullscreenchange"
: "webkitfullscreenchange"

const noop = () => {}

export default class Checker extends React.Component {
Expand All @@ -39,19 +44,34 @@ export default class Checker extends React.Component {
formStateValid: false,
errorIndex: 0,
config: {},
showWhyPopover: false
showWhyPopover: false,
}

static defaultProps = {
additionalRules: []
additionalRules: [],
}

componentDidMount() {
this.props.editor.on("Remove", editor => {
this.props.editor.on("Remove", (editor) => {
this.setState({ open: false })
})
}

componentDidUpdate(_prevProps, prevState) {
if (prevState.open !== this.state.open) {
if (this.state.open) {
window.addEventListener(FS_CHANGEEVENT, this.onFullscreenChange)
} else {
window.removeEventListener(FS_CHANGEEVENT, this.onFullscreenChange)
}
}
}

onFullscreenChange = (event) => {
clearIndicators(event.target)
this.selectCurrent()
}

setConfig(config) {
this.setState({ config })
}
Expand All @@ -64,7 +84,7 @@ export default class Checker extends React.Component {
open: true,
checking: true,
errors: [],
errorIndex: 0
errorIndex: 0,
},
() => {
if (typeof this.state.config.beforeCheck === "function") {
Expand All @@ -90,7 +110,7 @@ export default class Checker extends React.Component {

_check(done) {
const node = this.props.getBody()
const checkDone = errors => {
const checkDone = (errors) => {
this.setState({ errorIndex: 0, errors, checking: false }, () => {
this.selectCurrent()
done()
Expand Down Expand Up @@ -184,7 +204,7 @@ export default class Checker extends React.Component {
}
this.setState({
formState,
formStateValid: this.formStateValid(formState)
formStateValid: this.formStateValid(formState),
})
}

Expand Down Expand Up @@ -270,24 +290,25 @@ export default class Checker extends React.Component {
const rule = this.errorRule()
const issueNumberMessage = formatMessage("Issue { num }/{ total }", {
num: this.state.errorIndex + 1,
total: this.state.errors.length
total: this.state.errors.length,
})

return (
<LiveAnnouncer>
<Tray
data-mce-component
label={formatMessage("Accessibility Checker")}
mountNode={this.props.mountNode}
open={this.state.open}
onDismiss={() => this.handleClose()}
placement="end"
contentRef={e => (this.trayElement = e)}
contentRef={(e) => (this.trayElement = e)}
>
<CloseButton
placement="start"
offset="x-small"
onClick={() => this.handleClose()}
buttonRef={ref => (this._closeButtonRef = ref)}
buttonRef={(ref) => (this._closeButtonRef = ref)}
>
{formatMessage("Close Accessibility Checker")}
</CloseButton>
Expand Down Expand Up @@ -361,8 +382,8 @@ export default class Checker extends React.Component {
<ApplyTheme
theme={{
[Link.theme]: {
textDecoration: "underline"
}
textDecoration: "underline",
},
}}
>
<Link href={rule.link} target="_blank">
Expand All @@ -381,7 +402,7 @@ export default class Checker extends React.Component {
</View>
<form onSubmit={preventDefault(() => this.fixIssue())}>
<Text as="div">{this.errorMessage()}</Text>
{rule.form().map(f => (
{rule.form().map((f) => (
<View as="div" key={f.dataKey} margin="medium 0 0">
{this.renderField(f)}
</View>
Expand Down Expand Up @@ -459,14 +480,14 @@ export default class Checker extends React.Component {
this.updateFormState({
target: {
name: f.dataKey,
value: option.value
}
value: option.value,
},
})
}}
value={this.state.formState[f.dataKey]}
renderLabel={() => f.label}
>
{f.options.map(o => (
{f.options.map((o) => (
<SimpleSelect.Option key={o[0]} id={o[0]} value={o[0]}>
{o[1]}
</SimpleSelect.Option>
Expand Down
3 changes: 2 additions & 1 deletion src/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@ tinymce.create("tinymce.plugins.AccessibilityChecker", {
init: function (ed) {
ed.addCommand("openAccessibilityChecker", function (
ui,
{ done, config, additionalRules }
{ done, config, additionalRules, mountNode }
) {
ReactDOM.render(
<Checker
getBody={ed.getBody.bind(ed)}
editor={ed}
additionalRules={additionalRules}
mountNode={mountNode}
/>,
container,
function () {
Expand Down
Loading

0 comments on commit aa69a93

Please sign in to comment.