Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions packages/web-component/cypress/e2e/embedded.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
context("The Readalong Component", () => {
const EXPECTED_LOADING_TIME = 2000; // ms
const FOR_PAGE_TURN_ANIMATION = 500; // ms
const FOR_ERIC_TO_TALK_A_BIT = 3000; // ms

beforeEach(() => {
cy.visit("/ej-fra/index-embedded.html");
});

it("should load successfully", () => {
cy.readalongElement().should("be.visible");

cy.readalong().within(() => {
cy.contains("Page");
});
});

it("should play the entire ReadAlong", () => {
cy.wait(EXPECTED_LOADING_TIME);

cy.readalong().within(() => {
cy.get("[data-cy=play-button]").click();
cy.wait(FOR_ERIC_TO_TALK_A_BIT);
cy.get("[data-cy=stop-button]").click();
});
});

it("should play a single word when clicked", () => {
cy.wait(EXPECTED_LOADING_TIME);

cy.readalong().contains("technologies").click();
});

describe("the progress bar", () => {
it("should skip ahead when clicked", () => {
cy.wait(EXPECTED_LOADING_TIME);

cy.readalong().within(() => {
cy.get("[data-cy=play-button]").click();
cy.get("[data-cy=page-count__current]")
.filter("*:visible")
.invoke("text")
.should("eq", "1");

cy.get("[data-cy=progress-bar]")
.as("progress-bar")
.then((el) => {
// click 3/4 of the way in the readalong (should be second page)
cy.get("@progress-bar").click(el.width() * 0.75, el.height() * 0.5);
});
cy.get("[data-cy=stop-button]").click();
cy.wait(FOR_PAGE_TURN_ANIMATION);

cy.get("[data-cy=page-count__current]")
.filter("*:visible")
.invoke("text")
.should("eq", "2");
});
});
});
});
2 changes: 1 addition & 1 deletion packages/web-component/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@readalongs/web-component",
"version": "1.0.2",
"version": "1.1.0",
"description": "ReadAlong Web Component",
"main": "dist/index.cjs.js",
"module": "dist/index.js",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
import {
parseRAS,
Sprite,
extractPages,
extractAlignment,
isFileAvailable,
} from "../../utils/utils";
Expand Down Expand Up @@ -850,9 +851,11 @@ export class ReadAlongComponent {
this.playbackRateRange = 15;
}

