diff --git a/.gitignore b/.gitignore index 7cf84ae1f..cdae3b7e9 100644 --- a/.gitignore +++ b/.gitignore @@ -21,4 +21,7 @@ yarn-error.log* # Custom .vscode/ -*.drawio.* \ No newline at end of file +*.drawio.* + +# JetBrains' IDEs +.idea \ No newline at end of file diff --git a/content/docs/std/algo/ranges/_codes/find/example-Failing-to-find-a-value-safely-when-dealing-with-an-iterator-pair-subrange.mdx b/content/docs/std/algo/ranges/_codes/find/example-Failing-to-find-a-value-safely-when-dealing-with-an-iterator-pair-subrange.mdx new file mode 100644 index 000000000..f138d6d2d --- /dev/null +++ b/content/docs/std/algo/ranges/_codes/find/example-Failing-to-find-a-value-safely-when-dealing-with-an-iterator-pair-subrange.mdx @@ -0,0 +1,25 @@ +```cpp showLineNumbers +#include +#include +#include + +auto main() -> int +{ + auto const numbers = std::vector{ + 1, 2, 3, 4, 5, 0, 6 + }; + + auto const zeroInFirstThree = std::ranges::find( + numbers.begin(), numbers.begin() + 3, 0 + ); + + if (zeroInFirstThree != numbers.begin() + 3) + { + std::cout << "there is a 0 in the first three elements"; + } + else + { + std::cout << "there are no 0s in the first three elements"; + } +} +``` \ No newline at end of file diff --git a/content/docs/std/algo/ranges/_codes/find/example-Failing-to-find-a-value-safely.mdx b/content/docs/std/algo/ranges/_codes/find/example-Failing-to-find-a-value-safely.mdx new file mode 100644 index 000000000..b1bb23ecc --- /dev/null +++ b/content/docs/std/algo/ranges/_codes/find/example-Failing-to-find-a-value-safely.mdx @@ -0,0 +1,23 @@ +```cpp showLineNumbers +#include +#include +#include + +auto main() -> int +{ + auto const onlyEvens = std::vector{ + 2, 4, 6, 8, 10 + }; + + auto const positionOf1 = std::ranges::find(onlyEvens, 1); + + if (positionOf1 != onlyEvens.end()) + { + std::cout << "odd element found: " << *positionOf1; + } + else + { + std::cout << "no odd elements found"; + } +} +``` \ No newline at end of file diff --git a/content/docs/std/algo/ranges/_codes/find/example-Failing-to-find-a-value-unsafely.mdx b/content/docs/std/algo/ranges/_codes/find/example-Failing-to-find-a-value-unsafely.mdx new file mode 100644 index 000000000..041b2aa26 --- /dev/null +++ b/content/docs/std/algo/ranges/_codes/find/example-Failing-to-find-a-value-unsafely.mdx @@ -0,0 +1,17 @@ +```cpp showLineNumbers +#include +#include +#include + +auto main() -> int +{ + auto const onlyEvens = std::vector{ + 2, 4, 6, 8, 10 + }; + + auto const positionOf1 = std::ranges::find(onlyEvens, 1); + + // error-next-line + std::cout << "odd element found: " << *positionOf1; // dereferencing end, undefined behavior +} +``` \ No newline at end of file diff --git a/content/docs/std/algo/ranges/_codes/find/example-Failing-to-find-a-value-when-dealing-with-an-iterator-pair-subrange-unsafely.mdx b/content/docs/std/algo/ranges/_codes/find/example-Failing-to-find-a-value-when-dealing-with-an-iterator-pair-subrange-unsafely.mdx new file mode 100644 index 000000000..3643a642b --- /dev/null +++ b/content/docs/std/algo/ranges/_codes/find/example-Failing-to-find-a-value-when-dealing-with-an-iterator-pair-subrange-unsafely.mdx @@ -0,0 +1,26 @@ +```cpp showLineNumbers +#include +#include +#include + +auto main() -> int +{ + auto const numbers = std::vector{ + 1, 2, 3, 4, 5, 0, 6 + }; + + auto const zeroInFirstThree = std::ranges::find( + numbers.begin(), numbers.begin() + 3, 0 + ); + + // error-next-line + if (zeroInFirstThree != numbers.end()) + { + std::cout << "there is a 0 in the first three elements"; + } + else + { + std::cout << "there are no 0s in the first three elements"; + } +} +``` \ No newline at end of file diff --git a/content/docs/std/algo/ranges/_codes/find/example-Finding-and-changing-the-found-value.mdx b/content/docs/std/algo/ranges/_codes/find/example-Finding-and-changing-the-found-value.mdx new file mode 100644 index 000000000..54e2f4d3b --- /dev/null +++ b/content/docs/std/algo/ranges/_codes/find/example-Finding-and-changing-the-found-value.mdx @@ -0,0 +1,20 @@ +```cpp showLineNumbers +#include +#include +#include + +int main() +{ + const auto println = [](std::vector const& vec) + { + for (const int element : vec) std::cout << element << ' '; + std::cout << '\n'; + }; + + std::vector values{2, 4, 5, 8, 10}; + println(values); + auto iteratorTo5 = std::ranges::find(values, 5); + *iteratorTo5 = 6; + println(values); +} +``` \ No newline at end of file diff --git a/content/docs/std/algo/ranges/_codes/find/example-Finding-and-printing-the-found-value.mdx b/content/docs/std/algo/ranges/_codes/find/example-Finding-and-printing-the-found-value.mdx new file mode 100644 index 000000000..5d673fa29 --- /dev/null +++ b/content/docs/std/algo/ranges/_codes/find/example-Finding-and-printing-the-found-value.mdx @@ -0,0 +1,12 @@ +```cpp showLineNumbers +#include +#include +#include + +auto main() -> int +{ + auto const values = std::vector{2, 4, 6, 1, 8, 10}; + auto const iteratorTo1 = std::ranges::find(values, 1); + std::cout << *iteratorTo1; +} +``` \ No newline at end of file diff --git a/content/docs/std/algo/ranges/_codes/find/example-Finding-and-removing-the-found-value.mdx b/content/docs/std/algo/ranges/_codes/find/example-Finding-and-removing-the-found-value.mdx new file mode 100644 index 000000000..f40d9195a --- /dev/null +++ b/content/docs/std/algo/ranges/_codes/find/example-Finding-and-removing-the-found-value.mdx @@ -0,0 +1,34 @@ +```cpp showLineNumbers +#include +#include +#include +#include + +auto main() -> int +{ + auto const println = [](const std::vector& vec) + { + for (auto const element : vec) + { + std::cout << element << ' '; + } + std::cout << '\n'; + }; + + auto values = std::vector{2, 4, 6, 1, 8, 10}; + auto text = std::string("hello, there!"); + + println(values); + std::cout << text << '\n'; + + auto const iteratorTo1 = std::ranges::find(values, 1); + values.erase(iteratorTo1); + + auto const iteratorToComma = std::ranges::find(text, ','); + text.erase(iteratorToComma); + + std::cout << '\n'; + println(values); + std::cout << text << '\n'; +} +``` \ No newline at end of file diff --git a/content/docs/std/algo/ranges/_codes/find/example-Finding-the-last-suitable-value-thanks-to-reverse-iterators.mdx b/content/docs/std/algo/ranges/_codes/find/example-Finding-the-last-suitable-value-thanks-to-reverse-iterators.mdx new file mode 100644 index 000000000..d915f1fce --- /dev/null +++ b/content/docs/std/algo/ranges/_codes/find/example-Finding-the-last-suitable-value-thanks-to-reverse-iterators.mdx @@ -0,0 +1,36 @@ +```cpp showLineNumbers +#include +#include +#include +#include + +auto main() -> int +{ + auto const println = [](std::vector const& vec) + { + for (auto const element : vec) + { + std::cout << element << ' '; + } + std::cout << '\n'; + }; + + auto numbers = std::vector{ + 1, 2, 3, 2, 1 + }; + + auto const first1 = std::ranges::find(numbers, 1); + auto const last1 = std::ranges::find(numbers.rbegin(), numbers.rend(), 1); + + println(numbers); + *first1 = 9; + *last1 = 7; + println(numbers); + + // can also use reverse_view from + auto numbersReversed = numbers | std::views::reverse; + auto const last2 = std::ranges::find(numbersReversed, 2); + *last2 = 0; + println(numbers); +} +``` \ No newline at end of file diff --git a/content/docs/std/algo/ranges/_codes/find/example-Using-a-projection-to-find-a-value-with-a-given-characteristic1.mdx b/content/docs/std/algo/ranges/_codes/find/example-Using-a-projection-to-find-a-value-with-a-given-characteristic1.mdx new file mode 100644 index 000000000..7dd677572 --- /dev/null +++ b/content/docs/std/algo/ranges/_codes/find/example-Using-a-projection-to-find-a-value-with-a-given-characteristic1.mdx @@ -0,0 +1,21 @@ +```cpp showLineNumbers +#include +#include +#include +#include + +auto main() -> int +{ + auto const words = std::vector{ + "some", "of", "these", "words", "are", + "of", "the", "same", "lengths" + }; + + auto const bySize = [](const std::string& s) { + return s.size(); + }; + + auto const ofSize5 = std::ranges::find(words, 5, bySize); + std::cout << *ofSize5; +} +``` \ No newline at end of file diff --git a/content/docs/std/algo/ranges/_codes/find/example-Using-a-projection-to-find-a-value-with-a-given-characteristic2.mdx b/content/docs/std/algo/ranges/_codes/find/example-Using-a-projection-to-find-a-value-with-a-given-characteristic2.mdx new file mode 100644 index 000000000..a9cadd8de --- /dev/null +++ b/content/docs/std/algo/ranges/_codes/find/example-Using-a-projection-to-find-a-value-with-a-given-characteristic2.mdx @@ -0,0 +1,19 @@ +```cpp showLineNumbers +#include +#include +#include + +auto main() -> int +{ + auto const numbers = std::vector{ + 5, 6, 7, 8 + }; + + auto const byModulus5 = [](const int n) { + return n % 5; + }; + + auto const withRemainder2 = std::ranges::find(numbers, 2, byModulus5); + std::cout << *withRemainder2; +} +``` \ No newline at end of file diff --git a/content/docs/std/algo/ranges/_codes/find/since-cpp20-simplified.mdx b/content/docs/std/algo/ranges/_codes/find/since-cpp20-simplified.mdx index 8715d00ad..c2294dd6d 100644 --- a/content/docs/std/algo/ranges/_codes/find/since-cpp20-simplified.mdx +++ b/content/docs/std/algo/ranges/_codes/find/since-cpp20-simplified.mdx @@ -7,18 +7,22 @@ constexpr I constexpr ranges::borrowed_iterator_t find( R&& r, const T& value, Proj proj = {} ); ``` +
+Additional information regarding parameter constraints The type of arguments are generic and have the following constraints: - `I` - `std::input_iterator` - `S` - `std::sentinel_for` - `T` - **(none)** - `Proj` - **(none)** -- **(2)** - `R` - `std::ranges::input_range` +- $(2)$ - `R` - `std::ranges::input_range` The `Proj` template argument has a default type of `std::identity` for all overloads. Additionally, each overload has the following constraints: -- **(1)** - `indirect_binary_predicate, const T*>>` -- **(2)** - `indirect_binary_predicate, Proj>, const T*>` +- $(1)$ - `indirect_binary_predicate, const T*>>` +- $(2)$ - `indirect_binary_predicate, Proj>, const T*>` (The `std::` namespace was ommitted here for readability) + +
\ No newline at end of file diff --git a/content/docs/std/algo/ranges/find.mdx b/content/docs/std/algo/ranges/find.mdx index cd5a96e8f..abefa5c1a 100644 --- a/content/docs/std/algo/ranges/find.mdx +++ b/content/docs/std/algo/ranges/find.mdx @@ -1,6 +1,6 @@ --- title: ranges::find algorithm -sidebar_label: ranges::find( ) +sidebar_label: ranges::find() description: ranges::find algorithm C++ documentation hide_title: true tags: [ranges, algorithm, find, search] @@ -11,13 +11,36 @@ cppreference_origin_rel: w/cpp/algorithm/ranges/find import SymbolTable, { Symbol } from "@site-comps/SymbolTable"; import Columns from "@site-comps/Columns"; import VersionTabs from "@site-comps/VersionTabs"; +import CustomCodeBlock from "@site-comps/CustomCodeBlock"; + {/* Codes */} -import Signature_SinceCpp20_Detailed from './_codes/find/since-cpp20-detailed.mdx'; -import Signature_SinceCpp20_Simplified from './_codes/find/since-cpp20-simplified.mdx'; +import Signature_SinceCpp20_Detailed from './_codes/find/since-cpp20-detailed.mdx'; +import Signature_SinceCpp20_Simplified from './_codes/find/since-cpp20-simplified.mdx'; +import FullCode_FindingAndPrintingTheFoundValue from './_codes/find/example-Finding-and-printing-the-found-value.mdx'; +import FullCode_FindingAndRemovingTheFoundValue from './_codes/find/example-Finding-and-removing-the-found-value.mdx'; +import FullCode_FindingAndChangingTheFoundValue from './_codes/find/example-Finding-and-changing-the-found-value.mdx'; +import FullCode_UsingAProjectionToFindAValueWithAGivenCharacteristic1 from './_codes/find/example-Using-a-projection-to-find-a-value-with-a-given-characteristic1.mdx'; +import FullCode_UsingAProjectionToFindAValueWithAGivenCharacteristic2 from './_codes/find/example-Using-a-projection-to-find-a-value-with-a-given-characteristic2.mdx'; +import FullCode_FailingToFindAValueSafely from './_codes/find/example-Failing-to-find-a-value-safely.mdx'; +import FullCode_FailingToFindAValueUnsafely from './_codes/find/example-Failing-to-find-a-value-unsafely.mdx'; +import FullCode_FindingTheLastSuitableValueThanksToReverseIterators from './_codes/find/example-Finding-the-last-suitable-value-thanks-to-reverse-iterators.mdx'; +import FullCode_FailingToFindAValueSafelyWhenDealingWithAnIteratorPairSubrange from './_codes/find/example-Failing-to-find-a-value-safely-when-dealing-with-an-iterator-pair-subrange.mdx'; +import FullCode_FailingToFindAValueWhenDealingWithAnIteratorPairSubrangeUnsafely from './_codes/find/example-Failing-to-find-a-value-when-dealing-with-an-iterator-pair-subrange-unsafely.mdx'; + +# std::ranges::find() algorithm + +### Explanation + +Used to _locate_ an element inside a range, providing direct access to it through the returned iterator. -# std::ranges::find() algorithm +If there are multiple values that this algorithm could locate, it returns an iterator to the one that it first encounters. +This is determined by the passed range / iterators behavior. + +If there is no suitable value, i.e., if the finding process fails, the algorithm returns an iterator equal to the end of the supplied range. + +### Signature -Returns an iterator to the first element in the range satisfiying specific criteria (or `last` iterator if there is no such iterator): +- $(1)$ Searches for an element equal to `value` (using `operator==`) in a range represented as $[\texttt{first}, \texttt{last})$. Returns `last` if no such element was found. -- **(1)** Searches for an element equal to `value` (using `operator==`) - -- **(2)** Same as **(1)**, but uses `r` as the source range, as if using `ranges::begin(r)` as `first` and `ranges::end(r)` as `last`. +- $(2)$ Same as $(1)$, but uses `r` as the source range, as if using `ranges::begin(r)` as `first` and `ranges::end(r)` as `last`. The function-like entities described on this page are [**niebloids**](/docs/std/algo/niebloids). +The elements are passed through the projection `proj` before being compared. +However, if no custom projection is specified (i.e., the default one (`std::identity`) is used), passing them through it doesn't do anything. + ### Parameters @@ -59,7 +83,7 @@ Iterator to the first element satisfying the condition or iterator equal to `las ### Complexity -Exactly `last - first` applications of the predicate and projection. +Linear. Exactly `last - first` applications of the predicate and projection. ### Exceptions @@ -102,70 +126,264 @@ inline constexpr find_fn find; ### Examples - -
+#### Finding and printing the found value + +}> + +```cpp +auto const values = std::vector{2, 4, 6, 1, 8, 10}; +auto const iteratorTo1 = std::ranges::find(values, 1); +std::cout << *iteratorTo1; +``` + + + +```plaintext title="Output" +1 +``` + +#### Finding and removing the found value + +}> + +```cpp +auto values = std::vector{2, 4, 6, 1, 8, 10}; +auto text = std::string("hello, there!"); + +println(values); +std::cout << text << '\n'; + +auto const iteratorTo1 = std::ranges::find(values, 1); +values.erase(iteratorTo1); + +auto const iteratorToComma = std::ranges::find(text, ','); +text.erase(iteratorToComma); + +std::cout << '\n'; +println(values); +std::cout << text << '\n'; +``` + + + +```plaintext title="Output" +2 4 6 1 8 10 +hello, there! + +2 4 6 8 10 +hello there! +``` + +#### Finding and changing the found value + +}> -```cpp title='Main.cpp' showLineNumbers -#include -#include -#include +```cpp +auto values = std::vector{2, 4, 5, 8, 10}; +println(values); +auto const iteratorTo5 = std::ranges::find(values, 5); +*iteratorTo5 = 6; +println(values); +``` + + + +```plaintext title="Output" +2 4 5 8 10 +2 4 6 8 10 +``` + +:::info +Despite `iteratorTo5` being `const`, it's still fine to use it to alter the element it points to. That's because the `const` modifier in its declaration applies only to the iterator itself - we can't change **it** (we can't change *to which* element it points to), but we can alter _the object it points to_. +::: + +#### Using a projection to find a value with a given characteristic #1 + +}> + +```cpp +auto const words = std::vector{ + "some", "of", "these", "words", "are", + "of", "the", "same", "lengths" +}; + +auto const ofSize5 = std::ranges::find(words, 5, bySize); +std::cout << *ofSize5; +``` + + +```plaintext title="Output" +these +``` + +#### Using a projection to find a value with a given characteristic #2 + +}> + +```cpp +auto const numbers = std::vector{ + 5, 6, 7, 8 +}; + +auto const withRemainder2 = std::ranges::find(numbers, 2, byModulus5); +std::cout << *withRemainder2; +``` -int main() + + +```plaintext title="Output" +7 +``` + +#### Failing to find a value safely + +}> + +```cpp +auto const onlyEvens = std::vector{ + 2, 4, 6, 8, 10 +}; + +auto const positionOf1 = std::ranges::find(onlyEvens, 1); + +if (positionOf1 != onlyEvens.end()) +{ + std::cout << "odd element found: " << *positionOf1; +} +else +{ + std::cout << "no odd elements found"; +} +``` + + + +```plaintext title="Output" +no even elements found +``` + +:::info +Because finding _may_ fail, we should almost always compare the returned iterator with the _end_ of the supplied range before we use it. +::: + +#### Failing to find a value unsafely + +}> + +```cpp +auto const onlyEvens = std::vector{ + 2, 4, 6, 8, 10 +}; + +auto const positionOf1 = std::ranges::find(onlyEvens, 1); + +// error-next-line +std::cout << "odd element found: " << *positionOf1; // dereferencing end, undefined behavior +``` + + + +:::danger +Because `onlyEvens` does **not** contain the searched-for value `1`, it returns the _end_ of the supplied range, i.e., `onlyEvens.end()`. Dereferencing it invokes undefined behavior. +::: + +#### Finding the last (instead of the first) suitable value thanks to reverse iterators + +}> + +```cpp +auto numbers = std::vector{ + 1, 2, 3, 2, 1 +}; + +auto const first1 = std::ranges::find(numbers, 1); +auto const last1 = std::ranges::find(numbers.rbegin(), numbers.rend(), 1); + +println(numbers); +*first1 = 9; +*last1 = 7; +println(numbers); + +// can also use reverse_view from +auto numbersReversed = numbers | std::views::reverse; +auto const last2 = std::ranges::find(numbersReversed, 2); +*last2 = 0; +println(numbers); +} +``` + + + +```plaintext title="Output" +1 2 3 2 1 +9 2 3 2 7 +9 2 3 0 7 +``` + +#### Failing to find a value safely when dealing with an iterator-pair subrange + +}> + +```cpp +auto const numbers = std::vector{ + 1, 2, 3, 4, 5, 0, 6 +}; + +auto const zeroInFirstThree = std::ranges::find( + numbers.begin(), numbers.begin() + 3, 0 +); + +if (zeroInFirstThree != numbers.begin() + 3) +{ + std::cout << "there is a 0 in the first three elements"; +} +else +{ + std::cout << "there are no 0s in the first three elements"; +} +``` + + + +```plaintext title="Output" +there are no 0s in the first three elements +``` + +:::info +When dealing with an iterator-pair subrange, the _end_ of that subrange is the second iterator passed to the algorithm. Thus, in order to correctly test for the validity of the returned iterator, it needs to be compared with the second argument of the algorithm. +::: + + +#### Failing to find a value when dealing with an iterator-pair subrange unsafely + +}> + +```cpp +auto const numbers = std::vector{ + 1, 2, 3, 4, 5, 0, 6 +}; + +auto const zeroInFirstThree = std::ranges::find( + numbers.begin(), numbers.begin() + 3, 0 +); + +// error-next-line +if (zeroInFirstThree != numbers.end()) +{ + std::cout << "there is a 0 in the first three elements"; +} +else { - namespace ranges = std::ranges; - - const int n1 = 3; - const int n2 = 5; - const auto v = {4, 1, 3, 2}; - - if (ranges::find(v, n1) != v.end()) - std::cout << "v contains: " << n1 << '\n'; - else - std::cout << "v does not contain: " << n1 << '\n'; - - if (ranges::find(v.begin(), v.end(), n2) != v.end()) - std::cout << "v contains: " << n2 << '\n'; - else - std::cout << "v does not contain: " << n2 << '\n'; - - auto is_even = [](int x) { return x % 2 == 0; }; - - if (auto result = ranges::find_if(v.begin(), v.end(), is_even); result != v.end()) - std::cout << "First even element in v: " << *result << '\n'; - else - std::cout << "No even elements in v\n"; - - if (auto result = ranges::find_if_not(v, is_even); result != v.end()) - std::cout << "First odd element in v: " << *result << '\n'; - else - std::cout << "No odd elements in v\n"; - - auto divides_13 = [](int x) { return x % 13 == 0; }; - - if (auto result = ranges::find_if(v, divides_13); result != v.end()) - std::cout << "First element divisible by 13 in v: " << *result << '\n'; - else - std::cout << "No elements in v are divisible by 13\n"; - - if (auto result = ranges::find_if_not(v.begin(), v.end(), divides_13); - result != v.end()) - std::cout << "First element indivisible by 13 in v: " << *result << '\n'; - else - std::cout << "All elements in v are divisible by 13\n"; + std::cout << "there are no 0s in the first three elements"; } ``` -
-
+ ```plaintext title="Output" -v contains: 3 -v does not contain: 5 -First even element in v: 4 -First odd element in v: 1 -No elements in v are divisible by 13 -First element indivisible by 13 in v: 4 +there is a 0 in the first three elements ``` -
-
+:::danger +Here, instead of comparing the resulting iterator with the correct _end_, it was compared to the `numbers.end()`, which it had no chance of reaching. Thus, it is not equal to it, mistakenly suggesting that there indeed does exist a `0` value in the first three elements of `numbers`. +::: diff --git a/docusaurus.config.ts b/docusaurus.config.ts index 61ab0377a..66e75e1c1 100644 --- a/docusaurus.config.ts +++ b/docusaurus.config.ts @@ -4,6 +4,8 @@ import path from "path"; // Docusaurus import type { Config } from "@docusaurus/types"; import type * as Preset from "@docusaurus/preset-classic"; +import remarkMath from "remark-math"; +import rehypeKatex from "rehype-katex"; // Custom import * as Themes from "./src/prism/themes"; @@ -114,6 +116,8 @@ const config = { showLastUpdateTime: false, showLastUpdateAuthor: false, exclude: ["**/_codes/**.{mdx}"], + remarkPlugins: [remarkMath], + rehypePlugins: [rehypeKatex], }, blog: { showReadingTime: true, @@ -131,7 +135,15 @@ const config = { } satisfies Preset.Options, ], ], - + stylesheets: [ + { + href: "https://cdn.jsdelivr.net/npm/katex@0.13.24/dist/katex.min.css", + type: "text/css", + integrity: + "sha384-odtC+0UGzzFL/6PNoE8rX/SPcQDXBJ+uRepguP4QkPCm2LBxH3FA3y+fKSiJ+AmM", + crossorigin: "anonymous", + }, + ], themeConfig: { image: "img/favicon.png", diff --git a/package-lock.json b/package-lock.json index 4c5e4482a..ef1189fa8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,6 +23,8 @@ "raw-loader": "^4.0.2", "react": "^18.2.0", "react-dom": "^18.2.0", + "rehype-katex": "^7.0.1", + "remark-math": "^6.0.0", "sass": "^1.71.1", "sass-loader": "^14.1.1", "url-loader": "^4.1.1", @@ -4934,6 +4936,12 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, + "node_modules/@types/katex": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.7.tgz", + "integrity": "sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==", + "license": "MIT" + }, "node_modules/@types/mdast": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", @@ -9889,6 +9897,55 @@ "node": ">= 0.4" } }, + "node_modules/hast-util-from-dom": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/hast-util-from-dom/-/hast-util-from-dom-5.0.1.tgz", + "integrity": "sha512-N+LqofjR2zuzTjCPzyDUdSshy4Ma6li7p/c3pA78uTwzFgENbgbUrm2ugwsOdcjI1muO+o6Dgzp9p8WHtn/39Q==", + "license": "ISC", + "dependencies": { + "@types/hast": "^3.0.0", + "hastscript": "^9.0.0", + "web-namespaces": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-html": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz", + "integrity": "sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "devlop": "^1.1.0", + "hast-util-from-parse5": "^8.0.0", + "parse5": "^7.0.0", + "vfile": "^6.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-html-isomorphic": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hast-util-from-html-isomorphic/-/hast-util-from-html-isomorphic-2.0.0.tgz", + "integrity": "sha512-zJfpXq44yff2hmE0XmwEOzdWin5xwH+QIhMLOScpX91e/NSGPsAzNCvLQDIEPyO2TXi+lBmU6hjLIhV8MwP2kw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-from-dom": "^5.0.0", + "hast-util-from-html": "^2.0.0", + "unist-util-remove-position": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-from-parse5": { "version": "8.0.3", "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz", @@ -9908,6 +9965,19 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-is-element": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz", + "integrity": "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-parse-selector": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", @@ -10024,6 +10094,22 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/hast-util-to-text": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-4.0.2.tgz", + "integrity": "sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "hast-util-is-element": "^3.0.0", + "unist-util-find-after": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-whitespace": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", @@ -11244,6 +11330,31 @@ "node": ">=4.0" } }, + "node_modules/katex": { + "version": "0.16.21", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.21.tgz", + "integrity": "sha512-XvqR7FgOHtWupfMiigNzmh+MgUVmDGU2kXZm899ZkPfcuoPuFxyHmXsgATDpFZDAXCI8tvinaVcDo8PIIJSo4A==", + "funding": [ + "https://opencollective.com/katex", + "https://github.com/sponsors/katex" + ], + "license": "MIT", + "dependencies": { + "commander": "^8.3.0" + }, + "bin": { + "katex": "cli.js" + } + }, + "node_modules/katex/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -11713,6 +11824,25 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/mdast-util-math": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-math/-/mdast-util-math-3.0.0.tgz", + "integrity": "sha512-Tl9GBNeG/AhJnQM221bJR2HPvLOSnLE/T9cJI9tlc6zwQk2nPk/4f0cHkOdEixQPC/j8UtKDdITswvLAy1OZ1w==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "longest-streak": "^3.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.1.0", + "unist-util-remove-position": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/mdast-util-mdx": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz", @@ -12466,6 +12596,81 @@ } ] }, + "node_modules/micromark-extension-math": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-math/-/micromark-extension-math-3.1.0.tgz", + "integrity": "sha512-lvEqd+fHjATVs+2v/8kg9i5Q0AP2k85H0WUOwpIVvUML8BapsMvh1XAogmQjOCsLpoKRCVQqEkQBB3NhVBcsOg==", + "license": "MIT", + "dependencies": { + "@types/katex": "^0.16.0", + "devlop": "^1.0.0", + "katex": "^0.16.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-math/node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-math/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-math/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, "node_modules/micromark-extension-mdx-expression": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.0.tgz", @@ -16629,6 +16834,25 @@ "node": ">=6" } }, + "node_modules/rehype-katex": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/rehype-katex/-/rehype-katex-7.0.1.tgz", + "integrity": "sha512-OiM2wrZ/wuhKkigASodFoo8wimG3H12LWQaH8qSPVJn9apWKFSH3YOCtbKpBorTVw/eI7cuT21XBbvwEswbIOA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/katex": "^0.16.0", + "hast-util-from-html-isomorphic": "^2.0.0", + "hast-util-to-text": "^4.0.0", + "katex": "^0.16.0", + "unist-util-visit-parents": "^6.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/rehype-raw": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-7.0.0.tgz", @@ -16727,6 +16951,22 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/remark-math": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/remark-math/-/remark-math-6.0.0.tgz", + "integrity": "sha512-MMqgnP74Igy+S3WwnhQ7kqGlEerTETXMvJhrUzDikVZ2/uogJCb+WHUg97hK9/jcfc0dkD73s3LN8zU49cTEtA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-math": "^3.0.0", + "micromark-extension-math": "^3.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/remark-mdx": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.1.0.tgz", @@ -18555,6 +18795,20 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/unist-util-find-after": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-5.0.0.tgz", + "integrity": "sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/unist-util-is": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", @@ -18591,6 +18845,20 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/unist-util-remove-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz", + "integrity": "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/unist-util-stringify-position": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", diff --git a/package.json b/package.json index 51ed22bc3..3e9530bb8 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,8 @@ "raw-loader": "^4.0.2", "react": "^18.2.0", "react-dom": "^18.2.0", + "rehype-katex": "^7.0.1", + "remark-math": "^6.0.0", "sass": "^1.71.1", "sass-loader": "^14.1.1", "url-loader": "^4.1.1",