From 71e0b35b275b18b972da4715912d8fa6a9f3e256 Mon Sep 17 00:00:00 2001 From: Kevin Barabash Date: Tue, 3 Oct 2017 11:30:59 -0600 Subject: [PATCH] allow sizing commands inside optional groups (#885) * allow sizing commands inside optional groups * allow color, old font, and style commands inside optional groups --- package.json | 1 + src/Parser.js | 20 ++- test/__snapshots__/katex-spec.js.snap | 178 +++++++++++++++++++ test/katex-spec.js | 44 +++++ test/screenshotter/images/Sizing-chrome.png | Bin 7153 -> 9542 bytes test/screenshotter/images/Sizing-firefox.png | Bin 7172 -> 9720 bytes test/screenshotter/ss_data.yaml | 2 +- 7 files changed, 235 insertions(+), 10 deletions(-) create mode 100644 test/__snapshots__/katex-spec.js.snap diff --git a/package.json b/package.json index 0f8ea3c9..54078d65 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "jest": "^20.0.4", "jest-serializer-html": "^4.0.0", "js-yaml": "^3.3.1", + "json-stable-stringify": "^1.0.1", "jspngopt": "^0.2.0", "less": "~2.7.1", "less-plugin-clean-css": "^1.5.1", diff --git a/src/Parser.js b/src/Parser.js index 1daf6708..ada17808 100644 --- a/src/Parser.js +++ b/src/Parser.js @@ -203,7 +203,7 @@ export default class Parser { if (breakOnInfix && functions[lex.text] && functions[lex.text].infix) { break; } - const atom = this.parseAtom(); + const atom = this.parseAtom(breakOnTokenText); if (!atom) { if (!this.settings.throwOnError && lex.text[0] === "\\") { const errorNode = this.handleUnsupportedCmd(); @@ -349,12 +349,13 @@ export default class Parser { /** * Parses a group with optional super/subscripts. * + * @param {"]" | "}"} breakOnTokenText - character to stop parsing the group on. * @return {?ParseNode} */ - parseAtom() { + parseAtom(breakOnTokenText) { // The body of an atom is an implicit group, so that things like // \left(x\right)^2 work correctly. - const base = this.parseImplicitGroup(); + const base = this.parseImplicitGroup(breakOnTokenText); // In text mode, we don't have superscripts or subscripts if (this.mode === "text") { @@ -466,9 +467,10 @@ export default class Parser { * small text {\Large large text} small text again * It is also used for \left and \right to get the correct grouping. * + * @param {"]" | "}"} breakOnTokenText - character to stop parsing the group on. * @return {?ParseNode} */ - parseImplicitGroup() { + parseImplicitGroup(breakOnTokenText) { const start = this.parseSymbol(); if (start == null) { @@ -527,7 +529,7 @@ export default class Parser { } else if (utils.contains(Parser.sizeFuncs, func)) { // If we see a sizing function, parse out the implicit body this.consumeSpaces(); - const body = this.parseExpression(false); + const body = this.parseExpression(false, breakOnTokenText); return new ParseNode("sizing", { // Figure out what size to use based on the list of functions above size: utils.indexOf(Parser.sizeFuncs, func) + 1, @@ -536,7 +538,7 @@ export default class Parser { } else if (utils.contains(Parser.styleFuncs, func)) { // If we see a styling function, parse out the implicit body this.consumeSpaces(); - const body = this.parseExpression(true); + const body = this.parseExpression(true, breakOnTokenText); return new ParseNode("styling", { // Figure out what style to use by pulling out the style from // the function name @@ -547,7 +549,7 @@ export default class Parser { const style = Parser.oldFontFuncs[func]; // If we see an old font function, parse out the implicit body this.consumeSpaces(); - const body = this.parseExpression(true); + const body = this.parseExpression(true, breakOnTokenText); if (style.slice(0, 4) === 'text') { return new ParseNode("text", { style: style, @@ -565,7 +567,7 @@ export default class Parser { if (!color) { throw new ParseError("\\color not followed by color"); } - const body = this.parseExpression(true); + const body = this.parseExpression(true, breakOnTokenText); return new ParseNode("color", { type: "color", color: color.result.value, @@ -875,7 +877,7 @@ export default class Parser { if (this.nextToken.text === (optional ? "[" : "{")) { // If we get a brace, parse an expression this.consume(); - const expression = this.parseExpression(false, optional ? "]" : null); + const expression = this.parseExpression(false, optional ? "]" : "}"); const lastToken = this.nextToken; // Make sure we get a close brace this.expect(optional ? "]" : "}"); diff --git a/test/__snapshots__/katex-spec.js.snap b/test/__snapshots__/katex-spec.js.snap new file mode 100644 index 00000000..2989348a --- /dev/null +++ b/test/__snapshots__/katex-spec.js.snap @@ -0,0 +1,178 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`An implicit group parser within optional groups should work style commands \\sqrt[\\textstyle 3]{x} 1`] = ` +[ + { + "type": "sqrt", + "mode": "math", + "value": { + "type": "sqrt", + "body": { + "type": "ordgroup", + "mode": "math", + "value": [ + { + "type": "mathord", + "mode": "math", + "value": "x" + } + ] + }, + "index": { + "type": "ordgroup", + "mode": "math", + "value": [ + { + "type": "styling", + "mode": "math", + "value": { + "style": "text", + "value": [ + { + "type": "textord", + "mode": "math", + "value": "3" + } + ] + } + } + ] + } + } + } +] +`; + +exports[`An implicit group parser within optional groups should work with \\color: \\sqrt[\\color{red} 3]{x} 1`] = ` +[ + { + "type": "sqrt", + "mode": "math", + "value": { + "type": "sqrt", + "body": { + "type": "ordgroup", + "mode": "math", + "value": [ + { + "type": "mathord", + "mode": "math", + "value": "x" + } + ] + }, + "index": { + "type": "ordgroup", + "mode": "math", + "value": [ + { + "type": "color", + "mode": "math", + "value": { + "type": "color", + "color": "red", + "value": [ + { + "type": "textord", + "mode": "math", + "value": "3" + } + ] + } + } + ] + } + } + } +] +`; + +exports[`An implicit group parser within optional groups should work with sizing commands: \\sqrt[\\small 3]{x} 1`] = ` +[ + { + "type": "sqrt", + "mode": "math", + "value": { + "type": "sqrt", + "body": { + "type": "ordgroup", + "mode": "math", + "value": [ + { + "type": "mathord", + "mode": "math", + "value": "x" + } + ] + }, + "index": { + "type": "ordgroup", + "mode": "math", + "value": [ + { + "type": "sizing", + "mode": "math", + "value": { + "size": 5, + "value": [ + { + "type": "textord", + "mode": "math", + "value": "3" + } + ] + } + } + ] + } + } + } +] +`; + +exports[`An implicit group parser within optional groups should work wwith old font functions: \\sqrt[\\tt 3]{x} 1`] = ` +[ + { + "type": "sqrt", + "mode": "math", + "value": { + "type": "sqrt", + "body": { + "type": "ordgroup", + "mode": "math", + "value": [ + { + "type": "mathord", + "mode": "math", + "value": "x" + } + ] + }, + "index": { + "type": "ordgroup", + "mode": "math", + "value": [ + { + "type": "font", + "mode": "math", + "value": { + "body": { + "type": "ordgroup", + "mode": "math", + "value": [ + { + "type": "textord", + "mode": "math", + "value": "3" + } + ] + }, + "font": "mathtt" + } + } + ] + } + } + } +] +`; diff --git a/test/katex-spec.js b/test/katex-spec.js index 6c42f5f0..7e301a07 100644 --- a/test/katex-spec.js +++ b/test/katex-spec.js @@ -3,6 +3,7 @@ /* global expect: false */ /* global it: false */ /* global describe: false */ +import stringify from 'json-stable-stringify'; import buildMathML from "../src/buildMathML"; import buildTree from "../src/buildTree"; @@ -13,6 +14,27 @@ import Options from "../src/Options"; import Settings from "../src/Settings"; import Style from "../src/Style"; +const typeFirstCompare = (a, b) => { + if (a.key === 'type') { + return -1; + } else if (b.key === 'type') { + return 1; + } else { + return a.key < b.key ? -1 : 1; + } +}; + +const serializer = { + print(val) { + return stringify(val, {cmp: typeFirstCompare, space: ' '}); + }, + test() { + return true; + }, +}; + +expect.addSnapshotSerializer(serializer); + const defaultSettings = new Settings({}); const defaultOptions = new Options({ style: Style.TEXT, @@ -520,6 +542,28 @@ describe("An implicit group parser", function() { expect(sizing.type).toEqual("sizing"); expect(sizing.value.value.length).toBe(1); }); + + describe("within optional groups", () => { + it("should work with sizing commands: \\sqrt[\\small 3]{x}", () => { + const tree = stripPositions(getParsed("\\sqrt[\\small 3]{x}")); + expect(tree).toMatchSnapshot(); + }); + + it("should work with \\color: \\sqrt[\\color{red} 3]{x}", () => { + const tree = stripPositions(getParsed("\\sqrt[\\color{red} 3]{x}")); + expect(tree).toMatchSnapshot(); + }); + + it("should work style commands \\sqrt[\\textstyle 3]{x}", () => { + const tree = stripPositions(getParsed("\\sqrt[\\textstyle 3]{x}")); + expect(tree).toMatchSnapshot(); + }); + + it("should work wwith old font functions: \\sqrt[\\tt 3]{x}", () => { + const tree = stripPositions(getParsed("\\sqrt[\\tt 3]{x}")); + expect(tree).toMatchSnapshot(); + }); + }); }); describe("A function parser", function() { diff --git a/test/screenshotter/images/Sizing-chrome.png b/test/screenshotter/images/Sizing-chrome.png index ec2c28ae936b24fa198adae022379b1299de580a..15ecce73867456b0f980bbff8d8ed147f779d99d 100644 GIT binary patch literal 9542 zcmeAS@N?(olHy`uVBq!ia0y~yU}0cjU}oT8U|?XFf6?nA1A{8Br;B4q#hkZyD;usn zIe7e|4)^KW?xqDYTv7Tf!d6!}ZVkPn6moG@K6lrmu(cIizOBt&d+S=&_HCl~ZY4Q> ztO#5gZmXGP``R%(-bHuUA_v=mBhAT)<@Y?*j4hverkNRAZ+`Rs_s`>ZJ=JC(JX>x& z`AO$gCWX_hzHu?EkYi%tP-bW_7^Uz9!G<)}gqOO{dv32R&)uF|CS8A$dG+Gwx4#_e z@0Yo_-8uHXEdSqwcjr&t)x{9yb&>JLj|(UN>g?auS-!^n+|OTM?Ed|YVAxacmVWqIzVx@}7uFc>o|X36 zW;1J;ti#GK4u{7*ae}k=zg^;Avw5ARQP#H2v!dRpGI*>iV7T|E=*+YEW+k3^*UHPf z=e_+htwxkVNK>NWch&Ly|I@C1k1W4tzP)qy+gDuzY9UyqMU_^X|sr+#{sr1fWc`E~Vw+hpflzx?xE)_UQ9MK>7cOuSw8{a1L! zt>xA~xC?S$`R}yv$*w6jy;rrs{Bp~t^|h>b<7VG$Ke=q}!{~F|tM=|(wVGv$jvmAH zCuVoK&7S(#p8WsP;XG^Xo%Q?nT{J(h+<2I2?zO4aZ?)4S!%xq;H{*BN<8$Yyw299)NN+?z9PGqPxdriF5=(w{@s6_b&tFl zRl9i{4$pfR7F`^EL`MGE{4e=;AI`Q@&41N@diOigFB^Vy$(^@-6es=hu+}<}fK4YD zVkX?p((kXy`&Vh-{&U&6^XCs&K8^X@HS6iVCgbA%o)b0(8@sewr|4)g_@~~#GGFHJ zorw>5_uSRKcjQ>&PsSZP)~t^6G`<^Nkn(P#>|uU}*$X=uOx`^DcdY+j#=L{u@++9_ zubF?`_vh{XU%8Rtdne5+ia*G@)156Oy&=9{N-X!u{)-EXjhJH)+KGSa>lXd~E%0Bk{D;N;b^khhAKqm?o%P@E$|N)U{O#p& zmrndK6x__??ijtF>mT=`QiH$t@o`u999~VjknjIN#2X$@PIAudu75a;e~JaA8z`zwq&a5-;-KgV>JQZw~BmW>|S;(gm@7^%=jW9Jtc={it5fykFzLNbLLGJ5lcnv)@=ee<|BAacY#Nf~7M`O23ynk1~Hvh8gIZn3bL*^JRl`kPOWAWdpOQthorSJXI z&5pWqX8ZHBmCss#_|_McIUn0EZ&+(;&2YmFUIFAURUprn{0pd{j&>Z)scrp zcW4$L3)ufzzB>Eq*|(d$yRDAaS--D!Iy66APTz93=im8;{(C!Q8FJKw=Kn7A(qK3* zTGw^5>5QlQ^4d2wj5ym#ULgSy$j6E;4xef(y>hNVU7IctXZz3-}Aw_axqoo>SLpYtt) z%)AWE-g7gQOgC@7?|)MFyv?J3|8~BVP3{v3IdbPrRnM9Kdx}2aV5}&bkvccv?No=W zs=No*E@X(AnxVPBXx{7EdCz;5bM_Q{n0zOl<(l2eu-!FbJDnH(v&;9YVqcJ+ZU46N zXvpuy;!F)o7%g-~8pOHnRquN}Km6t5J<0al&!?sDDLP>;@N*~U_1!ghil?_d^OZ=7 z6c4Q{o%Oi&<;>eV1Q=9!9UdG@n08hB-DZQkn;TRk%`Ek=0q*IWIsa^wf4=V2%!85I8<`7MrJnWqU}Da&b@BS$ zlNl706B*i~8EYriuzZmIJ@f6oPjVH1rvJY2=D?c8I@v|t>(5_FVf-M#uwxQyLYW4G zVe@0RU)w*Q*?Et7c8&Co%pU^xHI789N4-8$)Gq%wSuW-NdY!N5GxHh7~s7h;&= zxrxDtkM+TP&S@XLe|OHc`zlv)A^M)f<<6tmD=+t(`s6v@lx~hJ-gErguETQd$Nx$M zcgiySo#Gu3bmO*8g`!-?0`?Ft}&MiK@y7II^eX{<0_J7(Z z`E?E+JmiIu2zr69knS*=!wI`1b#JGp0u`7J_Woj_;6lu5+TYu^k`%mBe z%DMK2XA3ew8X`0IKZ$*w>R*22NgTJS?T1s^W@0}!vM{7hQek*#&7@+*t#GD%@y2AI z%hJ25jE~%zxO%BhDVy@`e|y-ct-ZY^=bT2msa1^RoaIU8%rjjW0@OU23TibNI`vpM zKKB}=$b9^UswBx7SLu|Ni(^ z(Iuv;;{Jp)PyBZF3xs{$yvBY?;?p~!bFSR`zR3M7@BWXSHyJAmLcV2|KDXTNQIRM9 z{dZisdc@?#91N#a92sW)V%z>dC7H2h&U@YSHR2Bq@9|uhNdK|W{P5Lx&c~y#y}P(w zB4b~Fo>l65#@JimCI9uF7JKg7bB{4%`pwD}r+W^4JX(Hv?W-yO7IlAKw(Q%zXY1J+ z9d@d49Ozys+pvCmvTe6q)^AwTH`O{>p@{v#ud|u?a$yTnZ#XyVnfONR-=A8#SM_sg^XIUH zTMVaXCCz{HXHRj;;ff2!Vh}fmJ2Pq+IDCIS)A-LmDeKAQ*Uxr%|E(9ih`vchr`OeTtBHy4cDv3LUA?uu!|u(@pU-}z{WoB0C^BS!aF_c|bwR29Yx{?p{H_14 z$jSU?p7kp|?X1w5Z5!9jufD&FaYjo0T-#Z<{xJ4&GMqXp(y;9QmoIO<+TYig=V>sAOHX?+ zdG8dnZ`0p$dwx}thy6fH_@75dek+&eX&cb zjn_ZCc!tS%R=vc67{-i$``B+uIWw5~a^^gUZvDns#>JZ8_=o=l-)Cd}yk*UMjy}Dg zarl|_vGiXY54OJl^P~9yb9i*v-M=5Tui1QEtds5Y~@9LFTis zZ!Y~=yy7X>fkIVXmR!d=hFSY0Zyjphz2f2Rrt5XHwzKU2`p%R2nB%`qe~$mSXL!!= z*6f2dVh$HfUz*>0_?grG=g$qd;@baQ{eI$e`OfR#_uFnfF8*J?tdVFces+X-70?n&Ab10#sA?q(+X$U7kSC)g4h%G2jL5KZA#Yq|FC%w`0@1o z$LG>)_S?TU%rCT-NdHjJl3>HF@FIQMRl7aMH>wl|H%h%fbKtXXw)FGb!@s{VHVYQA z^VH4yd2#aMW%ngYIUYn$E8X}1x9*&$JItT{Iez4AnO(N)nf~6ObqpaD394J1Dj6eW zeoe4{EBgP-VJG3`NA>n;R-ej#Bi(v>&(WFwck7SLR($2eFrWKU{r|(|e80{sWUp_( z_a~?-TxIvsy@~aH5%2&0*zc~F|8>S2{`LJcl0B}l3U2qa_!fG9`@8nJ`V!AgD|X+@ zn3EctGjG$X4@SA%-7Ab#p0Fka-TNkQVfub^-@?v^(vMm0K0IftRJJa8&(X7{=N?#d zC)6wqzf$2wN3)-d%ap^;}baf7An|e2qn$&lZc+8c&cs z7u01}eyhC9WuldBOvTETF$`*=JLNKVA7YG%n*BezbasB#y|+t~>K~h>t^e4)zyGM* zy+^Nljo&;!8}Q=NVcwTbrL`u1UdV>Y{|z_Bwzge94nU$GeeX#h@`NEsZ zf1{O+?e|QtG?ou~bJn4+bXw4t+AD2l)(qFKEE4l!c)-Q}AnCCF)c;LeA0HB)zBDQ3 z<+&}n&Ua$=aWnpsSiXMk=eoE?Z+?4Qi@g*6Jg&F4d>D~Fe@aE{vx&Xm=62pq+&6!V zy!qX3johxiKlN9Y*Z*=|7TL95`bO9}r>=c9ziyR<8RrJx+0AXvaBR1}gO>#ZyHwrk zn%kFe&?lZ{;AigRy`LhZz%k=_}+Q#0{%tcFTel9zIW3150AsjtEVVd zXY7CTBlTQv$ENu{f0X`yl|IIL&fkCL9;@%~FP%0yKOw1{;f}TR6q|XTJMCC(R$UQ2 zn5Hk%(Dotv&z7kBo_n^psh4#}mOW;C=cDX<_|NYO_4l*vr+=HvDqt`3Ao}HY8S8y> z|Nq!>rqbiSmwtlvcg5e^SW2_+=G$fEmv&ol8SH#s^V|NNTC&xR@IQP9@{M`5e=@Ze zu^y=4FZ1AJO{o0$Ex-4xFMm8o3U5c`w(4cwp`TM4r+(nGnQ@%y#_`{k*N^I^e{?wg zYtzf-4}0f)o^b6J`@Q-nb}8~_Z<`aal+RujBFL*n^{KLH zd!D^8Ue2}sCU?Pod6REnjvn|o<>MTt*A`N9-S?gd{IeNT%vY~p#= zaW+bWq5ky!f8}5IzP2;U&uTxRs((_>_O{)>n1d$on_Kf|tNqqvc_F^}_a1}2Gfoyx zSL@rp=kv6fA8y%fB7PkM70QC)MvOocX)A zc3<*4<%TO>tDiM@q(4n5XB1=(a3I`{o&3-0W(ey#I5{b2jG`Spwb?^zW6hE=C< z|Hk`${pWmV<-d)q(5;r*KFjdveIAu!q0|RH%VzukI9KgzcYApZqeexL=&d~g3{tg= z-`{4lf9snqm44%&a$V=Nr*1zi)^<#_u-(3;?x%42kNR7ye_l4u%b#Cg^VjP1uSxHt ze~Yv|yqW(-`IG$#U#rXC3mukp-zi=3-993N{lU!Sa*3~Vzt7dbp3YYm^K|yD3)eTr znb{lq?PLm=c2Qyw4fE@ZS6e?%zQ5#sy8OS3)Am(n`M7VL|7!l+8jnAk4wC#8 z-K+Wicb~7%dUP$&d&k~u*2m4W4}Umd*Z5iRj^sP@{2Sh<=jz|tvNiO`4aU`XV;fHX zV?Tc6J;R*`H3GZVZ@&IM?!p6k$G7vCn3uX}gfsMMWGZHGA7cEmbo>kHgj?ZmQYOslOq(Df$u?K)*=>7SdcpR3j0teC#P=HAnW z-E7;BL>?5Lti*Pqc86Yl&ZD+3-{d7eKFX_RyqS3TO>pQ;@?^R+uU~F`Wn|NbGzTJ&kd5EE3(H|dt5$ubKXr&>0d|Y#XTr2XWZl6^hV`K?3@XAH&>cJomVaM zW5(yriPOIRT~t@V!RWB_32QxVBYjtZATfNNB zClXJ&4(tF2NxjPgdp7f3Www9P|6jfL=G@m3eeEUg&mVl3U6*l=G5`M3_rK%5$NcS@ z{(Rn)@4{<>ea_!`QIls`aGtSpbG>Q-XVYi#8+*l{t5wgLboUPD>$b>xUs3fEyMlwi z8`Jw%=4>~bD$RH0meud|mrByA#8savp&+oiJN!QTV>bNEbDN+A-e|dLix|vN*{h?cx&whnu{S1v>R=!*)?|&!r zh09%&%3GOTB=UKZ?uo5^+*BWA9vhZENB8gS+MqWEih^;s%<~=hrkUw}+Gjj>?ez_d zQ+-d=ZTbHG?Vg$bCw?;&_3r)J7x&}m?(1cnm))CQ*SS@E-^PFO%deC~Mf|a1JIAiK zgLy)h&5?OKk0<=jc<^p@(8|bjhSU5G&*3*`bK`Lgl3;Y$IpaOgmrF1H+@C1>iT!_7 zaaQ}EpKIjO#dZj1EUDfv=y8f~f81m1zXvwy8Q46X^<{U~`yGE)y?J_S_sn@|&N%wY~c7h0MVE==uNO$?d)U-TuT+l?Rh=3b&W%n?F*QcRiC`wsyDP*K@l5 zd^&$x*!SBms?NRdc{6yG`I&hea$~0}KCTac@?)=?C-a9hi++`d*Y7Gje9YI^*LUTz zWygGZU)#lhKKLno{=W?^TMs_d`StF={CmIuevE%{ed)4ox6OXfkt|;JCcFO6yBQCo z%T~QLEO;+m_p{<&W}|A=>D&Kyix-C#dVfC0-nU0O;M=^K4q*pcl+OVJ%dddODott z*~7C%`}DG=urAmTCeWZ-TyOjOz2M^7`OjD%v_G@dT4%T2%{(kyRPJWdb(QTRET2Mb z8NR2STPvAml{dZWy0qSw$Dh2`M@~6;^&TU`sb!}aBdVRsnDf6cNG!_Z5jt(P`q67K z)n{Ui2hx`9V!UB-?e?MabMya9ESGh7K6PsRZVmQL%njQX?PC1V_%wLF`Au_~7yjD& zizXWFW)KgpHf^{RYRd4Qb)CYw-Amtl-z#XaHvN5T(X^EL{4r0?Iy8i>UB$TL)c(KG z-`kg&RXTTXt-kf+Pu9+fvJ6`ULwOG*HZruZ3w-GH|Mhs)nz$_o-!Lr5U6IAW_Ivw( zzlEncvR*TQ5<_SJ@Ifma!Ry!(}1 z%E_nn;iGtQ@Go`QI0gsCP~L|88|QC5xLaxe-A(0X@SO>F8D_0t#rWahseDlz{tt(l zi-Wgi+2CAlqTF9=%h^6; zTy{9XaB9h}qsnH-9O$DPFVYDn5Ee=O(grQd(e*3Q#sptAa SXqgvift07KpUXO@geCyXFULs$ literal 7153 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 Zzv7j80V?@lIl@45d7iF*F6*2UngG(_Hr@aL diff --git a/test/screenshotter/images/Sizing-firefox.png b/test/screenshotter/images/Sizing-firefox.png index 8d5f97e45a1bccaacf6d9e0c5eadf82542c28129..0ecc6cef9e62f7e01b9969cd36bd91ee1526d147 100644 GIT binary patch literal 9720 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 literal 7172 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