Skip to content

Commit

Permalink
Merge branch 'main' into fix-memoize-types
Browse files Browse the repository at this point in the history
  • Loading branch information
caugner authored Mar 5, 2024
2 parents adfbc8c + 0071314 commit 212c499
Show file tree
Hide file tree
Showing 40 changed files with 796 additions and 490 deletions.
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "2.41.0"
".": "2.42.1"
}
62 changes: 62 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,67 @@
# Changelog

## [2.42.1](https://github.com/mdn/yari/compare/v2.42.0...v2.42.1) (2024-03-04)


### Bug Fixes

* **build/matches:** remove unnecessary type imports ([#10634](https://github.com/mdn/yari/issues/10634)) ([7a31bf6](https://github.com/mdn/yari/commit/7a31bf6297f0f7ea309f831ef34318abb80b287c))


### Miscellaneous

* **deps-dev:** bump @playwright/test from 1.42.0 to 1.42.1 ([#10641](https://github.com/mdn/yari/issues/10641)) ([83a4b83](https://github.com/mdn/yari/commit/83a4b83c89e7a50bbe51695c5f4f63003e50974a))
* **deps-dev:** bump eslint-plugin-react from 7.33.2 to 7.34.0 ([#10639](https://github.com/mdn/yari/issues/10639)) ([ae23d61](https://github.com/mdn/yari/commit/ae23d61db80f0b41069755e6c47d42bdb4063981))
* **deps-dev:** bump html-validate from 8.11.1 to 8.12.0 ([#10640](https://github.com/mdn/yari/issues/10640)) ([fc9bcec](https://github.com/mdn/yari/commit/fc9bcece20e5878cb2190a03304de1d69e4e6c3e))
* **deps:** bump @mdn/browser-compat-data from 5.5.12 to 5.5.13 ([#10642](https://github.com/mdn/yari/issues/10642)) ([bce0c1f](https://github.com/mdn/yari/commit/bce0c1fde52e6b17ac8ccb922d3bdabeedc861d9))
* **deps:** bump the dependencies group in /deployer with 2 updates ([#10637](https://github.com/mdn/yari/issues/10637)) ([2493ab5](https://github.com/mdn/yari/commit/2493ab5129a07d91c9d73c842be6d77dc2aa0223))
* **deps:** bump the dependencies group in /testing/integration with 1 update ([#10635](https://github.com/mdn/yari/issues/10635)) ([be0f9eb](https://github.com/mdn/yari/commit/be0f9eb2cfb06623bbdb51a79247089a23527fef))
* **deps:** bump the sentry group with 2 updates ([#10636](https://github.com/mdn/yari/issues/10636)) ([8b8d421](https://github.com/mdn/yari/commit/8b8d421d5778d4d87344ebdb0d38560772180d98))
* **macro:** Add ko DOMAttributeMethods ([9658fca](https://github.com/mdn/yari/commit/9658fcaba5bd7a7ecae28eb5129d9171c70e9d16))
* **macros/DOMAttributeMethods:** add ko locale ([#10502](https://github.com/mdn/yari/issues/10502)) ([9658fca](https://github.com/mdn/yari/commit/9658fcaba5bd7a7ecae28eb5129d9171c70e9d16))

## [2.42.0](https://github.com/mdn/yari/compare/v2.41.0...v2.42.0) (2024-03-01)


### Features

* **ai-help:** index short_title ([#10579](https://github.com/mdn/yari/issues/10579)) ([6939552](https://github.com/mdn/yari/commit/69395528f0943a99cc0fd033407b72830fb58f4f))
* **ai-help:** show canned answer without sources for off-topic questions ([#10575](https://github.com/mdn/yari/issues/10575)) ([fcd236a](https://github.com/mdn/yari/commit/fcd236a8565e506ae255483984315b81950d738d))


### Bug Fixes

* **ai-help:** hide "Stop answering" before we respond ([#10530](https://github.com/mdn/yari/issues/10530)) ([ad5f5a4](https://github.com/mdn/yari/commit/ad5f5a44dc0ce4285bb6c0471f89fa5b566235a2))
* **ai-help:** refetch quota after an ai error ([#10615](https://github.com/mdn/yari/issues/10615)) ([aa6b141](https://github.com/mdn/yari/commit/aa6b141a34e0542ee458ed0aeffcc3c434801188))
* **ai-help:** remove decorative images from a11y tree ([#10520](https://github.com/mdn/yari/issues/10520)) ([575420c](https://github.com/mdn/yari/commit/575420cf6100a94e3263d9834652a255660d9d1a))
* **build:** check for bad_src flaws in markdown files ([#8133](https://github.com/mdn/yari/issues/8133)) ([a76cc0e](https://github.com/mdn/yari/commit/a76cc0e2c43463b5bed3d48d0d0af94a9bbabc47))
* **modal:** make close button visible ([#10604](https://github.com/mdn/yari/issues/10604)) ([2e06a1a](https://github.com/mdn/yari/commit/2e06a1ad8adc5d97dc1d8b264ad06bd3f3cdcd36))


### Enhancements

* **ai-help:** disable top banner if quota banner is visible ([#10532](https://github.com/mdn/yari/issues/10532)) ([0b03586](https://github.com/mdn/yari/commit/0b03586af5d87eb86f2301c6309ed01c7c970250))
* **ai-help:** improve stopped state ([#10580](https://github.com/mdn/yari/issues/10580)) ([8c988be](https://github.com/mdn/yari/commit/8c988be94b8e89d26c0a847a3f98d443b7ab0421))
* **build/spas:** allow yarn dev without internet if DEV_MODE is enabled ([#10533](https://github.com/mdn/yari/issues/10533)) ([78a9500](https://github.com/mdn/yari/commit/78a95005b171b67dca006a51c2e54c245d281a95))


### Miscellaneous

* **deps-dev:** bump @babel/core from 7.23.9 to 7.24.0 ([#10621](https://github.com/mdn/yari/issues/10621)) ([514592d](https://github.com/mdn/yari/commit/514592d2cf4381811bee58abc095a8026ff55c10))
* **deps-dev:** bump @babel/preset-env from 7.23.9 to 7.24.0 ([#10619](https://github.com/mdn/yari/issues/10619)) ([0fc068f](https://github.com/mdn/yari/commit/0fc068f84de542231ff50a1f1b28feff6f9e1a0a))
* **deps-dev:** bump postcss-loader from 8.1.0 to 8.1.1 ([#10620](https://github.com/mdn/yari/issues/10620)) ([266d4d8](https://github.com/mdn/yari/commit/266d4d82ddd1a8f5214d081c6fa763f46d3b75d7))
* **deps-dev:** bump the types group with 1 update ([#10627](https://github.com/mdn/yari/issues/10627)) ([27ea44f](https://github.com/mdn/yari/commit/27ea44fbad8e30194d8e36c04bbf01bb265fb68e))
* **deps:** bump [@zip](https://github.com/zip).js/zip.js from 2.7.35 to 2.7.36 in /client/pwa ([#10623](https://github.com/mdn/yari/issues/10623)) ([aa34dab](https://github.com/mdn/yari/commit/aa34dabf46529798152e5c7869097d6fea0372a7))
* **deps:** bump @webref/css from 6.12.0 to 6.12.1 ([#10622](https://github.com/mdn/yari/issues/10622)) ([4f68cf5](https://github.com/mdn/yari/commit/4f68cf545249e3800a3d8e05644fb4be441eb895))
* **deps:** bump express from 4.18.2 to 4.18.3 ([#10628](https://github.com/mdn/yari/issues/10628)) ([368c2c4](https://github.com/mdn/yari/commit/368c2c40d229e5c6cd2261633e6cfadb7495f101))
* **deps:** bump openai from 4.28.0 to 4.28.4 ([#10618](https://github.com/mdn/yari/issues/10618)) ([2873cd9](https://github.com/mdn/yari/commit/2873cd9e83052b587a4dc430781a2374517e21bd))
* **deps:** bump sse.js from 2.2.0 to 2.3.0 ([#10631](https://github.com/mdn/yari/issues/10631)) ([4b89823](https://github.com/mdn/yari/commit/4b898230f7a66296c51da3b697de04264614ff49))
* **deps:** bump the sentry group with 2 updates ([#10626](https://github.com/mdn/yari/issues/10626)) ([5bd14de](https://github.com/mdn/yari/commit/5bd14de55ea0e3b95ae7505e81e83570ed9dbd06))
* **deps:** bump web-specs from 3.3.1 to 3.4.0 ([#10629](https://github.com/mdn/yari/issues/10629)) ([e9a2722](https://github.com/mdn/yari/commit/e9a272284bc04227be3566e8af0ad0b44af70f1e))
* **featured-articles:** update links for 2024 Q1 ([#10613](https://github.com/mdn/yari/issues/10613)) ([4725d59](https://github.com/mdn/yari/commit/4725d59fe89060595b83f4554d37da3ef24e3977))
* **footer:** replace Twitter with X logo ([#10438](https://github.com/mdn/yari/issues/10438)) ([a940648](https://github.com/mdn/yari/commit/a94064884b5027b43035450ab6bacd8232d29fbc))
* **macros/CSSRef:** add Containment guides ([#10611](https://github.com/mdn/yari/issues/10611)) ([c207fcc](https://github.com/mdn/yari/commit/c207fcce4016beaa40f612871ab1458de0499db3))

## [2.41.0](https://github.com/mdn/yari/compare/v2.40.0...v2.41.0) (2024-02-28)


Expand Down
89 changes: 47 additions & 42 deletions build/check-images.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import imagesize from "image-size";

import { Document, FileAttachment } from "../content/index.js";
import { FLAW_LEVELS } from "../libs/constants/index.js";
import { findMatchesInText } from "./matches-in-text.js";
import { findMatchesInText, findMatchesInMarkdown } from "./matches.js";
import * as cheerio from "cheerio";
import { Doc } from "../libs/types/document.js";

Expand All @@ -30,50 +30,57 @@ export function checkImageReferences(

const checkImages = options.flawLevels.get("images") !== FLAW_LEVELS.IGNORE;

const checked = new Map();
const checked = new Map<string, number>();

function addImageFlaw(
$img,
src,
{ explanation, externalImage = false, suggestion = null }
$img: cheerio.Cheerio<cheerio.Element>,
src: string,
{
explanation,
externalImage = false,
suggestion = null,
}: {
explanation: string;
externalImage?: boolean;
suggestion?: string;
}
) {
// If the document has *two* `<img src="XXX">` tags, this function
// (addImageFlaw) is called two times. We can then assume the
// findMatchesInText() will find it two times too. For each call,
// we need to match the call based in counting matches from findMatchesInText().
const matches = [
...findMatchesInText(src, rawContent, {
attribute: "src",
}),
];
const checkedBefore = checked.get(src) || 0;
matches.forEach((match, i) => {
if (i !== checkedBefore) {
return;
}
if (!("images" in doc.flaws)) {
doc.flaws.images = [];
}
let fixable = false;
if (suggestion) {
$img.attr("src", suggestion);
fixable = true;
}
const id = `image${doc.flaws.images.length + 1}`;
$img.attr("data-flaw", id);
doc.flaws.images.push({
id,
src,
fixable,
suggestion,
explanation,
externalImage,
...match,
});

// Use this to remember which in the list of matches we've dealt with.
checked.set(src, checkedBefore + 1);
const matches = doc.isMarkdown
? findMatchesInMarkdown(src, rawContent, { type: "image" })
: findMatchesInText(src, rawContent, { attribute: "src" });
const checkedBefore = checked.get(src) ?? 0;
if (matches.length <= checkedBefore) {
console.warn(
`Could not find enough matches for src: ${src}, index ${checkedBefore} out of bounds`
);
return;
}
const match = matches[checkedBefore];
if (!("images" in doc.flaws)) {
doc.flaws.images = [];
}
const fixable = Boolean(suggestion);
if (suggestion) {
$img.attr("src", suggestion);
}
const id = `image${doc.flaws.images.length + 1}`;
$img.attr("data-flaw", id);
doc.flaws.images.push({
id,
src,
fixable,
suggestion,
explanation,
externalImage,
...match,
});

// Use this to remember which in the list of matches we've dealt with.
checked.set(src, checkedBefore + 1);
}

$("img[src]").each((i, element) => {
Expand Down Expand Up @@ -238,11 +245,9 @@ export function checkImageWidths(
}
const id = `image_widths${doc.flaws.image_widths.length + 1}`;
$img.attr("data-flaw", id);
const matches = [
...findMatchesInText(style, rawContent, {
attribute: "style",
}),
];
const matches = findMatchesInText(style, rawContent, {
attribute: "style",
});
const checkedBefore = checked.get(style) || 0;
matches.forEach((match, i) => {
if (i !== checkedBefore) {
Expand Down
30 changes: 6 additions & 24 deletions build/flaws/broken-links.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import fs from "node:fs";

import { fromMarkdown } from "mdast-util-from-markdown";
import { visit } from "unist-util-visit";

import { Document, Redirect, FileAttachment } from "../../content/index.js";
import { findMatchesInText } from "../matches-in-text.js";
import { findMatchesInText, findMatchesInMarkdown } from "../matches.js";
import {
DEFAULT_LOCALE,
FLAW_LEVELS,
Expand All @@ -15,17 +12,6 @@ import * as cheerio from "cheerio";
import { Doc } from "../../libs/types/document.js";
import { Flaw } from "./index.js";

function findMatchesInMarkdown(rawContent: string, href: string) {
const matches = [];
visit(fromMarkdown(rawContent), "link", (node: any) => {
if (node.url == href) {
const { line, column } = node.position.start;
matches.push({ line, column });
}
});
return matches;
}

const _safeToHttpsDomains = new Map();

function getSafeToHttpDomains() {
Expand Down Expand Up @@ -127,17 +113,13 @@ export function getBrokenLinksFlaws(
href,

doc.isMarkdown
? findMatchesInMarkdown(rawContent, href)
: Array.from(
findMatchesInText(href, rawContent, {
attribute: "href",
})
)
? findMatchesInMarkdown(href, rawContent, { type: "link" })
: findMatchesInText(href, rawContent, {
attribute: "href",
})
);
}
// findMatchesInText() is a generator function so use `Array.from()`
// to turn it into an array so we can use `.forEach()` because that
// gives us an `i` for every loop.

matches.get(href).forEach((match, i) => {
if (i !== index) {
return;
Expand Down
2 changes: 1 addition & 1 deletion build/flaws/heading-links.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { findMatchesInText } from "../matches-in-text.js";
import { findMatchesInText } from "../matches.js";
import * as cheerio from "cheerio";
import { Doc } from "../../libs/types/document.js";
import { Flaw } from "./index.js";
Expand Down
2 changes: 1 addition & 1 deletion build/flaws/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
import {
replaceMatchesInText,
replaceMatchingLinksInMarkdown,
} from "../matches-in-text.js";
} from "../matches.js";
import { forceExternalURL, downloadAndResizeImage } from "../utils.js";
import { getBadBCDQueriesFlaws } from "./bad-bcd-queries.js";
import { getBrokenLinksFlaws } from "./broken-links.js";
Expand Down
2 changes: 1 addition & 1 deletion build/flaws/pre-tags.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Flaw } from "./index.js";

import { getFirstMatchInText } from "../matches-in-text.js";
import { getFirstMatchInText } from "../matches.js";
import * as cheerio from "cheerio";
import { Doc } from "../../libs/types/document.js";
const escapeHTML = (s: string) =>
Expand Down
2 changes: 1 addition & 1 deletion build/flaws/unsafe-html.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
INTERACTIVE_EXAMPLES_BASE_URL,
LIVE_SAMPLES_BASE_URL,
} from "../../libs/env/index.js";
import { findMatchesInText } from "../matches-in-text.js";
import { findMatchesInText } from "../matches.js";
import * as cheerio from "cheerio";
import { Doc } from "../../libs/types/document.js";

Expand Down
62 changes: 50 additions & 12 deletions build/matches-in-text.ts → build/matches.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,68 @@
import { fromMarkdown } from "mdast-util-from-markdown";
import { visit } from "unist-util-visit";

const ESCAPE_CHARS_RE = /[.*+?^${}()|[\]\\]/g;

export function* findMatchesInText(
needle,
haystack,
type Match = { line: number; column: number };

export function findMatchesInText(
needle: string,
haystack: string,
{ attribute = null } = {}
) {
): Match[] {
// Need to remove any characters that can affect a regex if we're going
// use the string in a manually constructed regex.
const escaped = needle.replace(ESCAPE_CHARS_RE, "\\$&");
let rex;
if (attribute) {
rex = new RegExp(`${attribute}=['"](${escaped})['"]`, "g");
} else {
rex = new RegExp(`(${escaped})`, "g");
}
const rex = attribute
? new RegExp(`${attribute}=['"](${escaped})['"]`, "g")
: new RegExp(`(${escaped})`, "g");
const matches: Match[] = [];
for (const match of haystack.matchAll(rex)) {
const left = haystack.slice(0, match.index);
const line = (left.match(/\n/g) || []).length + 1;
const lastIndexOf = left.lastIndexOf("\n") + 1;
const column =
match.index - lastIndexOf + 1 + (attribute ? attribute.length + 2 : 0);
yield { line, column };
matches.push({ line, column });
}
return matches;
}

// find links or images in markdown content that match the given URL
export function findMatchesInMarkdown(
url: string,
rawContent: string,
{ type }: { type: "link" | "image" }
): Match[] {
const matches: Match[] = [];
const attributeType = type === "link" ? "href" : "src";
const tree = fromMarkdown(rawContent);
// Find all the links and images in the markdown
// we should also find any HTML elements that contain links or images
visit(tree, [type, "html"], (node) => {
if (node.type === "html") {
const matchesInHtml = findMatchesInText(url, node.value, {
attribute: attributeType,
});
const correctedMatches = matchesInHtml.map(({ line, column }): Match => {
if (line === 1) {
// if it's the first line, we need to add the column offset
column += node.position.start.column - 1;
}
line += node.position.start.line - 1;
return { line, column };
});
matches.push(...correctedMatches);
} else if (node.type == type && node.url === url) {
// else this would be a markdown link or image
const { line, column } = node.position.start;
matches.push({ line, column });
}
});
return matches;
}

export function getFirstMatchInText(needle, haystack) {
export function getFirstMatchInText(needle, haystack): Match {
const index = haystack.indexOf(needle);
const left = haystack.substring(0, index);
const line = left.split("\n").length;
Expand Down
Loading

0 comments on commit 212c499

Please sign in to comment.