Skip to content

Commit

Permalink
update language checks related to accessibility
Browse files Browse the repository at this point in the history
  • Loading branch information
paulhiggs committed Aug 24, 2024
1 parent fb1e1c2 commit f36dac4
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 55 deletions.
39 changes: 18 additions & 21 deletions IANA_languages.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* IANA_languages.js
*
*
* Load and check language identifiers
*/
import { readFile, readFileSync } from "fs";
Expand Down Expand Up @@ -46,6 +46,9 @@ export default class IANAlanguages {
stats(res) {
res.numLanguages = this.#languagesList.length;
res.numRedundantLanguages = this.#redundantLanguagesList.length;
let t = [];
this.#redundantLanguagesList.forEach((e) => t.push(`${e.tag}${e.preferred ? `~${e.preferred}` : ""}`));
res.RedundantLanguages = t.join(", ");
res.numLanguageRanges = this.#languageRanges.length;
res.numSignLanguages = this.#signLanguagesList.length;
if (this.#languageFileDate) res.languageFileDate = this.#languageFileDate;
Expand All @@ -66,9 +69,7 @@ export default class IANAlanguages {
* @return {boolean} true if the language subtag is a sign language
*/
function isSignLanguage(items) {
for (let i = 0; i < items.length; i++)
if (items[i].startsWith("Description") && items[i].toLowerCase().includes("sign"))
return true;
for (let i = 0; i < items.length; i++) if (items[i].startsWith("Description") && items[i].toLowerCase().includes("sign")) return true;
return false;
}

Expand Down Expand Up @@ -141,9 +142,8 @@ export default class IANAlanguages {
} else console.log(chalk.red(`error loading languages ${err}`));
}.bind(this)
);
}
else {
let langs = readFileSync(languagesFile, { encoding: "utf-8" } ).toString();
} else {
let langs = readFileSync(languagesFile, { encoding: "utf-8" }).toString();
this.#processLanguageData(langs);
}
}
Expand All @@ -161,7 +161,7 @@ export default class IANAlanguages {

if (purge) this.empty();

if (async)
if (async)
fetch(languagesURL)
.then(handleErrors)
.then((response) => response.text())
Expand All @@ -175,14 +175,13 @@ export default class IANAlanguages {
console.log(chalk.red(error.message));
}
if (resp) {
if (resp.ok)
this.#processLanguageData(response.text);
else console.log(chalk.red(`error (${error}) retrieving ${languagesURL}`));
if (resp.ok) this.#processLanguageData(resp.text);
else console.log(chalk.red(`error (${resp.error}) retrieving ${languagesURL}`));
}
}
}

