diff --git a/lib/kuma/index.js b/lib/kuma/index.js index cde5799..5c893f7 100644 --- a/lib/kuma/index.js +++ b/lib/kuma/index.js @@ -33,6 +33,7 @@ import noTagOmission from './macros/no_tag_omission.js'; import svgelement from './macros/svgelement.js'; import jsPropertyAttributes from './macros/js_property_attributes.js'; import EmbedGhLiveSample from './macros/embed-gh-live-sample.js'; +import DeprecatedBadge from './macros/deprecated-badge.js'; export { parseMacroArgs, extractMacros } from './match.js'; @@ -91,6 +92,7 @@ export function macros(context) { svgelement, js_property_attributes: jsPropertyAttributes, embedghlivesample: EmbedGhLiveSample, + deprecatedbadge: DeprecatedBadge, }; // Attach outside context, like page registry or locale info to all macro functions diff --git a/lib/kuma/macros/api-list-alpha.js b/lib/kuma/macros/api-list-alpha.js new file mode 100644 index 0000000..a75ae25 --- /dev/null +++ b/lib/kuma/macros/api-list-alpha.js @@ -0,0 +1,119 @@ +import DeprecatedBadge from './deprecated-badge.js'; +import ExperimentalBadge from './experimental-badge.js'; +import NonStandardBadge from './non-standard-badge.js'; +import ObsoleteBadge from './obsolete-badge.js'; + +const letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZАБВГҐДЕЄЖЗИІЇЙКЛМНОПРСТУФХЦЧШЩЬЮЯ'; + +/** + * Prepares the title of the link. This includes wrapping the appropriate + * portion of the title with . Returns null if the page should not + * be included in the index. + * + * @param {string} base + * @returns {null | string} + */ +function buildTitle(base) { + const spaceIndex = base.indexOf(' '); + // If there are no spaces in the page's title, the entire base + // string is the title, so we just wrap the whole thing in and + // return it. + if (spaceIndex === -1 && base !== 'Reference') { + return '' + base + ''; + } + // If the character after the space is '(', then this is assumed to be an + // interface with a qualifier after its name (such as "(Firefox OS)"). + // These are allowed to appear in the index, but we end the block + // before the first space + if (spaceIndex < base.length - 1 && base[spaceIndex + 1] === '(') { + return ( + '' + + base.substring(0, spaceIndex) + + '' + + base.substring(spaceIndex) + ); + } + // It's not an interface, so return null. + return null; +} + +/** + * + * @param {string[]=} tagList + * @param {string} tag + * @returns {boolean} + */ +function containsTag(tagList, tag) { + if (!tagList) return false; + const normalizedTag = tag.toLowerCase(); + return tagList.some((tagItem) => tagItem.toLowerCase() === normalizedTag); +} +export default function ApiListAlpha(apiHref = '/uk/docs/Web/API') { + const locale = this.env.targetLocale; + const pages = this.registry.getChildren(apiHref); // get subpages, including tags + // The result of `getChildren()` does not guarantee the order to be + // alphabetical. Most of the time it is because of how the OS is iterating over + // files on disk. So sort it first, because the rendering loop (see far below) + // depends on it. + pages.sort((a, b) => + a.title.toLowerCase().localeCompare(b.title.toLowerCase(), locale) + ); + const numPages = pages.length; + let html = ''; + const p = 0; + for (const letter of letters) { + const insertedHeading = false; // Haven't done this letter's heading yet + if (p < numPages) { + do { + const tags = pages[p].tags; + const url = pages[p].path; + const title = pages[p].title; + // Build the formatted title string; skip this page if it's not + // an interface. + const builtTitle = buildTitle(title); + if (builtTitle === null) { + p++; + continue; + } + let badge = ''; + // add badges if needed + if ( + containsTag(tags, 'Non-standard') || + containsTag(tags, 'Non standard') + ) { + badge += ` ${NonStandardBadge('1')}`; + } + if (containsTag(tags, 'Obsolete')) { + badge += ` ${ObsoleteBadge(1)}`; + } else if (containsTag(tags, 'Deprecated')) { + badge += ` ${DeprecatedBadge(1)}`; + } + if (containsTag(tags, 'Experimental')) { + badge += ` ${ExperimentalBadge('1')}`; + } + // Wrap the badges in another span + if (badge.length > 0) + badge = `${badge}`; + if (title[0].toUpperCase() === letter) { + if (!containsTag(tags, 'junk')) { + if (!insertedHeading) { + html += `

${letter}

    `; + insertedHeading = true; + } + html += `\n
  • ${builtTitle}${badge}
  • `; + } + p++; + } else { + break; + } + } while (p < numPages); + } + html += '\n
\n'; + } + return `
+ ${html} +
`; +} diff --git a/lib/kuma/macros/deprecated-badge.js b/lib/kuma/macros/deprecated-badge.js new file mode 100644 index 0000000..4edc30c --- /dev/null +++ b/lib/kuma/macros/deprecated-badge.js @@ -0,0 +1,5 @@ +export default function DeprecatedBadge() { + return ` + Нерекомендовано + `; +} diff --git a/lib/kuma/macros/experimental-badge.js b/lib/kuma/macros/experimental-badge.js new file mode 100644 index 0000000..6021359 --- /dev/null +++ b/lib/kuma/macros/experimental-badge.js @@ -0,0 +1,5 @@ +export default function ExperimentalBadge() { + return ` + Експериментальне + `; +} diff --git a/lib/kuma/macros/non-standard-badge.js b/lib/kuma/macros/non-standard-badge.js new file mode 100644 index 0000000..1589855 --- /dev/null +++ b/lib/kuma/macros/non-standard-badge.js @@ -0,0 +1,8 @@ +/** + * Inserts a badge indicating a term or API is non-standard. + */ +export default function NonStandardBadge() { + return ` + Нестандартне + `; +} diff --git a/lib/kuma/macros/obsolete-badge.js b/lib/kuma/macros/obsolete-badge.js new file mode 100644 index 0000000..12bfb89 --- /dev/null +++ b/lib/kuma/macros/obsolete-badge.js @@ -0,0 +1,11 @@ +/** + * Inserts a badge marking an API or term as being obsolete. + */ +export default function ObsoleteBadge() { + return ` + Це застарілий API – немає гарантій, що він працюватиме. + + `; +} diff --git a/lib/kuma/utils/get-local-string.js b/lib/kuma/utils/get-local-string.js index 526f308..4844191 100644 --- a/lib/kuma/utils/get-local-string.js +++ b/lib/kuma/utils/get-local-string.js @@ -18,7 +18,7 @@ function getLocalString(strings, key) { return key; } - let lang = this.env.locale; + let lang = this.env.targetLocale; if (!(lang in strings[key])) { lang = 'en-US'; } diff --git a/lib/kuma/utils/local-string.js b/lib/kuma/utils/local-string.js index b6e328c..5147cd6 100644 --- a/lib/kuma/utils/local-string.js +++ b/lib/kuma/utils/local-string.js @@ -6,8 +6,8 @@ * Return the one which matches the current locale. */ function localString(strings) { - let lang = this.env.locale; // TODO: this clearly shouldn't work, needs replacement - if (!(lang in strings)) lang = 'en-US'; + let lang = this.env.targetLocale; + if (!strings[lang]) lang = 'en-US'; return strings[lang]; }