// Parse the text to be displayed
// TODO: if parseRAS has an error, we need ERROR_PARSING
this.parsed_text = await parseRAS(this.href);
// Parse the text to be displayed
const text = this.el.querySelector("read-along > text");
if (text) this.parsed_text = extractPages(text);
else this.parsed_text = await parseRAS(this.href);
if (this.parsed_text === null) {
this.parsed_text = [];
this.assetsStatus.RAS = ERROR_LOADING;
Expand Down Expand Up @@ -1374,7 +1377,10 @@ export class ReadAlongComponent {
}
/>
);
} else if (child.nodeName === "w") {
} else if (child.nodeName === "w" || child.nodeName === "W") {
/* It may be uppercase for embedded markup, because in
that case it has been parsed as "HTML". See
https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeName */
return (
<this.Word
text={child.textContent}
Expand Down
10 changes: 9 additions & 1 deletion packages/web-component/src/utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export function zip(arrays): Array<any[]> {
}

/**
* Return sentences from readalong XML file
* Return pages from readalong XML file
* @param {string} - the path to the readalong file
*/
export async function parseRAS(path: string): Promise<Array<Page>> {
Expand All @@ -27,6 +27,14 @@ export async function parseRAS(path: string): Promise<Array<Page>> {
let xmlDocument = await response.text();
let parser = new DOMParser();
let xml = parser.parseFromString(xmlDocument, "text/xml");
return extractPages(xml);
}

/**
* Return pages from parsed XML
* @param {xml} - the parsed XML (could be an element)
*/
export function extractPages(xml: Document | Element): Array<Page> {
let parsed_pages = Array.from(xml.querySelectorAll("div[type=page]")).map(
(page) => {
let img = page.querySelector("graphic[url]");
Expand Down
191 changes: 191 additions & 0 deletions packages/web-component/test-data/ej-fra/index-embedded.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Insert Title Here</title>
</head>

<body>
<!-- Here is how you declare the Web Component. Supported languages: en, fr -->
<read-along use-assets-folder="false" audio="ej-fra.m4a" language="fra">
<span slot="read-along-header">Insert Title Here Too</span>
<text xml:lang="fra" id="t0">
<body id="t0b0">
<div type="page" id="t0b0d0">
<graphic
url="http://localhost:5000/ej-fra/avatar.png"
id="t0b0d0graphic0"
/>
<p id="t0b0d0p0">
<s id="t0b0d0p0s0"
><w id="t0b0d0p0s0w0" time="0.455" dur="1.165">Bonjour</w>.</s
>
<s id="t0b0d0p0s1"
><w id="t0b0d0p0s1w0" time="1.620" dur="0.070">Je</w>
<w id="t0b0d0p0s1w1" time="1.690" dur="0.070">m</w>'<w
id="t0b0d0p0s1w2"
time="1.760"
dur="0.240"
>appelle</w
>
<w id="t0b0d0p0s1w3" time="2.000" dur="0.220">Éric</w>
<w id="t0b0d0p0s1w4" time="2.220" dur="0.370">Joanis</w>.</s
>
<s id="t0b0d0p0s2"
><w id="t0b0d0p0s2w0" time="2.590" dur="0.030">Je</w>
<w id="t0b0d0p0s2w1" time="2.620" dur="0.330">suis</w>
<w id="t0b0d0p0s2w2" time="2.950" dur="0.870">programmeur</w>
<w id="t0b0d0p0s2w3" time="3.820" dur="0.100">au</w>
<w id="t0b0d0p0s2w4" time="3.920" dur="0.230">sein</w>
<w id="t0b0d0p0s2w5" time="4.150" dur="0.040">de</w>
<w id="t0b0d0p0s2w6" time="4.190" dur="0.030">l</w>'<w
id="t0b0d0p0s2w7"
time="4.220"
dur="0.360"
>équipe</w
>
<w id="t0b0d0p0s2w8" time="4.580" dur="0.110">des</w>
<w id="t0b0d0p0s2w9" time="4.690" dur="0.560">technologies</w>
<w id="t0b0d0p0s2w10" time="5.250" dur="0.310">pour</w>
<w id="t0b0d0p0s2w11" time="5.560" dur="0.030">les</w>
<w id="t0b0d0p0s2w12" time="5.590" dur="0.280">langues</w>
<w id="t0b0d0p0s2w13" time="5.870" dur="0.460">autochtones</w>
<w id="t0b0d0p0s2w14" time="6.330" dur="0.080">au</w>
<w id="t0b0d0p0s2w15" time="6.410" dur="1.145">CNRC</w>.</s
>
</p>
</div>
<div type="page" id="t0b0d1">
<p id="t0b0d1p0">
<s id="t0b0d1p0s0"
><w id="t0b0d1p0s0w0" time="7.555" dur="0.485">J</w>'<w
id="t0b0d1p0s0w1"
time="8.040"
dur="0.050"
>ai</w
>
<w id="t0b0d1p0s0w2" time="8.090" dur="0.190">fait</w>
<w id="t0b0d1p0s0w3" time="8.280" dur="0.060">une</w>
<w id="t0b0d1p0s0w4" time="8.340" dur="0.170">bonne</w>
<w id="t0b0d1p0s0w5" time="8.510" dur="0.270">partie</w>
<w id="t0b0d1p0s0w6" time="8.780" dur="0.030">de</w>
<w id="t0b0d1p0s0w7" time="8.810" dur="0.120">ma</w>
<w id="t0b0d1p0s0w8" time="8.930" dur="0.350">carrière</w>
<w id="t0b0d1p0s0w9" time="9.280" dur="0.110">en</w>
<w id="t0b0d1p0s0w10" time="9.390" dur="0.530">traduction</w>
<w id="t0b0d1p0s0w11" time="9.920" dur="0.470">automatique</w>
<w id="t0b0d1p0s0w12" time="10.390" dur="0.905">statistique</w>,
<w id="t0b0d1p0s0w13" time="11.295" dur="0.255">mais</w>
<w id="t0b0d1p0s0w14" time="11.550" dur="0.300">maintenant</w>
<w id="t0b0d1p0s0w15" time="11.850" dur="0.220">cette</w>
<w id="t0b0d1p0s0w16" time="12.070" dur="0.290">approche</w>
<w id="t0b0d1p0s0w17" time="12.360" dur="0.050">est</w>
<w id="t0b0d1p0s0w18" time="12.410" dur="0.500">déclassée</w>
<w id="t0b0d1p0s0w19" time="12.910" dur="0.170">par</w>
<w id="t0b0d1p0s0w20" time="13.080" dur="0.030">l</w>'<w
id="t0b0d1p0s0w21"
time="13.110"
dur="0.600"
>apprentissage</w
>
<w id="t0b0d1p0s0w22" time="13.710" dur="0.755">profond</w>.</s
>
<s id="t0b0d1p0s1"
><w id="t0b0d1p0s1w0" time="14.465" dur="0.485">En</w>
<w id="t0b0d1p0s1w1" time="14.950" dur="0.050">ce</w>
<w id="t0b0d1p0s1w2" time="15.000" dur="0.300">moment</w>
<w id="t0b0d1p0s1w3" time="15.300" dur="0.050">je</w>
<w id="t0b0d1p0s1w4" time="15.350" dur="0.290">travaille</w>
<w id="t0b0d1p0s1w5" time="15.640" dur="0.030">à</w>
<w id="t0b0d1p0s1w6" time="15.670" dur="0.030">l</w>'<w
id="t0b0d1p0s1w7"
time="15.700"
dur="0.470"
>alignement</w
>
<w id="t0b0d1p0s1w8" time="16.170" dur="0.110">du</w>
<w id="t0b0d1p0s1w9" time="16.280" dur="0.540">hansard</w>
<w id="t0b0d1p0s1w10" time="16.820" dur="0.070">du</w>
<w id="t0b0d1p0s1w11" time="16.890" dur="0.480">Nunavut</w>
<w id="t0b0d1p0s1w12" time="17.370" dur="0.130">pour</w>
<w id="t0b0d1p0s1w13" time="17.500" dur="0.580">produire</w>
<w id="t0b0d1p0s1w14" time="18.080" dur="0.100">un</w>
<w id="t0b0d1p0s1w15" time="18.180" dur="0.280">corpus</w>
<w id="t0b0d1p0s1w16" time="18.460" dur="0.500">bilingue</w>
<w id="t0b0d1p0s1w17" time="18.960" dur="0.360">anglais</w>-<w
id="t0b0d1p0s1w18"
time="19.320"
dur="1.330"
>inuktitut</w
>.</s
>
<s id="t0b0d1p0s2"
><w id="t0b0d1p0s2w0" time="20.650" dur="0.490">Ce</w>
<w id="t0b0d1p0s2w1" time="21.140" dur="0.690">corpus</w>
<w id="t0b0d1p0s2w2" time="21.830" dur="0.710">permettra</w>
<w id="t0b0d1p0s2w3" time="22.540" dur="0.080">d</w>'<w
id="t0b0d1p0s2w4"
time="22.620"
dur="0.470"
>entraîner</w
>
<w id="t0b0d1p0s2w5" time="23.090" dur="0.090">la</w>
<w id="t0b0d1p0s2w6" time="23.180" dur="0.360">TA</w>,
<w id="t0b0d1p0s2w7" time="23.540" dur="0.600">neuronale</w>
<w id="t0b0d1p0s2w8" time="24.140" dur="0.030">ou</w>
<w id="t0b0d1p0s2w9" time="24.170" dur="0.920">statistique</w>,
<w id="t0b0d1p0s2w10" time="25.090" dur="0.420">ainsi</w>
<w id="t0b0d1p0s2w11" time="25.510" dur="0.060">que</w>
<w id="t0b0d1p0s2w12" time="25.570" dur="0.100">d</w>'<w
id="t0b0d1p0s2w13"
time="25.670"
dur="0.410"
>autres</w
>
<w id="t0b0d1p0s2w14" time="26.080" dur="0.680">applications</w>
<w id="t0b0d1p0s2w15" time="26.760" dur="0.030">de</w>
<w id="t0b0d1p0s2w16" time="26.790" dur="0.260">traitement</w>
<w id="t0b0d1p0s2w17" time="27.050" dur="0.160">du</w>
<w id="t0b0d1p0s2w18" time="27.210" dur="0.790">langage</w>
<w id="t0b0d1p0s2w19" time="28.000" dur="0.710">naturel</w>.</s
>
</p>
<p id="t0b0d1p1">
<s id="t0b0d1p1s0"
><w id="t0b0d1p1s0w0" time="28.710" dur="0.510">En</w>
<w id="t0b0d1p1s0w1" time="29.220" dur="0.680">parallèle</w>,
<w id="t0b0d1p1s0w2" time="29.900" dur="0.130">j</w>'<w
id="t0b0d1p1s0w3"
time="30.030"
dur="0.180"
>aide</w
>
<w id="t0b0d1p1s0w4" time="30.210" dur="0.030">à</w>
<w id="t0b0d1p1s0w5" time="30.240" dur="0.530">écrire</w>
<w id="t0b0d1p1s0w6" time="30.770" dur="0.040">des</w>
<w id="t0b0d1p1s0w7" time="30.810" dur="0.310">tests</w>
<w id="t0b0d1p1s0w8" time="31.120" dur="0.170">pour</w>
<w id="t0b0d1p1s0w9" time="31.290" dur="0.310">rendre</w>
<w id="t0b0d1p1s0w10" time="31.600" dur="0.030">le</w>
<w id="t0b0d1p1s0w11" time="31.630" dur="0.510">ReadAlong</w>-<w
id="t0b0d1p1s0w12"
time="32.140"
dur="0.520"
>Studio</w
>
<w id="t0b0d1p1s0w13" time="32.660" dur="0.110">plus</w>
<w id="t0b0d1p1s0w14" time="32.770" dur="0.610">robuste</w>.</s
>
</p>
</div>
</body>
</text>
</read-along>
</body>

<!-- The last step needed is to import the package -->
<script
type="module"
src="//127.0.0.1:3333/build/web-component.esm.js"
></script>
</html>