mirror of
https://github.com/Smaug123/KaTeX
synced 2025-10-05 19:28:39 +00:00
feat: text-mode cedilla accent via \c (#3036)
* feat: text-mode cedilla accent via \c Add text-mode accent function `\c` and corresponding Unicode support. Part of #638 Co-authored-by: Kevin Barabash <kevinb@khanacademy.org> * Update screenshots Co-authored-by: Kevin Barabash <kevinb@khanacademy.org>
This commit is contained in:
@@ -951,7 +951,8 @@ export default class Parser {
|
|||||||
if (!unicodeAccents[accent]) {
|
if (!unicodeAccents[accent]) {
|
||||||
throw new ParseError(`Unknown accent ' ${accent}'`, nucleus);
|
throw new ParseError(`Unknown accent ' ${accent}'`, nucleus);
|
||||||
}
|
}
|
||||||
const command = unicodeAccents[accent][this.mode];
|
const command = unicodeAccents[accent][this.mode] ||
|
||||||
|
unicodeAccents[accent].text;
|
||||||
if (!command) {
|
if (!command) {
|
||||||
throw new ParseError(
|
throw new ParseError(
|
||||||
`Accent ${accent} unsupported in ${this.mode} mode`,
|
`Accent ${accent} unsupported in ${this.mode} mode`,
|
||||||
|
@@ -108,11 +108,9 @@ import metricMap from "./fontMetricsData";
|
|||||||
const extraCharacterMap = {
|
const extraCharacterMap = {
|
||||||
// Latin-1
|
// Latin-1
|
||||||
'Å': 'A',
|
'Å': 'A',
|
||||||
'Ç': 'C',
|
|
||||||
'Ð': 'D',
|
'Ð': 'D',
|
||||||
'Þ': 'o',
|
'Þ': 'o',
|
||||||
'å': 'a',
|
'å': 'a',
|
||||||
'ç': 'c',
|
|
||||||
'ð': 'd',
|
'ð': 'd',
|
||||||
'þ': 'o',
|
'þ': 'o',
|
||||||
|
|
||||||
|
@@ -74,10 +74,14 @@ export const htmlBuilder: HtmlBuilderSupSub<"accent"> = (grp, options) => {
|
|||||||
// TODO(emily): Find a better way to get the skew
|
// TODO(emily): Find a better way to get the skew
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const accentBelow = group.label === "\\c";
|
||||||
|
|
||||||
// calculate the amount of space between the body and the accent
|
// calculate the amount of space between the body and the accent
|
||||||
let clearance = Math.min(
|
let clearance = accentBelow
|
||||||
body.height,
|
? body.height + body.depth
|
||||||
options.fontMetrics().xHeight);
|
: Math.min(
|
||||||
|
body.height,
|
||||||
|
options.fontMetrics().xHeight);
|
||||||
|
|
||||||
// Build the accent
|
// Build the accent
|
||||||
let accentBody;
|
let accentBody;
|
||||||
@@ -100,6 +104,9 @@ export const htmlBuilder: HtmlBuilderSupSub<"accent"> = (grp, options) => {
|
|||||||
// shift the accent over to a place we don't want.
|
// shift the accent over to a place we don't want.
|
||||||
accent.italic = 0;
|
accent.italic = 0;
|
||||||
width = accent.width;
|
width = accent.width;
|
||||||
|
if (accentBelow) {
|
||||||
|
clearance += accent.depth;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
accentBody = buildCommon.makeSpan(["accent-body"], [accent]);
|
accentBody = buildCommon.makeSpan(["accent-body"], [accent]);
|
||||||
@@ -244,7 +251,7 @@ defineFunction({
|
|||||||
type: "accent",
|
type: "accent",
|
||||||
names: [
|
names: [
|
||||||
"\\'", "\\`", "\\^", "\\~", "\\=", "\\u", "\\.", '\\"',
|
"\\'", "\\`", "\\^", "\\~", "\\=", "\\u", "\\.", '\\"',
|
||||||
"\\r", "\\H", "\\v", "\\textcircled",
|
"\\c", "\\r", "\\H", "\\v", "\\textcircled",
|
||||||
],
|
],
|
||||||
props: {
|
props: {
|
||||||
numArgs: 1,
|
numArgs: 1,
|
||||||
|
@@ -706,6 +706,7 @@ defineSymbol(text, main, accent, "\u02dc", "\\~"); // tilde
|
|||||||
defineSymbol(text, main, accent, "\u02c9", "\\="); // macron
|
defineSymbol(text, main, accent, "\u02c9", "\\="); // macron
|
||||||
defineSymbol(text, main, accent, "\u02d8", "\\u"); // breve
|
defineSymbol(text, main, accent, "\u02d8", "\\u"); // breve
|
||||||
defineSymbol(text, main, accent, "\u02d9", "\\."); // dot above
|
defineSymbol(text, main, accent, "\u02d9", "\\."); // dot above
|
||||||
|
defineSymbol(text, main, accent, "\u00b8", "\\c"); // cedilla
|
||||||
defineSymbol(text, main, accent, "\u02da", "\\r"); // ring above
|
defineSymbol(text, main, accent, "\u02da", "\\r"); // ring above
|
||||||
defineSymbol(text, main, accent, "\u02c7", "\\v"); // caron
|
defineSymbol(text, main, accent, "\u02c7", "\\v"); // caron
|
||||||
defineSymbol(text, main, accent, "\u00a8", '\\"'); // diaresis
|
defineSymbol(text, main, accent, "\u00a8", '\\"'); // diaresis
|
||||||
@@ -875,7 +876,7 @@ for (let i = 0; i < 10; i++) {
|
|||||||
// but they are not actually in the font, nor are they supported by the
|
// but they are not actually in the font, nor are they supported by the
|
||||||
// Unicode accent mechanism, so they fall back to Times font and look ugly.
|
// Unicode accent mechanism, so they fall back to Times font and look ugly.
|
||||||
// TODO(edemaine): Fix this.
|
// TODO(edemaine): Fix this.
|
||||||
export const extraLatin = "\u00c7\u00d0\u00de\u00e7\u00fe";
|
export const extraLatin = "\u00d0\u00de\u00fe";
|
||||||
for (let i = 0; i < extraLatin.length; i++) {
|
for (let i = 0; i < extraLatin.length; i++) {
|
||||||
const ch = extraLatin.charAt(i);
|
const ch = extraLatin.charAt(i);
|
||||||
defineSymbol(math, main, mathord, ch, ch);
|
defineSymbol(math, main, mathord, ch, ch);
|
||||||
|
@@ -14,4 +14,5 @@ module.exports = {
|
|||||||
'\u0307': {text: '\\.', math: '\\dot'},
|
'\u0307': {text: '\\.', math: '\\dot'},
|
||||||
'\u030a': {text: '\\r', math: '\\mathring'},
|
'\u030a': {text: '\\r', math: '\\mathring'},
|
||||||
'\u030b': {text: '\\H'},
|
'\u030b': {text: '\\H'},
|
||||||
|
'\u0327': {text: '\\c'},
|
||||||
};
|
};
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
Binary file not shown.
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
Binary file not shown.
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
@@ -9,6 +9,12 @@ describe("unicode", function() {
|
|||||||
.toBuild();
|
.toBuild();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should build Latin-1 inside \\text{} like accent commands", function() {
|
||||||
|
expect`\text{ÀÁÂÃÄÅÈÉÊËÌÍÎÏÑÒÓÔÕÖÙÚÛÜÝàáâãäåèéêëìíîïñòóôõöùúûüýÿÇç}`
|
||||||
|
.toParseLike`\text{\`A\'A\^A\~A\"A\r A\`E\'E\^E\"E\`I\'I\^I\"I\~N\`O\'O\^O\~O\"O\`U\'U\^U\"U\'Y\`a\'a\^a\~a\"a\r a\`e\'e\^e\"e\`ı\'ı\^ı\"ı\~n\`o\'o\^o\~o\"o\`u\'u\^u\"u\'y\"y\c C\c c}`;
|
||||||
|
// TODO(edemaine): A few characters don't have analogs yet.
|
||||||
|
});
|
||||||
|
|
||||||
it("should not parse Latin-1 outside \\text{} with strict", function() {
|
it("should not parse Latin-1 outside \\text{} with strict", function() {
|
||||||
const chars = 'ÀÁÂÃÄÅÈÉÊËÌÍÎÏÑÒÓÔÕÖÙÚÛÜÝàáâãäåèéêëìíîïñòóôõöùúûüýÿÇÐÞçþ';
|
const chars = 'ÀÁÂÃÄÅÈÉÊËÌÍÎÏÑÒÓÔÕÖÙÚÛÜÝàáâãäåèéêëìíîïñòóôõöùúûüýÿÇÐÞçþ';
|
||||||
for (const ch of chars) {
|
for (const ch of chars) {
|
||||||
|
Reference in New Issue
Block a user