loadLanguages(options, async=true) {
loadLanguages(options, async = true) {
if (!options) options = {};
if (!Object.prototype.hasOwnProperty.call(options, "purge")) options.purge = false;

Expand All @@ -202,6 +201,13 @@ export default class IANAlanguages {
if (datatypeIs(value, "string")) {
if (this.#languageRanges.find((range) => range.start <= value && value <= range.end)) return { resp: this.languageKnown };

let found = this.#redundantLanguagesList.find((e) => e.tag.toLowerCase() == value.toLowerCase());
if (found) {
let res = { resp: this.languageRedundant };
if (found?.preferred) res.pref = found.preferred;
return res;
}

if (value.indexOf("-") != -1) {
let matches = true;
let parts = value.split("-");
Expand All @@ -213,15 +219,6 @@ export default class IANAlanguages {

if (isIni(this.#languagesList, value)) return { resp: this.languageKnown };

let lc = value.toLowerCase();
let found = this.#redundantLanguagesList.find((e) => e.tag.toLowerCase() == lc);
if (found) {
let res = { resp: this.languageRedundant };
if (found?.preferred) res.pref = found.preferred;
[];
return res;
}

return { resp: this.languageUnknown };
}
return { resp: this.languageInvalidType };
Expand Down
40 changes: 32 additions & 8 deletions accessibility_attributes_checks.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* accessibility_attribites_checks.js
*
* Checks the value space of the <AccessibilityAttributes> element against the rules and
*
* Checks the value space of the <AccessibilityAttributes> element against the rules and
* values provided in DVB A177.
*/
import { datatypeIs } from "./phlib/phlib.js";
Expand All @@ -13,6 +13,7 @@ import { APPLICATION, WARNING } from "./error_list.js";
import { checkTopElementsAndCardinality } from "./schema_checks.js";
import { CS_URI_DELIMITER } from "./classification_scheme.js";

import { DumpString } from "./utils.js";

export function CheckAccessibilityAttributes(AccessibilityAttributes, cs, errs, errCode) {
const ACCESSIBILITY_CHECK_KEY = "accessibility attributes";
Expand Down Expand Up @@ -126,37 +127,59 @@ export function CheckAccessibilityAttributes(AccessibilityAttributes, cs, errs,
};

let checkCS = (elem, childName, cs, errNum, storage = null) => {
let children = elem.childNodes();
let rc = true,
children = elem.childNodes();
if (children)
children.forEachSubElement((e) => {
if (e.name() == childName) {
let href = e.attr(tva.a_href) ? e.attr(tva.a_href).value() : null;
if (href && !cs.isIn(href))
if (href && !cs.isIn(href)) {
errs.addError({
code: `${errCode}-${errNum}`,
fragment: e,
message: `"${href}" is not valid for ${e.name().elementize()} in ${elem.name().elementize()}`,
key: ACCESSIBILITY_CHECK_KEY,
});
rc = false;
}
if (storage && datatypeIs(storage, "array") && href) {
storage.push(href);
}
}
});
return rc;
};

let checkSignLanguage = (elem, childName, errNum) => {
let children = elem.childNodes();
if (children)
children.forEachSubElement((e) => {
if (e.name() == childName) {
if (cs.KnownLanguages.checkSignLanguage(e.text()) != cs.KnownLanguages.languageKnown)
let languageCode = e.text();
let lState = cs.KnownLanguages.isKnown(languageCode);
if (lState.resp == cs.KnownLanguages.languageRedundant) {
errs.addError({
code: `${errCode}-${errNum}`,
code: `${errCode}-${errNum}a`,
fragment: e,
message: `sign language ${languageCode.quote()} is redundant${lState.pref ? `, use ${lState.pref.quote()} instead` : ""}`,
key: "deprecated language",
type: WARNING,
});
if (lState.pref) languageCode = lState.pref;
}

if (cs.KnownLanguages.checkSignLanguage(languageCode) != cs.KnownLanguages.languageKnown) {
errs.addError({
code: `${errCode}-${errNum}b`,
fragment: e,
message: `"${e.text()}" is not a valid sign language for ${e.name().elementize()} in ${elem.name().elementize()}`,
message: `${languageCode.quote()} is not a valid sign language for ${e.name().elementize()} in ${elem.name().elementize()}`,
key: ACCESSIBILITY_CHECK_KEY,
});
errs.errorDescription({
code: `${errCode}-${errNum}b`,
description: `language used for ${e.name().elementize()}} must be a sign language in the IANA language-subtag-regostry`,
});
}
}
});
};
Expand Down Expand Up @@ -323,7 +346,8 @@ export function CheckAccessibilityAttributes(AccessibilityAttributes, cs, errs,
`${errCode}-71`
);
checkAppInformation(elem, 72);
checkCS(elem, tva.e_Coding, cs.VideoCodecCS, 73);
if (!checkCS(elem, tva.e_Coding, cs.VideoCodecCS, 73))
errs.errorDescription({ code: `${errCode}-73`, description: `value for ${tva.e_Coding.elementize()} is not taken from the VideoCodecCS` });
checkSignLanguage(elem, tva.e_SignLanguage, 74);
break;
case tva.e_DialogueEnhancementAttributes:
Expand Down
25 changes: 18 additions & 7 deletions cg_check.js
Original file line number Diff line number Diff line change
Expand Up @@ -1274,12 +1274,14 @@ export default class ContentGuideCheck {
const titleLang = GetNodeLanguage(Title, false, errs, `${errCode}-2`, this.#knownLanguages);
const titleStr = unEntity(Title.text());

if (titleStr.length > dvbi.MAX_TITLE_LENGTH)
if (titleStr.length > dvbi.MAX_TITLE_LENGTH) {
errs.addError({
code: `${errCode}-11`,
message: `${tva.e_Title.elementize()} length exceeds ${dvbi.MAX_TITLE_LENGTH} characters`,
fragment: Title,
});
errs.errorDescription({code:`${errCode}-11`, description: "refer clause 6.10.5 in A177"})
}
switch (titleType) {
case mpeg7.TITLE_TYPE_MAIN:
if (mainTitles.find((e) => e.lang == titleLang))
Expand Down Expand Up @@ -1310,6 +1312,8 @@ export default class ContentGuideCheck {
message: `${tva.a_type.attribute()} must be ${mpeg7.TITLE_TYPE_MAIN.quote()} or ${mpeg7.TITLE_TYPE_SECONDARY.quote()} for ${tva.e_Title.elementize()}`,
fragment: Title,
});
errs.errorDescription({code:`${errCode}-15`, description: "refer to the relevant subsection of clause 6.10.5 in A177"});
break;
}
}
secondaryTitles.forEach((item) => {
Expand Down Expand Up @@ -1522,6 +1526,12 @@ export default class ContentGuideCheck {
}
}

/*private*/ #NotCRIDFormat(errs, error)
{
errs.addError(error);
errs.errorDescription({code: error?.code, description: "format if a CRID is defined in clause 8 of ETSI TS 102 822"})
}

/**
* validate the <ProgramInformation> element against the profile for the given request/response type
*
Expand Down Expand Up @@ -1573,7 +1583,7 @@ export default class ContentGuideCheck {
if (ProgramInformation.attr(tva.a_programId)) {
programCRID = ProgramInformation.attr(tva.a_programId).value();
if (!isCRIDURI(programCRID))
errs.addError({
this.#NotCRIDFormat(errs, {
code: "PI011",
message: `${tva.a_programId.attribute(ProgramInformation.name())} is not a valid CRID (${programCRID})`,
line: ProgramInformation.line(),
Expand Down Expand Up @@ -1617,7 +1627,7 @@ export default class ContentGuideCheck {
fragment: child,
});
else if (!isCRIDURI(foundCRID))
errs.addError({
this.#NotCRIDFormat(errs, {
code: "PI033",
message: `${tva.a_crid.attribute(`${ProgramInformation.name()}.${tva.e_EpisodeOf}`)}=${foundCRID.quote()} is not a valid CRID`,
fragment: child,
Expand Down Expand Up @@ -1652,7 +1662,7 @@ export default class ContentGuideCheck {
fragment: child,
});
else if (!isCRIDURI(foundCRID))
errs.addError({
this.#NotCRIDFormat(errs,{
code: "PI045",
message: `${tva.a_crid.attribute(`${ProgramInformation.name()}.${tva.e_MemberOf}`)}=${foundCRID.quote()} is not a valid CRID`,
fragment: child,
Expand Down Expand Up @@ -1951,7 +1961,7 @@ export default class ContentGuideCheck {
if (GroupInformation.attr(tva.a_groupId)) {
const groupId = GroupInformation.attr(tva.a_groupId).value();
if (!isCRIDURI(groupId))
errs.addError({
this.#NotCRIDFormat(errs, {
code: "GIM003",
message: `${tva.a_groupId.attribute(GroupInformation.name())} value ${groupId.quote()} is not a valid CRID`,
line: GroupInformation.line(),
Expand Down Expand Up @@ -2974,12 +2984,13 @@ export default class ContentGuideCheck {

let ProgramCRID = Program.attr(tva.a_crid);
if (ProgramCRID) {
if (!isCRIDURI(ProgramCRID.value()))
errs.addError({
if (!isCRIDURI(ProgramCRID.value())) {
this.#NotCRIDFormat(errs, {
code: "SE011",
message: `${tva.a_crid.attribute(tva.e_Program)} is not a valid CRID (${ProgramCRID.value()})`,
fragment: Program,
});
}
if (!isIni(programCRIDs, ProgramCRID.value()))
errs.addError({
code: "SE012",
Expand Down
Loading

0 comments on commit f36dac4

Please sign in to comment.