kramdown-rfc2629-1.7.31/0000755000004100000410000000000015142163665014561 5ustar www-datawww-datakramdown-rfc2629-1.7.31/data/0000755000004100000410000000000015142163665015472 5ustar www-datawww-datakramdown-rfc2629-1.7.31/data/encoding-fallbacks.txt0000644000004100000410000000234415142163665021744 0ustar www-datawww-data00a0 00a1 ! 00a2 [cents] 00a3 GBP 00a4 [currency units] 00a5 JPY 00a6 | 00a7 S. 00a9 (C) 00aa a 00ab << 00ac [not] 00ae (R) 00af _ 00b0 o 00b1 +/- 00b2 ^2 00b3 ^3 00b4 ' 00b5 [micro] 00b6 P. 00b7 . 00b8 , 00b9 ^1 00ba o 00bb >> 00bc 1/4 00bd 1/2 00be 3/4 00bf ? 00c0 A 00c1 A 00c2 A 00c3 A 00c4 Ae 00c5 Ae 00c6 AE 00c7 C 00c8 E 00c9 E 00ca E 00cb E 00cc I 00cd I 00ce I 00cf I 00d0 [ETH] 00d1 N 00d2 O 00d3 O 00d4 O 00d5 O 00d6 Oe 00d7 x 00d8 Oe 00d9 U 00da U 00db U 00dc Ue 00dd Y 00de [THORN] 00df ss 00e0 a 00e1 a 00e2 a 00e3 a 00e4 ae 00e5 ae 00e6 ae 00e7 c 00e8 e 00e9 e 00ea e 00eb e 00ec i 00ed i 00ee i 00ef i 00f0 [eth] 00f1 n 00f2 o 00f3 o 00f4 o 00f5 o 00f6 oe 00f7 / 00f8 oe 00f9 u 00fa u 00fb u 00fc ue 00fd y 00fe [thorn] 00ff y 0152 OE 0153 oe 0161 s 0178 Y 0192 f 02dc ~ 2002 2003 2009 2013 -- 2014 --- 2018 ' 2019 ' 201a ' 201c " 201d " 201e " 2020 *!* 2021 *!!* 2022 o 2026 ... 2030 [/1000] 2032 ' 2039 < 203a > 2044 / 20ac EUR 2122 [TM] 2190 <-- 2192 --> 2194 <-> 21d0 <== 21d2 ==> 21d4 <=> 2212 - 2217 * 2264 <= 2265 >= 2329 < 232a > 0021 ! 0023 # 0024 $ 0025 % 0028 ( 0029 ) 002a * 002b + 002c , 002d - 002e . 002f / 003a : 003b ; 003d = 003f ? 0040 @ 005b [ 005d ] 005e ^ 005f _ 0060 ` 007b { 007c | 007d } 017d Z 017e z 2010 - kramdown-rfc2629-1.7.31/data/math.json0000644000004100000410000003534215142163665017325 0ustar www-datawww-data{"replacements":[["\\textfractionsolidus","⁄"],["\\leftrightsquigarrow","↭"],["\\textpertenthousand","‱"],["\\blacktriangleright","▸"],["\\blacktriangledown","▾"],["\\blacktriangleleft","◂"],["\\twoheadrightarrow","↠"],["\\leftrightharpoons","⇋"],["\\rightleftharpoons","⇌"],["\\textreferencemark","※"],["\\circlearrowright","↻"],["\\rightrightarrows","⇉"],["\\vartriangleright","⊳"],["\\textordmasculine","º"],["\\textvisiblespace","␣"],["\\twoheadleftarrow","↞"],["\\downharpoonright","⇂"],["\\ntrianglerighteq","⋭"],["\\rightharpoondown","⇁"],["\\textperthousand","‰"],["\\leftrightarrows","⇆"],["\\textmusicalnote","♪"],["\\nleftrightarrow","↮"],["\\rightleftarrows","⇄"],["\\bigtriangledown","▽"],["\\textordfeminine","ª"],["\\ntrianglelefteq","⋬"],["\\rightthreetimes","⋌"],["\\trianglerighteq","⊵"],["\\vartriangleleft","⊲"],["\\rightsquigarrow","⇝"],["\\downharpoonleft","⇃"],["\\curvearrowright","↷"],["\\circlearrowleft","↺"],["\\leftharpoondown","↽"],["\\nLeftrightarrow","⇎"],["\\curvearrowleft","↶"],["\\guilsinglright","›"],["\\leftthreetimes","⋋"],["\\leftrightarrow","↔"],["\\rightharpoonup","⇀"],["\\guillemotright","»"],["\\downdownarrows","⇊"],["\\hookrightarrow","↪"],["\\hspace{0.25em}"," "],["\\dashrightarrow","⇢"],["\\leftleftarrows","⇇"],["\\trianglelefteq","⊴"],["\\ntriangleright","⋫"],["\\doublebarwedge","⌆"],["\\upharpoonright","↾"],["\\rightarrowtail","↣"],["\\looparrowright","↬"],["\\Leftrightarrow","⇔"],["\\sphericalangle","∢"],["\\divideontimes","⋇"],["\\measuredangle","∡"],["\\blacktriangle","▴"],["\\ntriangleleft","⋪"],["\\mathchar\"1356","⁁"],["\\texttrademark","™"],["\\mathchar\"2208","⌖"],["\\triangleright","▹"],["\\leftarrowtail","↢"],["\\guilsinglleft","‹"],["\\upharpoonleft","↿"],["\\mathbb{gamma}","ℽ"],["\\fallingdotseq","≒"],["\\looparrowleft","↫"],["\\textbrokenbar","¦"],["\\hookleftarrow","↩"],["\\smallsetminus","﹨"],["\\dashleftarrow","⇠"],["\\guillemotleft","«"],["\\leftharpoonup","↼"],["\\mathbb{Gamma}","ℾ"],["\\bigtriangleup","△"],["\\textcircledP","℗"],["\\risingdotseq","≓"],["\\triangleleft","◃"],["\\mathsterling","£"],["\\textcurrency","¤"],["\\triangledown","▿"],["\\blacklozenge",""],["\\sfrac{5}{6}","⅚"],["\\preccurlyeq","≼"],["\\Rrightarrow","⇛"],["\\circledcirc","⊚"],["\\nRightarrow","⇏"],["\\sfrac{3}{8}","⅜"],["\\sfrac{1}{3}","⅓"],["\\sfrac{2}{5}","⅖"],["\\vartriangle","▵"],["\\Updownarrow","⇕"],["\\nrightarrow","↛"],["\\sfrac{1}{2}","½"],["\\sfrac{3}{5}","⅗"],["\\succcurlyeq","≽"],["\\sfrac{4}{5}","⅘"],["\\diamondsuit","♦"],["\\hphantom{0}"," "],["\\sfrac{1}{6}","⅙"],["\\curlyeqsucc","⋟"],["\\blacksquare","▪"],["\\hphantom{,}"," "],["\\curlyeqprec","⋞"],["\\sfrac{1}{8}","⅛"],["\\sfrac{7}{8}","⅞"],["\\sfrac{1}{5}","⅕"],["\\sfrac{2}{3}","⅔"],["\\updownarrow","↕"],["\\backepsilon","∍"],["\\circleddash","⊝"],["\\eqslantless","⋜"],["\\sfrac{3}{4}","¾"],["\\sfrac{5}{8}","⅝"],["\\hspace{1pt}"," "],["\\sfrac{1}{4}","¼"],["\\mathbb{Pi}","ℿ"],["\\mathcal{M}","ℳ"],["\\mathcal{o}","ȓ4"],["\\mathcal{O}","ᵊA"],["\\nsupseteqq","⊉"],["\\mathcal{B}","ℬ"],["\\textrecipe","℞"],["\\nsubseteqq","⊈"],["\\subsetneqq","⊊"],["\\mathcal{I}","ℑ"],["\\upuparrows","⇈"],["\\mathcal{e}","ℯ"],["\\mathcal{L}","ℒ"],["\\nleftarrow","↚"],["\\mathcal{H}","ℋ"],["\\mathcal{E}","ℰ"],["\\eqslantgtr","⋝"],["\\curlywedge","⋏"],["\\varepsilon","ε"],["\\supsetneqq","⊋"],["\\rightarrow","→"],["\\mathcal{R}","ℛ"],["\\sqsubseteq","⊑"],["\\mathcal{g}","ℊ"],["\\sqsupseteq","⊒"],["\\complement","∁"],["\\Rightarrow","⇒"],["\\gtreqqless","⋛"],["\\lesseqqgtr","⋚"],["\\circledast","⊛"],["\\nLeftarrow","⇍"],["\\Lleftarrow","⇚"],["\\varnothing","∅"],["\\mathcal{N}","𝒩"],["\\Leftarrow","⇐"],["\\gvertneqq","≩"],["\\mathbb{C}","ℂ"],["\\supsetneq","⊋"],["\\leftarrow","←"],["\\nleqslant","≰"],["\\mathbb{Q}","ℚ"],["\\mathbb{Z}","ℤ"],["\\llbracket","〚"],["\\mathbb{H}","ℍ"],["\\spadesuit","♠"],["\\mathit{o}","ℴ"],["\\mathbb{P}","ℙ"],["\\rrbracket","〛"],["\\supseteqq","⊇"],["\\copyright","©"],["\\textsc{k}","ĸ"],["\\gtreqless","⋛"],["\\mathbb{j}","ⅉ"],["\\pitchfork","⋔"],["\\estimated","℮"],["\\ngeqslant","≱"],["\\mathbb{e}","ⅇ"],["\\therefore","∴"],["\\triangleq","≜"],["\\varpropto","∝"],["\\subsetneq","⊊"],["\\heartsuit","♥"],["\\mathbb{d}","ⅆ"],["\\lvertneqq","≨"],["\\checkmark","✓"],["\\nparallel","∦"],["\\mathbb{R}","ℝ"],["\\lesseqgtr","⋚"],["\\downarrow","↓"],["\\mathbb{D}","ⅅ"],["\\mathbb{i}","ⅈ"],["\\backsimeq","⋍"],["\\mathbb{N}","ℕ"],["\\Downarrow","⇓"],["\\subseteqq","⊆"],["\\setminus","∖"],["\\succnsim","⋩"],["\\doteqdot","≑"],["\\clubsuit","♣"],["\\emptyset","∅"],["\\sqsupset","⊐"],["\\fbox{~~}","▭"],["\\curlyvee","⋎"],["\\varkappa","ϰ"],["\\llcorner","⌞"],["\\varsigma","ς"],["\\approxeq","≊"],["\\backcong","≌"],["\\supseteq","⊇"],["\\circledS","Ⓢ"],["\\circledR","®"],["\\textcent","¢"],["\\urcorner","⌝"],["\\lrcorner","⌟"],["\\boxminus","⊟"],["\\texteuro","€"],["\\vartheta","ϑ"],["\\barwedge","⊼"],["\\ding{86}","✶"],["\\sqsubset","⊏"],["\\subseteq","⊆"],["\\intercal","⊺"],["\\ding{73}","☆"],["\\ulcorner","⌜"],["\\recorder","⌕"],["\\precnsim","⋨"],["\\parallel","∥"],["\\boxtimes","⊠"],["\\ding{55}","✗"],["\\multimap","⊸"],["\\maltese","✠"],["\\nearrow","↗"],["\\swarrow","↙"],["\\lozenge","◊"],["\\sqrt[3]","∛"],["\\succsim","≿"],["\\dotplus","∔"],["\\tilde{}","~"],["\\check{}","ˇ"],["\\lessgtr","≶"],["\\Upsilon","ϒ"],["\\Cdprime","Ъ"],["\\gtrless","≷"],["\\backsim","∽"],["\\nexists","∄"],["\\dotplus","∔"],["\\searrow","↘"],["\\lessdot","⋖"],["\\boxplus","⊞"],["\\upsilon","υ"],["\\epsilon","ε"],["\\diamond","⋄"],["\\bigstar","★"],["\\ddagger","‡"],["\\cdprime","ъ"],["\\Uparrow","⇑"],["\\sqrt[4]","∜"],["\\between","≬"],["\\sqangle","∟"],["\\digamma","Ϝ"],["\\uparrow","↑"],["\\nwarrow","↖"],["\\precsim","≾"],["\\breve{}","˘"],["\\because","∵"],["\\bigcirc","◯"],["\\acute{}","´"],["\\grave{}","`"],["\\check{}","ˇ"],["\\lesssim","≲"],["\\partial","∂"],["\\natural","♮"],["\\supset","⊃"],["\\hstrok","ħ"],["\\Tstrok","Ŧ"],["\\coprod","∐"],["\\models","⊧"],["\\otimes","⊗"],["\\degree","°"],["\\gtrdot","⋗"],["\\preceq","≼"],["\\Lambda","Λ"],["\\lambda","λ"],["\\cprime","ь"],["\\varrho","ϱ"],["\\Bumpeq","≎"],["\\hybull","⁃"],["\\lmidot","ŀ"],["\\nvdash","⊬"],["\\lbrace","{"],["\\bullet","•"],["\\varphi","φ"],["\\bumpeq","≏"],["\\ddot{}","¨"],["\\Lmidot","Ŀ"],["\\Cprime","Ь"],["\\female","♀"],["\\rtimes","⋊"],["\\gtrsim","≳"],["\\mapsto","↦"],["\\daleth","ℸ"],["\\square","■"],["\\nVDash","⊯"],["\\rangle","〉"],["\\tstrok","ŧ"],["\\oslash","⊘"],["\\ltimes","⋉"],["\\lfloor","⌊"],["\\marker","▮"],["\\Subset","⋐"],["\\Vvdash","⊪"],["\\propto","∝"],["\\Hstrok","Ħ"],["\\dlcrop","⌍"],["\\forall","∀"],["\\nVdash","⊮"],["\\Supset","⋑"],["\\langle","〈"],["\\ominus","⊖"],["\\rfloor","⌋"],["\\circeq","≗"],["\\eqcirc","≖"],["\\drcrop","⌌"],["\\veebar","⊻"],["\\ulcrop","⌏"],["\\nvDash","⊭"],["\\urcrop","⌎"],["\\exists","∃"],["\\approx","≈"],["\\dagger","†"],["\\boxdot","⊡"],["\\succeq","≽"],["\\bowtie","⋈"],["\\subset","⊂"],["\\Sigma","Σ"],["\\Omega","Ω"],["\\nabla","∇"],["\\colon",":"],["\\boxHu","╧"],["\\boxHd","╤"],["\\aleph","ℵ"],["\\gnsim","⋧"],["\\boxHU","╩"],["\\boxHD","╦"],["\\equiv","≡"],["\\lneqq","≨"],["\\alpha","α"],["\\amalg","∐"],["\\boxhU","╨"],["\\boxhD","╥"],["\\uplus","⊎"],["\\boxhu","┴"],["\\kappa","κ"],["\\sigma","σ"],["\\boxDL","╗"],["\\Theta","Θ"],["\\Vdash","⊩"],["\\boxDR","╔"],["\\boxDl","╖"],["\\sqcap","⊓"],["\\boxDr","╓"],["\\bar{}","¯"],["\\dashv","⊣"],["\\vDash","⊨"],["\\boxdl","┐"],["\\boxVl","╢"],["\\boxVh","╫"],["\\boxVr","╟"],["\\boxdr","┌"],["\\boxdL","╕"],["\\boxVL","╣"],["\\boxVH","╬"],["\\boxVR","╠"],["\\boxdR","╒"],["\\theta","θ"],["\\lhblk","▄"],["\\uhblk","▀"],["\\ldotp","."],["\\ldots","…"],["\\boxvL","╡"],["\\boxvH","╪"],["\\boxvR","╞"],["\\boxvl","┤"],["\\boxvh","┼"],["\\boxvr","├"],["\\Delta","Δ"],["\\boxUR","╚"],["\\boxUL","╝"],["\\oplus","⊕"],["\\boxUr","╙"],["\\boxUl","╜"],["\\doteq","≐"],["\\happy","㋡"],["\\varpi","ϖ"],["\\smile","☺"],["\\boxul","┘"],["\\simeq","≃"],["\\boxuR","╘"],["\\boxuL","╛"],["\\boxhd","┬"],["\\gimel","ℷ"],["\\Gamma","Γ"],["\\lnsim","⋦"],["\\sqcup","⊔"],["\\omega","ω"],["\\sharp","♯"],["\\times","×"],["\\block","█"],["\\hat{}","^"],["\\wedge","∧"],["\\vdash","⊢"],["\\angle","∠"],["\\infty","∞"],["\\gamma","γ"],["\\asymp","≍"],["\\rceil","⌉"],["\\dot{}","˙"],["\\lceil","⌈"],["\\delta","δ"],["\\gneqq","≩"],["\\frown","⌢"],["\\phone","☎"],["\\vdots","⋮"],["\\boxr","└"],["\\k{i}","į"],["\\`{I}","Ì"],["\\perp","⊥"],["\\\"{o}","ö"],["\\={I}","Ī"],["\\`{a}","à"],["\\v{T}","Ť"],["\\surd","√"],["\\H{O}","Ő"],["\\vert","|"],["\\k{I}","Į"],["\\\"{y}","ÿ"],["\\\"{O}","Ö"],["\\'{Y}","Ý"],["\\u{u}","ў"],["\\u{G}","Ğ"],["\\.{E}","Ė"],["\\.{z}","ż"],["\\v{t}","ť"],["\\prec","≺"],["\\H{o}","ő"],["\\mldr","…"],["\\'{y}","ý"],["\\cong","≅"],["\\.{e}","ė"],["\\'{L}","Ĺ"],["\\star","*"],["\\.{Z}","Ż"],["\\'{e}","é"],["\\geqq","≧"],["\\cdot","⋅"],["\\`{U}","Ù"],["\\'{l}","ĺ"],["\\v{L}","Ľ"],["\\c{s}","ş"],["\\'{s}","ś"],["\\~{A}","Ã"],["\\Vert","‖"],["\\k{e}","ę"],["\\lnot","¬"],["\\'{z}","ź"],["\\leqq","≦"],["\\beta","β"],["\\beth","ℶ"],["\\'{E}","É"],["\\~{n}","ñ"],["\\u{i}","й"],["\\c{S}","Ş"],["\\c{N}","Ņ"],["\\H{u}","ű"],["\\v{n}","ň"],["\\'{S}","Ś"],["\\={U}","Ū"],["\\~{O}","Õ"],["\\'{Z}","Ź"],["\\v{E}","Ě"],["\\'{R}","Ŕ"],["\\H{U}","Ű"],["\\v{N}","Ň"],["\\prod","∏"],["\\v{s}","š"],["\\\"{U}","Ü"],["\\c{n}","ņ"],["\\k{U}","Ų"],["\\c{R}","Ŗ"],["\\'{A}","Á"],["\\~{o}","õ"],["\\v{e}","ě"],["\\v{S}","Š"],["\\u{A}","Ă"],["\\circ","∘"],["\\\"{u}","ü"],["\\flat","♭"],["\\v{z}","ž"],["\\r{U}","Ů"],["\\`{O}","Ò"],["\\={u}","ū"],["\\oint","∮"],["\\c{K}","Ķ"],["\\k{u}","ų"],["\\not<","≮"],["\\not>","≯"],["\\`{o}","ò"],["\\\"{I}","Ï"],["\\v{D}","Ď"],["\\.{G}","Ġ"],["\\r{u}","ů"],["\\not=","≠"],["\\`{u}","ù"],["\\v{c}","č"],["\\c{k}","ķ"],["\\.{g}","ġ"],["\\'{N}","Ń"],["\\odot","⊙"],["\\`{e}","э"],["\\c{T}","Ţ"],["\\v{d}","ď"],["\\\"{e}","ё"],["\\'{I}","Í"],["\\v{R}","Ř"],["\\k{a}","ą"],["\\nldr","‥"],["\\`{A}","À"],["\\'{n}","ń"],["\\~{N}","Ñ"],["\\nmid","∤"],["\\.{C}","Ċ"],["\\zeta","ζ"],["\\~{u}","ũ"],["\\`{E}","Э"],["\\~{a}","ã"],["\\c{t}","ţ"],["\\={o}","ō"],["\\v{r}","ř"],["\\={A}","Ā"],["\\.{c}","ċ"],["\\~{U}","Ũ"],["\\k{A}","Ą"],["\\\"{a}","ä"],["\\u{U}","Ў"],["\\iota","ι"],["\\={O}","Ō"],["\\c{C}","Ç"],["\\gneq","≩"],["\\'{c}","ć"],["\\boxH","═"],["\\hbar","ℏ"],["\\\"{A}","Ä"],["\\boxv","│"],["\\boxh","─"],["\\male","♂"],["\\'{u}","ú"],["\\sqrt","√"],["\\succ","≻"],["\\c{c}","ç"],["\\'{C}","Ć"],["\\v{l}","ľ"],["\\u{a}","ă"],["\\v{Z}","Ž"],["\\'{o}","ó"],["\\c{G}","Ģ"],["\\v{C}","Č"],["\\lneq","≨"],["\\\"{E}","Ё"],["\\={a}","ā"],["\\c{l}","ļ"],["\\'{a}","á"],["\\={E}","Ē"],["\\boxV","║"],["\\u{g}","ğ"],["\\'{O}","Ó"],["\\'{g}","ǵ"],["\\u{I}","Й"],["\\c{L}","Ļ"],["\\k{E}","Ę"],["\\.{I}","İ"],["\\~{I}","Ĩ"],["\\quad"," "],["\\c{r}","ŗ"],["\\'{r}","ŕ"],["\\\"{Y}","Ÿ"],["\\={e}","ē"],["\\'{U}","Ú"],["\\leq","≤"],["\\Cup","⋓"],["\\Psi","Ψ"],["\\neq","≠"],["\\k{}","˛"],["\\={}","‾"],["\\H{}","˝"],["\\cup","∪"],["\\geq","≥"],["\\mho","℧"],["\\Dzh","Џ"],["\\cap","∩"],["\\bot","⊥"],["\\psi","ψ"],["\\chi","χ"],["\\c{}","¸"],["\\Phi","Φ"],["\\ast","*"],["\\ell","ℓ"],["\\top","⊤"],["\\lll","⋘"],["\\tau","τ"],["\\Cap","⋒"],["\\sad","☹"],["\\iff","⇔"],["\\eta","η"],["\\eth","ð"],["\\d{}","̣"],["\\rho","ρ"],["\\dzh","џ"],["\\div","÷"],["\\phi","ϕ"],["\\Rsh","↱"],["\\vee","∨"],["\\b{}","ˍ"],["\\t{}","͡"],["\\int","∫"],["\\sim","∼"],["\\r{}","˚"],["\\Lsh","↰"],["\\yen","¥"],["\\ggg","⋙"],["\\mid","∣"],["\\sum","∑"],["\\Dz","Ѕ"],["\\Re","ℜ"],["\\oe","œ"],["\\DH","Ð"],["\\ll","≪"],["\\ng","ŋ"],["\\'G","Ѓ"],["\\wr","≀"],["\\wp","℘"],["\\=I","І"],["\\:)","☺"],["\\:(","☹"],["\\AE","Æ"],["\\AA","Å"],["\\ss","ß"],["\\dz","ѕ"],["\\ae","æ"],["\\aa","å"],["\\th","þ"],["\\to","→"],["\\Pi","Π"],["\\mp","∓"],["\\Im","ℑ"],["\\pm","±"],["\\pi","π"],["\\\"I","Ї"],["\\'C","Ћ"],["\\in","∈"],["\\'K","Ќ"],["\\'k","ќ"],["\\'c","ћ"],["\\'g","ѓ"],["\\ni","∋"],["\\ne","≠"],["\\TH","Þ"],["\\Xi","Ξ"],["\\nu","ν"],["\\NG","Ŋ"],["\\:G","㋡"],["\\xi","ξ"],["\\OE","Œ"],["\\gg","≫"],["\\DJ","Đ"],["\\=e","є"],["\\=E","Є"],["\\mu","μ"],["\\dj","đ"],["\\:"," "],["\\;"," "],["\\&","&"],["\\$","$"],["\\%","%"],["\\#","#"],["\\,"," "],["\\-","­"],["\\S","§"],["\\P","¶"],["\\O","Ø"],["\\L","Ł"],["\\}","}"],["\\o","ø"],["\\l","ł"],["\\h","ℎ"],["\\i","ℹ"],["-","−"]],"combiningmarks":[["\\doubleunderline","̳"],["\\strikethrough","̵"],["\\underline","̲"],["\\overline","̅"],["\\tilde","̃"],["\\grave","̀"],["\\acute","́"],["\\slash","̸"],["\\breve","̆"],["\\ddot","̈"],["\\dot","̇"],["\\bar","̅"],["\\vec","⃗"],["\\hat","̂"]],"subsuperscripts":[["_x","ₓ"],["_v","ᵥ"],["_u","ᵤ"],["_t","ₜ"],["_s","ₛ"],["_r","ᵣ"],["_p","ₚ"],["_o","ₒ"],["_n","ₙ"],["_m","ₘ"],["_l","ₗ"],["_k","ₖ"],["_j","ⱼ"],["_i","ᵢ"],["_h","ₕ"],["_e","ₑ"],["_a","ₐ"],["^∫","ᶴ"],["_>","˲"],["_=","₌"],["_<","˱"],["_9","₉"],["_8","₈"],["_7","₇"],["_6","₆"],["_5","₅"],["_4","₄"],["_3","₃"],["_2","₂"],["_1","₁"],["_0","₀"],["_-","₋"],["_−","₋"],["_+","₊"],["_)","₎"],["_(","₍"],["_ρ","ᵨ"],["_χ","ᵪ"],["_φ","ᵩ"],["_β","ᵦ"],["_γ","ᵧ"],["^φ","ᵠ"],["^χ","ᵡ"],["^δ","ᵟ"],["^γ","ᵞ"],["^β","ᵝ"],["^8","⁸"],["^9","⁹"],["^<","˂"],["^=","⁼"],["^>","˃"],["^0","⁰"],["^1","¹"],["^2","²"],["^3","³"],["^4","⁴"],["^5","⁵"],["^6","⁶"],["^7","⁷"],["^(","⁽"],["^)","⁾"],["^*","*"],["^+","⁺"],["^-","⁻"],["^−","⁻"],["^P","ᴾ"],["^R","ᴿ"],["^T","ᵀ"],["^U","ᵁ"],["^V","ᄑ"],["^W","ᵂ"],["^H","ᴴ"],["^I","ᴵ"],["^J","ᴶ"],["^K","ᴷ"],["^L","ᴸ"],["^M","ᴹ"],["^N","ᴺ"],["^O","ᴼ"],["^A","ᴬ"],["^B","ᴮ"],["^D","ᴰ"],["^E","ᴱ"],["^G","ᴳ"],["^x","ˣ"],["^y","ʸ"],["^z","ᶻ"],["^p","ᵖ"],["^r","ʳ"],["^s","ˢ"],["^t","ᵗ"],["^u","ᵘ"],["^v","ᵛ"],["^w","ʷ"],["^h","ʰ"],["^i","ⁱ"],["^j","ʲ"],["^k","ᵏ"],["^l","ˡ"],["^m","ᵐ"],["^n","ⁿ"],["^o","ᵒ"],["^a","ᵃ"],["^b","ᵇ"],["^c","ᶜ"],["^d","ᵈ"],["^e","ᵉ"],["^f","ᶠ"],["^g","ᵍ"]]} kramdown-rfc2629-1.7.31/data/rfcxml.xslt0000644000004100000410000201341715142163665017711 0ustar www-datawww-data yes no yes no yes no no yes 1 2 3 4 5 99 no yes yes no fft-sans-serif ffb-serif ff-cleartype 'Noto Serif', 'Noto Sans', cambria, georgia, candara, calibri, segoe, optima, arial, sans-serif, serif 'Noto Serif', 'Noto Sans', cambria, georgia, candara, calibri, serif, segoe, optima, arial, sans-serif 'Roboto Mono', consolas, monaco, monospace @import url('https://fonts.googleapis.com/css?family=Noto+Sans:r,b,i,bi'); @import url('https://fonts.googleapis.com/css?family=Noto+Serif:r,b,i,bi'); @import url('https://fonts.googleapis.com/css?family=Roboto+Mono:r,b,i,bi'); , ? include succeeded for best-guess URI while was specified - you may want to adjust the include directive in order to avoid future warnings 6 5 4 3 2 1 0 Unsupported LOG level '', defaulting to 'WARNING' This note is to be removed before publishing as an RFC. This section is to be removed before publishing as an RFC. unnumbered- yes no yes no no yes https://bib.ietf.org/public/rfc/bibxml/ https://bib.ietf.org/public/rfc/bibxml-ids/ https://www.worldcat.org/search?q=isbn:{isbn} https://www.rfc-editor.org/rfc/rfc{rfc}.html https://www.rfc-editor.org/info/std{std} https://www.rfc-editor.org/info/bcp{bcp} https://datatracker.ietf.org/doc/html/{internet-draft} https://www.ietf.org/rfcdiff?url2={internet-draft} https://dx.doi.org/{doi} http://www.rfc-editor.org/info/{type}{no} https://www.rfc-editor.org/info/{type}{no} https://www.rfc-editor.org/errata/eid{eid} https://www.rfc-editor.org/errata/rfc{rfc} https://datatracker.ietf.org/doc/{draftname} This stylesheet requires either an XSLT-1.0 processor with node-set() extension function, or an XSLT-2.0 processor. Therefore, parts of the document couldn't be displayed. RFC number given in /rfc/front/seriesInfo () inconsistent with rfc element () number given in /rfc/front/seriesInfo () inconsistent with first computed value () std STD bcp BCP info FYI IETF yes no 2010 2010 https http https http https://www.rfc-editor.org/rfc/rfc7841.html#section-2Section 2 of RFC 7841 https://www.rfc-editor.org/rfc/rfc5741.html#section-2Section 2 of RFC 5741 2010

Abstract

function parseXml(str) { try { var doc = new ActiveXObject("MSXML2.DOMDocument"); doc.async = false; if (doc.loadXML(str)) { return ""; } else { return doc.parseError.reason + "\n" + doc.parseError.srcText + " (" + doc.parseError.line + "/" + doc.parseError.linepos + ")"; } } catch(e) { return ""; } } inline text2 text drawing text
      <CODE BEGINS>
      
        
        
          
            
              illegal characters in @name attribute '': ''
            
          
          
             file "
            
            "
          
        
      
    
NOTE: '\' line wrapping per RFC 8792
NOTE: '\\' line wrapping per RFC 8792
<CODE ENDS>
artset needs to contain at least one artwork child element

sourcecode with both @src ('') and text content no cannot read from '': no sourcecode with @src requires XSLT2 processor no
XML PARSE ERROR; parsed the body below:
        
        
resulting in:
        
        
XML PARSE ERROR:
display:table; margin-left: auto; margin-right: 0em; display:table; margin-left: auto; margin-right: auto; margin-left: 0em; span div
      
      
        
      
      
      
      
    
(but trailing '\' missing) color: red; \ \ RFC 8792 line folding mode '\\' but no trailing '\' found artwork line too long: '' ( characters) 69 artwork line too long: '' ( characters)
Ignoring child elements of <contact> when used inside <t>. ( )


Additional contact information:

: ,
Multiple <address> elements inside <author>, all but the first ignored. , (org) ??? Element '' with value '' not displayed in postal address for ''. Multiple <postal> elements inside <address> for '', all but the first ignored. Postal address for '' is incomplete because country information is missing. It is not allowed to mix postalLine with other elements except country; these will be ignored. When combined with postalLine, country needs to be last. Phone Fax Email EMail URI fullname attribute should be specified for author (using surname instead) ( )
target attribute not an absolute URI: target attribute '' contains invalid scheme name '' < > span div

Figure :

[IESG Note][IESG Note:] The Internet-Draft name '' should contain the base name, not the filename (thus no file extension). The Internet-Draft name '' should not contain the character ''. The Internet-Draft name '' should not contain the character sequence '--'. The Internet-Draft name '' should start with 'draft-'. The Internet-Draft name '' should end with a two-digit sequence number or 'latest'. The Internet-Draft name '', excluding sequence number, should have less than 50 characters.

The @docName attribute '' is ignored because an RFC number () is specified as well.
-
Inconsistent draft names in /rfc/@docName ('') and /rfc/seriesInfo ('').

Note: a later version of this document has been published as .

Either /rfc/@ipr or /rfc/@number is required
iref "item" attribute contains non-normalized whitespace ("") iref "subitem" attribute contains non-normalized whitespace ("")
section. iref.. iref. extref.. extref.
 
compact
a A
compact nohang
margin-left: em
 
1

    empty bare support for "bare" is experimental, see https://trac.tools.ietf.org/tools/xml2rfc/trac/ticket/547 for more information invalid value for "bare" attribute: '' "bare" attribute is ignored when "empty" is not "true"
  • padding-left: em unexpected content in <li>: can not mix block-level and phrase-level elements unexpected content in <li>: can not mix phrase-level and block-level elements unexpected content in <li>
  • margin-left: em
     
  • margin-left: em
    % %d. note rfcEditorRemove

    section. Abstract References Not a fragment identifier: Anchor '' in not found in source file ''. A@ S@ Can't generate section link to ; no @x:rel specified Can't generate section link for to ; no @relative specified displayreference '' will create non-unique reference name. -_. displayreference '' contains illegal characters: ''. displayreference '' contains illegal characters: ''. displayreference '' starts with characters not allowed as start character: '' ( ) , Ed. Ignoring @target in link calculation invalid (empty) target attribute in reference '' , , , , Removing DOI from <reference> element , Unexpected DOI for RFC, found , expected , , Work in Progress , Work in Progress , Internet-Draft, ( work in progress ) , RFC number preceding number in reference '' (but found in element , consider marking up the text content which is supported by this processor, see https://greenbytes.de/tech/webdav/rfc2629xslt/rfc2629xslt.html#extension.pis) missing anchor attribute on reference, containing the text: unused reference '' unused (included) reference '' OK all references to the normative reference '' appear to be informative
    <front> element missing for '' <front> can be omitted when <x:source> is specified (for '')
    , and , , and , ( ) seriesInfo present both on reference and reference/front , DOI , , < > , < > , < > .
    x:has with anchor '' in is unused x:has with target '' not defined in x:has with anchor '' not defined in
    <date> missing in reference '' (note that it can be empty) date element has both year attribute and text content: '' in reference '' date/@year should be a number: '' in reference '' , , missing anchor on reference: unused reference '' unused (included) reference ''
    <>
    STD '' likely missing on reference [] likely incorrect number '' on reference [] (expected '')

    del- h4 h3 h2 both @title attribute and name child node present neither @title attribute nor name child node present, choosing default of '' .
    Cannot mix <references> elements with other child nodes such as (these will be ignored)
    <xsl:value-of select="$title"/> xml2rfc-ext-css-contents ignored, as xml2rfc-ext-css-resource was specified as well Specified as xml2rfc-ext-css-contents Support for css inclusion requires 'unparsed-text' function support (XSLT 2) , getMeta("","rfc.meta"); getMeta("","","rfc.meta"); initFeedback(); RfcRefresh.initRefresh() abstract note boilerplate section The paragraph below is misplaced; maybe a section is closed in the wrong place: avoidbreakafter avoidbreakbefore
    padding-left: em

    abstract note boilerplate section

    title/@abbrev too long (max 40 characters) title too long, should supply title/@abbrev attribute with less than 40 characters title/@abbrev was specified despite the title being short enough () Title: '', abbreviated title='' both @title attribute and name child node present Ignoring appendix containing <author> elements (likely added by preptool step). Ignoring appendix containing index (likely added by preptool step). The "appendix" element is deprecated, use "section" inside "back" instead. h h6 rfcEditorRemove </xsl:for-each> </xsl:variable> <xsl:for-each select="exslt:node-set($titles)/*"> <xsl:sort select="@t"/> <xsl:if test="position()!=@p"> <xsl:call-template name="error"> <xsl:with-param name="msg">Subsection '<xsl:value-of select="@t"/>' at wrong position (is <xsl:value-of select="@p"/>, should be <xsl:value-of select="position()"/>) in parent section (which should be supported alphabetically by title)</xsl:with-param> </xsl:call-template> </xsl:if> </xsl:for-each> </xsl:if> <section> <xsl:call-template name="copy-anchor"/> <xsl:if test="normalize-space($classes)!=''"> <xsl:attribute name="class"><xsl:value-of select="normalize-space($classes)"/></xsl:attribute> </xsl:if> <xsl:element name="{$elemtype}"> <xsl:if test="$sectionNumber!=''"> <xsl:attribute name="id"><xsl:value-of select="$anchor-pref"/>section.<xsl:value-of select="$sectionNumber"/></xsl:attribute> </xsl:if> <xsl:choose> <xsl:when test="$sectionNumber='1' or $sectionNumber='A'"> <!-- pagebreak, this the first section --> <xsl:attribute name="class">np</xsl:attribute> </xsl:when> <xsl:when test="not(ancestor::section) and not(ancestor::boilerplate)"> <xsl:call-template name="insert-conditional-pagebreak"/> </xsl:when> <xsl:otherwise/> </xsl:choose> <xsl:call-template name="insertInsDelClass" /> <xsl:if test="$sectionNumber!='' and not(contains($sectionNumber,$unnumbered))"> <a href="#{$anchor-pref}section.{$sectionNumber}"> <xsl:call-template name="emit-section-number"> <xsl:with-param name="no" select="$sectionNumber"/> <xsl:with-param name="appendixPrefix" select="true()"/> </xsl:call-template> </a> <xsl:text> </xsl:text> </xsl:if> <!-- issue tracking? --> <xsl:if test="@ed:resolves"> <xsl:call-template name="insert-issue-pointer"/> </xsl:if> <xsl:call-template name="check-anchor"/> <xsl:variable name="anchor"> <xsl:choose> <xsl:when test="@anchor"><xsl:value-of select="@anchor"/></xsl:when> <xsl:otherwise><xsl:call-template name="sluggy-anchor"/></xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:variable name="name"> <xsl:choose> <xsl:when test="starts-with(@title,'Since ')"> <xsl:value-of select="substring-after(@title,'Since ')"/> </xsl:when> <xsl:when test="starts-with(@title,'draft-')"> <xsl:value-of select="@title"/> </xsl:when> <xsl:otherwise/> </xsl:choose> </xsl:variable> <xsl:variable name="basename"> <xsl:call-template name="draft-base-name"> <xsl:with-param name="name" select="$name"/> </xsl:call-template> </xsl:variable> <xsl:variable name="seq"> <xsl:call-template name="draft-sequence-number"> <xsl:with-param name="name" select="$name"/> </xsl:call-template> </xsl:variable> <xsl:variable name="offset"> <xsl:choose> <xsl:when test="starts-with(@title,'Since ')">1</xsl:when> <xsl:otherwise>0</xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:variable name="smells-like-change-log" select="ancestor-or-self::section[@removeInRFC='true'] or ancestor::section[@title='Changes'] or ancestor::section[@title='Change Log']"/> <xsl:variable name="diff-uri"> <xsl:if test="$smells-like-change-log and $basename!=''"> <xsl:variable name="next" select="concat($basename,'-',format-number($offset + $seq,'00'))"/> <xsl:choose> <!-- check whether the "next" draft exists (is mentioned in a sibling section --> <xsl:when test="../section[contains(@title,$next)]"> <xsl:call-template name="compute-diff-uri"> <xsl:with-param name="name" select="$next"/> </xsl:call-template> </xsl:when> <xsl:when test="starts-with(ancestor::rfc/@docName,$basename)"> <xsl:call-template name="compute-latest-diff-uri"> <xsl:with-param name="name" select="$basename"/> </xsl:call-template> </xsl:when> <xsl:otherwise/> </xsl:choose> </xsl:if> </xsl:variable> <xsl:variable name="text-uri"> <xsl:if test="$smells-like-change-log and $basename!=''"> <xsl:call-template name="compute-internet-draft-uri"> <xsl:with-param name="internet-draft" select="$name"/> </xsl:call-template> </xsl:if> </xsl:variable> <xsl:choose> <xsl:when test="$anchor!=''"> <a href="#{$anchor}"><xsl:call-template name="insertTitle"/></a> </xsl:when> <xsl:otherwise> <xsl:call-template name="insertTitle"/> </xsl:otherwise> </xsl:choose> <xsl:if test="$xml2rfc-ext-paragraph-links='yes' and $text-uri!=''"> <xsl:text> </xsl:text> <a class="self" href="{$text-uri}" title="plain text">📄</a> </xsl:if> <xsl:if test="$xml2rfc-ext-paragraph-links='yes' and $diff-uri!=''"> <xsl:text> </xsl:text> <a class="self" href="{$diff-uri}" title="diffs">🔍</a> </xsl:if> </xsl:element> <xsl:if test="$sectionNumber!=''"> <xsl:call-template name="insert-errata"> <xsl:with-param name="section" select="$sectionNumber"/> </xsl:call-template> </xsl:if> <xsl:if test="@removeInRFC='true' and (not(t) or t[1]!=$section-removeInRFC)"> <xsl:variable name="t"> <t><xsl:value-of select="$section-removeInRFC"/></t> </xsl:variable> <xsl:variable name="link" select="concat($anchor-pref,'section.',$sectionNumber,'.p.1')"/> <div id="{$link}"> <xsl:apply-templates mode="t-content" select="exslt:node-set($t)//text()"> <xsl:with-param name="inherited-self-link" select="$link"/> </xsl:apply-templates> </div> </xsl:if> <!-- continue with all child elements but the irefs processed above --> <xsl:for-each select="*"> <xsl:if test="count(.|$section-level-irefs)!=count($section-level-irefs)"> <xsl:apply-templates select="."/> </xsl:if> </xsl:for-each> </section> </xsl:template> <!-- errata handling --> <xsl:template name="insert-erratum"> <xsl:param name="es"/> <xsl:param name="sec"/> <xsl:if test="$es"> <aside class="{$css-erratum}"> <xsl:for-each select="$es"> <xsl:sort select="@eid" data-type="number"/> <xsl:variable name="pf"> <xsl:variable name="entry" select="section[.=$sec]"/> <xsl:if test="count($entry/preceding-sibling::section)!=0"> <xsl:text>.</xsl:text> <xsl:value-of select="1 + count($entry/preceding-sibling::section)"/> </xsl:if> </xsl:variable> <div id="{$anchor-pref}erratum.{@eid}{$pf}"> <xsl:variable name="tooltip"> <xsl:value-of select="@reported-by"/> <xsl:text>, </xsl:text> <xsl:value-of select="@reported"/> <xsl:if test="@type"> (<xsl:value-of select="@type"/>)</xsl:if> </xsl:variable> <xsl:variable name="uri"> <xsl:call-template name="compute-rfc-erratum-uri"> <xsl:with-param name="eid" select="@eid"/> </xsl:call-template> </xsl:variable> <a href="{$uri}" title="{$tooltip}">Erratum <xsl:value-of select="@eid"/></a> <xsl:choose> <xsl:when test="@status='Verified'"><xsl:text> </xsl:text><span title="verified">✔</span></xsl:when> <xsl:when test="@status='Reported'"><xsl:text> </xsl:text><span title="reported">✉</span></xsl:when> <xsl:when test="@status='Held for Document Update'"><xsl:text> </xsl:text><span title="held for update">✀</span></xsl:when> <xsl:otherwise/> </xsl:choose> </div> </xsl:for-each> </aside> </xsl:if> </xsl:template> <xsl:template name="insert-errata"> <xsl:param name="section"> <xsl:call-template name="get-section-number"/> </xsl:param> <xsl:variable name="match-para" select="self::artwork or self::sourcecode or self::t or self::ul"/> <xsl:choose> <xsl:when test="$match-para"> <xsl:variable name="p"> <xsl:call-template name="get-paragraph-number"> <xsl:with-param name="delim">-</xsl:with-param> </xsl:call-template> </xsl:variable> <xsl:variable name="es" select="$errata-parsed[section[@part=concat('section-',$p) or @part=concat('appendix-',$p)]]"/> <xsl:if test="$p!='' and $es"> <xsl:call-template name="insert-erratum"> <xsl:with-param name="es" select="$es"/> <xsl:with-param name="sec" select="$section"/> </xsl:call-template> </xsl:if> </xsl:when> <xsl:otherwise> <xsl:variable name="es" select="$errata-parsed[section=$section or (not(section) and $section='1')]"/> <xsl:call-template name="insert-erratum"> <xsl:with-param name="es" select="$es[not(section/@part)]"/> <xsl:with-param name="sec" select="$section"/> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:template> <!-- already processed by insertTitle --> <xsl:template match="note/name"/> <xsl:template match="section/name"/> <xsl:template match="spanx[@style='emph' or not(@style)]|em"> <em> <xsl:call-template name="copy-anchor"/> <xsl:apply-templates /> </em> </xsl:template> <xsl:template match="spanx[@style='verb' or @style='vbare']|tt"> <span class="tt"> <xsl:call-template name="copy-anchor"/> <xsl:apply-templates /> </span> </xsl:template> <xsl:template match="spanx[@style='strong']|strong"> <strong> <xsl:call-template name="copy-anchor"/> <xsl:apply-templates /> </strong> </xsl:template> <xsl:template match="spanx[@style!='']" priority="0.1"> <xsl:call-template name="warning"> <xsl:with-param name="msg">unknown spanx style attribute '<xsl:value-of select="@style"/>' ignored</xsl:with-param> </xsl:call-template> <span> <xsl:call-template name="copy-anchor"/> <xsl:apply-templates /> </span> </xsl:template> <xsl:template name="insert-blank-lines"> <xsl:param name="no"/> <xsl:choose> <xsl:when test="$no >= $xml2rfc-ext-vspace-pagebreak"> <br/> <!-- done; this probably was an attempt to generate a pagebreak --> </xsl:when> <xsl:when test="$no <= 0"> <br/> <!-- done --> </xsl:when> <xsl:otherwise> <br/> <xsl:call-template name="insert-blank-lines"> <xsl:with-param name="no" select="$no - 1"/> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="vspace[not(@blankLines)]"> <br /> </xsl:template> <xsl:template match="vspace"> <xsl:call-template name="insert-blank-lines"> <xsl:with-param name="no" select="@blankLines"/> </xsl:call-template> </xsl:template> <xsl:template match="br"> <br/> </xsl:template> <!-- keep the root for the case when we process XSLT-inline markup --> <xsl:variable name="src" select="/" /> <xsl:template name="render-section-ref-title"> <xsl:param name="to" /> <xsl:choose> <xsl:when test="$to/name"> <xsl:call-template name="render-name-ref"> <xsl:with-param name="n" select="$to/name/node()"/> </xsl:call-template> </xsl:when> <xsl:when test="$to/@title"> <xsl:value-of select="normalize-space($to/@title)"/> </xsl:when> <xsl:when test="$to/self::abstract">Abstract</xsl:when> <xsl:when test="$to/self::references">References</xsl:when> <xsl:otherwise/> </xsl:choose> </xsl:template> <xsl:template name="render-section-ref"> <xsl:param name="from" /> <xsl:param name="to" /> <xsl:param name="child-nodes"/> <xsl:variable name="refname"> <xsl:for-each select="$to"> <xsl:call-template name="get-section-type"/> </xsl:for-each> </xsl:variable> <xsl:variable name="refnum"> <xsl:for-each select="$to"> <xsl:call-template name="get-section-number" /> </xsl:for-each> </xsl:variable> <xsl:choose> <xsl:when test="$child-nodes"> <xsl:apply-templates select="$child-nodes"/> </xsl:when> <xsl:when test="$from/@format='counter'"> <xsl:choose> <xsl:when test="$to/self::abstract"> <xsl:call-template name="error"> <xsl:with-param name="inline">no</xsl:with-param> <xsl:with-param name="msg">xref to abstract with format='counter' not allowed</xsl:with-param> <xsl:with-param name="node" select="$from"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:value-of select="$refnum"/> </xsl:otherwise> </xsl:choose> </xsl:when> <xsl:when test="$from/@format='title'"> <xsl:call-template name="render-section-ref-title"> <xsl:with-param name="to" select="$to"/> </xsl:call-template> </xsl:when> <xsl:when test="$from/@format='none'"> <!-- Nothing to do --> </xsl:when> <xsl:otherwise> <xsl:choose> <xsl:when test="starts-with($refnum,$unnumbered)"> <xsl:value-of select="$refname"/> <xsl:text> "</xsl:text> <xsl:choose> <xsl:when test="$to/name"> <xsl:apply-templates select="$to/name/node()"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="$to/@title"/> </xsl:otherwise> </xsl:choose> <xsl:text>"</xsl:text> </xsl:when> <xsl:otherwise> <xsl:value-of select="normalize-space(concat($refname,' ',$refnum))"/> </xsl:otherwise> </xsl:choose> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="get-section-xref-format"> <xsl:param name="default"/> <xsl:choose> <xsl:when test="self::relref"> <xsl:choose> <xsl:when test="not(@displayFormat)">of</xsl:when> <xsl:when test="@displayFormat='parens' or @displayFormat='of' or @displayFormat='comma' or @displayFormat='bare'"> <xsl:value-of select="@displayFormat"/> </xsl:when> <xsl:otherwise> <xsl:call-template name="warning"> <xsl:with-param name="msg">unknown format for @displayFormat: <xsl:value-of select="@displayFormat"/></xsl:with-param> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:when> <xsl:when test="self::xref and @section and not(@sectionFormat)"> <xsl:text>of</xsl:text> </xsl:when> <xsl:when test="self::xref and @sectionFormat"> <xsl:if test="@x:fmt"> <xsl:call-template name="warning"> <xsl:with-param name="msg">both @x:fmt and @sectionFormat specified</xsl:with-param> </xsl:call-template> </xsl:if> <xsl:choose> <xsl:when test="@sectionFormat='of' or @sectionFormat='comma' or @sectionFormat='parens' or @sectionFormat='bare'"> <xsl:value-of select="@sectionFormat"/> </xsl:when> <xsl:otherwise> <xsl:call-template name="warning"> <xsl:with-param name="msg">unknown value '<xsl:value-of select="@sectionFormat"/>' for @sectionFormat</xsl:with-param> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:when> <xsl:when test="self::xref and @x:fmt"> <xsl:choose> <xsl:when test="@x:fmt='()'">parens</xsl:when> <xsl:when test="@x:fmt='of'">of</xsl:when> <xsl:when test="@x:fmt=','">comma</xsl:when> <xsl:when test="@x:fmt='none'">none</xsl:when> <xsl:when test="@x:fmt='sec'">section</xsl:when> <xsl:when test="@x:fmt='number'">bare</xsl:when> <xsl:otherwise> <xsl:call-template name="warning"> <xsl:with-param name="msg">unknown value '<xsl:value-of select="@x:fmt"/>' for @x:fmt</xsl:with-param> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:when> <xsl:otherwise> <xsl:value-of select="$default"/> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="get-section-xref-section"> <xsl:choose> <xsl:when test="@section"> <xsl:value-of select="@section"/> </xsl:when> <xsl:when test="@x:sec"> <xsl:value-of select="@x:sec"/> </xsl:when> <xsl:otherwise/> </xsl:choose> </xsl:template> <xsl:key name="iref-xanch" match="iref[@x:for-anchor]" use="@x:for-anchor"/> <!-- xref to section or appendix --> <xsl:template name="xref-to-section"> <xsl:param name="from"/> <xsl:param name="to"/> <xsl:param name="id"/> <xsl:param name="irefs"/> <xsl:param name="child-nodes"/> <xsl:choose> <xsl:when test="$child-nodes and not($from/@format='none') and $xml2rfc-ext-xref-with-text-generate!='nothing'"> <xsl:apply-templates select="$child-nodes"/> <xsl:text> (</xsl:text> <a href="#{$from/@target}"> <xsl:if test="$irefs"> <!-- insert id when a backlink to this xref is needed in the index --> <xsl:attribute name="id"><xsl:value-of select="$id"/></xsl:attribute> </xsl:if> <xsl:attribute name="title"> <xsl:call-template name="get-title-as-string"> <xsl:with-param name="node" select="$to"/> </xsl:call-template> </xsl:attribute> <xsl:call-template name="render-section-ref"> <xsl:with-param name="from" select="$from"/> <xsl:with-param name="to" select="$to"/> </xsl:call-template> </a> <xsl:text>)</xsl:text> </xsl:when> <xsl:otherwise> <a href="#{$from/@target}"> <xsl:if test="$irefs"> <!-- insert id when a backlink to this xref is needed in the index --> <xsl:attribute name="id"><xsl:value-of select="$id"/></xsl:attribute> </xsl:if> <xsl:attribute name="title"> <xsl:call-template name="get-title-as-string"> <xsl:with-param name="node" select="$to"/> </xsl:call-template> </xsl:attribute> <xsl:call-template name="render-section-ref"> <xsl:with-param name="from" select="$from"/> <xsl:with-param name="to" select="$to"/> <xsl:with-param name="child-nodes" select="$child-nodes"/> </xsl:call-template> </a> </xsl:otherwise> </xsl:choose> </xsl:template> <!-- xref to figure --> <xsl:template name="xref-to-figure-text"> <xsl:param name="from"/> <xsl:param name="to"/> <xsl:param name="child-nodes"/> <xsl:variable name="figcnt"> <xsl:for-each select="$to"> <xsl:call-template name="get-figure-number"/> </xsl:for-each> </xsl:variable> <xsl:choose> <xsl:when test="$child-nodes"> <xsl:apply-templates select="$child-nodes" /> </xsl:when> <xsl:when test="$from/@format='counter'"> <xsl:value-of select="$figcnt" /> </xsl:when> <xsl:when test="$from/@format='none'"> <!-- Nothing to do --> </xsl:when> <xsl:when test="$from/@format='title'"> <xsl:choose> <xsl:when test="$to/name"> <xsl:call-template name="render-name-ref"> <xsl:with-param name="n" select="$to/name/node()"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:value-of select="normalize-space($to/@title)" /> </xsl:otherwise> </xsl:choose> </xsl:when> <xsl:otherwise> <xsl:value-of select="normalize-space(concat('Figure ',$figcnt))"/> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="xref-to-figure"> <xsl:param name="from"/> <xsl:param name="to"/> <xsl:param name="child-nodes"/> <xsl:variable name="title"> <xsl:call-template name="get-title-as-string"> <xsl:with-param name="node" select="$to"/> </xsl:call-template> </xsl:variable> <a href="#{$from/@target}"> <xsl:if test="$title!=''"> <xsl:attribute name="title"> <xsl:value-of select="$title"/> </xsl:attribute> </xsl:if> <xsl:call-template name="xref-to-figure-text"> <xsl:with-param name="from" select="$from"/> <xsl:with-param name="to" select="$to"/> <xsl:with-param name="child-nodes" select="$child-nodes"/> </xsl:call-template> </a> </xsl:template> <!-- xref to table --> <xsl:template name="xref-to-table-text"> <xsl:param name="from"/> <xsl:param name="to"/> <xsl:param name="child-nodes"/> <xsl:variable name="tabcnt"> <xsl:for-each select="$to"> <xsl:call-template name="get-table-number"/> </xsl:for-each> </xsl:variable> <xsl:choose> <xsl:when test="$child-nodes"> <xsl:apply-templates select="$child-nodes"/> </xsl:when> <xsl:when test="$from/@format='counter'"> <xsl:value-of select="$tabcnt" /> </xsl:when> <xsl:when test="$from/@format='none'"> <!-- Nothing to do --> </xsl:when> <xsl:when test="$from/@format='title'"> <xsl:choose> <xsl:when test="$to/self::table"> <xsl:call-template name="render-name-ref"> <xsl:with-param name="n" select="$to/name/node()"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:value-of select="$to/@title" /> </xsl:otherwise> </xsl:choose> </xsl:when> <xsl:otherwise> <xsl:value-of select="normalize-space(concat('Table ',$tabcnt))"/> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="xref-to-table"> <xsl:param name="from"/> <xsl:param name="to"/> <xsl:param name="child-nodes"/> <xsl:variable name="title"> <xsl:call-template name="get-title-as-string"> <xsl:with-param name="node" select="$to"/> </xsl:call-template> </xsl:variable> <a href="#{$from/@target}"> <xsl:if test="$title!=''"> <xsl:attribute name="title"> <xsl:value-of select="$title"/> </xsl:attribute> </xsl:if> <xsl:call-template name="xref-to-table-text"> <xsl:with-param name="from" select="$from"/> <xsl:with-param name="to" select="$to"/> <xsl:with-param name="child-nodes" select="$child-nodes"/> </xsl:call-template> </a> </xsl:template> <!-- xref to paragraph --> <xsl:template name="xref-to-paragraph-text"> <xsl:param name="from"/> <xsl:param name="to"/> <xsl:param name="child-nodes"/> <xsl:variable name="tcnt"> <xsl:for-each select="$to"> <xsl:call-template name="get-paragraph-number" /> </xsl:for-each> </xsl:variable> <xsl:variable name="pparent" select="$to/.."/> <xsl:variable name="listtype"> <xsl:choose> <xsl:when test="$pparent/self::list"> <xsl:value-of select="$pparent/@style"/> </xsl:when> <xsl:when test="$pparent/self::dl">definition</xsl:when> <xsl:when test="$pparent/self::ol[@type='a']">letters</xsl:when> <xsl:when test="$pparent/self::ol[@type='A']">Letters</xsl:when> <xsl:when test="$pparent/self::ol[@type='i']">rnumbers</xsl:when> <xsl:when test="$pparent/self::ol[@type='I']">Rnumbers</xsl:when> <xsl:when test="$pparent/self::ol[string-length(@type)>1]">format <xsl:value-of select="$pparent/self::ol/@type"/></xsl:when> <xsl:when test="$pparent/self::ol">numbers</xsl:when> <xsl:otherwise></xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:variable name="s"> <xsl:choose> <xsl:when test="$pparent/self::ol and $pparent/@group"> <xsl:call-template name="ol-start"> <xsl:with-param name="node" select="$pparent"/> </xsl:call-template> </xsl:when> <xsl:when test="$pparent/self::list and $pparent/@counter"> <xsl:for-each select="$pparent"> <xsl:value-of select="1 + count(preceding::list[@counter=$pparent/@counter]/*)"/> </xsl:for-each> </xsl:when> <xsl:when test="$pparent/self::ol and $pparent/@start"> <xsl:value-of select="$pparent/@start"/> </xsl:when> <xsl:otherwise>1</xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:variable name="n"> <xsl:for-each select="$to"> <xsl:number/> </xsl:for-each> </xsl:variable> <xsl:variable name="format"> <xsl:choose> <xsl:when test="$listtype='letters'">a</xsl:when> <xsl:when test="$listtype='Letters'">A</xsl:when> <xsl:when test="$listtype='rnumbers'">i</xsl:when> <xsl:when test="$listtype='Rnumbers'">I</xsl:when> <xsl:otherwise>1</xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:variable name="listindex"> <xsl:choose> <xsl:when test="starts-with($listtype,'format ')"> <xsl:call-template name="expand-format-percent"> <xsl:with-param name="format" select="substring-after($listtype,'format ')"/> <xsl:with-param name="pos" select="$n + $s - 1"/> <xsl:with-param name="item" select="$to"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:number value="$n + $s - 1" format="{$format}"/> </xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:choose> <xsl:when test="$child-nodes"> <xsl:apply-templates select="$child-nodes"/> </xsl:when> <xsl:when test="$from/@format='counter'"> <xsl:choose> <xsl:when test="$listtype!='' and $listindex!=''"> <xsl:value-of select="$listindex"/> </xsl:when> <xsl:when test="$listtype!='' and $listindex=''"> <xsl:call-template name="warning"> <xsl:with-param name="msg" select="concat('Use of format=counter for unsupported list type ',$listtype)"/> </xsl:call-template> <xsl:value-of select="$tcnt"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="$tcnt"/> </xsl:otherwise> </xsl:choose> </xsl:when> <xsl:when test="$from/@format='none'"> <!-- Nothing to do --> </xsl:when> <xsl:when test="$from/@format='title'"> <xsl:choose> <xsl:when test="$to/self::dt"> <xsl:apply-templates select="$to/node()"/> </xsl:when> <xsl:when test="$to/@hangText"> <xsl:value-of select="normalize-space($to/@hangText)"/> </xsl:when> <xsl:when test="$to/@title"> <xsl:value-of select="normalize-space($to/@title)"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="$to/@anchor"/> </xsl:otherwise> </xsl:choose> </xsl:when> <xsl:otherwise> <xsl:variable name="pn" select="normalize-space(substring-after($tcnt,'p.'))"/> <xsl:text>Paragraph </xsl:text> <xsl:choose> <xsl:when test="$pn=''"> <xsl:text>?</xsl:text> <xsl:call-template name="warning"> <xsl:with-param name="msg" select="concat('No paragraph number for link target ',$from/@target)"/> <xsl:with-param name="node" select="$from"/> </xsl:call-template> </xsl:when> <xsl:otherwise><xsl:value-of select="$pn"/></xsl:otherwise> </xsl:choose> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="xref-to-paragraph"> <xsl:param name="from"/> <xsl:param name="to"/> <xsl:param name="anchor"/> <xsl:param name="child-nodes"/> <a href="#{$anchor}"> <xsl:call-template name="xref-to-paragraph-text"> <xsl:with-param name="from" select="$from"/> <xsl:with-param name="to" select="$to"/> <xsl:with-param name="child-nodes" select="$child-nodes"/> </xsl:call-template> </a> </xsl:template> <!-- xref to comment --> <xsl:template name="xref-to-comment"> <xsl:param name="from"/> <xsl:param name="to"/> <xsl:param name="child-nodes"/> <xsl:call-template name="emit-link"> <xsl:with-param name="target" select="concat('#',$from/@target)"/> <xsl:with-param name="text"> <xsl:variable name="name"> <xsl:for-each select="$to"> <xsl:call-template name="get-comment-name" /> </xsl:for-each> </xsl:variable> <xsl:choose> <xsl:when test="$child-nodes"> <!-- no auto text --> </xsl:when> <xsl:when test="$from/@format='counter'"> <xsl:call-template name="error"> <xsl:with-param name="inline">no</xsl:with-param> <xsl:with-param name="msg">xref to cref with format='counter' not allowed</xsl:with-param> <xsl:with-param name="node" select="$from"/> </xsl:call-template> <xsl:value-of select="$name" /> </xsl:when> <xsl:when test="$from/@format='none'"> <!-- Nothing to do --> </xsl:when> <xsl:when test="$from/@format='title'"> <xsl:value-of select="$to/@anchor"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="normalize-space(concat('Comment ',$name))"/> </xsl:otherwise> </xsl:choose> </xsl:with-param> <xsl:with-param name="child-nodes" select="$child-nodes"/> </xsl:call-template> </xsl:template> <xsl:template name="emit-link"> <xsl:param name="target"/> <xsl:param name="id"/> <xsl:param name="title"/> <xsl:param name="citation-title"/> <xsl:param name="index-item"/> <xsl:param name="index-subitem"/> <xsl:param name="text"/> <xsl:param name="child-nodes"/> <xsl:if test="$text!='' and $child-nodes"> <xsl:call-template name="warning"> <xsl:with-param name="msg">emit-link called both with text and child-nodes</xsl:with-param> </xsl:call-template> </xsl:if> <xsl:variable name="element"> <xsl:choose> <xsl:when test="$target!=''">a</xsl:when> <xsl:when test="$citation-title!=''">cite</xsl:when> <xsl:when test="($id!='' and $xml2rfc-ext-include-references-in-index='yes') or $title!=''">span</xsl:when> <xsl:otherwise/> </xsl:choose> </xsl:variable> <xsl:choose> <xsl:when test="$element!=''"> <xsl:element name="{$element}"> <xsl:if test="$target!=''"> <xsl:attribute name="href"><xsl:value-of select="$target"/></xsl:attribute> </xsl:if> <xsl:if test="$element='cite' and $citation-title!=''"> <xsl:attribute name="title"><xsl:value-of select="$citation-title"/></xsl:attribute> </xsl:if> <xsl:if test="$id!='' and $xml2rfc-ext-include-references-in-index='yes'"> <xsl:attribute name="id"><xsl:value-of select="$id"/></xsl:attribute> </xsl:if> <xsl:if test="$title!=''"> <xsl:attribute name="title"><xsl:value-of select="$title"/></xsl:attribute> </xsl:if> <xsl:choose> <xsl:when test="$element!='cite' and $citation-title!=''"> <cite title="{$citation-title}"> <xsl:choose> <xsl:when test="$child-nodes"> <xsl:apply-templates select="$child-nodes"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="$text"/> </xsl:otherwise> </xsl:choose> </cite> </xsl:when> <xsl:otherwise> <xsl:choose> <xsl:when test="$child-nodes"> <xsl:apply-templates select="$child-nodes"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="$text"/> </xsl:otherwise> </xsl:choose> </xsl:otherwise> </xsl:choose> </xsl:element> </xsl:when> <xsl:otherwise> <xsl:choose> <xsl:when test="$child-nodes"> <xsl:apply-templates select="$child-nodes"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="$text"/> </xsl:otherwise> </xsl:choose> </xsl:otherwise> </xsl:choose> </xsl:template> <!-- xref to reference --> <xsl:template name="xref-to-reference"> <xsl:param name="from"/> <xsl:param name="to"/> <xsl:param name="id"/> <xsl:param name="child-nodes"/> <xsl:variable name="front" select="$to/front[1]|document($to/x:source/@href)/rfc/front[1]"/> <xsl:variable name="is-xref" select="$from/self::xref"/> <xsl:variable name="sfmt"> <xsl:for-each select="$from"> <xsl:call-template name="get-section-xref-format"> <xsl:with-param name="default"> <xsl:choose> <xsl:when test="ancestor::artwork or ancestor::sourcecode">comma</xsl:when> <xsl:otherwise>of</xsl:otherwise> </xsl:choose> </xsl:with-param> </xsl:call-template> </xsl:for-each> </xsl:variable> <xsl:variable name="ssec"> <xsl:for-each select="$from"> <xsl:call-template name="get-section-xref-section"/> </xsl:for-each> </xsl:variable> <!-- check normative/informative --> <xsl:variable name="t-is-normative" select="$from/ancestor-or-self::*[@x:nrm][1]"/> <xsl:variable name="is-normative" select="$t-is-normative/@x:nrm='true'"/> <xsl:if test="count($to)=1 and $is-normative"> <xsl:variable name="t-r-is-normative" select="$to/ancestor-or-self::*[@x:nrm][1]"/> <xsl:variable name="r-is-normative" select="$t-r-is-normative/@x:nrm='true'"/> <xsl:if test="not($r-is-normative)"> <xsl:for-each select="$from"> <xsl:call-template name="warning"> <xsl:with-param name="msg" select="concat('Potentially normative reference to ',$from/@target,' not referenced normatively')"/> </xsl:call-template> </xsl:for-each> </xsl:if> </xsl:if> <xsl:variable name="href"> <xsl:call-template name="computed-target"> <xsl:with-param name="bib" select="$to"/> <xsl:with-param name="ref" select="$from"/> </xsl:call-template> </xsl:variable> <xsl:variable name="tsec"> <xsl:choose> <xsl:when test="starts-with($from/@x:rel,'#') and $ssec=''"> <xsl:call-template name="compute-section-number"> <xsl:with-param name="bib" select="$to"/> <xsl:with-param name="ref" select="$from"/> </xsl:call-template> </xsl:when> <xsl:when test="$from/@x:rel and not(starts-with($from/@x:rel,'#')) and $ssec=''"> <xsl:call-template name="error"> <xsl:with-param name="msg">x:rel attribute '<xsl:value-of select="$from/@x:rel"/>' in reference to <xsl:value-of select="$to/@anchor"/> is expected to start with '#'.</xsl:with-param> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:value-of select="$ssec"/> </xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:variable name="sec"> <xsl:choose> <xsl:when test="contains($tsec,'@')">"<xsl:value-of select="substring-after($tsec,'@')"/>"</xsl:when> <xsl:otherwise><xsl:value-of select="$tsec"/></xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:variable name="secterm"> <xsl:variable name="before-dot"> <xsl:choose> <xsl:when test="contains($sec,'.')"> <xsl:value-of select="substring-before($sec,'.')"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="$sec"/> </xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:variable name="after-dot" select="substring-after($sec,'.')"/> <xsl:choose> <xsl:when test="translate($sec,'.0123456789','')='' or starts-with($tsec,'S@')">Section</xsl:when> <xsl:when test="(translate($before-dot,$ucase,'')='' and translate($after-dot,'.0123456789','')='') or starts-with($tsec,'A@')">Appendix</xsl:when> <xsl:otherwise>Part</xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:variable name="title"> <xsl:choose> <xsl:when test="starts-with($from/@x:rel,'#') and $ssec='' and $to/x:source/@href"> <xsl:variable name="extdoc" select="document($to/x:source/@href)"/> <xsl:variable name="anch" select="substring-after($from//@x:rel,'#')"/> <xsl:variable name="nodes" select="$extdoc//*[@anchor=$anch or x:anchor-alias/@value=$anch]"/> <xsl:if test="not($nodes)"> <xsl:call-template name="error"> <xsl:with-param name="msg">Anchor '<xsl:value-of select="substring-after($from//@x:rel,'#')"/>' not found in <xsl:value-of select="$to/x:source/@href"/>.</xsl:with-param> <xsl:with-param name="node" select="$from"/> </xsl:call-template> </xsl:if> <xsl:for-each select="$nodes"> <xsl:value-of select="@title"/> </xsl:for-each> </xsl:when> <xsl:otherwise /> </xsl:choose> </xsl:variable> <!-- Formats: parens [XXXX] (Section SS) comma [XXXX], Section SS of Section SS of [XXXX] sec Section SS number SS --> <xsl:if test="$sfmt!='' and not($sfmt='of' or $sfmt='section' or $sfmt='bare' or $sfmt='parens' or $sfmt='comma' or $sfmt='none')"> <xsl:call-template name="error"> <xsl:with-param name="msg" select="concat('unknown xref section format extension: ',$sfmt)"/> </xsl:call-template> </xsl:if> <xsl:if test="$sec!=''"> <xsl:choose> <xsl:when test="$sfmt='of'"> <xsl:call-template name="emit-link"> <xsl:with-param name="target" select="$href"/> <xsl:with-param name="text" select="concat($secterm,' ',$sec)"/> <xsl:with-param name="title" select="$title"/> </xsl:call-template> <xsl:text> of </xsl:text> </xsl:when> <xsl:when test="$sfmt='section'"> <xsl:call-template name="emit-link"> <xsl:with-param name="target" select="$href"/> <xsl:with-param name="text" select="concat($secterm,' ',$sec)"/> <xsl:with-param name="title" select="$title"/> <xsl:with-param name="id"> <xsl:if test="$sfmt='section'"> <xsl:value-of select="$id"/> </xsl:if> </xsl:with-param> <xsl:with-param name="index-item" select="$from/@target"/> <xsl:with-param name="index-subitem" select="$sec"/> </xsl:call-template> </xsl:when> <xsl:when test="$sfmt='bare'"> <xsl:call-template name="emit-link"> <xsl:with-param name="target" select="$href"/> <xsl:with-param name="text" select="$sec"/> <xsl:with-param name="title" select="$title"/> <xsl:with-param name="id" select="$id"/> <xsl:with-param name="index-item" select="$from/@target"/> <xsl:with-param name="index-subitem" select="$sec"/> </xsl:call-template> </xsl:when> <xsl:otherwise /> </xsl:choose> </xsl:if> <xsl:if test="$sec='' or ($sfmt!='section' and $sfmt!='bare')"> <xsl:call-template name="emit-link"> <xsl:with-param name="target"> <xsl:if test="$sfmt!='none'"> <xsl:value-of select="concat('#',$from/@target)"/> </xsl:if> </xsl:with-param> <xsl:with-param name="text"> <xsl:variable name="val"> <xsl:call-template name="reference-name"> <xsl:with-param name="node" select="$to" /> </xsl:call-template> </xsl:variable> <xsl:choose> <xsl:when test="$child-nodes"> <!-- nothing to do here --> </xsl:when> <xsl:when test="$is-xref and $from/@format='none'"> <!-- nothing to do here --> </xsl:when> <xsl:when test="$is-xref and $from/@format='counter' and $sec=''"> <xsl:call-template name="error"> <xsl:with-param name="inline">no</xsl:with-param> <xsl:with-param name="msg">xref to reference with format='counter' not allowed</xsl:with-param> <xsl:with-param name="node" select="$from"/> </xsl:call-template> <!-- remove brackets --> <xsl:value-of select="substring($val,2,string-length($val)-2)"/> </xsl:when> <xsl:when test="$is-xref and $from/@format='title'"> <xsl:choose> <xsl:when test="$to/self::referencegroup"> <xsl:value-of select="$to/@anchor"/> </xsl:when> <xsl:otherwise> <xsl:apply-templates select="$front[1]/title/node()" mode="get-text-content"/> </xsl:otherwise> </xsl:choose> </xsl:when> <xsl:otherwise> <xsl:if test="not($is-xref) and $from/@format"> <xsl:call-template name="warning"> <xsl:with-param name="msg">@format attribute is undefined for relref</xsl:with-param> </xsl:call-template> </xsl:if> <xsl:value-of select="$val"/> </xsl:otherwise> </xsl:choose> </xsl:with-param> <xsl:with-param name="id" select="$id"/> <xsl:with-param name="index-item" select="$from/@target"/> <xsl:with-param name="index-subitem" select="$sec"/> <xsl:with-param name="citation-title" select="normalize-space($front[1]/title)"/> <xsl:with-param name="child-nodes" select="$child-nodes"/> </xsl:call-template> <xsl:if test="$child-nodes and not($from/@format='none' or $from/@x:fmt='none' or $xml2rfc-ext-xref-with-text-generate='nothing')"> <xsl:text> </xsl:text> <xsl:call-template name="emit-link"> <xsl:with-param name="citation-title" select="normalize-space($front[1]/title)"/> <xsl:with-param name="text"> <xsl:call-template name="reference-name"> <xsl:with-param name="node" select="$to" /> </xsl:call-template> </xsl:with-param> </xsl:call-template> </xsl:if> </xsl:if> <xsl:if test="$sec!=''"> <xsl:choose> <xsl:when test="$sfmt='parens'"> <xsl:text> (</xsl:text> <xsl:call-template name="emit-link"> <xsl:with-param name="target" select="$href"/> <xsl:with-param name="text" select="concat($secterm,' ',$sec)"/> <xsl:with-param name="title" select="$title"/> </xsl:call-template> <xsl:text>)</xsl:text> </xsl:when> <xsl:when test="$sfmt='comma'"> <xsl:text>, </xsl:text> <xsl:call-template name="emit-link"> <xsl:with-param name="target" select="$href"/> <xsl:with-param name="text" select="concat($secterm,' ',$sec)"/> <xsl:with-param name="title" select="$title"/> </xsl:call-template> </xsl:when> <xsl:otherwise/> </xsl:choose> </xsl:if> </xsl:template> <xsl:template name="get-target-anchor"> <xsl:variable name="xref" select="."/> <xsl:for-each select="$src"> <xsl:variable name="tn" select="key('anchor-item',$xref/@target)|exslt:node-set($includeDirectives)//reference[@anchor=$xref/@target]"/> <xsl:for-each select="$src"> <xsl:choose> <xsl:when test="$tn/parent::artset and $tn/../@anchor"> <xsl:value-of select="$tn/../@anchor"/> </xsl:when> <xsl:when test="$tn/parent::artset and $tn/../artwork/@anchor"> <xsl:value-of select="$tn/../artwork[@anchor][1]/@anchor"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="$xref/@target"/> </xsl:otherwise> </xsl:choose> </xsl:for-each> </xsl:for-each> </xsl:template> <xsl:template match="xref|relref"> <xsl:variable name="xref" select="."/> <xsl:variable name="textContent"> <xsl:apply-templates select="node()"/> </xsl:variable> <xsl:variable name="useTextContent" select="normalize-space($textContent)!=''"/> <xsl:variable name="childNodes" select="node()[$useTextContent]"/> <xsl:variable name="target"> <xsl:call-template name="get-target-anchor"/> </xsl:variable> <xsl:if test="@target!=$target"> <xsl:call-template name="info"> <xsl:with-param name="msg">Target '<xsl:value-of select="@target"/>' rewritten to '<xsl:value-of select="$target"/>'.</xsl:with-param> </xsl:call-template> </xsl:if> <xsl:if test="self::relref"> <xsl:call-template name="warning"> <xsl:with-param name="msg"><relref> is deprecated; use <xref> extensions instead.</xsl:with-param> </xsl:call-template> </xsl:if> <xsl:variable name="anchor"><xsl:value-of select="$anchor-pref"/>xref.<xsl:value-of select="$target"/>.<xsl:number level="any" count="xref[@target=$target]|relref[@target=$target]"/></xsl:variable> <!-- ensure we have the right context, this <xref> may be processed from within the boilerplate --> <xsl:for-each select="$src"> <xsl:variable name="node" select="key('anchor-item',$target)|exslt:node-set($includeDirectives)//*[self::reference or self::referencegroup][@anchor=$target]"/> <xsl:if test="count($node)=0 and not($node/ancestor::ed:del)"> <xsl:for-each select="$xref"> <xsl:choose> <xsl:when test="not($xref/@target)"> <xsl:variable name="present"> <xsl:for-each select="$xref/@*"> <xsl:text> @</xsl:text> <xsl:value-of select="local-name(.)"/> </xsl:for-each> </xsl:variable> <xsl:call-template name="error"> <xsl:with-param name="msg">Undefined target: no @target attribute specified<xsl:if test="$present!=''"> (attributes found:<xsl:value-of select="$present"/>)</xsl:if></xsl:with-param> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:call-template name="error"> <xsl:with-param name="msg">Undefined target: '<xsl:value-of select="$xref/@target"/>'</xsl:with-param> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:for-each> </xsl:if> <xsl:choose> <!-- handle misuse of relref --> <xsl:when test="$xref/self::relref and not($xref/@section)"> <xsl:call-template name="error"> <xsl:with-param name="msg"><relref> requires @section attribute</xsl:with-param> <xsl:with-param name="node" select="$xref"/> </xsl:call-template> </xsl:when> <xsl:when test="$xref/self::relref and not($node/self::reference)"> <xsl:call-template name="error"> <xsl:with-param name="msg"><relref> @target must be a reference</xsl:with-param> <xsl:with-param name="node" select="$xref"/> </xsl:call-template> </xsl:when> <!-- Section links --> <xsl:when test="$node/self::section or $node/self::appendix or $node/self::references or $node/self::abstract or $node/self::note"> <!-- index links to this xref --> <xsl:variable name="ireftargets" select="key('iref-xanch',$target) | key('iref-xanch','')[../@anchor=$target]"/> <xsl:call-template name="xref-to-section"> <xsl:with-param name="from" select="$xref"/> <xsl:with-param name="to" select="$node"/> <xsl:with-param name="id" select="$anchor"/> <xsl:with-param name="irefs" select="$ireftargets"/> <xsl:with-param name="child-nodes" select="$childNodes"/> </xsl:call-template> </xsl:when> <!-- Figure links --> <xsl:when test="$node/self::figure"> <xsl:call-template name="xref-to-figure"> <xsl:with-param name="from" select="$xref"/> <xsl:with-param name="to" select="$node"/> <xsl:with-param name="child-nodes" select="$childNodes"/> </xsl:call-template> </xsl:when> <!-- Table links --> <xsl:when test="$node/self::texttable or $node/self::table"> <xsl:call-template name="xref-to-table"> <xsl:with-param name="from" select="$xref"/> <xsl:with-param name="to" select="$node"/> <xsl:with-param name="child-nodes" select="$childNodes"/> </xsl:call-template> </xsl:when> <!-- Paragraph links --> <xsl:when test="$node/self::t or $node/self::aside or $node/self::x:note or $node/self::blockquote or $node/self::x:blockquote or $node/self::dl or $node/self::ol or $node/self::ul or $node/self::dd or $node/self::dt or $node/self::li or $node/self::artwork or $node/self::sourcecode or $node/self::artset"> <xsl:call-template name="xref-to-paragraph"> <xsl:with-param name="from" select="$xref"/> <xsl:with-param name="to" select="$node"/> <xsl:with-param name="anchor" select="$target"/> <xsl:with-param name="child-nodes" select="$childNodes"/> </xsl:call-template> </xsl:when> <!-- Comment links --> <xsl:when test="$node/self::cref"> <xsl:choose> <xsl:when test="$node/@display='false'"> <xsl:call-template name="error"> <xsl:with-param name="msg" select="concat('Comment ',$node/@anchor,' is hidden and thus can not be referenced')"/> <xsl:with-param name="node" select="$xref"/> </xsl:call-template> </xsl:when> <xsl:when test="$xml2rfc-comments!='no'"> <xsl:call-template name="xref-to-comment"> <xsl:with-param name="from" select="$xref"/> <xsl:with-param name="to" select="$node"/> <xsl:with-param name="child-nodes" select="$childNodes"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:call-template name="error"> <xsl:with-param name="msg">xref to cref, but comments aren't included in the output</xsl:with-param> <xsl:with-param name="node" select="$xref"/> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:when> <!-- Reference links --> <xsl:when test="$node/self::reference or $node/self::referencegroup"> <xsl:call-template name="xref-to-reference"> <xsl:with-param name="from" select="$xref"/> <xsl:with-param name="to" select="$node"/> <xsl:with-param name="id" select="$anchor"/> <xsl:with-param name="child-nodes" select="$childNodes"/> </xsl:call-template> </xsl:when> <!-- Other elements we can link to if we have text content --> <xsl:when test="$childNodes and ($node/self::spanx or $node/self::strong)"> <xsl:call-template name="emit-link"> <xsl:with-param name="target" select="concat('#',$target)"/> <xsl:with-param name="id" select="$anchor"/> <xsl:with-param name="child-nodes" select="$childNodes"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:if test="$node"> <xsl:call-template name="error"> <xsl:with-param name="msg" select="concat('xref to unknown element: ',name($node))"/> <xsl:with-param name="node" select="$xref"/> </xsl:call-template> </xsl:if> </xsl:otherwise> </xsl:choose> </xsl:for-each> </xsl:template> <!-- mark unmatched elements red --> <xsl:template match="*"> <xsl:call-template name="error"> <xsl:with-param name="inline" select="'no'"/> <xsl:with-param name="msg">no XSLT template for element '<xsl:value-of select="name()"/>'</xsl:with-param> </xsl:call-template> <span class="tt {$css-error}"><<xsl:value-of select="name()" />></span> <xsl:copy><xsl:apply-templates select="node()|@*" /></xsl:copy> <span class="tt {$css-error}"></<xsl:value-of select="name()" />></span> </xsl:template> <xsl:template match="/"> <xsl:apply-templates select="*" mode="validate"/> <xsl:apply-templates select="*" /> </xsl:template> <!-- utility templates --> <xsl:template name="collectLeftHeaderColumn"> <!-- default case --> <xsl:if test="$xml2rfc-private=''"> <xsl:if test="count(/rfc/front/workgroup)>1"> <xsl:call-template name="error"> <xsl:with-param name="inline">no</xsl:with-param> <xsl:with-param name="msg">There are multiple /rfc/front/workgroup elements; ignoring all but the first</xsl:with-param> </xsl:call-template> </xsl:if> <xsl:for-each select="/rfc/front/workgroup"> <xsl:variable name="v" select="normalize-space(.)"/> <xsl:if test="translate($v, $ucase, $lcase)='internet engineering task force' or $v=''"> <xsl:call-template name="warning"> <xsl:with-param name="msg">'<xsl:value-of select="$v"/>' definitively is not the name of a Working Group</xsl:with-param> </xsl:call-template> </xsl:if> </xsl:for-each> <xsl:choose> <xsl:when test="$is-rfc and $header-format='2010' and $submissionType='independent'"> <myns:item>Independent Submission</myns:item> </xsl:when> <xsl:when test="$is-rfc and $header-format='2010' and $submissionType='IETF'"> <myns:item>Internet Engineering Task Force (IETF)</myns:item> </xsl:when> <xsl:when test="$is-rfc and $header-format='2010' and $submissionType='IRTF'"> <myns:item>Internet Research Task Force (IRTF)</myns:item> </xsl:when> <xsl:when test="$is-rfc and $header-format='2010' and $submissionType='IAB'"> <myns:item>Internet Architecture Board (IAB)</myns:item> </xsl:when> <xsl:when test="/rfc/front/workgroup and (not($is-rfc) or $rfcno='')"> <xsl:choose> <xsl:when test="starts-with(/rfc/@docName,'draft-ietf-') and $submissionType='IETF'"/> <xsl:when test="starts-with(/rfc/@docName,'draft-irft-') and $submissionType='IRTF'"/> <xsl:otherwise> <xsl:call-template name="info"> <xsl:with-param name="msg">The /rfc/front/workgroup should only be used for Working/Research Group drafts</xsl:with-param> </xsl:call-template> </xsl:otherwise> </xsl:choose> <xsl:for-each select="/rfc/front/workgroup"> <xsl:variable name="v" select="normalize-space(.)"/> <xsl:variable name="tmp" select="translate($v, $ucase, $lcase)"/> <xsl:if test="contains($tmp,' research group') or contains($tmp,' working group')"> <xsl:call-template name="info"> <xsl:with-param name="msg">No need to include 'Working Group' or 'Research Group' postfix in /rfc/front/workgroup value '<xsl:value-of select="$v"/>'</xsl:with-param> </xsl:call-template> </xsl:if> <xsl:variable name="real-ietf-wg"> <xsl:if test="starts-with(/rfc/@docName,'draft-ietf-') and $submissionType='IETF'"> <xsl:value-of select="substring-before(substring-after(/rfc/@docName,'draft-ietf-'),'-')"/> </xsl:if> </xsl:variable> <xsl:variable name="h"> <!-- when a single name, append WG/RG postfix automatically --> <xsl:choose> <xsl:when test="not(contains($v, ' ')) and starts-with(/rfc/@docName,'draft-ietf-') and $submissionType='IETF'"> <xsl:value-of select="concat($v, ' Working Group')"/> </xsl:when> <xsl:when test="not(contains($v, ' ')) and starts-with(/rfc/@docName,'draft-irtf-') and $submissionType='IRTF'"> <xsl:value-of select="concat($v, ' Research Group')"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="$v"/> </xsl:otherwise> </xsl:choose> </xsl:variable> <myns:item> <xsl:choose> <xsl:when test="normalize-space($real-ietf-wg)!=''"> <xsl:variable name="specified" select="translate(substring-before($h, ' '), $ucase, $lcase)"/> <xsl:if test="$specified!='$real-ietf-wg'"> <!-- special case HTTP --> <xsl:if test="specified!='http' and $real-ietf-wg!='httpbis'"> <xsl:call-template name="warning"> <xsl:with-param name="msg">WG name '<xsl:value-of select="$v"/>' does not match the value included in the draft name (<xsl:value-of select="$real-ietf-wg"/>)</xsl:with-param> </xsl:call-template> </xsl:if> </xsl:if> <a href="https://datatracker.ietf.org/wg/{$real-ietf-wg}"><xsl:value-of select="$h"/></a> </xsl:when> <xsl:otherwise> <xsl:value-of select="$h"/> </xsl:otherwise> </xsl:choose> </myns:item> </xsl:for-each> </xsl:when> <xsl:otherwise> <xsl:if test="starts-with(/rfc/@docName,'draft-ietf-') and not(/rfc/front/workgroup)"> <xsl:call-template name="info"> <xsl:with-param name="msg">WG submissions should include a /rfc/front/workgroup element</xsl:with-param> </xsl:call-template> </xsl:if> <myns:item>Network Working Group</myns:item> </xsl:otherwise> </xsl:choose> <!-- check <area> value --> <xsl:for-each select="/rfc/front/area"> <xsl:variable name="area" select="normalize-space(.)"/> <xsl:variable name="rallowed"> <xsl:if test="$pub-yearmonth < 201509"> <ed:v>applications</ed:v> <ed:v>app</ed:v> </xsl:if> <xsl:if test="$pub-yearmonth > 201505"> <ed:v>applications and real-time</ed:v> <ed:v>art</ed:v> </xsl:if> <ed:v>general</ed:v> <ed:v>gen</ed:v> <ed:v>internet</ed:v> <ed:v>int</ed:v> <ed:v>operations and management</ed:v> <ed:v>ops</ed:v> <xsl:if test="$pub-yearmonth < 201509"> <ed:v>real-time applications and infrastructure</ed:v> <ed:v>rai</ed:v> </xsl:if> <ed:v>routing</ed:v> <ed:v>rtg</ed:v> <ed:v>security</ed:v> <ed:v>sec</ed:v> <xsl:if test="$pub-yearmonth < 202406"> <ed:v>transport</ed:v> <ed:v>tsv</ed:v> </xsl:if> <xsl:if test="$pub-yearmonth > 202402"> <ed:v>web and internet transport</ed:v> <ed:v>wit</ed:v> </xsl:if> </xsl:variable> <xsl:variable name="allowed" select="exslt:node-set($rallowed)"/> <xsl:choose> <xsl:when test="$allowed/ed:v=translate($area,$ucase,$lcase)"> <!-- ok --> </xsl:when> <xsl:otherwise> <xsl:call-template name="warning"> <xsl:with-param name="msg">Unknown IETF area: "<xsl:value-of select="$area"/>" - should be one of: <xsl:for-each select="$allowed/ed:v"> <xsl:text>"</xsl:text> <xsl:value-of select="."/> <xsl:text>"</xsl:text> <xsl:if test="position()!=last()"> <xsl:text>, </xsl:text> </xsl:if> </xsl:for-each> <xsl:text> (as of the publication date of </xsl:text> <xsl:value-of select="$pub-yearmonth"/> <xsl:text>)</xsl:text> </xsl:with-param> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:for-each> <myns:item> <xsl:choose> <xsl:when test="/rfc/@ipr and not($is-rfc)">Internet-Draft</xsl:when> <xsl:otherwise> <xsl:text>Request for Comments: </xsl:text> <xsl:value-of select="$rfcno"/> </xsl:otherwise> </xsl:choose> </myns:item> <xsl:if test="/rfc/@obsoletes!=''"> <myns:item> <xsl:text>Obsoletes: </xsl:text> <xsl:call-template name="rfclist"> <xsl:with-param name="list" select="normalize-space(/rfc/@obsoletes)" /> </xsl:call-template> <xsl:if test="not($is-rfc)"> (if approved)</xsl:if> </myns:item> </xsl:if> <xsl:if test="$stdno!='' or $bcpno!='' or $fyino!=''"> <myns:item> <xsl:choose> <xsl:when test="$bcpno!=''"> <xsl:text>BCP: </xsl:text> <xsl:variable name="uri"> <xsl:call-template name="compute-bcp-uri"> <xsl:with-param name="bcp" select="$bcpno"/> </xsl:call-template> </xsl:variable> <a href="{$uri}"><xsl:value-of select="$bcpno"/></a> </xsl:when> <xsl:when test="$fyino!=''"> <xsl:text>FYI: </xsl:text> <xsl:value-of select="$fyino"/> </xsl:when> <xsl:when test="$stdno!=''"> <xsl:text>STD: </xsl:text> <xsl:variable name="uri"> <xsl:call-template name="compute-std-uri"> <xsl:with-param name="std" select="$stdno"/> </xsl:call-template> </xsl:variable> <a href="{$uri}"><xsl:value-of select="$stdno"/></a> </xsl:when> <xsl:otherwise/> </xsl:choose> </myns:item> </xsl:if> <xsl:if test="/rfc/@updates!=''"> <myns:item> <xsl:text>Updates: </xsl:text> <xsl:call-template name="rfclist"> <xsl:with-param name="list" select="normalize-space(/rfc/@updates)" /> </xsl:call-template> <xsl:if test="not($is-rfc)"> (if approved)</xsl:if> </myns:item> </xsl:if> <myns:item> <xsl:choose> <xsl:when test="$is-rfc"> <xsl:text>Category: </xsl:text> </xsl:when> <xsl:otherwise> <xsl:text>Intended status: </xsl:text> </xsl:otherwise> </xsl:choose> <xsl:call-template name="get-category-long" /> </myns:item> <xsl:if test="/rfc/@ipr and not($is-rfc)"> <myns:item>Expires: <xsl:call-template name="expirydate" /></myns:item> </xsl:if> </xsl:if> <!-- private case --> <xsl:if test="$xml2rfc-private!=''"> <myns:item><xsl:value-of select="$xml2rfc-private" /></myns:item> </xsl:if> <xsl:if test="$header-format='2010' and $is-rfc"> <myns:item>ISSN: 2070-1721</myns:item> </xsl:if> </xsl:template> <!-- author name handling --> <xsl:template name="get-surname-from-fullname"> <xsl:param name="s"/> <xsl:variable name="n" select="normalize-space($s)"/> <xsl:choose> <xsl:when test="contains($n,' ')"> <xsl:call-template name="get-surname-from-fullname"> <xsl:with-param name="s" select="substring-after($n,' ')"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:value-of select="$n"/> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="get-author-surname"> <xsl:variable name="s" select="normalize-space(@surname)"/> <xsl:choose> <xsl:when test="$s='' and normalize-space(@fullname)!=''"> <xsl:variable name="computed"> <xsl:call-template name="get-surname-from-fullname"> <xsl:with-param name="s" select="@fullname"/> </xsl:call-template> </xsl:variable> <xsl:call-template name="info"> <xsl:with-param name="msg">author/@surname is missing for author with fullname '<xsl:value-of select="@fullname"/>', extracted as '<xsl:value-of select="normalize-space($computed)"/>'</xsl:with-param> </xsl:call-template> <xsl:value-of select="normalize-space($computed)"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="$s"/> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="get-initials-from-fullname"> <xsl:param name="s"/> <xsl:variable name="n" select="normalize-space($s)"/> <xsl:choose> <xsl:when test="contains($n,' ')"> <xsl:value-of select="substring($n,1,1)"/><xsl:text>. </xsl:text> <xsl:call-template name="get-initials-from-fullname"> <xsl:with-param name="s" select="substring-after($n,' ')"/> </xsl:call-template> </xsl:when> <xsl:otherwise/> </xsl:choose> </xsl:template> <xsl:template name="get-author-initials"> <xsl:variable name="s" select="normalize-space(@initials)"/> <xsl:choose> <xsl:when test="$s='' and normalize-space(@fullname)!='' and normalize-space(@surname)=''"> <xsl:variable name="computed"> <xsl:call-template name="get-initials-from-fullname"> <xsl:with-param name="s" select="@fullname"/> </xsl:call-template> </xsl:variable> <xsl:call-template name="info"> <xsl:with-param name="msg">author/@initials is missing for author with fullname '<xsl:value-of select="@fullname"/>', extracted as '<xsl:value-of select="normalize-space($computed)"/>'</xsl:with-param> </xsl:call-template> <xsl:value-of select="normalize-space($computed)"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="$s"/> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="collectRightHeaderColumn"> <xsl:for-each select="author"> <xsl:variable name="surname"> <xsl:call-template name="get-author-surname"/> </xsl:variable> <xsl:variable name="rawinitials"> <xsl:call-template name="get-author-initials"/> </xsl:variable> <xsl:variable name="initials"> <xsl:call-template name="format-initials"> <xsl:with-param name="initials" select="$rawinitials"/> </xsl:call-template> </xsl:variable> <xsl:variable name="truncated-initials"> <xsl:call-template name="truncate-initials"> <xsl:with-param name="initials" select="$initials"/> </xsl:call-template> </xsl:variable> <xsl:if test="$surname!=''"> <myns:item> <xsl:value-of select="$truncated-initials"/> <xsl:if test="$truncated-initials!=''"> <xsl:text> </xsl:text> </xsl:if> <xsl:value-of select="$surname" /> <xsl:if test="@asciiInitials!='' or @asciiSurname!=''"> <xsl:text> (</xsl:text> <xsl:value-of select="@asciiInitials"/> <xsl:if test="@asciiInitials!='' and @asciiSurname!=''"> </xsl:if> <xsl:value-of select="@asciiSurname"/> <xsl:text>)</xsl:text> </xsl:if> <xsl:if test="@role"> <xsl:choose> <xsl:when test="@role='editor'"> <xsl:text>, Editor</xsl:text> </xsl:when> <xsl:otherwise> <xsl:text>, </xsl:text><xsl:value-of select="@role" /> </xsl:otherwise> </xsl:choose> </xsl:if> </myns:item> </xsl:if> <xsl:variable name="org"> <xsl:choose> <xsl:when test="organization/@showOnFrontPage='false'"/> <xsl:when test="organization/@abbrev"><xsl:value-of select="organization/@abbrev"/></xsl:when> <xsl:otherwise><xsl:value-of select="organization"/></xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:variable name="orgOfFollowing"> <xsl:choose> <xsl:when test="following-sibling::*[1]/organization/@showOnFrontPage='false'"/> <xsl:when test="following-sibling::*[1]/organization/@abbrev"><xsl:value-of select="following-sibling::*[1]/organization/@abbrev" /></xsl:when> <xsl:otherwise><xsl:value-of select="following-sibling::*/organization" /></xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:if test="$org != $orgOfFollowing and $org != ''"> <myns:item> <xsl:value-of select="$org"/> <xsl:if test="organization/@ascii"> <xsl:value-of select="concat(' (',organization/@ascii,')')"/> </xsl:if> </myns:item> </xsl:if> </xsl:for-each> <myns:item> <xsl:if test="$xml2rfc-ext-pub-month!=''"> <xsl:if test="$xml2rfc-ext-pub-day!='' and /rfc/front/date/@x:include-day='true' and $is-rfc"> <xsl:value-of select="number($xml2rfc-ext-pub-day)" /> <xsl:text> </xsl:text> </xsl:if> <xsl:value-of select="$xml2rfc-ext-pub-month" /> <xsl:if test="$xml2rfc-ext-pub-day!='' and /rfc/@ipr and not($is-rfc)"> <xsl:text> </xsl:text> <xsl:value-of select="number($xml2rfc-ext-pub-day)" /> <xsl:text>,</xsl:text> </xsl:if> </xsl:if> <xsl:if test="$xml2rfc-ext-pub-month='' and $rfcno!=''"> <xsl:call-template name="error"> <xsl:with-param name="msg" select="'month missing but is required for RFCs'"/> </xsl:call-template> </xsl:if> <xsl:if test="$xml2rfc-ext-pub-day='' and /rfc/@docName and $rfcno='' and not(substring(/rfc/@docName, string-length(/rfc/@docName) - string-length('-latest') + 1) = '-latest')"> <xsl:call-template name="warning"> <xsl:with-param name="msg" select="concat('/rfc/front/date/@day appears to be missing for a historic draft dated ', $pub-yearmonth)"/> </xsl:call-template> </xsl:if> <xsl:value-of select="concat(' ',$xml2rfc-ext-pub-year)" /> </myns:item> </xsl:template> <xsl:template name="emitheader"> <xsl:param name="lc" /> <xsl:param name="rc" /> <tbody> <xsl:for-each select="$lc/myns:item | $rc/myns:item"> <xsl:variable name="pos" select="position()" /> <xsl:if test="$pos < count($lc/myns:item) + 1 or $pos < count($rc/myns:item) + 1"> <tr> <td class="{$css-left}"><xsl:call-template name="copynodes"><xsl:with-param name="nodes" select="$lc/myns:item[$pos]/node()" /></xsl:call-template></td> <td class="{$css-right}"><xsl:call-template name="copynodes"><xsl:with-param name="nodes" select="$rc/myns:item[$pos]/node()" /></xsl:call-template></td> </tr> </xsl:if> </xsl:for-each> </tbody> </xsl:template> <!-- convenience template that avoids copying namespace nodes we don't want --> <xsl:template name="copynodes"> <xsl:param name="nodes" /> <xsl:for-each select="$nodes"> <xsl:choose> <xsl:when test="namespace-uri()='http://www.w3.org/1999/xhtml'"> <xsl:element name="{name()}" namespace="{namespace-uri()}"> <xsl:copy-of select="@*|node()" /> </xsl:element> </xsl:when> <xsl:when test="self::*"> <xsl:element name="{name()}"> <xsl:copy-of select="@*|node()" /> </xsl:element> </xsl:when> <xsl:otherwise> <xsl:copy-of select="." /> </xsl:otherwise> </xsl:choose> </xsl:for-each> </xsl:template> <xsl:template name="expirydate"> <xsl:param name="in-prose"/> <xsl:choose> <xsl:when test="number($xml2rfc-ext-pub-day) >= 1"> <!-- have day of month? --> <xsl:if test="$in-prose"> <xsl:text>on </xsl:text> </xsl:if> <xsl:call-template name="normalize-date"> <xsl:with-param name="year" select="$xml2rfc-ext-pub-year"/> <xsl:with-param name="month" select="$pub-month-numeric"/> <xsl:with-param name="day" select="$xml2rfc-ext-pub-day + 185"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:if test="$in-prose"> <xsl:text>in </xsl:text> </xsl:if> <xsl:variable name="month"> <xsl:call-template name="get-month-as-num"> <xsl:with-param name="month" select="$xml2rfc-ext-pub-month"/> </xsl:call-template> </xsl:variable> <xsl:choose> <xsl:when test="string(number($month))!='NaN' and number($month) > 0 and number($month) < 7"> <xsl:call-template name="get-month-as-name"> <xsl:with-param name="month" select="number($month) + 6"/> </xsl:call-template> <xsl:text> </xsl:text> <xsl:value-of select="$xml2rfc-ext-pub-year" /> </xsl:when> <xsl:when test="string(number($month))!='NaN' and number($month) > 6 and number($month) < 13"> <xsl:call-template name="get-month-as-name"> <xsl:with-param name="month" select="number($month) - 6"/> </xsl:call-template> <xsl:text> </xsl:text> <xsl:value-of select="$xml2rfc-ext-pub-year + 1" /> </xsl:when> <xsl:otherwise>WRONG SYNTAX FOR MONTH</xsl:otherwise> </xsl:choose> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="normalize-date"> <xsl:param name="year"/> <xsl:param name="month"/> <xsl:param name="day"/> <xsl:variable name="isleap" select="(($year mod 4) = 0 and ($year mod 100 != 0)) or ($year mod 400) = 0" /> <!--<xsl:message> <xsl:value-of select="concat($year,' ',$month,' ',$day)"/> </xsl:message>--> <xsl:variable name="dim"> <xsl:choose> <xsl:when test="$month=1 or $month=3 or $month=5 or $month=7 or $month=8 or $month=10 or $month=12">31</xsl:when> <xsl:when test="$month=2 and $isleap">29</xsl:when> <xsl:when test="$month=2 and not($isleap)">28</xsl:when> <xsl:otherwise>30</xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:choose> <xsl:when test="$day > $dim and $month=12"> <xsl:call-template name="normalize-date"> <xsl:with-param name="year" select="$year + 1"/> <xsl:with-param name="month" select="1"/> <xsl:with-param name="day" select="$day - $dim"/> </xsl:call-template> </xsl:when> <xsl:when test="$day > $dim"> <xsl:call-template name="normalize-date"> <xsl:with-param name="year" select="$year"/> <xsl:with-param name="month" select="$month + 1"/> <xsl:with-param name="day" select="$day - $dim"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:call-template name="get-month-as-name"> <xsl:with-param name="month" select="$month"/> </xsl:call-template> <xsl:value-of select="concat(' ',$day,', ',$year)"/> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="get-month-as-num"> <xsl:param name="month" /> <xsl:choose> <xsl:when test="$month='January'">01</xsl:when> <xsl:when test="$month='February'">02</xsl:when> <xsl:when test="$month='March'">03</xsl:when> <xsl:when test="$month='April'">04</xsl:when> <xsl:when test="$month='May'">05</xsl:when> <xsl:when test="$month='June'">06</xsl:when> <xsl:when test="$month='July'">07</xsl:when> <xsl:when test="$month='August'">08</xsl:when> <xsl:when test="$month='September'">09</xsl:when> <xsl:when test="$month='October'">10</xsl:when> <xsl:when test="$month='November'">11</xsl:when> <xsl:when test="$month='December'">12</xsl:when> <xsl:otherwise>WRONG SYNTAX FOR MONTH</xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="get-month-as-name"> <xsl:param name="month"/> <xsl:choose> <xsl:when test="$month=1">January</xsl:when> <xsl:when test="$month=2">February</xsl:when> <xsl:when test="$month=3">March</xsl:when> <xsl:when test="$month=4">April</xsl:when> <xsl:when test="$month=5">May</xsl:when> <xsl:when test="$month=6">June</xsl:when> <xsl:when test="$month=7">July</xsl:when> <xsl:when test="$month=8">August</xsl:when> <xsl:when test="$month=9">September</xsl:when> <xsl:when test="$month=10">October</xsl:when> <xsl:when test="$month=11">November</xsl:when> <xsl:when test="$month=12">December</xsl:when> <xsl:otherwise>WRONG SYNTAX FOR MONTH</xsl:otherwise> </xsl:choose> </xsl:template> <!-- produce back section with author information --> <xsl:template name="get-authors-section-title"> <xsl:choose> <xsl:when test="count(/rfc/front/author)=1">Author's Address</xsl:when> <xsl:otherwise>Authors' Addresses</xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="get-authors-section-number"> <xsl:if test="/*/x:assign-section-number[@builtin-target='authors']"> <xsl:value-of select="/*/x:assign-section-number[@builtin-target='authors']/@number"/> </xsl:if> </xsl:template> <xsl:template name="insertAuthors"> <xsl:variable name="number"> <xsl:call-template name="get-authors-section-number"/> </xsl:variable> <xsl:if test="$number!='suppress' and $xml2rfc-authorship!='no'"> <xsl:call-template name="insert-conditional-hrule"/> <section id="{$anchor-pref}authors" class="avoidbreakinside"> <xsl:call-template name="insert-conditional-pagebreak"/> <h2> <xsl:if test="$number != ''"> <a href="#{$anchor-pref}section.{$number}" id="{$anchor-pref}section.{$number}"><xsl:value-of select="$number"/>.</a> <xsl:text> </xsl:text> </xsl:if> <a href="#{$anchor-pref}authors"><xsl:call-template name="get-authors-section-title"/></a> </h2> <xsl:apply-templates select="/rfc/front/author" /> </section> </xsl:if> </xsl:template> <!-- insert copyright statement --> <xsl:template name="insertCopyright" myns:namespaceless-elements="xml2rfc"> <boilerplate> <xsl:if test="not($no-copylong)"> <section title="Full Copyright Statement" anchor="{$anchor-pref}copyright" x:fixed-section-number="3"> <xsl:choose> <xsl:when test="$ipr-rfc3667"> <t> <xsl:choose> <xsl:when test="$ipr-rfc4748"> Copyright © The IETF Trust (<xsl:value-of select="$xml2rfc-ext-pub-year" />). </xsl:when> <xsl:otherwise> Copyright © The Internet Society (<xsl:value-of select="$xml2rfc-ext-pub-year" />). </xsl:otherwise> </xsl:choose> </t> <t> This document is subject to the rights, licenses and restrictions contained in BCP 78<xsl:if test="$submissionType='independent'"> and at <eref target="http://www.rfc-editor.org/copyright.html">http://www.rfc-editor.org/copyright.html</eref></xsl:if>, and except as set forth therein, the authors retain all their rights. </t> <t> This document and the information contained herein are provided on an “AS IS” basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY<xsl:if test="$ipr-rfc4748">, THE IETF TRUST</xsl:if> AND THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. </t> </xsl:when> <xsl:otherwise> <!-- <https://www.rfc-editor.org/rfc/rfc2026.html#section-10.4> --> <t> Copyright © The Internet Society (<xsl:value-of select="$xml2rfc-ext-pub-year" />). All Rights Reserved. </t> <t> This document and translations of it may be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implementation may be prepared, copied, published and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and this paragraph are included on all such copies and derivative works. However, this document itself may not be modified in any way, such as by removing the copyright notice or references to the Internet Society or other Internet organizations, except as needed for the purpose of developing Internet standards in which case the procedures for copyrights defined in the Internet Standards process must be followed, or as required to translate it into languages other than English. </t> <t> The limited permissions granted above are perpetual and will not be revoked by the Internet Society or its successors or assigns. </t> <t> This document and the information contained herein is provided on an “AS IS” basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. </t> </xsl:otherwise> </xsl:choose> </section> <section title="Intellectual Property" anchor="{$anchor-pref}ipr" x:fixed-section-number="4"> <xsl:choose> <xsl:when test="$ipr-rfc3667"> <t> The IETF takes no position regarding the validity or scope of any Intellectual Property Rights or other rights that might be claimed to pertain to the implementation or use of the technology described in this document or the extent to which any license under such rights might or might not be available; nor does it represent that it has made any independent effort to identify any such rights. Information on the procedures with respect to rights in RFC documents can be found in BCP 78 and BCP 79. </t> <t> Copies of IPR disclosures made to the IETF Secretariat and any assurances of licenses to be made available, or the result of an attempt made to obtain a general license or permission for the use of such proprietary rights by implementers or users of this specification can be obtained from the IETF on-line IPR repository at <eref target="http://www.ietf.org/ipr">http://www.ietf.org/ipr</eref>. </t> <t> The IETF invites any interested party to bring to its attention any copyrights, patents or patent applications, or other proprietary rights that may cover technology that may be required to implement this standard. Please address the information to the IETF at <eref target="mailto:ietf-ipr@ietf.org">ietf-ipr@ietf.org</eref>. </t> </xsl:when> <xsl:otherwise> <t> The IETF takes no position regarding the validity or scope of any intellectual property or other rights that might be claimed to pertain to the implementation or use of the technology described in this document or the extent to which any license under such rights might or might not be available; neither does it represent that it has made any effort to identify any such rights. Information on the IETF's procedures with respect to rights in standards-track and standards-related documentation can be found in BCP-11. Copies of claims of rights made available for publication and any assurances of licenses to be made available, or the result of an attempt made to obtain a general license or permission for the use of such proprietary rights by implementors or users of this specification can be obtained from the IETF Secretariat. </t> <t> The IETF invites any interested party to bring to its attention any copyrights, patents or patent applications, or other proprietary rights which may cover technology that may be required to practice this standard. Please address the information to the IETF Executive Director. </t> <xsl:if test="$xml2rfc-iprnotified='yes'"> <t> The IETF has been notified of intellectual property rights claimed in regard to some or all of the specification contained in this document. For more information consult the online list of claimed rights. </t> </xsl:if> </xsl:otherwise> </xsl:choose> </section> <xsl:choose> <xsl:when test="$no-funding"/> <xsl:when test="$funding1 and $is-rfc"> <section x:fixed-section-number="5"> <xsl:attribute name="title"> <xsl:choose> <xsl:when test="$xml2rfc-rfcedstyle='yes'">Acknowledgement</xsl:when> <xsl:otherwise>Acknowledgment</xsl:otherwise> </xsl:choose> </xsl:attribute> <t> Funding for the RFC Editor function is provided by the IETF Administrative Support Activity (IASA). </t> </section> </xsl:when> <xsl:when test="$funding0 and $is-rfc"> <section x:fixed-section-number="5"> <xsl:attribute name="title"> <xsl:choose> <xsl:when test="$xml2rfc-rfcedstyle='yes'">Acknowledgement</xsl:when> <xsl:otherwise>Acknowledgment</xsl:otherwise> </xsl:choose> </xsl:attribute> <t> Funding for the RFC Editor function is currently provided by the Internet Society. </t> </section> </xsl:when> <xsl:otherwise/> </xsl:choose> </xsl:if> </boilerplate> </xsl:template> <!-- optional scripts --> <xsl:template name="insertScripts"> <xsl:if test="$xml2rfc-ext-refresh-from!=''"> <script> var RfcRefresh = {}; RfcRefresh.NS_XHTML = "http://www.w3.org/1999/xhtml"; RfcRefresh.NS_MOZERR = "http://www.mozilla.org/newlayout/xml/parsererror.xml"; RfcRefresh.lastTxt = ""; RfcRefresh.lastEtag = ""; RfcRefresh.xslt = null; RfcRefresh.xmlsource = "<xsl:value-of select='$xml2rfc-ext-refresh-from'/>"; RfcRefresh.xsltsource = "<xsl:value-of select='$xml2rfc-ext-refresh-xslt'/>"; RfcRefresh.interval = "<xsl:value-of select='number($xml2rfc-ext-refresh-interval)'/>"; RfcRefresh.getXSLT = function() { if (! window.XSLTProcessor) { var err = document.createElement("pre"); err.className = "refreshbrowsererror <xsl:value-of select="$css-noprint"/>"; var msg = "This browser does not support the window.XSLTProcessor functionality."; err.appendChild(document.createTextNode(msg)); RfcRefresh.showMessage("refreshxmlerror", err); } else { try { var xhr = new XMLHttpRequest(); xhr.open("GET", RfcRefresh.xsltsource, true); xhr.onload = function (e) { if (xhr.readyState === 4) { RfcRefresh.xslt = new XSLTProcessor(); RfcRefresh.xslt.importStylesheet(xhr.responseXML); } } xhr.onerror = function (e) { console.error(xhr.status + " " + xhr.statusText); }; xhr.send(null); } catch (e) { var err = document.createElement("pre"); err.className = "refreshbrowsererror <xsl:value-of select="$css-noprint"/>"; var msg = "Failed to load XSLT code from <" + RfcRefresh.xsltsource + ">.\n"; msg += "Your browser might not support loading from a file: URI.\n"; msg += "Error details: " + e; err.appendChild(document.createTextNode(msg)); RfcRefresh.showMessage("refreshxmlerror", err); } } } RfcRefresh.findAndUpdate = function(olddoc, elem) { var changed = ""; var children = elem.childNodes; for (var i = 0; i != children.length; i++) { var n = children[i]; if (n.nodeType == 1) { var c = RfcRefresh.findAndUpdate(olddoc, n); if (changed == '') { changed = c; } var id = n.id; if (id != "") { var old = olddoc.getElementById(id); var newtext = n.innerHTML; if (!old) { console.debug("new " + id); } else { var oldtext = old.innerHTML; if (oldtext != newtext) { console.debug("updating " + id); old.innerHTML = n.innerHTML; if (changed == '') { changed = id; } } } } } } return changed; } RfcRefresh.findDifferences = function(olddoc, newdoc) { var changed = RfcRefresh.findAndUpdate(olddoc, newdoc.documentElement); if (changed != "") { console.debug("changed: " + changed); document.location = "#" + changed; } // final check for changes; if those were not processed earlier, // we refresh the whole document var oldtext = olddoc.documentElement.getElementsByTagName("body")[0].innerHTML; var newtext = newdoc.documentElement.getElementsByTagName("body")[0].innerHTML; if (oldtext != newtext) { console.debug("full refresh: " + newtext); olddoc.documentElement.innerHTML = newdoc.documentElement.innerHTML; } } RfcRefresh.getNodeText = function(elem) { var result = ""; var children = elem.childNodes; for (var i = 0; i != children.length; i++) { if (children[i].nodeType == 3) { result += children[i].nodeValue; } } return result; } RfcRefresh.getParserError = function(dom) { // FIREFOX if ("parsererror" == dom.documentElement.nodeName && RfcRefresh.NS_MOZERR == dom.documentElement.namespaceURI) { var errmsg = new Object(); errmsg.msg = ""; errmsg.src = ""; var children = dom.documentElement.childNodes; for (var i = 0; i != children.length; i++) { if (children[i].nodeType == 3) { errmsg.msg += children[i].nodeValue; } else if (children[i].nodeName == "sourcetext") { errmsg.src = RfcRefresh.getNodeText(children[i]); } } return errmsg; } var list = dom.getElementsByTagNameNS(RfcRefresh.NS_XHTML, "parsererror"); if (list.length != 0) { // Webkit var errmsg = new Object(); errmsg.msg = "XML parse error"; list = dom.getElementsByTagNameNS(RfcRefresh.NS_XHTML, "div"); if (list.length != 0) { errmsg.msg = RfcRefresh.getNodeText(list[0]); } return errmsg; } return null; } RfcRefresh.showMessage = function(cls, node) { // remove previous message var list = document.getElementsByClassName(cls); if (list.length != 0) { list[0].parentNode.removeChild(list[0]); } document.body.appendChild(node); } RfcRefresh.refresh = function(txt) { if (txt != RfcRefresh.lastTxt) { RfcRefresh.lastTxt = txt; // try to parse var parser = new DOMParser(); var dom = parser.parseFromString(txt, "text/xml"); var errmsg = RfcRefresh.getParserError(dom); if (errmsg != null) { var err = document.createElement("pre"); err.className = "refreshxmlerror <xsl:value-of select="$css-noprint"/>"; err.appendChild(document.createTextNode(errmsg.msg)); if (errmsg.src != null) { err.appendChild(document.createElement("hr")); err.appendChild(document.createTextNode(errmsg.src)); } RfcRefresh.showMessage("refreshxmlerror", err); } else { // find new refresh var children = dom.childNodes; for (var i = 0; i != children.length; i++) { if (children[i].nodeType == 7 && children[i].target == "rfc-ext") { var s = "<foo " + children[i].data + "/>"; var sd = parser.parseFromString(s, "text/xml"); var refresh = sd.documentElement.getAttribute("refresh-interval"); if (refresh != null && refresh != "") { refresh = parseInt(refresh, 10); if (RfcRefresh.interval != refresh) { if (Number.isNaN(refresh) || refresh < 5) { console.debug("refresh requested to be: " + refresh + " - ignored, using 5 instead."); RfcRefresh.interval = 5; } else { RfcRefresh.interval = refresh; console.debug("refresh changed to: " + refresh); } } } } } var html = RfcRefresh.xslt.transformToDocument(dom); RfcRefresh.findDifferences(document, html); } } } RfcRefresh.initRefresh = function() { RfcRefresh.getXSLT(); window.setTimeout(function(){ if (RfcRefresh.xslt != null) { var xhr = new XMLHttpRequest(); xhr.open("GET", RfcRefresh.xmlsource, true); if (RfcRefresh.lastEtag != "") { xhr.setRequestHeader("If-None-Match", RfcRefresh.lastEtag); } xhr.onload = function (e) { if (xhr.readyState === 4) { console.debug(xhr.status + " " + xhr.statusText); if (xhr.status != 304) { RfcRefresh.refresh(xhr.responseText); } RfcRefresh.lastEtag = xhr.getResponseHeader("ETag"); } } xhr.onerror = function (e) { console.error(xhr.status + " " + xhr.statusText); }; xhr.send(null); setTimeout(arguments.callee, RfcRefresh.interval * 1000); } }, RfcRefresh.interval * 1000); } </script> </xsl:if> <xsl:if test="/rfc/x:feedback"> <script> var buttonsAdded = false; function initFeedback() { var fb = document.createElement("div"); fb.className = "<xsl:value-of select="concat($css-feedback,' ',$css-noprint)"/>"; fb.setAttribute("onclick", "feedback();"); fb.appendChild(document.createTextNode("feedback")); document.body.appendChild(fb); } function feedback() { toggleButtonsToElementsByName("h2"); toggleButtonsToElementsByName("h3"); toggleButtonsToElementsByName("h4"); toggleButtonsToElementsByName("h5"); buttonsAdded = !buttonsAdded; } function toggleButtonsToElementsByName(name) { var list = document.getElementsByTagName(name); for (var i = 0; i < list.length; i++) { toggleButton(list.item(i)); } } function toggleButton(node) { if (! buttonsAdded) { // docname var template = "<xsl:call-template name="replace-substring"> <xsl:with-param name="string" select="/rfc/x:feedback/@template"/> <xsl:with-param name="replace">"</xsl:with-param> <xsl:with-param name="by">\"</xsl:with-param> </xsl:call-template>"; var id = node.getAttribute("id"); // try also parent if (id == null || id == "") { var id = node.parentNode.getAttribute("id"); } // better id available? var titlelinks = node.getElementsByTagName("a"); for (var i = 0; i < titlelinks.length; i++) { var tl = titlelinks.item(i); if (tl.getAttribute("id")) { id = tl.getAttribute("id"); } } // ref var ref = window.location.toString(); var hash = ref.indexOf("#"); if (hash != -1) { ref = ref.substring(0, hash); } if (id != null && id != "") { ref += "#" + id; } // docname var docname = "<xsl:value-of select="/rfc/@docName"/>"; // section var section = node.textContent; section = section.replace("\u00a0", " ").trim(); // build URI from template var uri = template.replace("{docname}", encodeURIComponent(docname)); uri = uri.replace("{section}", encodeURIComponent(section)); uri = uri.replace("{ref}", encodeURIComponent(ref)); var button = document.createElement("a"); button.className = "<xsl:value-of select="concat($css-fbbutton,' ',$css-noprint)"/>"; button.setAttribute("href", uri); button.appendChild(document.createTextNode("send feedback")); node.appendChild(button); } else { var buttons = node.getElementsByTagName("a"); for (var i = 0; i < buttons.length; i++) { var b = buttons.item(i); if (b.className == "<xsl:value-of select="concat($css-fbbutton,' ',$css-noprint)"/>") { node.removeChild(b); } } } }</script></xsl:if> <xsl:if test="$xml2rfc-ext-insert-metadata='yes' and ($is-rfc or $is-submitted-draft)"><script> <xsl:if test="$is-rfc"> function getMeta(rfcno, container) { var xhr = new XMLHttpRequest(); xhr.open("GET", "https://www.rfc-editor.org/rfc/rfc" + rfcno + ".json", true); xhr.onload = function (e) { if (xhr.readyState === 4) { if (xhr.status === 200) { var data = JSON.parse(xhr.response); var cont = document.getElementById(container); // empty the container while (cont.firstChild) { cont.removeChild(myNode.firstChild); } var c = data.status; if (c) { var bld = newElementWithText("b", c); cont.appendChild(bld); } else { cont.appendChild(newElementWithText("i", "(document status unknown)")); } c = data.updated_by; if (c && c.length > 0 && c[0] !== null && c[0].length > 0) { cont.appendChild(newElement("br")); cont.appendChild(newText("Updated by: ")); appendRfcLinks(cont, c); } c = data.obsoleted_by; if (c && c.length > 0 && c[0] !== null && c[0].length > 0) { cont.appendChild(newElement("br")); cont.appendChild(newText("Obsoleted by: ")); appendRfcLinks(cont, c); } c = data.errata_url; if (c) { cont.appendChild(newElement("br")); var link = newElementWithText("a", "errata"); link.setAttribute("href", c); var errata = newElementWithText("i", "This document has "); errata.appendChild(link); errata.appendChild(newText(".")); cont.appendChild(errata); } cont.style.display = "block"; } else { console.error(xhr.statusText); } } }; xhr.onerror = function (e) { console.error(xhr.status + " " + xhr.statusText); }; xhr.send(null); } function appendRfcLinks(parent, updates) { var template = "<xsl:call-template name="replace-substring"> <xsl:with-param name="string" select="$xml2rfc-ext-rfc-uri"/> <xsl:with-param name="replace">"</xsl:with-param> <xsl:with-param name="by">\"</xsl:with-param> </xsl:call-template>"; for (var i = 0; i < updates.length; i++) { var rfc = updates[i].trim().toLowerCase(); if (rfc.substring(0, 3) == "rfc") { var no = parseInt(rfc.substring(3), 10); var link = newElement("a"); link.setAttribute("href", template.replace("{rfc}", no)); link.appendChild(newText(no)); parent.appendChild(link); } else { parent.appendChild(newText(rfc)); } if (i != updates.length - 1) { parent.appendChild(newText(", ")); } } }</xsl:if><xsl:if test="$is-submitted-draft and not($is-rfc)"> function getMeta(docname, revision, container) { var xhr = new XMLHttpRequest(); var datatracker = "https://datatracker.ietf.org/doc/" + docname; xhr.open("GET", datatracker + "/doc.json", true); xhr.onload = function (e) { if (xhr.readyState === 4) { if (xhr.status === 200) { var data = JSON.parse(xhr.response); var cont = document.getElementById(container); // empty the container while (cont.firstChild) { cont.removeChild(myNode.firstChild); } if (data.rev) { cont.style.display = "block"; var bld = newElementWithText("b", "Internet Draft Status"); cont.appendChild(bld); cont.appendChild(newElement("br")); if (data.state == "RFC") { var txt = newElementWithText("i", "This document has been published as RFC - please see "); cont.appendChild(txt); var link = newElement("a"); link.setAttribute("href", datatracker); link.appendChild(newText("IETF Datatracker")); cont.appendChild(link); txt = newElementWithText("i", " for details."); cont.appendChild(txt); } else if (data.rev == revision) { var rev = newElementWithText("i", "This is the latest submitted version."); cont.appendChild(rev); } else { var rev = newElementWithText("i", "This is not the current version:"); cont.appendChild(rev); cont.appendChild(newElement("br")); var dat = ""; if (data.time) { dat = ", submitted on " + data.time.substring(0,10); } rev = newElementWithText("i", "please see version " + data.rev + dat + "."); cont.appendChild(rev); } } } else { console.error(xhr.statusText); } } }; xhr.onerror = function (e) { console.error(xhr.status + " " + xhr.statusText); }; xhr.send(null); }</xsl:if> // DOM helpers function newElement(name) { return document.createElement(name); } function newElementWithText(name, txt) { var e = document.createElement(name); e.appendChild(newText(txt)); return e; } function newText(text) { return document.createTextNode(text); } </script> </xsl:if> <script> function anchorRewrite() { <xsl:text> map = { </xsl:text> <xsl:for-each select="//x:anchor-alias"> <xsl:text>"</xsl:text> <xsl:call-template name="replace-substring"> <xsl:with-param name="string" select="@value"/> <xsl:with-param name="replace">"</xsl:with-param> <xsl:with-param name="by">\"</xsl:with-param> </xsl:call-template> <xsl:text>": "</xsl:text> <xsl:call-template name="replace-substring"> <xsl:with-param name="string" select="ancestor::*[@anchor][1]/@anchor"/> <xsl:with-param name="replace">"</xsl:with-param> <xsl:with-param name="by">\"</xsl:with-param> </xsl:call-template> <xsl:text>"</xsl:text> <xsl:if test="position()!=last()">, </xsl:if> </xsl:for-each> <xsl:text>};</xsl:text> if (window.location.hash.length >= 1) { var fragid = window.location.hash.substr(1); if (fragid) { if (! document.getElementById(fragid)) { var prefix = "<xsl:value-of select="$anchor-pref"/>"; var mapped = map[fragid]; if (mapped) { window.location.hash = mapped; } else if (fragid.indexOf("section-") == 0) { window.location.hash = prefix + "section." + fragid.substring(8).replace("-",".p."); } else if (fragid.indexOf("appendix-") == 0) { window.location.hash = prefix + "section." + fragid.substring(9).replace("-",".p."); } else if (fragid.indexOf("s-") == 0) { var postfix = fragid.substring(2); if (postfix.startsWith("abstract")) { window.location.hash = prefix + postfix; } else if (postfix.startsWith("note-")) { window.location.hash = prefix + "note." + postfix.substring(5).replace("-",".p."); } else { window.location.hash = prefix + "section." + postfix.replace("-",".p."); } } else if (fragid.indexOf("p-") == 0) { var r = fragid.substring(2); var p = r.indexOf("-"); if (p >= 0) { window.location.hash = prefix + "section." + r.substring(0, p) + ".p." + r.substring(p + 1); } } } } } } window.addEventListener('hashchange', anchorRewrite); window.addEventListener('DOMContentLoaded', anchorRewrite); </script><xsl:if test="$prettyprint-script!=''"> <script src="{$prettyprint-script}"/></xsl:if><xsl:if test="contains($prettyprint-script,'prettify') and (//artwork[contains(@type,'abnf')] or //sourcecode[contains(@type,'abnf')])"> <script><![CDATA[try { PR['registerLangHandler']( PR['createSimpleLexer']( [ // comment [PR['PR_COMMENT'], /^;[^\x00-\x1f]*/, null, ";"], ], [ // string literals [PR['PR_STRING'], /^(\%s|\%i)?"[^"\x00-\x1f]*"/, null], // binary literals [PR['PR_LITERAL'], /^\%b[01]+((-[01]+)|(\.[01]+)*)/, null], // decimal literals [PR['PR_LITERAL'], /^\%d[0-9]+((-[0-9]+)|(\.[0-9]+)*)/, null], // hex literals [PR['PR_LITERAL'], /^(\%x[A-Za-z0-9]+((-[A-Za-z0-9]+)|(\.[A-Za-z0-9]+)*))/, null], // prose rule [PR['PR_NOCODE'], /^<[^>\x00-\x1f]*>/, null], // rule name [PR['PR_TYPE'], /^([A-Za-z][A-Za-z0-9-]*)/, null], [PR['PR_PUNCTUATION'], /^[=\(\)\*\/\[\]#]/, null], ]), ['ietf_abnf']); } catch(e){}]]> </script> </xsl:if></xsl:template> <!-- insert CSS style info --> <xsl:template name="insertCss"> <style title="rfc2629.xslt"> <xsl:value-of select="$xml2rfc-ext-webfonts"/> :root { --col-bg: white; --col-bg-error: red; --col-bg-highlight: yellow; --col-bg-highligh2: lime; --col-bg-light: gray; --col-bg-pre: lightyellow; --col-bg-pre1: #f8f8f8; --col-bg-pre2: #f0f0f0; --col-bg-th: #e9e9e9; --col-bg-tr: #f5f5f5; --col-fg: black; --col-fg-del: red; --col-fg-error: red; --col-fg-ins: green; --col-fg-light: gray; --col-fg-link: blue; --col-fg-title: green; } a { color: var(--col-fg-link); text-decoration: none; } a.smpl { color: var(--col-fg); } a:hover { text-decoration: underline; } a:active { text-decoration: underline; } address { margin-top: 1em; margin-left: 2em; font-style: normal; }<xsl:if test="//x:blockquote|//blockquote"> blockquote { border-style: solid; border-color: var(--col-fg-light); border-width: 0 0 0 .25em; font-style: italic; padding-left: 0.5em; }</xsl:if> body {<xsl:if test="$xml2rfc-background!=''"> background: url(<xsl:value-of select="$xml2rfc-background" />) var(--col-bg) left top;</xsl:if> background-color: var(--col-bg); color: var(--col-fg); font-family: <xsl:value-of select="$xml2rfc-ext-ff-body"/>; font-size: 16px; line-height: 1.5; margin: 10px 0px 10px 10px; }<xsl:if test="$parsedMaxwidth!=''"> @media screen and (min-width: <xsl:value-of select="number($parsedMaxwidth + 40)"/>px) { body { margin: 10px auto; max-width: <xsl:value-of select="$parsedMaxwidth"/>px; } }</xsl:if> samp, span.tt, code, pre { font-family: <xsl:value-of select="$xml2rfc-ext-ff-pre"/>; }<xsl:if test="//xhtml:p"> br.p { line-height: 150%; }</xsl:if> cite { font-style: normal; }<xsl:if test="//x:note|//aside"> aside { margin-left: 2em; }</xsl:if> dl { margin-left: 2em; } dl > dt { float: left; margin-right: 1em; } dl.nohang > dt { float: none; } dl > dd { margin-bottom: .5em; } dl.compact > dd { margin-bottom: .0em; } dl > dd > dl { margin-top: 0.5em; } dt > span { line-height: 0; } dd > span { line-height: 0; } ul.empty {<!-- spacing between two entries in definition lists --> list-style-type: none; } <xsl:if test="//ul[@bare='true']">ul.bare { margin-left: -2em; } </xsl:if>ul.empty li { margin-top: .5em; } dl p { margin-left: 0em; } dl.<xsl:value-of select="$css-reference"/> > dt { font-weight: bold; } dl.<xsl:value-of select="$css-reference"/> > dd { margin-left: <xsl:choose><xsl:when test="$xml2rfc-symrefs='no'">3.5</xsl:when><xsl:otherwise>6</xsl:otherwise></xsl:choose>em; } h1 { color: var(--col-fg-title); font-size: 150%; font-weight: bold; text-align: center; margin-top: 36pt; margin-bottom: 0pt; } h2 { font-size: 130%; page-break-after: avoid; } h2.np { page-break-before: always; } h3 { font-size: 120%; page-break-after: avoid; } h4 { font-size: 110%; page-break-after: avoid; } h5, h6 { font-size: 100%; page-break-after: avoid; } h1 a, h2 a, h3 a, h4 a, h5 a, h6 a { color: var(--col-fg); } img { margin-left: 3em; } ol { margin-left: 2em; } li ol { margin-left: 0em; } ol p { margin-left: 0em; }<xsl:if test="//xhtml:q"> q { font-style: italic; }</xsl:if> p { margin-left: 2em; } pre { font-size: 90%; margin-left: 3em; background-color: var(--col-bg-pre); padding: .25em; page-break-inside: avoid; }<xsl:if test="//artwork[@x:is-code-component='yes']|//sourcecode[@markers='true' or @x:line-folding]"><!-- support "<CODE BEGINS>" and "<CODE ENDS>" markers--> pre.ccmarker { background-color: var(--col-bg); color: var(--col-fg-light); } pre.ccmarker > span { font-size: small; } pre.cct { margin-bottom: -1em; } pre.ccb { margin-top: -1em; }</xsl:if> pre.text2 { border-style: dotted; border-width: 1px; background-color: var(--col-bg-pre2); } pre.inline { background-color: var(--col-bg); padding: 0em; page-break-inside: auto;<xsl:if test="$prettyprint-script!=''"> border: none !important;</xsl:if> } pre.text { border-style: dotted; border-width: 1px; background-color: var(--col-bg-pre1); } pre.drawing { border-style: solid; border-width: 1px; background-color: var(--col-bg-pre1); padding: 2em; }<xsl:if test="//@x:line-folding"> span.folding { text-decoration: dashed underline overline; } </xsl:if><xsl:if test="//x:q"> q { font-style: italic; }</xsl:if> <xsl:if test="//x:sup|//sup"> sup { font-size: 60%; }</xsl:if><xsl:if test="//x:sub|//sub"> sub { font-size: 60%; }</xsl:if> table { margin-left: 2em; }<xsl:if test="//texttable|//table"> div.<xsl:value-of select="$css-tt"/> { margin-left: 2em; } table.<xsl:value-of select="$css-tt"/> { border-collapse: collapse; border-color: var(--col-fg-light); border-spacing: 0; vertical-align: top; } table.<xsl:value-of select="$css-tt"/> th { border-color: var(--col-fg-light); padding: 3px; } table.<xsl:value-of select="$css-tt"/> td { border-color: var(--col-fg-light); padding: 3px; } table.all { border-style: solid; border-width: 2px; } table.full { border-style: solid; border-width: 2px; } table.<xsl:value-of select="$css-tt"/> td { vertical-align: top; } table.all td { border-style: solid; border-width: 1px; } table.full td { border-style: none solid; border-width: 1px; } table.<xsl:value-of select="$css-tt"/> th { vertical-align: top; } table.all th { border-style: solid; border-width: 1px; } table.full th { border-style: solid; border-width: 1px 1px 2px 1px; } table.<xsl:value-of select="$css-tleft"/> { margin-right: auto; } table.<xsl:value-of select="$css-tright"/> { margin-left: auto; } table.<xsl:value-of select="$css-tcenter"/> { margin-left: auto; margin-right: auto; } caption { caption-side: bottom; font-weight: bold; font-size: 80%; margin-top: .5em; } <xsl:if test="//@x:caption-side"> caption.caption-top { caption-side: top; } </xsl:if> <xsl:if test="//table"> table.v3 tr { vertical-align: top; } table.v3 th { background-color: var(--col-bg-th); vertical-align: top; padding: 0.25em 0.5em; } table.v3 td { padding: 0.25em 0.5em; } table.v3 tr:nth-child(2n) > td { background-color: var(--col-bg-tr); vertical-align: top; } tr p { margin-left: 0em; } tr pre { margin-left: 1em; } tr ol { margin-left: 1em; } tr ul { margin-left: 1em; } tr dl { margin-left: 1em; } </xsl:if> </xsl:if> table.<xsl:value-of select="$css-header"/> { border-spacing: 1px; width: 95%; font-size: 90%;<xsl:if test="not(contains($styles,' header-bw '))"> color: var(--col-bg);</xsl:if> } td.top { vertical-align: top; } td.topnowrap { vertical-align: top; white-space: nowrap; } table.<xsl:value-of select="$css-header"/> td { vertical-align: top;<xsl:if test="not(contains($styles,' header-bw '))"> background-color: var(--col-bg-light);</xsl:if> width: 50%; } table.<xsl:value-of select="$css-header"/> a { color: <xsl:choose><xsl:when test="not(contains($styles,' header-bw '))">var(--col-bg)</xsl:when><xsl:otherwise>var(--col-fg)</xsl:otherwise></xsl:choose>; } ul.toc, ul.toc ul { list-style: none; margin-left: 1.5em; padding-left: 0em; } ul.toc li { line-height: 150%; font-weight: bold; margin-left: 0em; } ul.toc li li { line-height: normal; font-weight: normal; font-size: 90%; margin-left: 0em; } li.excluded { font-size: 0%; } ul { margin-left: 2em; } li ul { margin-left: 0em; } ul p { margin-left: 0em; } .filename, h1, h2, h3, h4 { font-family: <xsl:value-of select="$xml2rfc-ext-ff-title"/>; } .nobr { white-space: nowrap; } <xsl:if test="$has-index">ul.ind, ul.ind ul { list-style: none; margin-left: 1.5em; padding-left: 0em; page-break-before: avoid; } ul.ind li { font-weight: bold; line-height: 200%; margin-left: 0em; } ul.ind li li { font-weight: normal; line-height: 150%; margin-left: 0em; }</xsl:if><xsl:if test="//svg:svg"> @namespace svg url(http://www.w3.org/2000/svg); svg|svg { margin-left: 3em; } svg { margin-left: 3em; }</xsl:if> .avoidbreakinside { page-break-inside: avoid; } .avoidbreakafter { page-break-after: avoid; } <xsl:if test="//t/@keepWithPrevious">.avoidbreakbefore { page-break-before: avoid; } </xsl:if><xsl:if test="//*[@removeInRFC='true']">section.rfcEditorRemove > div:first-of-type { font-style: italic; }</xsl:if><xsl:if test="//x:bcp14|//bcp14">.bcp14 { font-style: normal; text-transform: lowercase; font-variant: small-caps; }</xsl:if><xsl:if test="//x:blockquote|//blockquote"> blockquote > * .bcp14 { font-style: italic; }</xsl:if> .comment { background-color: var(--col-bg-highlight); }<xsl:if test="$xml2rfc-editing='yes'"> .editingmark { background-color: var(--col-bg-highlight); }</xsl:if> .<xsl:value-of select="$css-center"/> { text-align: center; } .<xsl:value-of select="$css-error"/> { color: var(--col-fg-error); font-style: italic; font-weight: bold; } .figure { font-weight: bold; text-align: center; font-size: 80%; } .filename { font-size: 112%; font-weight: bold; line-height: 21pt; text-align: center; margin-top: 0pt; } .fn { font-weight: bold; } .<xsl:value-of select="$css-left"/> { text-align: left; } .<xsl:value-of select="$css-right"/> { text-align: right; } .warning { font-size: 130%; background-color: var(--col-bg-highlight); }<xsl:if test="$xml2rfc-ext-paragraph-links='yes'"> .self { color: var(--col-fg-light); margin-left: .3em; text-decoration: none; visibility: hidden; user-select: none; } .self:hover { text-decoration: none; } h1:hover > a.self, h2:hover > a.self, h3:hover > a.self, li:hover > a.self, p:hover > a.self { visibility: visible; }</xsl:if><xsl:if test="$has-edits">del { color: var(--col-fg-del); text-decoration: line-through; } .del { color: var(--col-fg-del); text-decoration: line-through; } ins { color: var(--col-fg-ins); text-decoration: underline; } .ins { color: var(--col-fg-ins); text-decoration: underline; } div.issuepointer { float: left; }</xsl:if><xsl:if test="//ed:issue"> table.openissue { background-color: var(--col-bg-highlight); border-width: thin; border-style: solid; border-color: var(--col-fg); } table.closedissue { background-color: var(--col-bg); border-width: thin; border-style: solid; border-color: var(--col-fg-light); color: var(--col-fg-light); } thead th { text-align: left; } .bg-issue { border: solid; border-width: 1px; font-size: 66%; } .closed-issue { border: solid; border-width: thin; background-color: var(--col-bg-highlight2); font-size: smaller; font-weight: bold; } .open-issue { border: solid; border-width: thin; background-color: var(--col-bg-error); font-size: smaller; font-weight: bold; } .editor-issue { border: solid; border-width: thin; background-color: var(--col-bg-highlight); font-size: smaller; font-weight: bold; }</xsl:if><xsl:if test="$xml2rfc-ext-refresh-from!=''">.refreshxmlerror { position: fixed; top: 1%; right: 1%; padding: 5px 5px; color: var(--col-bg-highlight); background: var(--col-fg); } .refreshbrowsererror { position: fixed; top: 1%; left: 1%; padding: 5px 5px; color: var(--col-bg-error); background: var(--col-fg); }</xsl:if><xsl:if test="/rfc/x:feedback">.<xsl:value-of select="$css-feedback"/> { position: fixed; bottom: 1%; right: 1%; padding: 3px 5px; color: var(--col-bg); border-radius: 5px; background: #006400; border: 1px solid silver; -webkit-user-select: none;<!-- not std CSS yet--> -moz-user-select: none; -ms-user-select: none; } .<xsl:value-of select="$css-fbbutton"/> { margin-left: 1em; color: #303030; font-size: small; font-weight: normal; background: #d0d000; padding: 1px 4px; border: 1px solid silver; border-radius: 5px; -webkit-user-select: none;<!-- not std CSS yet--> -moz-user-select: none; -ms-user-select: none; }</xsl:if><xsl:if test="$xml2rfc-ext-justification='always'"> dd, li, p { text-align: justify; }</xsl:if><xsl:if test="$xml2rfc-ext-insert-metadata='yes' and ($is-rfc or $is-submitted-draft)"> .<xsl:value-of select="$css-docstatus"/> { border: 1px solid var(--col-fg); display: none; float: right; margin: 2em; padding: 1em; -webkit-user-select: none;<!-- not std CSS yet--> -moz-user-select: none; -ms-user-select: none; }</xsl:if><xsl:if test="$errata-parsed"> .<xsl:value-of select="$css-erratum"/> { border: 1px solid orangered; border-left: 0.75em solid orangered; float: right; padding: 0.5em; -webkit-user-select: none;<!-- not std CSS yet--> -moz-user-select: none; -ms-user-select: none; }<xsl:if test="$parsedMaxwidth!=''"> @media screen and (min-width: <xsl:value-of select="number($parsedMaxwidth + 350)"/>px) { .<xsl:value-of select="$css-erratum"/> { margin-right: -150px; } }</xsl:if></xsl:if><xsl:if test="$published-as-rfc"> .<xsl:value-of select="$css-publishedasrfc"/> { background-color: var(--col-bg-highlight); color: var(--col-fg); font-size: 115%; text-align: center; }</xsl:if><xsl:if test="$prettyprint-class='prettyprint' and contains($prettyprint-script,'prettify') and not(contains($prettyprint-script,'skin='))"> pre.prettyprint .pln { color: #000; } pre.prettyprint .str, pre.prettyprint .atv { color: #080; } pre.prettyprint .kwd, pre.prettyprint .tag { color: #008; } pre.prettyprint .com { color: #800; } pre.prettyprint .typ, pre.prettyprint .atn, pre.prettyprint .dec, pre.prettyprint .var { color: #606; } pre.prettyprint .lit { color: #066; } pre.prettyprint .pun, pre.prettyprint .opn, pre.prettyprint .clo { color: #660; } </xsl:if> @media screen { pre.text, pre.text2, pre.drawing { width: 69ch; } } @media print { .<xsl:value-of select="$css-noprint"/> { display: none; } a { color: black; text-decoration: none; } table.<xsl:value-of select="$css-header"/> { width: 90%; } td.<xsl:value-of select="$css-header"/> { width: 50%; color: black; background-color: white; vertical-align: top; font-size: 110%; } ul.toc a:last-child::after { content: leader('.') target-counter(attr(href), page); } ul.ind li li a {<!-- links in the leaf nodes of the index should go to page numbers --> content: target-counter(attr(href), page); } .print2col { column-count: 2; } <xsl:if test="$xml2rfc-ext-justification='print'"> dd, li, p { text-align: justify; } </xsl:if>} @page<xsl:if test="$xml2rfc-ext-duplex='yes'">:right</xsl:if> { font-family: <xsl:value-of select="$xml2rfc-ext-ff-body"/>; @top-left { content: "<xsl:call-template name="get-header-left"/>"; } @top-right { content: "<xsl:call-template name="get-header-right"/>"; } @top-center { content: "<xsl:call-template name="get-header-center"/>"; } @bottom-left { content: "<xsl:call-template name="get-author-summary"/>"; } @bottom-center { content: "<xsl:call-template name="get-bottom-center"/>"; } @bottom-right { content: "[Page " counter(page) "]"; } }<xsl:if test="$xml2rfc-ext-duplex='yes'"> @page:left { font-family: <xsl:value-of select="$xml2rfc-ext-ff-body"/>; @top-left { content: "<xsl:call-template name="get-header-right"/>"; } @top-right { content: "<xsl:call-template name="get-header-left"/>"; } @top-center { content: "<xsl:call-template name="get-header-center"/>"; } @bottom-left { content: "[Page " counter(page) "]"; } @bottom-center { content: "<xsl:call-template name="get-bottom-center"/>"; } @bottom-right { content: "<xsl:call-template name="get-author-summary"/>"; } } </xsl:if> @page:first { @top-left { content: normal; } @top-right { content: normal; } @top-center { content: normal; } } <xsl:if test="$xml2rfc-ext-dark-mode!='no'"> @media (prefers-color-scheme: dark) { :root { --col-bg: black; --col-bg-error: red; --col-bg-highlight: #9e9e20; --col-bg-highligh2: lime; --col-bg-light: gray; --col-bg-pre: #202000; --col-bg-pre1: #080808; --col-bg-pre2: #101010; --col-bg-th: #303030; --col-bg-tr: #202020; --col-fg: white; --col-fg-del: red; --col-fg-error: red; --col-fg-ins: green; --col-fg-light: gray; --col-fg-link: lightblue; --col-fg-title: green; } pre.prettyprint .pln { color: #fff; } pre.prettyprint .str, pre.prettyprint .atv { color: #8f8; } pre.prettyprint .kwd, pre.prettyprint .tag { color: #88f; } pre.prettyprint .com { color: #f88; } pre.prettyprint .typ, pre.prettyprint .atn, pre.prettyprint .dec, pre.prettyprint .var { color: #f8f; } pre.prettyprint .lit { color: #8ff; } pre.prettyprint .pun, pre.prettyprint .opn, pre.prettyprint .clo { color: #ff8; } } </xsl:if> </style> </xsl:template> <!-- generate the index section --> <xsl:template name="insertSingleIref"> <xsl:choose> <xsl:when test="@ed:xref"> <!-- special index generator mode --> <xsl:text>[</xsl:text> <a href="#{@ed:xref}"><xsl:value-of select="@ed:xref"/></a> <xsl:text>, </xsl:text> <a> <xsl:variable name="htmluri" select="//reference[@anchor=current()/@ed:xref]/format[@type='HTML']/@target"/> <xsl:if test="$htmluri"> <xsl:attribute name="href"><xsl:value-of select="concat($htmluri,'#',@ed:frag)"/></xsl:attribute> </xsl:if> <xsl:choose> <xsl:when test="@primary='true'"><b><xsl:value-of select="@ed:label" /></b></xsl:when> <xsl:otherwise><xsl:value-of select="@ed:label" /></xsl:otherwise> </xsl:choose> </a> <xsl:text>]</xsl:text> <xsl:if test="position()!=last()">, </xsl:if> </xsl:when> <xsl:otherwise> <xsl:variable name="_n"> <xsl:call-template name="get-section-number" /> </xsl:variable> <xsl:variable name="n"> <xsl:choose> <xsl:when test="starts-with($_n,$unnumbered)"> <xsl:text>"</xsl:text> <xsl:call-template name="render-section-ref-title"> <xsl:with-param name="to" select="ancestor::section"/> </xsl:call-template> <xsl:text>"</xsl:text> </xsl:when> <xsl:when test="$_n!=''"> <xsl:value-of select="$_n"/> </xsl:when> <xsl:otherwise>§</xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:variable name="backlink"> <xsl:choose> <xsl:when test="self::xref"> <xsl:variable name="target" select="@target"/> <xsl:comment>workaround for Saxon 9.1 bug; force evaluation of: <xsl:value-of select="$target"/></xsl:comment> <xsl:variable name="no"><xsl:number level="any" count="xref[@target=$target]"/></xsl:variable> <xsl:text>#</xsl:text> <xsl:value-of select="$anchor-pref"/> <xsl:text>xref.</xsl:text> <xsl:value-of select="@target"/> <xsl:text>.</xsl:text> <xsl:value-of select="$no"/> </xsl:when> <xsl:when test="self::iref"> <xsl:text>#</xsl:text> <xsl:call-template name="compute-iref-anchor"/> </xsl:when> <xsl:when test="self::x:ref"> <xsl:text>#</xsl:text> <xsl:call-template name="compute-extref-anchor"/> </xsl:when> <xsl:otherwise> <xsl:message>Unsupported element type for insertSingleIref</xsl:message> </xsl:otherwise> </xsl:choose> </xsl:variable> <a href="{$backlink}"> <xsl:call-template name="insertInsDelClass"/> <xsl:choose> <xsl:when test="@primary='true'"><b><xsl:value-of select="$n"/></b></xsl:when> <xsl:otherwise><xsl:value-of select="$n"/></xsl:otherwise> </xsl:choose> </a> <xsl:if test="position()!=last()">, </xsl:if> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="insertSingleXref"> <xsl:variable name="_n"> <xsl:call-template name="get-section-number" /> </xsl:variable> <xsl:variable name="n"> <xsl:choose> <xsl:when test="starts-with($_n,$unnumbered)"> <xsl:text>"</xsl:text> <xsl:call-template name="render-section-ref-title"> <xsl:with-param name="to" select="ancestor::section"/> </xsl:call-template> <xsl:text>"</xsl:text> </xsl:when> <xsl:when test="$_n!=''"> <xsl:value-of select="$_n"/> </xsl:when> <xsl:otherwise>§</xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:choose> <xsl:when test="self::reference"> <a href="#{@anchor}"> <xsl:call-template name="insertInsDelClass"/> <b><xsl:value-of select="$n"/></b> </a> </xsl:when> <xsl:otherwise> <xsl:variable name="target" select="@target"/> <xsl:variable name="backlink">#<xsl:value-of select="$anchor-pref"/>xref.<xsl:value-of select="$target"/>.<xsl:number level="any" count="xref[@target=$target]|relref[@target=$target]"/></xsl:variable> <a href="{$backlink}"> <xsl:call-template name="insertInsDelClass"/> <xsl:value-of select="$n"/> </a> </xsl:otherwise> </xsl:choose> <xsl:if test="position()!=last()">, </xsl:if> </xsl:template> <!-- generate navigation links to index subsections --> <xsl:template name="insert-index-navigation"> <p class="{$css-noprint}"> <xsl:for-each select="//iref | //reference[not(starts-with(@anchor,'deleted-'))]"> <xsl:sort select="translate(concat(@item,/rfc/back/displayreference[@target=current()/@anchor]/@to,@anchor),$lcase,$ucase)" /> <xsl:variable name="letter" select="translate(substring(concat(@item,/rfc/back/displayreference[@target=current()/@anchor]/@to,@anchor),1,1),$lcase,$ucase)"/> <!-- first of character and character? --> <xsl:if test="generate-id(.) = generate-id(key('index-first-letter',$letter)[1]) and translate($letter,$alnum,'')=''"> <xsl:variable name="showit" select="$xml2rfc-ext-include-references-in-index='yes' or self::iref"/> <xsl:if test="$showit"> <a href="#{$anchor-pref}index.{$letter}"> <xsl:value-of select="$letter" /> </a> <xsl:text> </xsl:text> </xsl:if> </xsl:if> </xsl:for-each> </p> </xsl:template> <xsl:template name="format-section-ref"> <xsl:param name="number"/> <xsl:choose> <xsl:when test="translate(substring($number,1,1),$ucase,'')=''"> <xsl:text>Appendix </xsl:text> </xsl:when> <xsl:otherwise> <xsl:text>Section </xsl:text> </xsl:otherwise> </xsl:choose> <xsl:value-of select="$number"/> </xsl:template> <xsl:template name="insert-index-item"> <xsl:param name="in-artwork"/> <xsl:param name="irefs"/> <xsl:param name="xrefs"/> <xsl:param name="extrefs"/> <xsl:choose> <xsl:when test="$in-artwork"> <span class="tt"><xsl:value-of select="@item" /></span> </xsl:when> <xsl:otherwise> <xsl:value-of select="@item" /> </xsl:otherwise> </xsl:choose> <xsl:text>  </xsl:text> <xsl:for-each select="$irefs|$xrefs|$extrefs"> <xsl:call-template name="insertSingleIref" /> </xsl:for-each> </xsl:template> <xsl:template name="insert-index-subitem"> <xsl:param name="in-artwork"/> <xsl:param name="irefs"/> <xsl:param name="xrefs"/> <xsl:param name="extrefs"/> <li> <xsl:choose> <xsl:when test="$in-artwork"> <span class="tt"><xsl:value-of select="@subitem" /></span> </xsl:when> <xsl:otherwise> <xsl:value-of select="@subitem" /> </xsl:otherwise> </xsl:choose> <xsl:text>  </xsl:text> <xsl:for-each select="$irefs|$xrefs|$extrefs"> <xsl:call-template name="insertSingleIref" /> </xsl:for-each> </li> </xsl:template> <xsl:variable name="item-wrapper-element">li</xsl:variable> <xsl:attribute-set name="item-wrapper-element"/> <xsl:variable name="subitems-wrapper-element">ul</xsl:variable> <xsl:template name="insert-index-regular-iref"> <xsl:if test="generate-id(.) = generate-id(key('index-item',concat(@item,@anchor))[1])"> <xsl:variable name="item" select="@item"/> <xsl:variable name="in-artwork" select="key('index-item',$item)[@primary='true' and ancestor::artwork]"/> <xsl:element name="{$item-wrapper-element}" use-attribute-sets="item-wrapper-element"> <xsl:variable name="irefs3" select="key('index-item',@item)[not(@subitem) or @subitem='']"/> <xsl:variable name="xrefs3" select="key('xref-item',$irefs3[@x:for-anchor='']/../@anchor) | key('xref-item',$irefs3/@x:for-anchor)"/> <xsl:variable name="extrefs3" select="key('extref-item',$irefs3[@x:for-anchor='']/../@anchor) | key('extref-item',$irefs3/@x:for-anchor)"/> <xsl:call-template name="insert-index-item"> <xsl:with-param name="in-artwork" select="key('index-item',@item)[@primary='true' and (ancestor::artwork or ancestor::sourcecode)]"/> <xsl:with-param name="irefs" select="$irefs3"/> <xsl:with-param name="xrefs" select="$xrefs3"/> <xsl:with-param name="extrefs" select="$extrefs3"/> </xsl:call-template> <xsl:variable name="s2" select="key('index-item',@item)[@subitem!='']"/> <xsl:if test="$s2"> <xsl:element name="{$subitems-wrapper-element}"> <xsl:for-each select="$s2"> <xsl:sort select="translate(@subitem,$lcase,$ucase)" /> <xsl:if test="generate-id(.) = generate-id(key('index-item-subitem',concat(@item,'..',@subitem))[1])"> <xsl:variable name="irefs4" select="key('index-item-subitem',concat(@item,'..',@subitem))"/> <xsl:variable name="xrefs4" select="key('xref-item',$irefs4[@x:for-anchor='']/../@anchor) | key('xref-item',$irefs4/@x:for-anchor)"/> <xsl:variable name="extrefs4" select="key('extref-item',$irefs4[@x:for-anchor='']/../@anchor) | key('extref-item',$irefs4/@x:for-anchor)"/> <xsl:call-template name="insert-index-subitem"> <xsl:with-param name="in-artwork" select="key('index-item-subitem',concat(@item,'..',@subitem))[@primary='true' and (ancestor::artwork or ancestor::sourcecode)]"/> <xsl:with-param name="irefs" select="$irefs4"/> <xsl:with-param name="xrefs" select="$xrefs4"/> <xsl:with-param name="extrefs" select="$extrefs4"/> </xsl:call-template> </xsl:if> </xsl:for-each> </xsl:element> </xsl:if> </xsl:element> </xsl:if> </xsl:template> <!-- generate the index section --> <xsl:template name="insertIndex"> <xsl:call-template name="insert-conditional-hrule"/> <section id="{$anchor-pref}index"> <xsl:call-template name="insert-conditional-pagebreak"/> <h2> <a href="#{$anchor-pref}index">Index</a> </h2> <xsl:call-template name="insert-index-navigation"/> <!-- for each index subsection --> <div class="print2col"> <ul class="ind"> <xsl:for-each select="//iref | //reference[not(starts-with(@anchor,'deleted-'))]"> <xsl:sort select="translate(concat(normalize-space(@item),/rfc/back/displayreference[@target=current()/@anchor]/@to,@anchor),$lcase,$ucase)" /> <xsl:variable name="letter" select="translate(substring(concat(normalize-space(@item),/rfc/back/displayreference[@target=current()/@anchor]/@to,@anchor),1,1),$lcase,$ucase)"/> <xsl:variable name="showit" select="$xml2rfc-ext-include-references-in-index='yes' or self::iref"/> <xsl:if test="$showit and generate-id(.) = generate-id(key('index-first-letter',$letter)[1])"> <li> <!-- make letters and digits stand out --> <xsl:choose> <xsl:when test="translate($letter,concat($lcase,$ucase,'0123456789'),'')=''"> <a id="{$anchor-pref}index.{$letter}" href="#{$anchor-pref}index.{$letter}"> <b><xsl:value-of select="$letter"/></b> </a> </xsl:when> <xsl:otherwise> <b><xsl:value-of select="$letter"/></b> </xsl:otherwise> </xsl:choose> <ul> <xsl:for-each select="key('index-first-letter',$letter)"> <xsl:sort select="translate(concat(@item,@anchor),$lcase,$ucase)" /> <xsl:choose> <xsl:when test="self::reference"> <xsl:if test="$xml2rfc-ext-include-references-in-index='yes' and not(starts-with(@anchor,'deleted-'))"> <li> <xsl:variable name="val"> <xsl:call-template name="reference-name"/> </xsl:variable> <em> <xsl:value-of select="substring($val,2,string-length($val)-2)"/> </em> <xsl:text>  </xsl:text> <xsl:variable name="rs" select="key('xref-item',current()/@anchor) | . | key('anchor-item',concat('deleted-',current()/@anchor))"/> <xsl:for-each select="$rs"> <xsl:call-template name="insertSingleXref" /> </xsl:for-each> <xsl:variable name="rs2" select="$rs[@x:sec|@section]"/> <xsl:if test="$rs2"> <ul> <xsl:for-each select="$rs2"> <xsl:sort select="substring-before(concat(@x:sec,@section,'.'),'.')" data-type="number"/> <xsl:sort select="substring(concat(@x:sec,@section),2+string-length(substring-before(concat(@x:sec,@section),'.')))" data-type="number"/> <xsl:if test="generate-id(.) = generate-id(key('index-xref-by-sec',concat(@target,'..',@x:sec,@section))[1])"> <li> <em> <xsl:call-template name="format-section-ref"> <xsl:with-param name="number" select="concat(@x:sec,@section)"/> </xsl:call-template> </em> <xsl:text>  </xsl:text> <xsl:for-each select="key('index-xref-by-sec',concat(@target,'..',@x:sec,@section))"> <xsl:call-template name="insertSingleXref" /> </xsl:for-each> </li> </xsl:if> </xsl:for-each> </ul> </xsl:if> <xsl:if test="current()/x:source/@href"> <xsl:variable name="rs3" select="$rs[not(@x:sec) and @x:rel]"/> <xsl:variable name="doc" select="document(current()/x:source/@href)"/> <xsl:if test="$rs3"> <ul> <xsl:for-each select="$rs3"> <xsl:sort select="count($doc//*[@anchor and following::*/@anchor=substring-after(current()/@x:rel,'#')])" order="ascending" data-type="number"/> <xsl:if test="generate-id(.) = generate-id(key('index-xref-by-anchor',concat(@target,'..',@x:rel))[1])"> <xsl:variable name="sec"> <xsl:for-each select="$doc//*[@anchor=substring-after(current()/@x:rel,'#')]"> <xsl:call-template name="get-section-number"/> </xsl:for-each> </xsl:variable> <xsl:if test="$sec!=''"> <li> <em> <xsl:choose> <xsl:when test="starts-with($sec,$unnumbered)"> <xsl:for-each select="$doc//*[@anchor=substring-after(current()/@x:rel,'#')]"> <xsl:call-template name="get-title-as-string"/> </xsl:for-each> </xsl:when> <xsl:otherwise> <xsl:call-template name="format-section-ref"> <xsl:with-param name="number" select="$sec"/> </xsl:call-template> </xsl:otherwise> </xsl:choose> </em> <xsl:text>  </xsl:text> <xsl:for-each select="key('index-xref-by-anchor',concat(@target,'..',@x:rel))"> <xsl:call-template name="insertSingleXref" /> </xsl:for-each> </li> </xsl:if> </xsl:if> </xsl:for-each> </ul> </xsl:if> </xsl:if> </li> </xsl:if> </xsl:when> <xsl:otherwise> <xsl:call-template name="insert-index-regular-iref"/> </xsl:otherwise> </xsl:choose> </xsl:for-each> </ul> </li> </xsl:if> </xsl:for-each> </ul> </div> </section> </xsl:template> <xsl:template name="insertPreamble" myns:namespaceless-elements="xml2rfc"> <xsl:param name="notes"/> <boilerplate> <!-- TLP4, Section 6.c.iii --> <xsl:variable name="pre5378EscapeClause"> This document may contain material from IETF Documents or IETF Contributions published or made publicly available before November 10, 2008. The person(s) controlling the copyright in some of this material may not have granted the IETF Trust the right to allow modifications of such material outside the IETF Standards Process. Without obtaining an adequate license from the person(s) controlling the copyright in such materials, this document may not be modified outside the IETF Standards Process, and derivative works of it may not be created outside the IETF Standards Process, except to format it for publication as an RFC or to translate it into languages other than English. </xsl:variable> <!-- TLP1, Section 6.c.i --> <xsl:variable name="noModificationTrust200811Clause"> This document may not be modified, and derivative works of it may not be created, except to format it for publication as an RFC and to translate it into languages other than English. </xsl:variable> <!-- TLP2..4, Section 6.c.i --> <xsl:variable name="noModificationTrust200902Clause"> This document may not be modified, and derivative works of it may not be created, except to format it for publication as an RFC or to translate it into languages other than English.<!-- "and" changes to "or" --> </xsl:variable> <!-- TLP1..4, Section 6.c.ii --> <xsl:variable name="noDerivativesTrust200___Clause"> This document may not be modified, and derivative works of it may not be created, and it may not be published except as an Internet-Draft. </xsl:variable> <section anchor="{$anchor-pref}status"> <name> <xsl:choose> <xsl:when test="$xml2rfc-rfcedstyle='yes' or $src/rfc/@version >= 3">Status of This Memo</xsl:when> <xsl:otherwise>Status of this Memo</xsl:otherwise> </xsl:choose> </name> <xsl:choose> <xsl:when test="@ipr and not($is-rfc)"> <t> <xsl:choose> <!-- RFC2026 --> <xsl:when test="@ipr = 'full2026'"> This document is an Internet-Draft and is in full conformance with all provisions of Section 10 of RFC2026. </xsl:when> <xsl:when test="@ipr = 'noDerivativeWorks2026'"> This document is an Internet-Draft and is in full conformance with all provisions of Section 10 of RFC2026 except that the right to produce derivative works is not granted. </xsl:when> <xsl:when test="@ipr = 'noDerivativeWorksNow'"> This document is an Internet-Draft and is in full conformance with all provisions of Section 10 of RFC2026 except that the right to produce derivative works is not granted. (If this document becomes part of an IETF working group activity, then it will be brought into full compliance with Section 10 of RFC2026.) </xsl:when> <xsl:when test="@ipr = 'none'"> This document is an Internet-Draft and is NOT offered in accordance with Section 10 of RFC2026, and the author does not provide the IETF with any rights other than to publish as an Internet-Draft. </xsl:when> <!-- RFC3667 --> <xsl:when test="@ipr = 'full3667'"> This document is an Internet-Draft and is subject to all provisions of section 3 of RFC 3667. By submitting this Internet-Draft, each author represents that any applicable patent or other IPR claims of which he or she is aware have been or will be disclosed, and any of which he or she become aware will be disclosed, in accordance with RFC 3668. </xsl:when> <xsl:when test="@ipr = 'noModification3667'"> This document is an Internet-Draft and is subject to all provisions of section 3 of RFC 3667. By submitting this Internet-Draft, each author represents that any applicable patent or other IPR claims of which he or she is aware have been or will be disclosed, and any of which he or she become aware will be disclosed, in accordance with RFC 3668. This document may not be modified, and derivative works of it may not be created, except to publish it as an RFC and to translate it into languages other than English<xsl:if test="@iprExtract">, other than to extract <xref target="{@iprExtract}"/> as-is for separate use</xsl:if>. </xsl:when> <xsl:when test="@ipr = 'noDerivatives3667'"> This document is an Internet-Draft and is subject to all provisions of section 3 of RFC 3667 except for the right to produce derivative works. By submitting this Internet-Draft, each author represents that any applicable patent or other IPR claims of which he or she is aware have been or will be disclosed, and any of which he or she become aware will be disclosed, in accordance with RFC 3668. This document may not be modified, and derivative works of it may not be created<xsl:if test="@iprExtract">, other than to extract <xref target="{@iprExtract}"/> as-is for separate use</xsl:if>. </xsl:when> <!-- RFC3978 --> <xsl:when test="@ipr = 'full3978'"> By submitting this Internet-Draft, each author represents that any applicable patent or other IPR claims of which he or she is aware have been or will be disclosed, and any of which he or she becomes aware will be disclosed, in accordance with Section 6 of BCP 79. </xsl:when> <xsl:when test="@ipr = 'noModification3978'"> By submitting this Internet-Draft, each author represents that any applicable patent or other IPR claims of which he or she is aware have been or will be disclosed, and any of which he or she becomes aware will be disclosed, in accordance with Section 6 of BCP 79. This document may not be modified, and derivative works of it may not be created, except to publish it as an RFC and to translate it into languages other than English<xsl:if test="@iprExtract">, other than to extract <xref target="{@iprExtract}"/> as-is for separate use</xsl:if>. </xsl:when> <xsl:when test="@ipr = 'noDerivatives3978'"> By submitting this Internet-Draft, each author represents that any applicable patent or other IPR claims of which he or she is aware have been or will be disclosed, and any of which he or she becomes aware will be disclosed, in accordance with Section 6 of BCP 79. This document may not be modified, and derivative works of it may not be created<xsl:if test="@iprExtract">, other than to extract <xref target="{@iprExtract}"/> as-is for separate use</xsl:if>. </xsl:when> <!-- as of Jan 2010, TLP 4.0 --> <xsl:when test="$ipr-2010-01 and (@ipr = 'trust200902' or @ipr = 'noModificationTrust200902' or @ipr = 'noDerivativesTrust200902' or @ipr = 'pre5378Trust200902')"> This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79. </xsl:when> <!-- as of Nov 2008, Feb 2009 and Sep 2009 --> <xsl:when test="@ipr = 'trust200811' or @ipr = 'noModificationTrust200811' or @ipr = 'noDerivativesTrust200811' or @ipr = 'trust200902' or @ipr = 'noModificationTrust200902' or @ipr = 'noDerivativesTrust200902' or @ipr = 'pre5378Trust200902'"> This Internet-Draft is submitted to IETF in full conformance with the provisions of BCP 78 and BCP 79. </xsl:when> <xsl:otherwise> CONFORMANCE UNDEFINED. </xsl:otherwise> </xsl:choose> <!-- warn about iprExtract without effect --> <xsl:if test="@iprExtract and (@ipr != 'noModification3667' and @ipr != 'noDerivatives3667' and @ipr != 'noModification3978' and @ipr != 'noDerivatives3978')"> <xsl:call-template name="warning"> <xsl:with-param name="msg" select="concat('/rfc/@iprExtract does not have any effect for /rfc/@ipr=',@ipr)"/> </xsl:call-template> </xsl:if> <!-- restrictions --> <xsl:choose> <xsl:when test="@ipr = 'noModificationTrust200811'"> <xsl:value-of select="$noModificationTrust200811Clause"/> </xsl:when> <xsl:when test="@ipr = 'noDerivativesTrust200811'"> <xsl:value-of select="$noDerivativesTrust200___Clause"/> </xsl:when> <xsl:when test="@ipr = 'noModificationTrust200902'"> <xsl:value-of select="$noModificationTrust200902Clause"/> </xsl:when> <xsl:when test="@ipr = 'noDerivativesTrust200902'"> <xsl:value-of select="$noDerivativesTrust200___Clause"/> </xsl:when> <!-- escape clause moved to Copyright Notice as of 2009-11 --> <xsl:when test="@ipr = 'pre5378Trust200902' and $pub-yearmonth < 200911"> <xsl:value-of select="$pre5378EscapeClause"/> </xsl:when> <xsl:otherwise /> </xsl:choose> </t> <xsl:choose> <xsl:when test="$id-boilerplate='2010'"> <xsl:variable name="current-uri">http<xsl:if test="$rfc-boilerplate-use-https">s</xsl:if>://datatracker.ietf.org/drafts/current/</xsl:variable> <t> Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at <eref target="{$current-uri}"><xsl:value-of select="$current-uri"/></eref>. </t> </xsl:when> <xsl:otherwise> <t> Internet-Drafts are working documents of the Internet Engineering Task Force (IETF), its areas, and its working groups. Note that other groups may also distribute working documents as Internet-Drafts. </t> </xsl:otherwise> </xsl:choose> <t> Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as “work in progress”. </t> <xsl:if test="$id-boilerplate=''"> <t> The list of current Internet-Drafts can be accessed at <eref target='http://www.ietf.org/ietf/1id-abstracts.txt'>http://www.ietf.org/ietf/1id-abstracts.txt</eref>. </t> <t> The list of Internet-Draft Shadow Directories can be accessed at <eref target='http://www.ietf.org/shadow.html'>http://www.ietf.org/shadow.html</eref>. </t> </xsl:if> <t> This Internet-Draft will expire <xsl:call-template name="expirydate"><xsl:with-param name="in-prose" select="true()"/></xsl:call-template>. </t> </xsl:when> <xsl:when test="@category='bcp' and $rfc-boilerplate='2010'"> <t> This memo documents an Internet Best Current Practice. </t> </xsl:when> <xsl:when test="@category='bcp'"> <t> This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements. Distribution of this memo is unlimited. </t> </xsl:when> <xsl:when test="@category='exp' and $rfc-boilerplate='2010'"> <t> This document is not an Internet Standards Track specification; it is published for examination, experimental implementation, and evaluation. </t> </xsl:when> <xsl:when test="@category='exp'"> <t> This memo defines an Experimental Protocol for the Internet community. It does not specify an Internet standard of any kind. Discussion and suggestions for improvement are requested. Distribution of this memo is unlimited. </t> </xsl:when> <xsl:when test="@category='historic' and $rfc-boilerplate='2010'"> <t> This document is not an Internet Standards Track specification; it is published for the historical record. </t> </xsl:when> <xsl:when test="@category='historic'"> <t> This memo describes a historic protocol for the Internet community. It does not specify an Internet standard of any kind. Distribution of this memo is unlimited. </t> </xsl:when> <xsl:when test="@category='std' and $rfc-boilerplate='2010'"> <t> This is an Internet Standards Track document. </t> </xsl:when> <xsl:when test="@category='std'"> <t> This document specifies an Internet standards track protocol for the Internet community, and requests discussion and suggestions for improvements. Please refer to the current edition of the “Internet Official Protocol Standards” (STD 1) for the standardization state and status of this protocol. Distribution of this memo is unlimited. </t> </xsl:when> <xsl:when test="(@category='info' or not(@category)) and $rfc-boilerplate='2010'"> <t> This document is not an Internet Standards Track specification; it is published for informational purposes. </t> </xsl:when> <xsl:when test="@category='info' or not(@category)"> <t> This memo provides information for the Internet community. It does not specify an Internet standard of any kind. Distribution of this memo is unlimited. </t> </xsl:when> <xsl:otherwise> <t> UNSUPPORTED CATEGORY. </t> <xsl:call-template name="error"> <xsl:with-param name="msg" select="concat('Unsupported value for /rfc/@category: ', @category)"/> <xsl:with-param name="inline" select="'no'"/> </xsl:call-template> </xsl:otherwise> </xsl:choose> <!-- 2nd and 3rd paragraph --> <xsl:if test="$rfc-boilerplate='2010' and $is-rfc"> <t> <xsl:if test="@category='exp'"> This document defines an Experimental Protocol for the Internet community. </xsl:if> <xsl:if test="@category='historic'"> This document defines a Historic Document for the Internet community. </xsl:if> <xsl:choose> <xsl:when test="$submissionType='IETF'"> This document is a product of the Internet Engineering Task Force (IETF). <xsl:choose> <xsl:when test="$consensus='yes'"> It represents the consensus of the IETF community. It has received public review and has been approved for publication by the Internet Engineering Steering Group (IESG). </xsl:when> <xsl:otherwise> It has been approved for publication by the Internet Engineering Steering Group (IESG). <!-- sanity check of $consensus --> <xsl:if test="@category='std' or @category='bcp'"> <xsl:call-template name="error"> <xsl:with-param name="msg" select="'IETF BCPs and Standards Track documents require IETF consensus, check values of @category and @consensus!'"/> <xsl:with-param name="inline" select="'no'"/> </xsl:call-template> </xsl:if> </xsl:otherwise> </xsl:choose> </xsl:when> <xsl:when test="$submissionType='IAB'"> This document is a product of the Internet Architecture Board (IAB) and represents information that the IAB has deemed valuable to provide for permanent record. <xsl:if test="$consensus='yes'"> It represents the consensus of the Internet Architecture Board (IAB). </xsl:if> </xsl:when> <xsl:when test="$submissionType='IRTF'"> This document is a product of the Internet Research Task Force (IRTF). The IRTF publishes the results of Internet-related research and development activities. These results might not be suitable for deployment. <xsl:choose> <xsl:when test="$consensus='yes' and front/workgroup[1]!=''"> This RFC represents the consensus of the <xsl:value-of select="front/workgroup[1]"/> Research Group of the Internet Research Task Force (IRTF). </xsl:when> <xsl:when test="$consensus='no' and front/workgroup[1]!=''"> This RFC represents the individual opinion(s) of one or more members of the <xsl:value-of select="front/workgroup[1]"/> Research Group of the Internet Research Task Force (IRTF). </xsl:when> <xsl:otherwise> <!-- no research group --> </xsl:otherwise> </xsl:choose> </xsl:when> <xsl:when test="$submissionType='independent'"> This is a contribution to the RFC Series, independently of any other RFC stream. The RFC Editor has chosen to publish this document at its discretion and makes no statement about its value for implementation or deployment. </xsl:when> <xsl:otherwise> <!-- will contain error message already --> <xsl:value-of select="$submissionType"/> </xsl:otherwise> </xsl:choose> <xsl:variable name="candidates"> <!-- see https://www.rfc-editor.org/errata/eid5248 --> <xsl:choose> <xsl:when test="$pub-yearmonth < 201802">a candidate</xsl:when> <xsl:otherwise>candidates</xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:choose> <xsl:when test="$submissionType='IETF'"> <xsl:choose> <xsl:when test="@category='bcp'"> Further information on BCPs is available in <xsl:copy-of select="$hab-reference"/>. </xsl:when> <xsl:when test="@category='std'"> Further information on Internet Standards is available in <xsl:copy-of select="$hab-reference"/>. </xsl:when> <xsl:otherwise> Not all documents approved by the IESG are <xsl:value-of select="$candidates"/> for any level of Internet Standard; see <xsl:copy-of select="$hab-reference"/>. </xsl:otherwise> </xsl:choose> </xsl:when> <xsl:otherwise> <xsl:variable name="approver"> <xsl:choose> <xsl:when test="$submissionType='IAB'">IAB</xsl:when> <xsl:when test="$submissionType='IRTF'">IRSG</xsl:when> <xsl:otherwise>RFC Editor</xsl:otherwise> </xsl:choose> </xsl:variable> Documents approved for publication by the <xsl:value-of select="$approver"/> are not <xsl:value-of select="$candidates"/> for any level of Internet Standard; see <xsl:copy-of select="$hab-reference"/>. </xsl:otherwise> </xsl:choose> </t> <t> Information about the current status of this document, any errata, and how to provide feedback on it may be obtained at <eref target="{$rfc-info-link}"><xsl:value-of select="$rfc-info-link"/></eref>. </t> </xsl:if> </section> <!-- some notes might go here; see http://www.rfc-editor.org/rfc-style-guide/rfc-style --> <xsl:copy-of select="$notes"/> <xsl:choose> <xsl:when test="$src/rfc/@ipr='none'"/> <xsl:when test="$ipr-2008-11"> <section anchor="{$anchor-pref}copyrightnotice"> <name>Copyright Notice</name> <t> Copyright (c) <xsl:value-of select="$xml2rfc-ext-pub-year" /> IETF Trust and the persons identified as the document authors. All rights reserved. </t> <xsl:variable name="license"> <xsl:choose> <xsl:when test="$pub-yearmonth > 202110">Revised BSD License</xsl:when> <xsl:otherwise>Simplified BSD License</xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:choose> <xsl:when test="$ipr-2010-01"> <t> This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (<eref target="{$trust-license-info-link}"><xsl:value-of select="$trust-license-info-link"/></eref>) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. <xsl:if test="$submissionType='IETF'"> Code Components extracted from this document must include <xsl:value-of select="$license"/> text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the <xsl:value-of select="$license"/>. </xsl:if> </t> </xsl:when> <xsl:when test="$ipr-2009-09"> <t> This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (<eref target="http://trustee.ietf.org/license-info">http://trustee.ietf.org/license-info</eref>) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the BSD License. </t> </xsl:when> <xsl:when test="$ipr-2009-02"> <t> This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents in effect on the date of publication of this document (<eref target="http://trustee.ietf.org/license-info">http://trustee.ietf.org/license-info</eref>). Please review these documents carefully, as they describe your rights and restrictions with respect to this document. </t> </xsl:when> <xsl:otherwise> <t> This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (<eref target="http://trustee.ietf.org/license-info">http://trustee.ietf.org/license-info</eref>) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. </t> </xsl:otherwise> </xsl:choose> <!-- add warning for incompatible IPR attribute on RFCs --> <xsl:variable name="stds-rfc-compatible-ipr" select="@ipr='pre5378Trust200902' or @ipr='trust200902' or @ipr='trust200811' or @ipr='full3978' or @ipr='full3667' or @ipr='full2026'"/> <xsl:variable name="rfc-compatible-ipr" select="$stds-rfc-compatible-ipr or @ipr='noModificationTrust200902' or @ipr='noDerivativesTrust200902' or @ipr='noModificationTrust200811' or @ipr='noDerivativesTrust200811'"/> <!-- TODO: may want to add more historic variants --> <xsl:variable name="is-stds-track" select="$submissionType='IETF' and @category='std'"/> <xsl:variable name="status-diags"> <xsl:choose> <xsl:when test="$is-stds-track and $is-rfc and @ipr and not($stds-rfc-compatible-ipr)"> <xsl:value-of select="concat('The /rfc/@ipr attribute value of ',@ipr,' is not allowed on standards-track RFCs.')"/> </xsl:when> <xsl:when test="$is-rfc and @ipr and not($rfc-compatible-ipr)"> <xsl:value-of select="concat('The /rfc/@ipr attribute value of ',@ipr,' is not allowed on RFCs.')"/> </xsl:when> <xsl:otherwise/> </xsl:choose> </xsl:variable> <xsl:choose> <xsl:when test="$status-diags!=''"> <t> <spanx><xsl:value-of select="$status-diags"/></spanx> </t> <xsl:call-template name="error"> <xsl:with-param name="msg" select="$status-diags"/> <xsl:with-param name="inline" select="'no'"/> </xsl:call-template> </xsl:when> <xsl:when test="($is-rfc or $pub-yearmonth >= 200911) and @ipr = 'pre5378Trust200902'"> <!-- special case: RFC5378 escape applies to RFCs as well --> <!-- for IDs historically in Status Of This Memo, over here starting 2009-11 --> <t> <xsl:value-of select="$pre5378EscapeClause"/> </t> </xsl:when> <xsl:when test="not($is-rfc)"> <!-- not an RFC, handled elsewhere --> </xsl:when> <xsl:when test="not(@ipr)"> <!-- no IPR value; done --> </xsl:when> <xsl:when test="@ipr='trust200902' or @ipr='trust200811' or @ipr='full3978' or @ipr='full3667' or @ipr='full2026'"> <!-- default IPR, allowed here --> </xsl:when> <xsl:when test="@ipr='noModificationTrust200811'"> <t> <xsl:value-of select="$noModificationTrust200811Clause"/> </t> </xsl:when> <xsl:when test="@ipr='noModificationTrust200902'"> <t> <xsl:value-of select="$noModificationTrust200902Clause"/> </t> </xsl:when> <xsl:when test="@ipr='noDerivativesTrust200902' or @ipr='noDerivativesTrust200811'"> <t> <xsl:value-of select="$noDerivativesTrust200___Clause"/> </t> </xsl:when> <xsl:otherwise> <xsl:variable name="msg" select="concat('unexpected value of /rfc/@ipr for this type of document: ',@ipr)"/> <t> <spanx><xsl:value-of select="$msg"/></spanx> </t> <xsl:call-template name="error"> <xsl:with-param name="msg" select="$msg"/> <xsl:with-param name="inline" select="'no'"/> </xsl:call-template> </xsl:otherwise> </xsl:choose> </section> </xsl:when> <xsl:when test="$ipr-2007-08"> <!-- no copyright notice --> </xsl:when> <xsl:when test="$ipr-rfc4748"> <section anchor="{$anchor-pref}copyrightnotice"> <name>Copyright Notice</name> <t> Copyright © The IETF Trust (<xsl:value-of select="$xml2rfc-ext-pub-year" />). All Rights Reserved. </t> </section> </xsl:when> <xsl:otherwise> <section anchor="{$anchor-pref}copyrightnotice"> <name>Copyright Notice</name> <t> Copyright © The Internet Society (<xsl:value-of select="$xml2rfc-ext-pub-year" />). All Rights Reserved. </t> </section> </xsl:otherwise> </xsl:choose> </boilerplate> </xsl:template> <!-- TOC generation --> <xsl:template match="/" mode="toc"> <hr class="{$css-noprint}"/> <nav id="{$anchor-pref}toc"> <xsl:call-template name="insert-errata"> <xsl:with-param name="section" select="'toc'"/> </xsl:call-template> <h2 class="np"> <!-- this pagebreak occurs always --> <a href="#{$anchor-pref}toc">Table of Contents</a> </h2> <ul class="toc"> <xsl:apply-templates mode="toc" /> </ul> <xsl:call-template name="insertTocAppendix" /> </nav> </xsl:template> <xsl:template name="insert-toc-line"> <xsl:param name="number" /> <xsl:param name="target" /> <xsl:param name="title" /> <xsl:param name="name" /> <xsl:param name="tocparam" /> <xsl:param name="oldtitle" /> <xsl:param name="waschanged" /> <xsl:variable name="depth"> <!-- count the dots --> <xsl:choose> <xsl:when test="starts-with($number,$unnumbered)"> <xsl:value-of select="string-length(translate(substring-after($number,$unnumbered),'.ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890§','.'))"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="string-length(translate($number,'.ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890§','.'))"/> </xsl:otherwise> </xsl:choose> </xsl:variable> <!-- handle tocdepth parameter --> <xsl:choose> <xsl:when test="(not($tocparam) or $tocparam='' or $tocparam='default') and $depth >= $parsedTocDepth"> <!-- dropped entry because excluded --> <xsl:attribute name="class">excluded</xsl:attribute> </xsl:when> <xsl:when test="$tocparam='exclude'"> <!-- dropped entry because excluded --> <xsl:attribute name="class">excluded</xsl:attribute> </xsl:when> <xsl:otherwise> <xsl:choose> <xsl:when test="starts-with($number,'del-')"> <del> <xsl:value-of select="$number" /> <a href="#{$target}"><xsl:value-of select="$title"/></a> </del> </xsl:when> <xsl:otherwise> <xsl:if test="$number != '' and not(contains($number,$unnumbered))"> <a href="#{$anchor-pref}section.{$number}"> <xsl:call-template name="emit-section-number"> <xsl:with-param name="no" select="$number"/> <xsl:with-param name="appendixPrefix" select="true()"/> </xsl:call-template> </a> <xsl:text>   </xsl:text> </xsl:if> <a href="#{$target}"> <xsl:choose> <xsl:when test="$waschanged!=''"> <ins><xsl:value-of select="$title"/></ins> <del><xsl:value-of select="$oldtitle"/></del> </xsl:when> <xsl:when test="$name"> <xsl:call-template name="render-name-ref"> <xsl:with-param name="n" select="$name/node()"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:value-of select="$title"/> </xsl:otherwise> </xsl:choose> </a> </xsl:otherwise> </xsl:choose> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="back-toc"> <xsl:if test="//cref and $xml2rfc-comments='yes' and $xml2rfc-inline!='yes'"> <li> <xsl:call-template name="insert-toc-line"> <xsl:with-param name="target" select="concat($anchor-pref,'comments')"/> <xsl:with-param name="title" select="'Editorial Comments'"/> </xsl:call-template> </li> </xsl:if> <xsl:if test="$xml2rfc-ext-authors-section='before-appendices'"> <xsl:apply-templates select="/rfc/front" mode="toc" /> </xsl:if> <xsl:apply-templates select="back/*[not(self::references)]" mode="toc" /> <!-- insert the index if index entries exist --> <xsl:if test="$has-index"> <li> <xsl:call-template name="insert-toc-line"> <xsl:with-param name="target" select="concat($anchor-pref,'index')"/> <xsl:with-param name="title" select="'Index'"/> </xsl:call-template> </li> </xsl:if> <xsl:if test="$xml2rfc-ext-authors-section='end'"> <xsl:apply-templates select="/rfc/front" mode="toc" /> </xsl:if> <!-- copyright statements --> <xsl:if test="$xml2rfc-private='' and not($no-copylong)"> <li> <xsl:call-template name="insert-toc-line"> <xsl:with-param name="target" select="concat($anchor-pref,'ipr')"/> <xsl:with-param name="title" select="'Intellectual Property and Copyright Statements'"/> </xsl:call-template> </li> </xsl:if> </xsl:template> <xsl:template match="front" mode="toc"> <xsl:variable name="authors-title"> <xsl:call-template name="get-authors-section-title"/> </xsl:variable> <xsl:variable name="authors-number"> <xsl:call-template name="get-authors-section-number"/> </xsl:variable> <xsl:if test="$authors-number!='suppress' and $xml2rfc-authorship!='no'"> <li> <xsl:call-template name="insert-toc-line"> <xsl:with-param name="target" select="concat($anchor-pref,'authors')"/> <xsl:with-param name="title" select="$authors-title"/> <xsl:with-param name="number" select="$authors-number"/> </xsl:call-template> </li> </xsl:if> </xsl:template> <xsl:template name="references-toc"> <!-- distinguish two cases: (a) single references element (process as toplevel section; (b) multiple references sections (add one toplevel container with subsection) --> <xsl:variable name="refsecs" select="/rfc/back/references|/rfc/back/ed:replace/ed:ins/references"/> <xsl:choose> <xsl:when test="count($refsecs) = 0"> <!-- nop --> </xsl:when> <xsl:when test="count($refsecs) = 1"> <xsl:for-each select="$refsecs"> <xsl:variable name="title"> <xsl:choose> <xsl:when test="@title!=''"><xsl:value-of select="@title" /></xsl:when> <xsl:otherwise><xsl:value-of select="$xml2rfc-refparent"/></xsl:otherwise> </xsl:choose> </xsl:variable> <li> <xsl:call-template name="insert-toc-line"> <xsl:with-param name="number"> <xsl:call-template name="get-references-section-number"/> </xsl:with-param> <xsl:with-param name="target" select="concat($anchor-pref,'references')"/> <xsl:with-param name="title" select="$title"/> <xsl:with-param name="name" select="name"/> </xsl:call-template> <xsl:if test="references"> <ul> <xsl:for-each select="references"> <xsl:call-template name="references-toc-entry"/> </xsl:for-each> </ul> </xsl:if> </li> </xsl:for-each> </xsl:when> <xsl:otherwise> <li> <!-- insert pseudo container --> <xsl:call-template name="insert-toc-line"> <xsl:with-param name="number"> <xsl:call-template name="get-references-section-number"/> </xsl:with-param> <xsl:with-param name="target" select="concat($anchor-pref,'references')"/> <xsl:with-param name="title" select="$xml2rfc-refparent"/> </xsl:call-template> <ul> <!-- ...with subsections... --> <xsl:for-each select="$refsecs"> <xsl:call-template name="references-toc-entry"/> </xsl:for-each> </ul> </li> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="references-toc-entry"> <xsl:variable name="title"> <xsl:choose> <xsl:when test="@title!=''"><xsl:value-of select="@title" /></xsl:when> <xsl:otherwise><xsl:value-of select="$xml2rfc-refparent"/></xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:variable name="sectionNumber"> <xsl:call-template name="get-section-number" /> </xsl:variable> <xsl:variable name="num"> <xsl:number level="any"/> </xsl:variable> <li> <xsl:call-template name="insert-toc-line"> <xsl:with-param name="number" select="$sectionNumber"/> <xsl:with-param name="target" select="concat($anchor-pref,'references','.',$num)"/> <xsl:with-param name="title" select="$title"/> <xsl:with-param name="name" select="name"/> </xsl:call-template> <xsl:if test="references"> <ul> <xsl:for-each select="references"> <xsl:call-template name="references-toc-entry"/> </xsl:for-each> </ul> </xsl:if> </li> </xsl:template> <!-- suppress xml2rfc preptool artefacts: see https://github.com/ietf-tools/xml2rfc/issues/791 --> <xsl:template match="section[ancestor::*/@prepTime][author]" mode="toc"/> <xsl:template match="back[ancestor::*/@prepTime]/section[@numbered='false' and name/@slugifiedName='name-index']" mode="toc"/> <xsl:template match="section|appendix" mode="toc"> <xsl:variable name="sectionNumber"> <xsl:call-template name="get-section-number" /> </xsl:variable> <xsl:variable name="target"> <xsl:choose> <xsl:when test="@anchor"><xsl:value-of select="@anchor" /></xsl:when> <xsl:otherwise><xsl:value-of select="$anchor-pref"/>section.<xsl:value-of select="$sectionNumber" /></xsl:otherwise> </xsl:choose> </xsl:variable> <!-- obtain content, just to check whether we need to recurse at all --> <xsl:variable name="content"> <li> <xsl:call-template name="insert-toc-line"> <xsl:with-param name="number" select="$sectionNumber"/> <xsl:with-param name="target" select="$target"/> <xsl:with-param name="title" select="@title"/> <xsl:with-param name="name" select="name"/> <xsl:with-param name="tocparam" select="@toc"/> <xsl:with-param name="oldtitle" select="@ed:old-title"/> <xsl:with-param name="waschanged" select="@ed:resolves"/> </xsl:call-template> <ul> <xsl:apply-templates mode="toc" /> </ul> </li> </xsl:variable> <xsl:if test="$content!=''"> <li> <xsl:call-template name="insert-toc-line"> <xsl:with-param name="number" select="$sectionNumber"/> <xsl:with-param name="target" select="$target"/> <xsl:with-param name="title" select="@title"/> <xsl:with-param name="name" select="name"/> <xsl:with-param name="tocparam" select="@toc"/> <xsl:with-param name="oldtitle" select="@ed:old-title"/> <xsl:with-param name="waschanged" select="@ed:resolves"/> </xsl:call-template> <!-- obtain nested content, just to check whether we need to recurse at all --> <xsl:variable name="nested-content"> <ul> <xsl:apply-templates mode="toc" /> </ul> </xsl:variable> <!-- only recurse if we need to (do not produce useless list container) --> <xsl:if test="$nested-content!=''"> <ul> <xsl:apply-templates mode="toc" /> </ul> </xsl:if> </li> </xsl:if> </xsl:template> <xsl:template match="middle" mode="toc"> <xsl:apply-templates mode="toc" /> <xsl:call-template name="references-toc" /> </xsl:template> <xsl:template match="rfc" mode="toc"> <xsl:apply-templates select="middle" mode="toc" /> <xsl:call-template name="back-toc" /> </xsl:template> <xsl:template match="ed:del|ed:ins|ed:replace" mode="toc"> <xsl:apply-templates mode="toc" /> </xsl:template> <xsl:template match="*|text()" mode="toc" /> <xsl:template name="insertTocAppendix"> <xsl:if test="//figure[@title!='' or @anchor!='' or name]"> <ul class="toc"> <li> <xsl:text>Figures</xsl:text> <ul> <xsl:for-each select="//figure"> <xsl:variable name="n"><xsl:call-template name="get-figure-number"/></xsl:variable> <xsl:variable name="title"> <xsl:if test="not(starts-with($n,'u'))"> <xsl:text>Figure </xsl:text> <xsl:value-of select="$n"/> <xsl:if test="@title!='' or name">: </xsl:if> </xsl:if> <xsl:choose> <xsl:when test="name"> <xsl:call-template name="render-name-ref"> <xsl:with-param name="n" select="name/node()"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:value-of select="normalize-space(@title)" /> </xsl:otherwise> </xsl:choose> </xsl:variable> <li> <xsl:call-template name="insert-toc-line"> <xsl:with-param name="target" select="concat($anchor-pref,'figure.',$n)" /> <xsl:with-param name="title" select="$title" /> </xsl:call-template> </li> </xsl:for-each> </ul> </li> </ul> </xsl:if> <!-- experimental --> <xsl:if test="//ed:issue"> <xsl:call-template name="insertIssuesList" /> </xsl:if> </xsl:template> <xsl:template name="reference-name"> <xsl:param name="node" select="."/> <xsl:param name="anchor"/> <xsl:for-each select="$node"> <xsl:text>[</xsl:text> <xsl:choose> <xsl:when test="$anchor!=''"> <a href="#{$anchor}" class="smpl"> <xsl:call-template name="reference-name-text"/> </a> </xsl:when> <xsl:otherwise> <xsl:call-template name="reference-name-text"/> </xsl:otherwise> </xsl:choose> <xsl:text>]</xsl:text> </xsl:for-each> </xsl:template> <xsl:template name="reference-name-text"> <xsl:choose> <xsl:when test="$xml2rfc-symrefs!='no' and ancestor::ed:del"> <xsl:variable name="unprefixed" select="substring-after(@anchor,'deleted-')"/> <xsl:choose> <xsl:when test="$unprefixed!=''"> <xsl:value-of select="$unprefixed"/> </xsl:when> <xsl:otherwise> <xsl:if test="count(//reference[@anchor=current()/@anchor])!=1"> <xsl:message>Deleted duplicate anchors should have the prefix "deleted-": <xsl:value-of select="@anchor"/></xsl:message> </xsl:if> <xsl:value-of select="@anchor"/> </xsl:otherwise> </xsl:choose> </xsl:when> <xsl:when test="$xml2rfc-symrefs!='no'"> <xsl:choose> <xsl:when test="$src/rfc/back/displayreference[@target=current()/@anchor]"> <xsl:value-of select="$src/rfc/back/displayreference[@target=current()/@anchor]/@to"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="@anchor"/> </xsl:otherwise> </xsl:choose> </xsl:when> <xsl:when test="ancestor::ed:del"> <xsl:text>del</xsl:text> </xsl:when> <xsl:otherwise> <xsl:number level="any" count="reference[not(ancestor::ed:del)]"/> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="replace-substring"> <xsl:param name="string" /> <xsl:param name="replace" /> <xsl:param name="by" /> <xsl:choose> <xsl:when test="contains($string,$replace)"> <xsl:value-of select="concat(substring-before($string, $replace),$by)" /> <xsl:call-template name="replace-substring"> <xsl:with-param name="string" select="substring-after($string,$replace)" /> <xsl:with-param name="replace" select="$replace" /> <xsl:with-param name="by" select="$by" /> </xsl:call-template> </xsl:when> <xsl:otherwise><xsl:value-of select="$string" /></xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="rfc-or-id-link"> <xsl:param name="name" /> <xsl:choose> <xsl:when test="starts-with($name,'draft-')"> <xsl:variable name="uri"> <xsl:call-template name="compute-internet-draft-uri"> <xsl:with-param name="internet-draft" select="$name"/> </xsl:call-template> </xsl:variable> <a href="{$uri}"><xsl:value-of select="$name"/></a> <xsl:call-template name="check-front-matter-ref"> <xsl:with-param name="name" select="$name"/> </xsl:call-template> </xsl:when> <xsl:when test="string(number($name))=$name"> <xsl:variable name="uri"> <xsl:variable name="refs" select="exslt:node-set($includeDirectives)//reference|/rfc/back/references//reference"/> <xsl:variable name="ref" select="$refs[not(starts-with(front/title,'Erratum ID')) and seriesInfo[@name='RFC' and @value=$name]]"/> <xsl:choose> <xsl:when test="$ref"> <xsl:value-of select="concat('#',$ref/@anchor)"/> </xsl:when> <xsl:otherwise> <xsl:call-template name="compute-rfc-uri"> <xsl:with-param name="rfc" select="$name"/> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:variable> <a href="{$uri}"><xsl:value-of select="$name"/></a> <xsl:call-template name="check-front-matter-ref"> <xsl:with-param name="name" select="$name"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:value-of select="$name"/> <xsl:call-template name="error"> <xsl:with-param name="msg">In metadata obsoletes/updates, RFC number of draft name is expected - found: '<xsl:value-of select="$name"/>'</xsl:with-param> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="rfclist"> <xsl:param name="list" /> <xsl:choose> <xsl:when test="contains($list,',')"> <xsl:variable name="rfcNo" select="substring-before($list,',')" /> <xsl:call-template name="rfc-or-id-link"> <xsl:with-param name="name" select="$rfcNo"/> </xsl:call-template> <xsl:text>, </xsl:text> <xsl:call-template name="rfclist"> <xsl:with-param name="list" select="normalize-space(substring-after($list,','))" /> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:variable name="rfcNo" select="$list" /> <xsl:call-template name="rfc-or-id-link"> <xsl:with-param name="name" select="$rfcNo"/> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="check-front-matter-ref"> <xsl:param name="name"/> <xsl:variable name="refs" select="exslt:node-set($includeDirectives)//reference|/rfc/back/references//reference"/> <xsl:choose> <xsl:when test="starts-with($name,'draft-')"> <xsl:if test="not($refs//seriesInfo[@name='Internet-Draft' and @value=$name])"> <xsl:call-template name="warning"> <xsl:with-param name="msg" select="concat('front matter mentions I-D ',$name,' for which there is no reference element')"/> </xsl:call-template> </xsl:if> </xsl:when> <xsl:otherwise> <xsl:variable name="ref" select="$refs[not(starts-with(front/title,'Erratum ID')) and seriesInfo[@name='RFC' and @value=$name]]"/> <xsl:if test="not($ref)"> <xsl:call-template name="warning"> <xsl:with-param name="msg" select="concat('front matter mentions RFC ',$name,' for which there is no reference element')"/> </xsl:call-template> </xsl:if> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="check-anchor"> <xsl:if test="@anchor and @anchor!=''"> <!-- check validity of anchor name --> <xsl:variable name="t" select="@anchor"/> <xsl:variable name="tstart" select="substring($t,1,1)"/> <!-- we only check for disallowed ASCII characters for now --> <xsl:variable name="not-namestartchars"> !"#$%&'()*+,-./0123456789;<=>?@[\]^`[|}~</xsl:variable> <xsl:if test="$tstart!=translate($tstart,$not-namestartchars,'')"> <xsl:call-template name="error"> <xsl:with-param name="msg" select="concat('anchor "',$t,'" can not start with character "',$tstart,'"')"/> </xsl:call-template> </xsl:if> <xsl:call-template name="check-anchor-non-start"> <xsl:with-param name="f" select="$t"/> <xsl:with-param name="t" select="$t"/> </xsl:call-template> </xsl:if> </xsl:template> <xsl:template name="check-anchor-non-start"> <xsl:param name="f"/> <xsl:param name="t"/> <xsl:variable name="not-namechars"> !"#$%&'()*+,/;<=>?@[\]^`[|}~</xsl:variable> <xsl:choose> <xsl:when test="$t=''"> <!-- Done --> </xsl:when> <xsl:otherwise> <xsl:variable name="s" select="substring($t,1,1)"/> <xsl:choose> <xsl:when test="$s!=translate($s,$not-namechars,'')"> <xsl:call-template name="error"> <xsl:with-param name="msg" select="concat('anchor "',$f,'" contains invalid character "',$s,'" at position ',string-length($f) - string-length($t))"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:call-template name="check-anchor-non-start"> <xsl:with-param name="f" select="$f"/> <xsl:with-param name="t" select="substring($t,2)"/> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="sluggy-anchor"> <xsl:if test="self::section and (not(@anchor) or @anchor='')"> <xsl:variable name="fr">ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.'"()+-_ :!%,/@=<>*—
</xsl:variable> <xsl:variable name="to">abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789.__----_--.-------.--</xsl:variable> <xsl:variable name="canslug" select="translate(normalize-space(concat(@title,name)),$fr,'')=''"/> <xsl:if test="$canslug"> <xsl:variable name="slug" select="translate(normalize-space(concat(@title,name)),$fr,$to)"/> <xsl:variable name="conflicts" select="//section[not(@anchor) and $slug=translate(normalize-space(concat(@title,name)),$fr,$to)]"/> <xsl:choose> <xsl:when test="count($conflicts)>1"> <xsl:variable name="c" select="preceding::*[not(@anchor) and $slug=translate(normalize-space(concat(@title,name)),$fr,$to)]"/> <xsl:value-of select="concat('n-',$slug,'_',(1+count($c)))"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="concat('n-',$slug)"/> </xsl:otherwise> </xsl:choose> </xsl:if> </xsl:if> </xsl:template> <xsl:template name="copy-anchor"> <xsl:call-template name="check-anchor"/> <xsl:choose> <xsl:when test="@anchor and @anchor!=''"> <xsl:attribute name="id"><xsl:value-of select="@anchor"/></xsl:attribute> </xsl:when> <xsl:when test="self::section"> <xsl:variable name="slug"> <xsl:call-template name="sluggy-anchor"/> </xsl:variable> <xsl:if test="$slug!=''"> <xsl:attribute name="id"><xsl:value-of select="$slug"/></xsl:attribute> </xsl:if> </xsl:when> <xsl:otherwise/> </xsl:choose> </xsl:template> <xsl:template name="rfclist-for-dcmeta"> <xsl:param name="list" /> <xsl:choose> <xsl:when test="contains($list,',')"> <xsl:variable name="rfcNo" select="substring-before($list,',')" /> <meta name="dct.replaces" content="urn:ietf:rfc:{$rfcNo}" /> <xsl:call-template name="rfclist-for-dcmeta"> <xsl:with-param name="list" select="normalize-space(substring-after($list,','))" /> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:variable name="rfcNo" select="$list" /> <meta name="dct.replaces" content="urn:ietf:rfc:{$rfcNo}" /> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="get-paragraph-number"> <xsl:param name="delim">.p.</xsl:param> <xsl:choose> <!-- inside artset --> <xsl:when test="parent::artset"> <xsl:for-each select=".."> <xsl:call-template name="get-paragraph-number"/> </xsl:for-each> </xsl:when> <!-- no numbering inside certain containers --> <xsl:when test="ancestor::dl or ancestor::figure or ancestor::ol or ancestor::ul or ancestor::ed:del or ancestor::ed:ins"/> <xsl:when test="parent::blockquote or parent::x:blockquote"> <!-- boilerplate --> <xsl:for-each select="parent::blockquote|parent::x:blockquote"><xsl:call-template name="get-paragraph-number" />.</xsl:for-each> <xsl:number count="artset|artwork|aside|blockquote|dl|ol|sourcecode|t|ul|x:blockquote|x:note"/> </xsl:when> <xsl:when test="parent::aside or parent::x:note"> <!-- boilerplate --> <xsl:for-each select="parent::aside|parent::x:note"><xsl:call-template name="get-paragraph-number" />.</xsl:for-each> <xsl:number count="artset|artwork|aside|blockquote|dl|ol|sourcecode|t|ul|x:blockquote|x:note"/> </xsl:when> <xsl:when test="ancestor::section"> <!-- get section number of ancestor section element, then add t number --> <xsl:for-each select="ancestor::section[1]"><xsl:call-template name="get-section-number" /><xsl:value-of select="$delim"/></xsl:for-each> <xsl:variable name="b"><xsl:number count="artset|artwork|aside|blockquote|dl|ol|sourcecode|t|ul|x:blockquote|x:note"/></xsl:variable> <xsl:choose> <xsl:when test="parent::section and ../@removeInRFC='true' and ../t[1]!=$section-removeInRFC"> <xsl:value-of select="1 + $b"/> </xsl:when> <xsl:otherwise><xsl:value-of select="$b"/></xsl:otherwise> </xsl:choose> </xsl:when> <xsl:when test="ancestor::note"> <!-- get section number of ancestor note element, then add t number --> <xsl:for-each select="ancestor::note[1]"><xsl:call-template name="get-section-number" /><xsl:value-of select="$delim"/></xsl:for-each> <xsl:variable name="b"><xsl:number count="artset|artwork|aside|blockquote|dl|ol|sourcecode|t|ul|x:blockquote|x:note"/></xsl:variable> <xsl:choose> <xsl:when test="parent::note and ../@removeInRFC='true' and ../t[1]!=$note-removeInRFC"> <xsl:value-of select="1 + $b"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="$b"/> </xsl:otherwise> </xsl:choose> </xsl:when> <!-- abstract --> <xsl:when test="ancestor::abstract"> <xsl:text>p.</xsl:text> <xsl:number count="t|x:blockquote|blockquote|x:note|aside|ul|dl|ol|artwork|artset|sourcecode"/> </xsl:when> <xsl:otherwise/> </xsl:choose> </xsl:template> <xsl:template name="attach-paragraph-number-as-id"> <xsl:variable name="p"> <xsl:call-template name="get-paragraph-number"/> </xsl:variable> <xsl:variable name="container"> <xsl:choose> <xsl:when test="ancestor::abstract">abstract</xsl:when> <xsl:when test="ancestor::note">note</xsl:when> <xsl:when test="ancestor::boilerplate">boilerplate</xsl:when> <xsl:otherwise>section</xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:if test="$p!='' and not(ancestor::list)"> <xsl:attribute name="id"><xsl:value-of select="concat($anchor-pref,$container,'.',$p)"/></xsl:attribute> </xsl:if> </xsl:template> <xsl:template name="editingMark"> <xsl:if test="$xml2rfc-editing='yes' and ancestor::rfc"> <sup class="editingmark"><span><xsl:number level="any" count="postamble|preamble|t"/></span> </sup> </xsl:if> </xsl:template> <!-- internal ref support --> <xsl:key name="anchor-item-alias" match="//*[@anchor and (x:anchor-alias/@value or ed:replace/ed:ins/x:anchor-alias)]" use="x:anchor-alias/@value | ed:replace/ed:ins/x:anchor-alias/@value"/> <xsl:template match="x:ref"> <xsl:variable name="val" select="normalize-space(.)"/> <xsl:variable name="target" select="key('anchor-item',$val) | key('anchor-item-alias',$val) | //reference/x:source[x:defines=$val]"/> <xsl:if test="count($target)>1"> <xsl:call-template name="warning"> <xsl:with-param name="msg">internal link target for '<xsl:value-of select="."/>' is ambiguous; picking first.</xsl:with-param> </xsl:call-template> </xsl:if> <xsl:choose> <xsl:when test="$target[1]/@anchor"> <a href="#{$target[1]/@anchor}" class="smpl"> <xsl:call-template name="copy-anchor"/> <!-- insert id when a backlink to this xref is needed in the index --> <xsl:if test="//iref[@x:for-anchor=$val] | //iref[@x:for-anchor='' and ../@anchor=$val]"> <xsl:attribute name="id"><xsl:call-template name="compute-extref-anchor"/></xsl:attribute> </xsl:if> <xsl:value-of select="."/> </a> </xsl:when> <xsl:when test="$target[1]/self::x:source"> <xsl:variable name="extdoc" select="document($target[1]/@href)"/> <xsl:variable name="nodes" select="$extdoc//*[@anchor and (x:anchor-alias/@value=$val)]"/> <xsl:choose> <xsl:when test="not($nodes)"> <xsl:call-template name="error"> <xsl:with-param name="msg">Anchor '<xsl:value-of select="$val"/>' not found in source file '<xsl:value-of select="$target[1]/@href"/>'.</xsl:with-param> </xsl:call-template> <xsl:value-of select="."/> </xsl:when> <xsl:otherwise> <xsl:variable name="t"> <xsl:call-template name="computed-auto-target"> <xsl:with-param name="bib" select="$target[1]/.."/> <xsl:with-param name="ref" select="$nodes[1]"/> </xsl:call-template> </xsl:variable> <a href="{$t}" class="smpl"> <xsl:value-of select="."/> </a> </xsl:otherwise> </xsl:choose> </xsl:when> <xsl:when test="//x:source"> <xsl:variable name="ref" select="."/> <xsl:variable name="out"> <!-- try referenced documents one by one --> <xsl:for-each select="//reference[x:source]"> <xsl:variable name="extdoc" select="document(x:source/@href)"/> <xsl:variable name="nodes" select="$extdoc//*[@anchor and (x:anchor-alias/@value=$val)]"/> <xsl:choose> <xsl:when test="not($nodes)"> <xsl:call-template name="trace"> <xsl:with-param name="msg">Anchor '<xsl:value-of select="$val"/>' not found in source file '<xsl:value-of select="x:source/@href"/>'.</xsl:with-param> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:call-template name="info"> <xsl:with-param name="msg">Anchor '<xsl:value-of select="$val"/>' found in source file '<xsl:value-of select="x:source/@href"/>'.</xsl:with-param> </xsl:call-template> <xsl:variable name="t"> <xsl:call-template name="computed-auto-target"> <xsl:with-param name="ref" select="$nodes[1]"/> </xsl:call-template> </xsl:variable> <a href="{$t}" class="smpl"> <xsl:value-of select="$ref"/> </a> </xsl:otherwise> </xsl:choose> </xsl:for-each> </xsl:variable> <xsl:copy-of select="$out"/> <xsl:variable name="plainout" select="normalize-space($out)"/> <xsl:if test="string-length($plainout)=0"> <xsl:call-template name="warning"> <xsl:with-param name="msg">Anchor '<xsl:value-of select="$val"/>' not found anywhere in references.</xsl:with-param> </xsl:call-template> <xsl:value-of select="$val"/> </xsl:if> <xsl:if test="string-length($plainout)!=string-length($val)"> <xsl:call-template name="error"> <xsl:with-param name="msg">Multiple targets found for anchor '<xsl:value-of select="$val"/>' - need to disambiguate.</xsl:with-param> </xsl:call-template> </xsl:if> </xsl:when> <xsl:otherwise> <xsl:call-template name="warning"> <xsl:with-param name="msg">internal link target for '<xsl:value-of select="."/>' does not exist.</xsl:with-param> </xsl:call-template> <xsl:value-of select="."/> </xsl:otherwise> </xsl:choose> </xsl:template> <!-- Nothing to do here --> <xsl:template match="x:anchor-alias" /> <!-- Quotes --> <xsl:template match="x:q"> <q> <xsl:copy-of select="@cite"/> <xsl:apply-templates/> </q> </xsl:template> <!-- Notes --> <xsl:template match="x:note|aside"> <xsl:call-template name="check-no-text-content"/> <div> <xsl:call-template name="attach-paragraph-number-as-id"/> <aside> <xsl:call-template name="copy-anchor"/> <xsl:apply-templates select="*"/> </aside> </div> </xsl:template> <xsl:variable name="has-bcp14-reference" select="$all-refs//seriesInfo[@name='RFC' and @value='2119'] or $all-refs//seriesInfo[@name='BCP' and @value='14']"/> <xsl:template match="x:bcp14|bcp14"> <!-- check valid BCP14 keywords, then emphasize them --> <xsl:variable name="c" select="normalize-space(translate(.,' ',' '))"/> <xsl:choose> <xsl:when test="$c='MUST' or $c='REQUIRED' or $c='SHALL' or $c='MUST NOT' or $c='SHALL NOT' or $c='SHOULD' or $c='RECOMMENDED' or $c='SHOULD NOT' or $c='NOT RECOMMENDED' or $c='MAY' or $c='OPTIONAL'"> <em class="bcp14"><xsl:value-of select="."/></em> </xsl:when> <xsl:otherwise> <xsl:value-of select="."/> <xsl:call-template name="error"> <xsl:with-param name="msg">Unknown BCP14 keyword: '<xsl:value-of select="$c"/>'</xsl:with-param> </xsl:call-template> </xsl:otherwise> </xsl:choose> <xsl:if test="not($has-bcp14-reference)"> <xsl:call-template name="warning"> <xsl:with-param name="msg">BCP14 markup used without referencing RFC 2119 or BCP 14</xsl:with-param> </xsl:call-template> </xsl:if> </xsl:template> <xsl:template match="x:blockquote|blockquote"> <div> <xsl:call-template name="insertInsDelClass"/> <xsl:call-template name="editingMark" /> <xsl:call-template name="attach-paragraph-number-as-id"/> <blockquote> <xsl:call-template name="copy-anchor"/> <xsl:copy-of select="@cite"/> <xsl:choose> <xsl:when test="t|ul|ol|dl|artwork|figure|sourcecode"> <xsl:apply-templates/> </xsl:when> <xsl:otherwise> <p> <xsl:apply-templates/> </p> </xsl:otherwise> </xsl:choose> <xsl:if test="@quotedFrom"> <cite> <xsl:text>— </xsl:text> <xsl:choose> <xsl:when test="@cite"><a href="{@cite}"><xsl:value-of select="@quotedFrom"/></a></xsl:when> <xsl:otherwise><xsl:value-of select="@quotedFrom"/></xsl:otherwise> </xsl:choose> </cite> </xsl:if> </blockquote> </div> </xsl:template> <!-- Definitions --> <xsl:template match="x:dfn"> <dfn> <xsl:call-template name="copy-anchor"/> <xsl:apply-templates/> </dfn> </xsl:template> <!-- headings --> <xsl:template match="x:h"> <b> <xsl:call-template name="copy-anchor"/> <xsl:apply-templates/> </b> </xsl:template> <!-- superscripts --> <xsl:template match="x:sup|sup"> <sup> <xsl:call-template name="copy-anchor"/> <xsl:apply-templates/> </sup> </xsl:template> <!-- subscripts --> <xsl:template match="sub"> <sub> <xsl:call-template name="copy-anchor"/> <xsl:apply-templates/> </sub> </xsl:template> <!-- bold --> <xsl:template match="x:highlight"> <b> <xsl:call-template name="copy-anchor"/> <xsl:apply-templates/> </b> </xsl:template> <!-- measuring lengths --> <xsl:template match="x:length-of"> <xsl:variable name="target" select="//*[@anchor=current()/@target]"/> <xsl:if test="count($target)!=1"> <xsl:call-template name="error"> <xsl:with-param name="msg" select="concat('@target ',@target,' defined ',count($target),' times.')"/> </xsl:call-template> </xsl:if> <xsl:variable name="content"> <xsl:apply-templates select="$target"/> </xsl:variable> <xsl:variable name="lineends" select="string-length($content) - string-length(translate($content,' ',''))"/> <xsl:variable name="indents"> <xsl:choose> <xsl:when test="@indented"> <xsl:value-of select="number(@indented) * $lineends"/> </xsl:when> <xsl:otherwise>0</xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:value-of select="string-length($content) + $lineends - $indents"/> </xsl:template> <!-- Almost Nop --> <xsl:template match="x:span"> <xsl:choose> <xsl:when test="@x:lang and $prettyprint-class!=''"> <code class="{$prettyprint-class}"> <xsl:call-template name="copy-anchor"/> <xsl:apply-templates/> </code> </xsl:when> <xsl:otherwise> <span> <xsl:call-template name="copy-anchor"/> <xsl:apply-templates/> </span> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="x:parse-xml"> <xsl:apply-templates/> <xsl:if test="function-available('exslt:node-set')"> <xsl:variable name="cleaned"> <xsl:apply-templates mode="cleanup-edits"/> </xsl:variable> <xsl:if test="$xml2rfc-ext-trace-parse-xml='yes'"> <xsl:call-template name="trace"> <xsl:with-param name="msg" select="concat('Parsing XML: ', $cleaned)"/> </xsl:call-template> </xsl:if> <xsl:choose> <xsl:when test="function-available('myns:parseXml')" use-when="function-available('myns:parseXml')"> <xsl:if test="myns:parseXml(concat($cleaned,''))!=''"> <xsl:call-template name="error"> <xsl:with-param name="msg" select="concat('Parse error in XML: ', myns:parseXml(concat($cleaned,'')))"/> </xsl:call-template> </xsl:if> </xsl:when> <xsl:when test="function-available('saxon:parse')" use-when="function-available('saxon:parse')"> <xsl:variable name="parsed" select="saxon:parse(concat($cleaned,''))"/> <xsl:if test="$parsed='foo'"> <xsl:comment>should not get here</xsl:comment> </xsl:if> </xsl:when> <xsl:when test="false()"></xsl:when> <xsl:otherwise></xsl:otherwise> </xsl:choose> </xsl:if> </xsl:template> <!-- inlined RDF support --> <xsl:template match="rdf:Description"> <!-- ignore --> </xsl:template> <!-- cleanup for ins/del --> <xsl:template match="comment()|@*" mode="cleanup-edits"><xsl:copy/></xsl:template> <xsl:template match="text()" mode="cleanup-edits"><xsl:copy/></xsl:template> <xsl:template match="/" mode="cleanup-edits"> <xsl:copy><xsl:apply-templates select="node()" mode="cleanup-edits" /></xsl:copy> </xsl:template> <xsl:template match="ed:del" mode="cleanup-edits"/> <xsl:template match="ed:replace" mode="cleanup-edits"> <xsl:apply-templates mode="cleanup-edits"/> </xsl:template> <xsl:template match="ed:ins" mode="cleanup-edits"> <xsl:apply-templates mode="cleanup-edits"/> </xsl:template> <!-- ABNF support --> <xsl:template name="to-abnf-char-sequence"> <xsl:param name="chars"/> <xsl:variable name="asciistring">  !"#$%&'()*+,-./<xsl:value-of select="$digits"/>:;<=>?@<xsl:value-of select="$ucase"/>[\]^_`<xsl:value-of select="$lcase"/>{|}~</xsl:variable> <xsl:variable name="hex">0123456789ABCDEF</xsl:variable> <xsl:variable name="c" select="substring($chars,1,1)"/> <xsl:variable name="r" select="substring($chars,2)"/> <xsl:variable name="pos" select="string-length(substring-before($asciistring,$c))"/> <xsl:choose> <xsl:when test="$pos >= 1"> <xsl:variable name="ascii" select="$pos + 31"/> <xsl:variable name="h" select="floor($ascii div 16)"/> <xsl:variable name="l" select="floor($ascii mod 16)"/> <xsl:value-of select="concat(substring($hex,1 + $h,1),substring($hex,1 + $l,1))"/> </xsl:when> <xsl:otherwise> <xsl:text>??</xsl:text> <xsl:call-template name="error"> <xsl:with-param name="msg" select="concat('unexpected character in ABNF char sequence: ',substring($chars,1,1))" /> </xsl:call-template> </xsl:otherwise> </xsl:choose> <xsl:if test="$r!=''"> <xsl:text>.</xsl:text> <xsl:call-template name="to-abnf-char-sequence"> <xsl:with-param name="chars" select="$r"/> </xsl:call-template> </xsl:if> </xsl:template> <xsl:template match="x:abnf-char-sequence"> <xsl:choose> <xsl:when test="substring(.,1,1) != '"' or substring(.,string-length(.),1) != '"'"> <xsl:call-template name="error"> <xsl:with-param name="msg" select="'contents of x:abnf-char-sequence needs to be quoted.'" /> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:text>%x</xsl:text> <xsl:call-template name="to-abnf-char-sequence"> <xsl:with-param name="chars" select="substring(.,2,string-length(.)-2)"/> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:template> <!-- box drawing --> <!-- nop for alignment --> <xsl:template match="x:x"/> <!-- box (top) --> <xsl:template match="x:bt"> <xsl:text>┌</xsl:text> <xsl:value-of select="translate(substring(.,2,string-length(.)-2),'-','─')"/> <xsl:text>┐</xsl:text> </xsl:template> <!-- box (center) --> <xsl:template match="x:bc"> <xsl:variable name="first" select="substring(.,1)"/> <xsl:variable name="content" select="substring(.,2,string-length(.)-2)"/> <xsl:variable name="is-delimiter" select="translate($content,'-','')=''"/> <xsl:choose> <xsl:when test="$is-delimiter"> <xsl:text>├</xsl:text> <xsl:value-of select="translate($content,'-','─')"/> <xsl:text>┤</xsl:text> </xsl:when> <xsl:when test="*"> <xsl:for-each select="*|text()"> <xsl:choose> <xsl:when test="position()=1"> <xsl:text>│</xsl:text> <xsl:value-of select="substring(.,2)"/> </xsl:when> <xsl:when test="position()=last()"> <xsl:value-of select="substring(.,1,string-length(.)-1)"/> <xsl:text>│</xsl:text> </xsl:when> <xsl:otherwise> <xsl:apply-templates select="."/> </xsl:otherwise> </xsl:choose> </xsl:for-each> </xsl:when> <xsl:otherwise> <xsl:text>│</xsl:text> <xsl:value-of select="$content"/> <xsl:text>│</xsl:text> </xsl:otherwise> </xsl:choose> </xsl:template> <!-- box (bottom) --> <xsl:template match="x:bb"> <xsl:text>└</xsl:text> <xsl:value-of select="translate(substring(.,2,string-length(.)-2),'-','─')"/> <xsl:text>┘</xsl:text> </xsl:template> <!-- author handling extensions --> <xsl:template match="x:include-author"> <xsl:for-each select="/*/front/author[@anchor=current()/@target]"> <xsl:apply-templates select="."/> </xsl:for-each> </xsl:template> <!-- boilerplate --> <xsl:template match="boilerplate"> <xsl:apply-templates/> </xsl:template> <!-- experimental annotation support --> <xsl:template match="ed:issueref"> <xsl:choose> <xsl:when test=".=//ed:issue/@name"> <a href="#{$anchor-pref}issue.{.}"> <xsl:apply-templates/> </a> </xsl:when> <xsl:when test="@href"> <a href="{@href}" id="{$anchor-pref}issue.{.}"> <xsl:apply-templates/> </a> </xsl:when> <xsl:otherwise> <xsl:call-template name="warning"> <xsl:with-param name="msg">Dangling ed:issueref: <xsl:value-of select="."/></xsl:with-param> </xsl:call-template> <xsl:apply-templates/> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="ed:issue"> <xsl:variable name="class"> <xsl:choose> <xsl:when test="@status='closed'">closedissue</xsl:when> <xsl:otherwise>openissue</xsl:otherwise> </xsl:choose> </xsl:variable> <table class="{$class}"> <tr> <td colspan="3"> <a id="{$anchor-pref}issue.{@name}"> <xsl:choose> <xsl:when test="@status='closed'"> <xsl:attribute name="class">closed-issue</xsl:attribute> </xsl:when> <xsl:when test="@status='editor'"> <xsl:attribute name="class">editor-issue</xsl:attribute> </xsl:when> <xsl:otherwise> <xsl:attribute name="class">open-issue</xsl:attribute> </xsl:otherwise> </xsl:choose> <xsl:text> I </xsl:text> </a> <xsl:text> </xsl:text> <xsl:choose> <xsl:when test="@href"> <em><a href="{@href}"><xsl:value-of select="@name" /></a></em> </xsl:when> <xsl:when test="@alternate-href"> <em>[<a href="{@alternate-href}">alternate link</a>]</em> </xsl:when> <xsl:otherwise> <em><xsl:value-of select="@name" /></em> </xsl:otherwise> </xsl:choose>   (type: <xsl:value-of select="@type"/>, status: <xsl:value-of select="@status"/>) </td> </tr> <xsl:apply-templates select="ed:item"/> <xsl:apply-templates select="ed:resolution"/> <xsl:variable name="changes" select="//*[@ed:resolves=current()/@name or ed:resolves=current()/@name]" /> <xsl:if test="$changes"> <tr> <td class="top" colspan="3"> Associated changes in this document: <xsl:variable name="issue" select="@name"/> <xsl:for-each select="$changes"> <a href="#{$anchor-pref}change.{$issue}.{position()}"> <xsl:variable name="label"> <xsl:call-template name="get-section-number"/> </xsl:variable> <xsl:choose> <xsl:when test="$label!=''"><xsl:value-of select="$label"/></xsl:when> <xsl:otherwise><<xsl:value-of select="concat('#',$anchor-pref,'change.',$issue,'.',position())"/>></xsl:otherwise> </xsl:choose> </a> <xsl:if test="position()!=last()">, </xsl:if> </xsl:for-each> <xsl:text>.</xsl:text> </td> </tr> </xsl:if> </table> </xsl:template> <xsl:template match="ed:item"> <tr> <td class="top"> <xsl:if test="@entered-by"> <a href="mailto:{@entered-by}?subject={/rfc/@docName},%20{../@name}"> <i><xsl:value-of select="@entered-by"/></i> </a> </xsl:if> </td> <td class="topnowrap"> <xsl:value-of select="@date"/> </td> <td class="top"> <xsl:apply-templates select="node()" mode="issuehtml"/> </td> </tr> </xsl:template> <xsl:template match="ed:resolution"> <tr> <td class="top"> <xsl:if test="@entered-by"> <a href="mailto:{@entered-by}?subject={/rfc/@docName},%20{../@name}"><i><xsl:value-of select="@entered-by"/></i></a> </xsl:if> </td> <td class="topnowrap"> <xsl:value-of select="@datetime"/> </td> <td class="top"> <em>Resolution:</em> <xsl:apply-templates select="node()" mode="issuehtml"/> </td> </tr> </xsl:template> <xsl:template match="ed:annotation"> <em> <xsl:apply-templates/> </em> </xsl:template> <!-- special templates for handling XHTML in issues --> <xsl:template match="text()" mode="issuehtml"> <xsl:value-of select="."/> </xsl:template> <xsl:template match="*|@*" mode="issuehtml"> <xsl:message terminate="yes">Unexpected node in issue HTML: <xsl:value-of select="name(.)"/></xsl:message> </xsl:template> <xsl:template match="xhtml:a|xhtml:b|xhtml:br|xhtml:cite|xhtml:del|xhtml:em|xhtml:i|xhtml:ins|xhtml:q|xhtml:pre|xhtml:tt" mode="issuehtml"> <xsl:element name="{local-name()}"> <xsl:apply-templates select="@*|node()" mode="issuehtml"/> </xsl:element> </xsl:template> <xsl:template match="xhtml:p" mode="issuehtml"> <xsl:apply-templates select="node()" mode="issuehtml"/> <br class="p"/> </xsl:template> <xsl:template match="xhtml:a/@href|xhtml:q/@cite" mode="issuehtml"> <xsl:attribute name="{local-name(.)}"> <xsl:value-of select="."/> </xsl:attribute> </xsl:template> <xsl:template match="ed:issueref" mode="issuehtml"> <xsl:apply-templates select="."/> </xsl:template> <xsl:template match="ed:eref" mode="issuehtml"> <xsl:text><</xsl:text> <a href="{.}"><xsl:value-of select="."/></a> <xsl:text>></xsl:text> </xsl:template> <xsl:template name="insertIssuesList"> <h2 id="{$anchor-pref}issues-list" ><a href="#{$anchor-pref}issues-list">Issues list</a></h2> <table> <thead> <tr> <th>Id</th> <th>Type</th> <th>Status</th> <th>Date</th> <th>Raised By</th> </tr> </thead> <tbody> <xsl:for-each select="//ed:issue"> <xsl:sort select="@status" /> <xsl:sort select="@name" /> <tr> <td><a href="#{$anchor-pref}issue.{@name}"><xsl:value-of select="@name" /></a></td> <td><xsl:value-of select="@type" /></td> <td><xsl:value-of select="@status" /></td> <td><xsl:value-of select="ed:item[1]/@date" /></td> <td><a href="mailto:{ed:item[1]/@entered-by}?subject={/rfc/@docName},%20{@name}"><xsl:value-of select="ed:item[1]/@entered-by" /></a></td> </tr> </xsl:for-each> </tbody> </table> </xsl:template> <xsl:variable name="all-refs" select="/rfc/back//references/reference|exslt:node-set($includeDirectives)//reference|exslt:node-set($sourcedReferences)//reference"/> <xsl:template name="insert-diagnostics"> <!-- check anchor names --> <xsl:variable name="badAnchors" select="//*[starts-with(@anchor,$anchor-pref)]" /> <xsl:if test="$badAnchors"> <xsl:variable name="text"> <xsl:text>The following anchor names may collide with internally generated anchors because of their prefix "</xsl:text> <xsl:value-of select="$anchor-pref" /> <xsl:text>": </xsl:text> <xsl:for-each select="$badAnchors"> <xsl:value-of select="@anchor"/> <xsl:call-template name="lineno"/> <xsl:if test="position()!=last()">, </xsl:if> </xsl:for-each> </xsl:variable> <xsl:call-template name="warning"> <xsl:with-param name="msg"><xsl:value-of select="normalize-space($text)"/></xsl:with-param> <xsl:with-param name="lineno" select="false()"/> </xsl:call-template> </xsl:if> <xsl:variable name="badV3Anchors" select="//*[substring(@anchor,2,1)='-' and translate(substring(@anchor,1,1),$lcase,'')='']" /> <xsl:if test="$badV3Anchors"> <xsl:variable name="text"> <xsl:text>The following anchor names may collide with internally generated anchors in XML2RFCV3 mode because: </xsl:text> <xsl:for-each select="$badV3Anchors"> <xsl:value-of select="@anchor"/> <xsl:call-template name="lineno"/> <xsl:if test="position()!=last()">, </xsl:if> </xsl:for-each> </xsl:variable> <xsl:call-template name="warning"> <xsl:with-param name="msg"><xsl:value-of select="normalize-space($text)"/></xsl:with-param> <xsl:with-param name="lineno" select="false()"/> </xsl:call-template> </xsl:if> <!-- check ABNF syntax references --> <xsl:if test="//artwork[@type='abnf2616' or @type='abnf7230' or @type='abnf9110']|//sourcecode[@type='abnf2616' or type='abnf7320' or @type='abnf9110']"> <xsl:if test="not($all-refs//seriesInfo[@name='RFC' and (@value='2068' or @value='2616' or @value='7230' or @value='9110')]) and not($all-refs//seriesInfo[@name='Internet-Draft' and (starts-with(@value, 'draft-ietf-httpbis-p1-messaging-') or starts-with(@value, 'draft-ietf-httpbis-semantics-'))])"> <!-- check for draft-ietf-httpbis-p1-messaging- is for backwards compat --> <xsl:call-template name="warning"> <xsl:with-param name="msg">document uses HTTP-style ABNF syntax, but doesn't reference RFC 2068, RFC 2616, RFC 7230, or RFC 9110.</xsl:with-param> </xsl:call-template> </xsl:if> </xsl:if> <xsl:if test="//artwork[@type='abnf']|//sourcecode[@type='abnf']"> <xsl:if test="not($all-refs//seriesInfo[@name='RFC' and (@value='2234' or @value='4234' or @value='5234')])"> <xsl:call-template name="warning"> <xsl:with-param name="msg">document uses ABNF syntax, but doesn't reference RFC 2234, 4234 or 5234.</xsl:with-param> </xsl:call-template> </xsl:if> </xsl:if> <!-- check IDs --> <xsl:variable name="badTargets" select="//xref[not(ancestor::toc)][not(@target=//@anchor) and not(@target=//@pn) and not(@target=exslt:node-set($includeDirectives)//@anchor) and not(ancestor::ed:del)]" /> <xsl:if test="$badTargets"> <xsl:variable name="text"> <xsl:text>The following target names do not exist: </xsl:text> <xsl:for-each select="$badTargets"> <xsl:value-of select="@target"/> <xsl:if test="not(@target)">(@target attribute missing)</xsl:if> <xsl:call-template name="lineno"/> <xsl:if test="position()!=last()"> <xsl:text>, </xsl:text> </xsl:if> </xsl:for-each> </xsl:variable> <xsl:call-template name="warning"> <xsl:with-param name="msg"><xsl:value-of select="$text"/></xsl:with-param> </xsl:call-template> </xsl:if> </xsl:template> <!-- special change mark support, not supported by RFC2629 yet --> <xsl:template match="@ed:*" /> <xsl:template match="ed:del"> <xsl:call-template name="insert-issue-pointer"/> <del> <xsl:copy-of select="@*[namespace-uri()='']"/> <xsl:if test="not(@title) and ancestor-or-self::*[@ed:entered-by] and @datetime"> <xsl:attribute name="title"><xsl:value-of select="concat(@datetime,', ',ancestor-or-self::*[@ed:entered-by][1]/@ed:entered-by)"/></xsl:attribute> </xsl:if> <xsl:apply-templates /> </del> </xsl:template> <xsl:template match="ed:ins"> <xsl:call-template name="insert-issue-pointer"/> <ins> <xsl:copy-of select="@*[namespace-uri()='']"/> <xsl:if test="not(@title) and ancestor-or-self::*[@ed:entered-by] and @datetime"> <xsl:attribute name="title"><xsl:value-of select="concat(@datetime,', ',ancestor-or-self::*[@ed:entered-by][1]/@ed:entered-by)"/></xsl:attribute> </xsl:if> <xsl:apply-templates /> </ins> </xsl:template> <xsl:template name="insert-issue-pointer"> <xsl:param name="deleted-anchor"/> <xsl:variable name="change" select="."/> <xsl:for-each select="@ed:resolves|ed:resolves"> <xsl:variable name="resolves" select="."/> <!-- need the right context node for proper numbering --> <xsl:variable name="count"><xsl:for-each select=".."><xsl:number level="any" count="*[@ed:resolves=$resolves or ed:resolves=$resolves]" /></xsl:for-each></xsl:variable> <xsl:variable name="total" select="count(//*[@ed:resolves=$resolves or ed:resolves=$resolves])" /> <xsl:variable name="id"> <xsl:value-of select="$anchor-pref"/>change.<xsl:value-of select="$resolves"/>.<xsl:value-of select="$count" /> </xsl:variable> <xsl:choose> <!-- block level? --> <xsl:when test="not(ancestor::t) and not(ancestor::title) and not(ancestor::figure) and not($change/@ed:old-title)"> <div class="issuepointer {$css-noprint}"> <xsl:if test="not($deleted-anchor)"> <xsl:attribute name="id"><xsl:value-of select="$id"/></xsl:attribute> </xsl:if> <xsl:if test="$count > 1"> <a class="bg-issue" title="previous change for {$resolves}" href="#{$anchor-pref}change.{$resolves}.{$count - 1}">↑</a> </xsl:if> <a class="open-issue" href="#{$anchor-pref}issue.{$resolves}" title="resolves: {$resolves}"> <xsl:choose> <xsl:when test="//ed:issue[@name=$resolves and @status='closed']"> <xsl:attribute name="class">closed-issue</xsl:attribute> </xsl:when> <xsl:when test="//ed:issue[@name=$resolves and @status='editor']"> <xsl:attribute name="class">editor-issue</xsl:attribute> </xsl:when> <xsl:otherwise> <xsl:attribute name="class">open-issue</xsl:attribute> </xsl:otherwise> </xsl:choose> <xsl:text> I </xsl:text> </a> <xsl:if test="$count < $total"> <a class="bg-issue" title="next change for {$resolves}" href="#{$anchor-pref}change.{$resolves}.{$count + 1}">↓</a> </xsl:if> <xsl:text> </xsl:text> </div> </xsl:when> <xsl:otherwise> <xsl:if test="$count > 1"> <a class="bg-issue" title="previous change for {$resolves}" href="#{$anchor-pref}change.{$resolves}.{$count - 1}">↑</a> </xsl:if> <a title="resolves: {$resolves}" href="#{$anchor-pref}issue.{$resolves}"> <xsl:if test="not($deleted-anchor)"> <xsl:attribute name="id"><xsl:value-of select="$id"/></xsl:attribute> </xsl:if> <xsl:choose> <xsl:when test="//ed:issue[@name=$resolves and @status='closed']"> <xsl:attribute name="class">closed-issue <xsl:value-of select="$css-noprint"/></xsl:attribute> </xsl:when> <xsl:when test="//ed:issue[@name=$resolves and @status='editor']"> <xsl:attribute name="class">editor-issue <xsl:value-of select="$css-noprint"/></xsl:attribute> </xsl:when> <xsl:otherwise> <xsl:attribute name="class">open-issue <xsl:value-of select="$css-noprint"/></xsl:attribute> </xsl:otherwise> </xsl:choose> <xsl:text> I </xsl:text> </a> <xsl:if test="$count < $total"> <a class="bg-issue" title="next change for {$resolves}" href="#{$anchor-pref}change.{$resolves}.{$count + 1}">↓</a> </xsl:if> </xsl:otherwise> </xsl:choose> </xsl:for-each> </xsl:template> <xsl:template match="ed:replace"> <!-- we need to special-case things like lists and tables --> <xsl:choose> <xsl:when test="parent::list"> <xsl:apply-templates select="ed:del/node()" /> <xsl:apply-templates select="ed:ins/node()" /> </xsl:when> <xsl:when test="parent::references"> <xsl:apply-templates select="ed:del/node()" /> <xsl:apply-templates select="ed:ins/node()" /> </xsl:when> <xsl:otherwise> <xsl:if test="@cite"> <a class="editor-issue" href="{@cite}" target="_blank" title="see {@cite}"> <xsl:text> i </xsl:text> </a> </xsl:if> <xsl:call-template name="insert-issue-pointer"/> <xsl:if test="ed:del"> <del> <xsl:copy-of select="@*[namespace-uri()='']"/> <xsl:if test="not(@title) and ancestor-or-self::xsl:template[@ed:entered-by] and @datetime"> <xsl:attribute name="title"><xsl:value-of select="concat(@datetime,', ',ancestor-or-self::*[@ed:entered-by][1]/@ed:entered-by)"/></xsl:attribute> </xsl:if> <xsl:apply-templates select="ed:del/node()" /> </del> </xsl:if> <xsl:if test="ed:ins"> <ins> <xsl:copy-of select="@*[namespace-uri()='']"/> <xsl:if test="not(@title) and ancestor-or-self::*[@ed:entered-by] and @datetime"> <xsl:attribute name="title"><xsl:value-of select="concat(@datetime,', ',ancestor-or-self::*[@ed:entered-by][1]/@ed:entered-by)"/></xsl:attribute> </xsl:if> <xsl:apply-templates select="ed:ins/node()" /> </ins> </xsl:if> </xsl:otherwise> </xsl:choose> </xsl:template> <!-- convenience template for helping Mozilla (pre/ins inheritance problem) --> <xsl:template name="insertInsDelClass"> <xsl:if test="ancestor::ed:del"> <xsl:attribute name="class">del</xsl:attribute> </xsl:if> <xsl:if test="ancestor::ed:ins"> <xsl:attribute name="class">ins</xsl:attribute> </xsl:if> </xsl:template> <xsl:template name="sectionnumberAndEdits"> <xsl:choose> <xsl:when test="ancestor::ed:del"> <xsl:text>del-</xsl:text> <xsl:number count="ed:del//section" level="any"/> </xsl:when> <xsl:when test="@x:fixed-section-number and @x:fixed-section-number!=''"> <xsl:value-of select="@x:fixed-section-number"/> </xsl:when> <xsl:when test="(@x:fixed-section-number and @x:fixed-section-number='') or @numbered='false'"> <xsl:value-of select="$unnumbered"/> <xsl:number count="section[@x:fixed-section-number='' or @numbered='false']" level="any"/> </xsl:when> <xsl:when test="self::section and parent::ed:ins and local-name(../..)='replace'"> <xsl:for-each select="../.."><xsl:call-template name="sectionnumberAndEdits" /></xsl:for-each> <xsl:for-each select=".."> <xsl:if test="parent::ed:replace"> <xsl:for-each select=".."> <xsl:if test="parent::section">.</xsl:if> <xsl:variable name="cnt" select="1+count(preceding-sibling::section|preceding-sibling::ed:ins/section|preceding-sibling::ed:replace/ed:ins/section)" /> <xsl:choose> <xsl:when test="ancestor::back and not(ancestor::section)"><xsl:number format="A" value="$cnt"/></xsl:when> <xsl:otherwise><xsl:value-of select="$cnt"/></xsl:otherwise> </xsl:choose> </xsl:for-each> </xsl:if> </xsl:for-each> </xsl:when> <xsl:when test="self::section[parent::ed:ins]"> <xsl:for-each select="../.."><xsl:call-template name="sectionnumberAndEdits" /></xsl:for-each> <xsl:for-each select=".."> <xsl:if test="parent::section">.</xsl:if><xsl:value-of select="1+count(preceding-sibling::section|preceding-sibling::ed:ins/section|preceding-sibling::ed:replace/ed:ins/section)" /> </xsl:for-each> </xsl:when> <xsl:when test="self::section"> <xsl:for-each select=".."><xsl:call-template name="sectionnumberAndEdits" /></xsl:for-each> <xsl:if test="parent::section">.</xsl:if> <xsl:choose> <xsl:when test="parent::back"> <xsl:number format="A" value="1+count(preceding-sibling::section|preceding-sibling::ed:ins/section|preceding-sibling::ed:replace/ed:ins/section)" /> </xsl:when> <xsl:otherwise> <xsl:number value="1+count(preceding-sibling::section|preceding-sibling::ed:ins/section|preceding-sibling::ed:replace/ed:ins/section)" /> </xsl:otherwise> </xsl:choose> </xsl:when> <xsl:when test="self::references"> <xsl:choose> <xsl:when test="count(/*/back/references)+count(/*/back/ed:replace/ed:ins/references)=1"><xsl:call-template name="get-references-section-number"/></xsl:when> <xsl:otherwise><xsl:call-template name="get-references-section-number"/>.<xsl:number level="any"/></xsl:otherwise> </xsl:choose> </xsl:when> <xsl:when test="self::middle or self::back"><!-- done --></xsl:when> <xsl:otherwise> <!-- go up one level --> <xsl:for-each select=".."><xsl:call-template name="sectionnumberAndEdits" /></xsl:for-each> </xsl:otherwise> </xsl:choose> </xsl:template> <!-- utilities for warnings --> <xsl:template name="trace"> <xsl:param name="msg"/> <xsl:param name="msg2"/> <xsl:param name="inline" select="'no'"/> <xsl:param name="lineno" select="true()"/> <xsl:param name="node" select="."/> <xsl:call-template name="emit-message"> <xsl:with-param name="level">TRACE</xsl:with-param> <xsl:with-param name="msg" select="$msg"/> <xsl:with-param name="msg2" select="$msg2"/> <xsl:with-param name="inline" select="$inline"/> <xsl:with-param name="lineno" select="$lineno"/> <xsl:with-param name="node" select="$node"/> </xsl:call-template> </xsl:template> <xsl:template name="debug"> <xsl:param name="msg"/> <xsl:param name="msg2"/> <xsl:param name="inline" select="'no'"/> <xsl:param name="lineno" select="true()"/> <xsl:param name="node" select="."/> <xsl:call-template name="emit-message"> <xsl:with-param name="level">DEBUG</xsl:with-param> <xsl:with-param name="msg" select="$msg"/> <xsl:with-param name="msg2" select="$msg2"/> <xsl:with-param name="inline" select="$inline"/> <xsl:with-param name="lineno" select="$lineno"/> <xsl:with-param name="node" select="$node"/> </xsl:call-template> </xsl:template> <xsl:template name="inline-warning"> <xsl:param name="msg"/> <xsl:param name="msg2"/> <xsl:param name="lineno" select="true()"/> <xsl:param name="node" select="."/> <xsl:call-template name="emit-message"> <xsl:with-param name="level">WARNING</xsl:with-param> <xsl:with-param name="dlevel">3</xsl:with-param> <xsl:with-param name="msg" select="$msg"/> <xsl:with-param name="msg2" select="$msg2"/> <xsl:with-param name="inline" select="'yes'"/> <xsl:with-param name="lineno" select="$lineno"/> <xsl:with-param name="node" select="$node"/> </xsl:call-template> </xsl:template> <xsl:template name="warning"> <xsl:param name="msg"/> <xsl:param name="msg2"/> <xsl:param name="lineno" select="true()"/> <xsl:param name="node" select="."/> <xsl:call-template name="emit-message"> <xsl:with-param name="level">WARNING</xsl:with-param> <xsl:with-param name="dlevel">3</xsl:with-param> <xsl:with-param name="msg" select="$msg"/> <xsl:with-param name="msg2" select="$msg2"/> <xsl:with-param name="inline" select="'no'"/> <xsl:with-param name="lineno" select="$lineno"/> <xsl:with-param name="node" select="$node"/> </xsl:call-template> </xsl:template> <xsl:template name="info"> <xsl:param name="msg"/> <xsl:param name="msg2"/> <xsl:param name="lineno" select="true()"/> <xsl:param name="node" select="."/> <xsl:call-template name="emit-message"> <xsl:with-param name="level">INFO</xsl:with-param> <xsl:with-param name="dlevel">2</xsl:with-param> <xsl:with-param name="msg" select="$msg"/> <xsl:with-param name="msg2" select="$msg2"/> <xsl:with-param name="inline" select="'no'"/> <xsl:with-param name="lineno" select="$lineno"/> <xsl:with-param name="node" select="$node"/> </xsl:call-template> </xsl:template> <xsl:template name="error"> <xsl:param name="msg"/> <xsl:param name="msg2"/> <xsl:param name="inline"/> <xsl:param name="lineno" select="true()"/> <xsl:param name="node" select="."/> <xsl:call-template name="emit-message"> <xsl:with-param name="level">ERROR</xsl:with-param> <xsl:with-param name="dlevel">4</xsl:with-param> <xsl:with-param name="msg" select="$msg"/> <xsl:with-param name="msg2" select="$msg2"/> <xsl:with-param name="inline" select="$inline"/> <xsl:with-param name="lineno" select="$lineno"/> <xsl:with-param name="node" select="$node"/> </xsl:call-template> </xsl:template> <xsl:template name="emit-message-inline"> <xsl:param name="message"/> <xsl:param name="node" select="."/> <xsl:choose> <xsl:when test="$node/ancestor::t or $node/ancestor-or-self::seriesInfo"> <span class="{$css-error}"><xsl:value-of select="$message"/></span> </xsl:when> <xsl:otherwise> <div class="{$css-error}"><xsl:value-of select="$message"/></div> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="emit-message"> <xsl:param name="level">DEBUG</xsl:param> <xsl:param name="dlevel">0</xsl:param> <xsl:param name="msg"/> <xsl:param name="msg2"/> <xsl:param name="inline"/> <xsl:param name="lineno" select="true()"/> <xsl:param name="node" select="."/> <xsl:if test="$dlevel >= $log-level"> <xsl:variable name="message"><xsl:value-of select="$level"/>: <xsl:value-of select="$msg"/><xsl:if test="$msg2!=''"> - <xsl:value-of select="$msg2"/></xsl:if><xsl:if test="$lineno"><xsl:call-template name="lineno"><xsl:with-param name="node" select="$node"/></xsl:call-template></xsl:if></xsl:variable> <xsl:choose> <xsl:when test="$inline!='no'"> <xsl:call-template name="emit-message-inline"> <xsl:with-param name="message" select="$message"/> <xsl:with-param name="node" select="$node"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <!-- this fails when the message contains characters not encodable in the output encoding --> <!-- <xsl:comment><xsl:value-of select="$message"/></xsl:comment> --> </xsl:otherwise> </xsl:choose> <xsl:choose> <xsl:when test="$dlevel >= $abort-log-level"> <xsl:message terminate="yes"><xsl:value-of select="$message"/></xsl:message> </xsl:when> <xsl:otherwise> <xsl:message><xsl:value-of select="$message"/></xsl:message> </xsl:otherwise> </xsl:choose> </xsl:if> </xsl:template> <!-- table formatting --> <xsl:template match="table"> <div class="{$css-tt}"> <xsl:call-template name="copy-anchor"/> <xsl:apply-templates select="iref"/> <xsl:variable name="style"> <xsl:text>v3 </xsl:text> <xsl:choose> <xsl:when test="@align='left'"><xsl:value-of select="$css-tleft"/></xsl:when> <xsl:when test="@align='right'"><xsl:value-of select="$css-tright"/></xsl:when> <xsl:when test="@align='center' or not(@align) or @align=''"><xsl:value-of select="$css-tcenter"/></xsl:when> <xsl:otherwise/> </xsl:choose> </xsl:variable> <table class="{$style}"> <xsl:variable name="n"><xsl:call-template name="get-table-number"/></xsl:variable> <caption> <xsl:text>Table </xsl:text> <xsl:value-of select="$n"/> <xsl:if test="name"> <xsl:text>: </xsl:text> <xsl:apply-templates select="name/node()"/> </xsl:if> </caption> <xsl:apply-templates select="*[not(self::iref)]"/> </table> </div> </xsl:template> <xsl:template match="table/name"/> <xsl:template match="tbody"> <tbody> <xsl:call-template name="copy-anchor"/> <xsl:apply-templates select="*"/> </tbody> </xsl:template> <xsl:template match="tfoot"> <tfoot> <xsl:call-template name="copy-anchor"/> <xsl:apply-templates select="*"/> </tfoot> </xsl:template> <xsl:template match="thead"> <thead> <xsl:call-template name="copy-anchor"/> <xsl:apply-templates select="*"/> </thead> </xsl:template> <xsl:template match="tr"> <tr> <xsl:call-template name="copy-anchor"/> <xsl:apply-templates select="*"/> </tr> </xsl:template> <xsl:template name="t-alignment"> <xsl:attribute name="class"> <xsl:choose> <xsl:when test="@align='left' or not(@align) or @align=''"><xsl:value-of select="$css-left"/></xsl:when> <xsl:when test="@align='right'"><xsl:value-of select="$css-right"/></xsl:when> <xsl:when test="@align='center'"><xsl:value-of select="$css-center"/></xsl:when> <xsl:otherwise> <xsl:call-template name="warning"> <xsl:with-param name="msg">Unknown align attribute: <xsl:value-of select="@align"/></xsl:with-param> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:attribute> </xsl:template> <xsl:template match="td"> <td> <xsl:call-template name="copy-anchor"/> <xsl:call-template name="t-alignment"/> <xsl:copy-of select="@colspan|@rowspan"/> <xsl:apply-templates select="node()"/> </td> </xsl:template> <xsl:template match="th"> <th> <xsl:call-template name="copy-anchor"/> <xsl:call-template name="t-alignment"/> <xsl:copy-of select="@colspan|@rowspan"/> <xsl:apply-templates select="node()"/> </th> </xsl:template> <xsl:template match="texttable"> <xsl:call-template name="check-no-text-content"/> <xsl:variable name="anch"> <xsl:call-template name="get-table-anchor"/> </xsl:variable> <div id="{$anch}" class="{$css-tt}"> <xsl:if test="@anchor!=''"> <div id="{@anchor}"/> </xsl:if> <xsl:apply-templates select="preamble" /> <xsl:variable name="style"> <xsl:value-of select="$css-tt"/> <xsl:text> </xsl:text> <xsl:choose> <xsl:when test="@style!=''"> <xsl:value-of select="@style"/> </xsl:when> <xsl:otherwise>full</xsl:otherwise> </xsl:choose> <xsl:choose> <xsl:when test="@align='left'"><xsl:text> </xsl:text><xsl:value-of select="$css-tleft"/></xsl:when> <xsl:when test="@align='right'"><xsl:text> </xsl:text><xsl:value-of select="$css-tright"/></xsl:when> <xsl:when test="@align='center' or not(@align) or @align=''"><xsl:text> </xsl:text><xsl:value-of select="$css-tcenter"/></xsl:when> <xsl:otherwise/> </xsl:choose> </xsl:variable> <table class="{$style}"> <xsl:if test="(@title!='') or (@anchor!='' and not(@suppress-title='true'))"> <xsl:variable name="n"><xsl:call-template name="get-table-number"/></xsl:variable> <caption> <xsl:if test="@x:caption-side='top'"> <xsl:attribute name="class">caption-top</xsl:attribute> </xsl:if> <xsl:if test="not(starts-with($n,'u'))"> <xsl:text>Table </xsl:text> <xsl:value-of select="$n"/> <xsl:if test="@title!=''">: </xsl:if> </xsl:if> <xsl:if test="@title!=''"> <xsl:value-of select="@title" /> </xsl:if> </caption> </xsl:if> <xsl:if test="ttcol!=''"> <!-- skip header when all column titles are empty --> <thead> <tr> <xsl:apply-templates select="ttcol" /> </tr> </thead> </xsl:if> <tbody> <xsl:variable name="columns" select="count(ttcol)" /> <xsl:variable name="fields" select="c | ed:replace/ed:ins/c | ed:replace/ed:del/c" /> <xsl:for-each select="$fields[$columns=1 or (position() mod $columns) = 1]"> <tr> <xsl:for-each select=". | following-sibling::c[position() < $columns]"> <td> <xsl:call-template name="copy-anchor"/> <xsl:call-template name="insertInsDelClass"/> <xsl:variable name="pos" select="position()" /> <xsl:variable name="col" select="../ttcol[position() = $pos]" /> <xsl:choose> <xsl:when test="$col/@align='right' or $col/@align='center'"> <xsl:attribute name="class"><xsl:value-of select="$col/@align"/></xsl:attribute> </xsl:when> <xsl:when test="$col/@align='left' or not($col/@align)"> <xsl:attribute name="class"><xsl:value-of select="$css-left"/></xsl:attribute> </xsl:when> <xsl:otherwise> <xsl:call-template name="warning"> <xsl:with-param name="msg">Unknown align attribute on ttcol: <xsl:value-of select="$col/@align"/></xsl:with-param> </xsl:call-template> </xsl:otherwise> </xsl:choose> <xsl:apply-templates select="node()" /> </td> </xsl:for-each> </tr> </xsl:for-each> </tbody> </table> <xsl:apply-templates select="postamble" /> </div> </xsl:template> <xsl:template match="ttcol"> <th> <xsl:choose> <xsl:when test="@align='right' or @align='center' or @align='left'"> <xsl:attribute name="class"><xsl:value-of select="@align"/></xsl:attribute> </xsl:when> <xsl:when test="not(@align)"> <!-- that's the default, nothing to do here --> </xsl:when> <xsl:otherwise> <xsl:message>Unknown align attribute on ttcol: <xsl:value-of select="@align"/></xsl:message> </xsl:otherwise> </xsl:choose> <xsl:if test="@width"> <xsl:attribute name="style">width: <xsl:value-of select="@width" />;</xsl:attribute> </xsl:if> <xsl:apply-templates /> </th> </xsl:template> <!-- cref support --> <xsl:template name="get-comment-name"> <xsl:choose> <xsl:when test="@anchor"> <xsl:value-of select="@anchor"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="$anchor-pref"/> <xsl:text>comment.</xsl:text> <xsl:number count="cref[not(@anchor)]" level="any"/> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="cref[@display='false']"> <!-- hidden --> </xsl:template> <xsl:template match="cref[not(@display) or @display!='false']"> <xsl:if test="$xml2rfc-comments!='no'"> <xsl:variable name="cid"> <xsl:call-template name="get-comment-name"/> </xsl:variable> <span class="comment"> <xsl:choose> <xsl:when test="$xml2rfc-inline='yes'"> <xsl:attribute name="id"> <xsl:value-of select="$cid"/> </xsl:attribute> <xsl:text>[</xsl:text> <xsl:if test="@anchor or (not(/rfc/@version) or /rfc/@version < 3)"> <a href="#{$cid}" class="smpl"> <xsl:value-of select="$cid"/> </a> <xsl:text>: </xsl:text> </xsl:if> <xsl:apply-templates select="text()|eref|xref"/> <xsl:if test="@source"> --<xsl:value-of select="@source"/></xsl:if> <xsl:text>]</xsl:text> </xsl:when> <xsl:otherwise> <xsl:attribute name="title"> <xsl:if test="@source"><xsl:value-of select="@source"/>: </xsl:if> <xsl:variable name="content"> <xsl:apply-templates select="text()|eref|xref"/> </xsl:variable> <xsl:value-of select="$content"/> </xsl:attribute> <xsl:text>[</xsl:text> <a href="#{$cid}"> <xsl:value-of select="$cid"/> </a> <xsl:text>]</xsl:text> </xsl:otherwise> </xsl:choose> </span> </xsl:if> </xsl:template> <xsl:template name="insertComments"> <xsl:call-template name="insert-conditional-hrule"/> <h2> <xsl:call-template name="insert-conditional-pagebreak"/> <a id="{$anchor-pref}comments" href="#{$anchor-pref}comments">Editorial Comments</a> </h2> <dl> <xsl:for-each select="//cref[not(@display) or @display!='false']"> <xsl:variable name="cid"> <xsl:choose> <xsl:when test="@anchor"> <xsl:value-of select="@anchor"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="$anchor-pref"/> <xsl:text>comment.</xsl:text> <xsl:number count="cref[not(@anchor)]" level="any"/> </xsl:otherwise> </xsl:choose> </xsl:variable> <dt id="{$cid}"> [<xsl:value-of select="$cid"/>] </dt> <dd> <xsl:apply-templates select="node()"/> <xsl:if test="@source"> --<xsl:value-of select="@source"/></xsl:if> </dd> </xsl:for-each> </dl> </xsl:template> <!-- Chapter Link Generation --> <xsl:template match="*" mode="links"><xsl:apply-templates mode="links"/></xsl:template> <xsl:template match="text()" mode="links" /> <xsl:template match="/*/middle//section[not(ancestor::section)]" mode="links"> <xsl:variable name="sectionNumber"><xsl:call-template name="get-section-number" /></xsl:variable> <xsl:variable name="title"> <xsl:if test="$sectionNumber!='' and not(contains($sectionNumber,$unnumbered))"> <xsl:value-of select="$sectionNumber"/> <xsl:text> </xsl:text> </xsl:if> <xsl:choose> <xsl:when test="name"> <xsl:variable name="hold"> <xsl:apply-templates select="name/node()"/> </xsl:variable> <xsl:value-of select="normalize-space($hold)"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="@title"/> </xsl:otherwise> </xsl:choose> </xsl:variable> <link rel="Chapter" title="{$title}" href="#{$anchor-pref}section.{$sectionNumber}"/> <xsl:apply-templates mode="links" /> </xsl:template> <xsl:template match="/*/back//section[not(ancestor::section)][not(author)][not(@numbered='false' and name/@slugifiedName='name-index')]" mode="links"> <xsl:variable name="sectionNumber"><xsl:call-template name="get-section-number" /></xsl:variable> <xsl:variable name="title"> <xsl:if test="$sectionNumber!='' and not(contains($sectionNumber,$unnumbered))"> <xsl:value-of select="$sectionNumber"/> <xsl:text> </xsl:text> </xsl:if> <xsl:choose> <xsl:when test="name"> <xsl:variable name="hold"> <xsl:apply-templates select="name/node()"/> </xsl:variable> <xsl:value-of select="normalize-space($hold)"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="@title"/> </xsl:otherwise> </xsl:choose> </xsl:variable> <link rel="Appendix" title="{$title}" href="#{$anchor-pref}section.{$sectionNumber}"/> <xsl:apply-templates mode="links" /> </xsl:template> <xsl:template match="/*/back/references[position()=1]" mode="links"> <xsl:variable name="sectionNumber"><xsl:call-template name="get-references-section-number" /></xsl:variable> <xsl:variable name="title"> <xsl:choose> <xsl:when test="@title and count(/*/back/references)=1"> <xsl:call-template name="get-references-section-number"/> <xsl:text> </xsl:text> <xsl:value-of select="@title"/> </xsl:when> <xsl:otherwise> <xsl:call-template name="get-references-section-number"/> <xsl:text> </xsl:text> <xsl:value-of select="$xml2rfc-refparent"/> </xsl:otherwise> </xsl:choose> </xsl:variable> <link rel="Chapter" title="{$title}" href="#{$anchor-pref}section.{$sectionNumber}"/> </xsl:template> <!-- convenience templates --> <xsl:template name="get-author-summary"> <xsl:choose> <xsl:when test="count(/rfc/front/author)=1"> <xsl:value-of select="/rfc/front/author[1]/@surname" /> </xsl:when> <xsl:when test="count(/rfc/front/author)=2"> <xsl:value-of select="concat(/rfc/front/author[1]/@surname,' & ',/rfc/front/author[2]/@surname)" /> </xsl:when> <xsl:otherwise> <xsl:value-of select="concat(/rfc/front/author[1]/@surname,', et al.')" /> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="get-bottom-center"> <xsl:choose> <xsl:when test="/rfc/@docName"> <!-- for IDs, use the expiry date --> <xsl:text>Expires </xsl:text><xsl:call-template name="expirydate" /> </xsl:when> <xsl:otherwise> <xsl:call-template name="get-category-long"/> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="get-category-long"> <xsl:choose> <xsl:when test="$xml2rfc-footer!=''"><xsl:value-of select="$xml2rfc-footer" /></xsl:when> <xsl:when test="$xml2rfc-private!=''"/> <!-- private draft, footer not set --> <xsl:when test="/rfc/@category='bcp'">Best Current Practice</xsl:when> <xsl:when test="/rfc/@category='historic'">Historic</xsl:when> <xsl:when test="/rfc/@category='info' or not(/rfc/@category)">Informational</xsl:when> <xsl:when test="/rfc/@category='std'">Standards Track</xsl:when> <xsl:when test="/rfc/@category='exp'">Experimental</xsl:when> <xsl:otherwise>(category unknown)</xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="get-header-center"> <xsl:choose> <xsl:when test="string-length(/rfc/front/title/@abbrev) > 0"> <xsl:value-of select="/rfc/front/title/@abbrev" /> </xsl:when> <xsl:otherwise> <xsl:apply-templates select="/rfc/front/title" mode="get-text-content" /> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="get-header-left"> <xsl:choose> <xsl:when test="$xml2rfc-header!=''"><xsl:value-of select="$xml2rfc-header" /></xsl:when> <xsl:when test="$xml2rfc-private!=''"/> <!-- private draft, header not set --> <xsl:when test="/rfc/@ipr and not($is-rfc)">Internet-Draft</xsl:when> <xsl:otherwise>RFC <xsl:value-of select="$rfcno"/></xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="get-generator"> <xsl:variable name="gen"> <xsl:text>http://greenbytes.de/tech/webdav/rfcxml.xslt, </xsl:text> <!-- when RCS keyword substitution in place, add version info --> <xsl:if test="contains('$Revision: 1.1469 $',':')"> <xsl:value-of select="concat('Revision ',normalize-space(translate(substring-after('$Revision: 1.1469 $', 'Revision: '),'$','')),', ')" /> </xsl:if> <xsl:if test="contains('$Date: 2024/04/10 17:40:38 $',':')"> <xsl:value-of select="concat(normalize-space(translate(substring-after('$Date: 2024/04/10 17:40:38 $', 'Date: '),'$','')),', ')" /> </xsl:if> <xsl:variable name="product" select="normalize-space(concat(system-property('xsl:product-name'),' ',system-property('xsl:product-version')))"/> <xsl:if test="$product!=''"> <xsl:value-of select="concat('XSLT processor: ',$product,', ')"/> </xsl:if> <xsl:value-of select="concat('XSLT vendor: ',system-property('xsl:vendor'),' ',system-property('xsl:vendor-url'))" /> </xsl:variable> <xsl:variable name="via"> <xsl:variable name="c1" select="/comment()[starts-with(normalize-space(.),'generated by ')]"/> <xsl:variable name="mmark-lookup">name="GENERATOR" content=</xsl:variable> <xsl:variable name="c2" select="/comment()[starts-with(normalize-space(.),$mmark-lookup)]"/> <xsl:choose> <xsl:when test="$c1"> <xsl:value-of select="substring-after(normalize-space($c1),'generated by ')"/> </xsl:when> <xsl:when test="$c2"> <xsl:variable name="remove">"</xsl:variable> <xsl:value-of select="translate(substring-after(normalize-space($c2),$mmark-lookup),$remove,'')"/> </xsl:when> <xsl:otherwise/> </xsl:choose> </xsl:variable> <xsl:value-of select="$gen" /> <xsl:if test="$via!=''"> <xsl:text>, via: </xsl:text> <xsl:value-of select="$via"/> </xsl:if> </xsl:template> <xsl:template name="get-header-right"> <xsl:if test="$xml2rfc-ext-pub-day!='' and /rfc/front/date/@x:include-day='true' and $is-rfc"> <xsl:value-of select="number($xml2rfc-ext-pub-day)" /> <xsl:text> </xsl:text> </xsl:if> <xsl:value-of select="concat($xml2rfc-ext-pub-month, ' ', $xml2rfc-ext-pub-year)" /> </xsl:template> <xsl:template name="get-keywords"> <xsl:for-each select="/rfc/front/keyword"> <xsl:if test="contains(.,',')"> <xsl:call-template name="warning"> <xsl:with-param name="msg">keyword element appears to contain a comma-separated list, split into multiple elements instead.</xsl:with-param> </xsl:call-template> </xsl:if> <xsl:value-of select="normalize-space(.)" /> <xsl:if test="position()!=last()">, </xsl:if> </xsl:for-each> </xsl:template> <!-- get language from context node. nearest ancestor or return the default of "en" --> <xsl:template name="get-lang"> <xsl:choose> <xsl:when test="ancestor-or-self::*[@xml:lang]"><xsl:value-of select="ancestor-or-self::*/@xml:lang" /></xsl:when> <xsl:otherwise>en</xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="get-section-number"> <xsl:variable name="anchor" select="@anchor"/> <xsl:choose> <xsl:when test="self::note"> <xsl:number count="note"/> </xsl:when> <xsl:when test="@x:fixed-section-number and @x:fixed-section-number!=''"> <xsl:value-of select="@x:fixed-section-number"/> </xsl:when> <xsl:when test="(@x:fixed-section-number and @x:fixed-section-number='') or ancestor-or-self::*/@numbered='false'"> <xsl:value-of select="$unnumbered"/> <xsl:number count="section[@x:fixed-section-number='' or ancestor-or-self::*/@numbered='false']" level="any"/> <!-- checks --> <xsl:if test="@numbered='false'"> <xsl:if test="ancestor::section"> <xsl:call-template name="debug"> <xsl:with-param name="inline" select="'no'"/> <xsl:with-param name="msg">Only top-level sections can be unnumbered</xsl:with-param> </xsl:call-template> </xsl:if> <xsl:if test="following-sibling::section[not(@numbered) or @numbered!='false']"> <xsl:call-template name="error"> <xsl:with-param name="inline" select="'no'"/> <xsl:with-param name="msg">Unnumbered section is followed by numbered sections</xsl:with-param> </xsl:call-template> </xsl:if> <xsl:if test="ancestor::middle and ../../back/references"> <xsl:call-template name="error"> <xsl:with-param name="inline" select="'no'"/> <xsl:with-param name="msg">Unnumbered section is followed by (numbered) references section</xsl:with-param> </xsl:call-template> </xsl:if> </xsl:if> <xsl:if test="@numbered='true'"> <xsl:for-each select="ancestor::section[@numbered='false']"> <xsl:call-template name="error"> <xsl:with-param name="inline" select="'no'"/> <xsl:with-param name="msg">Numbered section as child of an unnumbered section</xsl:with-param> </xsl:call-template> </xsl:for-each> </xsl:if> </xsl:when> <xsl:when test="$has-edits or ancestor::*/@x:fixed-section-number"> <xsl:call-template name="sectionnumberAndEdits" /> </xsl:when> <xsl:otherwise> <xsl:choose> <xsl:when test="self::references and not(parent::references)"> <xsl:choose> <xsl:when test="count(/*/back/references)=1"> <xsl:call-template name="get-references-section-number"/> </xsl:when> <xsl:otherwise> <xsl:call-template name="get-references-section-number"/>.<xsl:number count="references"/> </xsl:otherwise> </xsl:choose> </xsl:when> <xsl:when test="self::references and parent::references"> <xsl:for-each select=".."><xsl:call-template name="get-section-number"/></xsl:for-each>.<xsl:number count="references"/> </xsl:when> <xsl:when test="self::reference"> <xsl:for-each select="parent::references"> <xsl:choose> <xsl:when test="count(/*/back/references)=1"> <xsl:call-template name="get-references-section-number"/> </xsl:when> <xsl:otherwise> <xsl:call-template name="get-references-section-number"/>.<xsl:number count="references"/> </xsl:otherwise> </xsl:choose> </xsl:for-each> </xsl:when> <xsl:when test="ancestor::reference"> <xsl:for-each select="ancestor::reference"> <xsl:call-template name="get-section-number"/> </xsl:for-each> </xsl:when> <xsl:when test="ancestor::back"><xsl:number count="section|appendix" level="multiple" format="A.1.1.1.1.1.1.1" /></xsl:when> <xsl:when test="self::appendix"><xsl:number count="appendix" level="multiple" format="A.1.1.1.1.1.1.1" /></xsl:when> <xsl:otherwise><xsl:number count="section" level="multiple"/></xsl:otherwise> </xsl:choose> </xsl:otherwise> </xsl:choose> </xsl:template> <!-- get the section number for the references section --> <xsl:template name="get-references-section-number"> <xsl:value-of select="count(/rfc/middle/section[not(@numbered) or @numbered!='false']) + count(/rfc/middle/ed:replace/ed:ins/section[not(@numbered) or @numbered!='false']) + 1"/> </xsl:template> <xsl:template name="emit-section-number"> <xsl:param name="no"/> <xsl:param name="appendixPrefix" select="false()"/> <xsl:if test="$appendixPrefix and translate($no,$ucase,'')=''">Appendix </xsl:if> <xsl:value-of select="$no"/><xsl:if test="not(contains($no,'.')) or $xml2rfc-ext-sec-no-trailing-dots!='no'">.</xsl:if> </xsl:template> <xsl:template name="get-section-type"> <xsl:choose> <xsl:when test="self::abstract">Abstract</xsl:when> <xsl:when test="self::note">Note</xsl:when> <xsl:when test="ancestor::back and not(self::references)">Appendix</xsl:when> <xsl:otherwise>Section</xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="get-table-number"> <xsl:choose> <xsl:when test="self::table or @anchor!=''"> <xsl:number level="any" count="texttable[@anchor!='']|table" /> </xsl:when> <xsl:otherwise> <xsl:text>u.</xsl:text> <xsl:number level="any" count="texttable[not(@anchor) or @anchor='']" /> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="get-table-anchor"> <xsl:value-of select="$anchor-pref"/> <xsl:text>table.</xsl:text> <xsl:call-template name="get-table-number"/> </xsl:template> <xsl:template name="get-figure-number"> <xsl:choose> <xsl:when test="@anchor!='' or @title or name"> <xsl:number level="any" count="figure[@anchor!='' or @title or name]" /> </xsl:when> <xsl:otherwise> <xsl:text>u.</xsl:text> <xsl:number level="any" count="figure[(not(@anchor) or @anchor='') and not(@title) and not(name)]" /> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="get-figure-anchor"> <xsl:value-of select="$anchor-pref"/> <xsl:text>figure.</xsl:text> <xsl:call-template name="get-figure-number"/> </xsl:template> <!-- reformat contents of author/@initials --> <xsl:template name="format-initials"> <xsl:param name="initials" select="@initials"/> <xsl:variable name="computed-initials"> <xsl:choose> <xsl:when test="normalize-space($initials)!=''"> <xsl:value-of select="$initials"/> </xsl:when> <xsl:otherwise> <xsl:call-template name="get-author-initials"/> </xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:variable name="normalized" select="normalize-space($computed-initials)"/> <xsl:choose> <xsl:when test="$normalized=''"> <!-- nothing to do --> </xsl:when> <xsl:otherwise> <xsl:variable name="r"> <xsl:call-template name="t-format-initials"> <xsl:with-param name="remainder" select="$normalized"/> </xsl:call-template> </xsl:variable> <xsl:if test="$r!=@initials"> <xsl:call-template name="warning"> <xsl:with-param name="msg">@initials '<xsl:value-of select="@initials"/>': did you mean '<xsl:value-of select="$r"/>'?</xsl:with-param> </xsl:call-template> </xsl:if> <xsl:value-of select="$r"/> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="t-format-initials"> <xsl:param name="have"/> <xsl:param name="remainder"/> <xsl:variable name="first" select="substring($remainder,1,1)"/> <xsl:variable name="prev" select="substring($have,string-length($have))"/> <!--<xsl:message> have: <xsl:value-of select="$have"/> remainder: <xsl:value-of select="$remainder"/> first: <xsl:value-of select="$first"/> prev: <xsl:value-of select="$prev"/> </xsl:message>--> <xsl:choose> <xsl:when test="$remainder='' and $prev!='.'"> <xsl:value-of select="concat($have,'.')"/> </xsl:when> <xsl:when test="$remainder=''"> <xsl:value-of select="$have"/> </xsl:when> <xsl:when test="$prev='.' and $first='.'"> <!-- repeating dots --> <xsl:call-template name="t-format-initials"> <xsl:with-param name="have" select="$have"/> <xsl:with-param name="remainder" select="substring($remainder,2)"/> </xsl:call-template> </xsl:when> <!-- missing dot before '-' --> <!-- <xsl:when test="$prev!='.' and $first='-'"> <xsl:call-template name="t-format-initials"> <xsl:with-param name="have" select="concat($have,'.-')"/> <xsl:with-param name="remainder" select="substring($remainder,2)"/> </xsl:call-template> </xsl:when>--> <!-- missing space after '.' --> <!-- <xsl:when test="$prev='.' and $first!=' '"> <xsl:call-template name="t-format-initials"> <xsl:with-param name="have" select="concat($have,' ',$first)"/> <xsl:with-param name="remainder" select="substring($remainder,2)"/> </xsl:call-template> </xsl:when>--> <xsl:otherwise> <xsl:call-template name="t-format-initials"> <xsl:with-param name="have" select="concat($have,$first)"/> <xsl:with-param name="remainder" select="substring($remainder,2)"/> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="truncate-initials"> <xsl:param name="initials"/> <xsl:variable name="local-multiple-initials"> <xsl:call-template name="parse-pis"> <xsl:with-param name="nodes" select="../../processing-instruction('rfc')|../processing-instruction('rfc')|./processing-instruction('rfc')"/> <xsl:with-param name="attr" select="'multiple-initials'"/> </xsl:call-template> </xsl:variable> <xsl:variable name="use-multiple-initials"> <xsl:choose> <xsl:when test="$local-multiple-initials!=''"> <xsl:value-of select="$local-multiple-initials"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="$xml2rfc-multiple-initials"/> </xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:choose> <xsl:when test="normalize-space($initials)=''"/> <xsl:when test="$use-multiple-initials='yes'"> <xsl:value-of select="$initials"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="concat(substring-before($initials,'.'),'.')"/> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="extract-normalized"> <xsl:param name="node" select="."/> <xsl:param name="ascii" select="false()"/> <xsl:variable name="name" select="local-name($node)"/> <xsl:variable name="n"> <xsl:choose> <xsl:when test="$ascii and $node/@ascii!=''"> <xsl:value-of select="$node/@ascii"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="$node"/> </xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:variable name="text" select="normalize-space($n)"/> <xsl:if test="string-length($n) != string-length($text)"> <xsl:call-template name="warning"> <xsl:with-param name="msg">excessive whitespace in <xsl:value-of select="$name"/>: '<xsl:value-of select="$n"/>'</xsl:with-param> </xsl:call-template> </xsl:if> <xsl:if test="$text=''"> <xsl:call-template name="warning"> <xsl:with-param name="msg">missing text in <xsl:value-of select="$name"/></xsl:with-param> </xsl:call-template> </xsl:if> <xsl:value-of select="$text"/> </xsl:template> <!-- checking for email element --> <xsl:template name="extract-email"> <xsl:variable name="email" select="normalize-space(.)"/> <xsl:if test="contains($email,' ')"> <xsl:call-template name="error"> <xsl:with-param name="msg">whitespace in email address: '<xsl:value-of select="."/>'</xsl:with-param> </xsl:call-template> </xsl:if> <xsl:variable name="email2"> <xsl:choose> <xsl:when test="starts-with($email,'mailto:')"> <xsl:call-template name="warning"> <xsl:with-param name="msg">email should not include URI scheme: '<xsl:value-of select="."/>'</xsl:with-param> </xsl:call-template> <xsl:value-of select="substring($email, 1 + string-length('mailto:'))"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="$email"/> </xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:value-of select="$email2"/> </xsl:template> <!-- checking for uri element --> <xsl:template name="extract-uri"> <xsl:variable name="uri" select="normalize-space(.)"/> <xsl:if test="string-length(.) != string-length($uri) or contains($uri,' ')"> <xsl:call-template name="warning"> <xsl:with-param name="msg">excessive whitespace in URI: '<xsl:value-of select="."/>'</xsl:with-param> </xsl:call-template> </xsl:if> <xsl:if test="$uri=''"> <xsl:call-template name="warning"> <xsl:with-param name="msg">URI is empty</xsl:with-param> </xsl:call-template> </xsl:if> <xsl:value-of select="$uri"/> </xsl:template> <xsl:template name="insert-conditional-pagebreak"> <xsl:if test="$xml2rfc-compact!='yes'"> <xsl:attribute name="class">np</xsl:attribute> </xsl:if> </xsl:template> <xsl:template name="insert-conditional-hrule"> <xsl:if test="$xml2rfc-compact!='yes'"> <hr class="{$css-noprint}" /> </xsl:if> </xsl:template> <!-- get text content from marked-up text --> <xsl:template match="text()" mode="get-text-content"> <xsl:value-of select="normalize-space(.)"/> </xsl:template> <xsl:template match="br" mode="get-text-content"> <xsl:text> </xsl:text> </xsl:template> <xsl:template match="*" mode="get-text-content"> <xsl:apply-templates mode="get-text-content"/> </xsl:template> <xsl:template match="ed:del" mode="get-text-content"> </xsl:template> <!-- parsing of processing instructions --> <xsl:template name="parse-pis"> <xsl:param name="nodes"/> <xsl:param name="attr"/> <xsl:param name="sep"/> <xsl:param name="ret"/> <xsl:param name="default"/> <xsl:param name="duplicate-warning" select="'yes'"/> <xsl:choose> <xsl:when test="count($nodes)=0"> <xsl:choose> <xsl:when test="$ret!=''"> <xsl:value-of select="$ret"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="$default"/> </xsl:otherwise> </xsl:choose> </xsl:when> <xsl:otherwise> <xsl:variable name="ret2"> <xsl:for-each select="$nodes[1]"> <xsl:call-template name="parse-one-pi"> <xsl:with-param name="str" select="."/> <xsl:with-param name="attr" select="$attr"/> <xsl:with-param name="sep" select="$sep"/> <xsl:with-param name="ret" select="$ret"/> <xsl:with-param name="duplicate-warning" select="$duplicate-warning"/> </xsl:call-template> </xsl:for-each> </xsl:variable> <xsl:call-template name="parse-pis"> <xsl:with-param name="nodes" select="$nodes[position()!=1]"/> <xsl:with-param name="attr" select="$attr"/> <xsl:with-param name="sep" select="$sep"/> <xsl:with-param name="ret" select="$ret2"/> <xsl:with-param name="default" select="$default"/> <xsl:with-param name="duplicate-warning" select="$duplicate-warning"/> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="parse-one-pi"> <xsl:param name="str"/> <xsl:param name="attr"/> <xsl:param name="sep"/> <xsl:param name="ret"/> <xsl:param name="duplicate-warning"/> <xsl:variable name="str2"> <xsl:call-template name="eat-leading-whitespace"> <xsl:with-param name="str" select="$str"/> </xsl:call-template> </xsl:variable> <xsl:choose> <xsl:when test="$str2=''"> <!-- done --> <xsl:value-of select="$ret"/> </xsl:when> <xsl:otherwise> <xsl:variable name="attrname" select="substring-before($str2,'=')"/> <xsl:choose> <xsl:when test="$attrname=''"> <xsl:call-template name="warning"> <xsl:with-param name="msg">bad PI syntax: <xsl:value-of select="$str2"/></xsl:with-param> </xsl:call-template> <xsl:value-of select="$ret"/> </xsl:when> <xsl:otherwise> <xsl:variable name="remainder" select="substring($str2,2+string-length($attrname))"/> <xsl:choose> <xsl:when test="string-length($remainder) < 2"> <xsl:call-template name="warning"> <xsl:with-param name="msg">bad PI value syntax: <xsl:value-of select="$remainder"/></xsl:with-param> </xsl:call-template> <xsl:value-of select="$ret"/> </xsl:when> <xsl:otherwise> <xsl:variable name="rem"> <xsl:call-template name="eat-leading-whitespace"> <xsl:with-param name="str" select="$remainder"/> </xsl:call-template> </xsl:variable> <xsl:variable name="qchars">'"</xsl:variable> <xsl:variable name="qchar" select="substring($rem,1,1)"/> <xsl:variable name="rem2" select="substring($rem,2)"/> <xsl:choose> <xsl:when test="not(contains($qchars,$qchar))"> <xsl:call-template name="warning"> <xsl:with-param name="msg">pseudo-attribute value needs to be quoted: <xsl:value-of select="$rem"/></xsl:with-param> </xsl:call-template> <xsl:value-of select="$ret"/> </xsl:when> <xsl:when test="not(contains($rem2,$qchar))"> <xsl:call-template name="warning"> <xsl:with-param name="msg">unmatched quote in: <xsl:value-of select="$rem2"/></xsl:with-param> </xsl:call-template> <xsl:value-of select="$ret"/> </xsl:when> <xsl:otherwise> <xsl:variable name="value" select="substring-before($rem2,$qchar)"/> <!-- check pseudo-attribute names --> <xsl:if test="name()='rfc-ext' and $attr='SANITYCHECK'"> <xsl:choose> <xsl:when test="$attrname='abort-on'"/> <xsl:when test="$attrname='allow-markup-in-artwork'"/> <xsl:when test="$attrname='authors-section'"/> <xsl:when test="$attrname='check-artwork-width'"/> <xsl:when test="$attrname='css-contents'"/> <xsl:when test="$attrname='css-resource'"/> <xsl:when test="$attrname='duplex'"/> <xsl:when test="$attrname='html-pretty-print'"/> <xsl:when test="$attrname='include-index'"/> <xsl:when test="$attrname='include-references-in-index'"/> <xsl:when test="$attrname='internet-draft-uri'"/> <xsl:when test="$attrname='internet-draft-reference-base-uri'"/> <xsl:when test="$attrname='justification'"/> <xsl:when test="$attrname='log-level'"/> <xsl:when test="$attrname='map-dfn'"/> <xsl:when test="$attrname='paragraph-links'"/> <xsl:when test="$attrname='parse-xml-in-artwork'"/> <xsl:when test="$attrname='refresh-from'"/> <xsl:when test="$attrname='refresh-interval'"/> <xsl:when test="$attrname='refresh-xslt'"/> <xsl:when test="$attrname='rfc-uri'"/> <xsl:when test="$attrname='rfc-reference-base-uri'"/> <xsl:when test="$attrname='sec-no-trailing-dots'"/> <xsl:when test="$attrname='trace-parse-xml'"/> <xsl:when test="$attrname='ucd-file'"/> <xsl:when test="$attrname='use-system-time'"/> <xsl:when test="$attrname='vspace-pagebreak'"/> <xsl:when test="$attrname='xml2rfc-backend'"/> <xsl:when test="$attrname='xref-with-text-generate'"/> <xsl:otherwise> <xsl:call-template name="warning"> <xsl:with-param name="msg">unsupported rfc-ext pseudo-attribute '<xsl:value-of select="$attrname"/>'</xsl:with-param> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:if> <xsl:if test="name()='rfc' and $attr='SANITYCHECK'"> <xsl:choose> <xsl:when test="$attrname='authorship'"/> <xsl:when test="$attrname='comments'"/> <xsl:when test="$attrname='compact'"/> <xsl:when test="$attrname='docmapping'"> <xsl:if test="$value!='yes'"> <xsl:call-template name="warning"> <xsl:with-param name="msg">the rfc docmapping pseudo-attribute with values other than 'yes' in not supported by this processor.</xsl:with-param> </xsl:call-template> </xsl:if> </xsl:when> <xsl:when test="$attrname='editing'"/> <xsl:when test="$attrname='footer'"/> <xsl:when test="$attrname='header'"/> <xsl:when test="$attrname='include'"> <xsl:choose> <xsl:when test="not(parent::references)"> <xsl:call-template name="error"> <xsl:with-param name="msg">the rfc include pseudo-attribute (unless a child node of <references>) is not supported by this processor, see http://greenbytes.de/tech/webdav/rfc2629xslt/rfc2629xslt.html#examples.internalsubset for alternative syntax.</xsl:with-param> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:call-template name="warning"> <xsl:with-param name="msg">the rfc include pseudo-attribute is only partially supported by this processor, see http://greenbytes.de/tech/webdav/rfc2629xslt/rfc2629xslt.html#examples.internalsubset for alternative syntax.</xsl:with-param> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:when> <xsl:when test="$attrname='inline'"/> <xsl:when test="$attrname='iprnotified'"/> <xsl:when test="$attrname='linefile'"/> <xsl:when test="$attrname='linkmailto'"/> <xsl:when test="$attrname='multiple-initials'"/> <xsl:when test="$attrname='private'"/> <xsl:when test="$attrname='rfcedstyle'"/> <xsl:when test="$attrname='sortrefs'"/> <xsl:when test="$attrname='subcompact'"/> <xsl:when test="$attrname='strict'"/> <xsl:when test="$attrname='symrefs'"/> <xsl:when test="$attrname='toc'"/> <xsl:when test="$attrname='tocdepth'"/> <xsl:when test="$attrname='tocindent'"> <xsl:if test="$value!='yes'"> <xsl:call-template name="warning"> <xsl:with-param name="msg">the rfc tocindent pseudo-attribute with values other than 'yes' in not supported by this processor.</xsl:with-param> </xsl:call-template> </xsl:if> </xsl:when> <xsl:otherwise> <xsl:call-template name="info"> <xsl:with-param name="msg">unsupported rfc pseudo-attribute '<xsl:value-of select="$attrname"/>'</xsl:with-param> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:if> <xsl:choose> <xsl:when test="$attrname != $attr"> <!-- pseudo-attr does not match, continue --> <xsl:call-template name="parse-one-pi"> <xsl:with-param name="str" select="substring($rem2, 2 + string-length($value))"/> <xsl:with-param name="attr" select="$attr"/> <xsl:with-param name="sep" select="$sep"/> <xsl:with-param name="ret" select="$ret"/> <xsl:with-param name="duplicate-warning" select="$duplicate-warning"/> </xsl:call-template> </xsl:when> <xsl:when test="$sep='' and $ret!=''"> <!-- pseudo-attr does match, but we only want one value --> <xsl:if test="$ret != $value and $duplicate-warning='yes'"> <xsl:call-template name="warning"> <xsl:with-param name="msg">duplicate pseudo-attribute <xsl:value-of select="$attr"/>, overwriting value <xsl:value-of select="$ret"/></xsl:with-param> </xsl:call-template> </xsl:if> <xsl:call-template name="parse-one-pi"> <xsl:with-param name="str" select="substring($rem2, 2 + string-length($value))"/> <xsl:with-param name="attr" select="$attr"/> <xsl:with-param name="sep" select="$sep"/> <xsl:with-param name="ret" select="$value"/> <xsl:with-param name="duplicate-warning" select="$duplicate-warning"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <!-- pseudo-attr does match --> <xsl:call-template name="parse-one-pi"> <xsl:with-param name="str" select="substring($rem2, 2 + string-length($value))"/> <xsl:with-param name="attr" select="$attr"/> <xsl:with-param name="sep" select="$sep"/> <xsl:with-param name="duplicate-warning" select="$duplicate-warning"/> <xsl:with-param name="ret"> <xsl:choose> <xsl:when test="$ret!=''"> <xsl:value-of select="concat($ret,$sep,$value)"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="$value"/> </xsl:otherwise> </xsl:choose> </xsl:with-param> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:otherwise> </xsl:choose> </xsl:otherwise> </xsl:choose> </xsl:otherwise> </xsl:choose> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="eat-leading-whitespace"> <xsl:param name="str"/> <xsl:choose> <xsl:when test="$str=''"> </xsl:when> <xsl:when test="translate(substring($str,1,1),' ',' ')=' '"> <xsl:call-template name="eat-leading-whitespace"> <xsl:with-param name="str" select="substring($str,2)"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:value-of select="$str"/> </xsl:otherwise> </xsl:choose> </xsl:template> <!-- diag support --> <xsl:template name="get-line-number"> <xsl:if test="function-available('saxon-old:line-number')" use-when="function-available('saxon-old:line-number')"> <xsl:value-of select="saxon-old:line-number()"/> </xsl:if> <xsl:if test="function-available('saxon:line-number')" use-when="function-available('saxon:line-number')"> <xsl:value-of select="saxon:line-number()"/> </xsl:if> </xsl:template> <xsl:template name="get-system-id"> <xsl:if test="function-available('saxon-old:systemId')" use-when="function-available('saxon-old:systemId')"> <xsl:value-of select="saxon-old:systemId()"/> </xsl:if> <xsl:if test="function-available('saxon:systemId')" use-when="function-available('saxon:systemId')"> <xsl:value-of select="saxon:systemId()"/> </xsl:if> </xsl:template> <xsl:template name="lineno"> <xsl:param name="node" select="."/> <xsl:for-each select="$node"> <xsl:variable name="l"> <xsl:call-template name="get-line-number"/> </xsl:variable> <xsl:variable name="s"> <xsl:call-template name="get-system-id"/> </xsl:variable> <xsl:if test="$l!='' and number($l) > 0"> <xsl:text> (at line </xsl:text> <xsl:value-of select="$l"/> <xsl:variable name="rootsys"> <xsl:for-each select="/*"> <xsl:call-template name="get-system-id"/> </xsl:for-each> </xsl:variable> <xsl:if test="$rootsys != $s"> <xsl:text> of </xsl:text> <xsl:value-of select="$s"/> </xsl:if> <xsl:text>)</xsl:text> </xsl:if> </xsl:for-each> </xsl:template> <!-- define exslt:node-set for msxml --> <msxsl:script language="JScript" implements-prefix="exslt"> this['node-set'] = function (x) { return x; } </msxsl:script> <!-- date handling --> <msxsl:script language="JScript" implements-prefix="date"> function twodigits(s) { return s < 10 ? "0" + s : s; } this['date-time'] = function (x) { var now = new Date(); var offs = now.getTimezoneOffset(); return now.getFullYear() + "-" + twodigits(1 + now.getMonth()) + "-" + twodigits(now.getDate()) + "T" + twodigits(now.getHours()) + ":" + twodigits(now.getMinutes()) + ":" + twodigits(now.getSeconds()) + (offs >= 0 ? "-" : "+") + twodigits(Math.abs(offs) / 60) + ":" + twodigits(Math.abs(offs) % 60); } </msxsl:script> <xsl:variable name="current-year"> <xsl:choose> <xsl:when test="$xml2rfc-ext-use-system-time='no'"/> <xsl:when test="function-available('date:date-time')" use-when="function-available('date:date-time')"> <xsl:value-of select="substring-before(date:date-time(),'-')"/> </xsl:when> <xsl:when test="function-available('current-date')"> <xsl:value-of select="substring-before(string(current-date()),'-')"/> </xsl:when> <xsl:otherwise/> </xsl:choose> </xsl:variable> <xsl:variable name="current-month"> <xsl:choose> <xsl:when test="$xml2rfc-ext-use-system-time='no'"/> <xsl:when test="function-available('date:date-time')" use-when="function-available('date:date-time')"> <xsl:value-of select="substring-before(substring-after(date:date-time(),'-'),'-')"/> </xsl:when> <xsl:when test="function-available('current-date')"> <xsl:value-of select="substring-before(substring-after(string(current-date()),'-'),'-')"/> </xsl:when> <xsl:otherwise/> </xsl:choose> </xsl:variable> <xsl:variable name="current-day"> <xsl:choose> <xsl:when test="$xml2rfc-ext-use-system-time='no'"/> <xsl:when test="function-available('date:date-time')" use-when="function-available('date:date-time')"> <xsl:value-of select="substring-after(substring-after(substring-before(date:date-time(),'T'),'-'),'-')"/> </xsl:when> <xsl:when test="function-available('current-dateTime')"> <xsl:value-of select="substring-after(substring-after(substring-before(string(current-dateTime()),'T'),'-'),'-')"/> </xsl:when> <xsl:otherwise/> </xsl:choose> </xsl:variable> <xsl:variable name="may-default-dates"> <xsl:choose> <xsl:when test="$current-year!='' and $current-month!='' and $current-day!=''"> <xsl:variable name="year-specified" select="/rfc/front/date/@year and /rfc/front/date/@year!=''"/> <xsl:variable name="month-specified" select="/rfc/front/date/@month and /rfc/front/date/@month!=''"/> <xsl:variable name="day-specified" select="/rfc/front/date/@day and /rfc/front/date/@day!=''"/> <xsl:variable name="system-month"> <xsl:call-template name="get-month-as-name"> <xsl:with-param name="month" select="$current-month"/> </xsl:call-template> </xsl:variable> <xsl:choose> <xsl:when test="$year-specified and /rfc/front/date/@year!=$current-year">Specified year <xsl:value-of select="/rfc/front/date/@year"/> does not match system date (<xsl:value-of select="$current-year"/>)</xsl:when> <xsl:when test="$month-specified and /rfc/front/date/@month!=$system-month">Specified month <xsl:value-of select="/rfc/front/date/@month"/> does not match system date (<xsl:value-of select="$system-month"/>)</xsl:when> <xsl:when test="$day-specified and /rfc/front/date/@day!=$current-day">Specified day does not match system date</xsl:when> <xsl:when test="not($year-specified) and ($month-specified or $day-specified)">Can't default year when month or day is specified</xsl:when> <xsl:when test="not($month-specified) and $day-specified">Can't default month when day is specified</xsl:when> <xsl:otherwise>yes</xsl:otherwise> </xsl:choose> </xsl:when> <!-- may, but won't --> <xsl:otherwise>yes</xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:param name="xml2rfc-ext-pub-year"> <xsl:choose> <xsl:when test="/rfc/front/date/@year and /rfc/front/date/@year!=''"> <xsl:value-of select="/rfc/front/date/@year"/> </xsl:when> <xsl:when test="$current-year!='' and $may-default-dates='yes'"> <xsl:value-of select="$current-year"/> </xsl:when> <xsl:when test="$current-year!='' and $may-default-dates!='yes'"> <xsl:call-template name="warning"> <xsl:with-param name="msg" select="$may-default-dates"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:call-template name="error"> <xsl:with-param name="msg" select="'/rfc/front/date/@year missing (and XSLT processor cannot compute the system date)'"/> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:param> <xsl:param name="xml2rfc-ext-pub-month"> <xsl:choose> <xsl:when test="/rfc/front/date/@month and /rfc/front/date/@month!=''"> <xsl:variable name="m" select="/rfc/front/date/@month"/> <xsl:choose> <xsl:when test="string(number($m))!='NaN' and number($m) > 0 and number($m) < 13"> <xsl:call-template name="get-month-as-name"> <xsl:with-param name="month" select="$m"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:value-of select="$m"/> </xsl:otherwise> </xsl:choose> </xsl:when> <xsl:when test="$current-month!='' and $may-default-dates='yes'"> <xsl:call-template name="get-month-as-name"> <xsl:with-param name="month" select="$current-month"/> </xsl:call-template> </xsl:when> <xsl:when test="$current-month!='' and $may-default-dates!='yes'"> <xsl:call-template name="warning"> <xsl:with-param name="msg" select="$may-default-dates"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:call-template name="error"> <xsl:with-param name="msg" select="'/rfc/front/date/@month missing (and XSLT processor cannot compute the system date)'"/> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:param> <xsl:param name="pub-month-numeric"> <xsl:call-template name="get-month-as-num"> <xsl:with-param name="month" select="$xml2rfc-ext-pub-month" /> </xsl:call-template> </xsl:param> <xsl:param name="xml2rfc-ext-pub-day"> <xsl:choose> <xsl:when test="/rfc/front/date/@day and /rfc/front/date/@day!=''"> <xsl:value-of select="/rfc/front/date/@day"/> </xsl:when> <xsl:when test="$current-day!='' and $may-default-dates='yes'"> <xsl:value-of select="$current-day"/> </xsl:when> <xsl:otherwise /> <!-- harmless, we just don't have it --> </xsl:choose> </xsl:param> <xsl:param name="pub-yearmonth"> <!-- year or 0000 --> <xsl:choose> <xsl:when test="$xml2rfc-ext-pub-year!=''"> <xsl:value-of select="format-number($xml2rfc-ext-pub-year,'0000')"/> </xsl:when> <xsl:otherwise>0000</xsl:otherwise> </xsl:choose> <!-- month or 00 --> <xsl:choose> <xsl:when test="number($pub-month-numeric) > 0"> <xsl:value-of select="format-number($pub-month-numeric,'00')"/> </xsl:when> <xsl:otherwise>00</xsl:otherwise> </xsl:choose> </xsl:param> <!-- <u> element --> <xsl:template name="convert-u-compact-remainder"> <xsl:param name="f"/> <xsl:choose> <xsl:when test="contains($f,'-')"> <xsl:text>{</xsl:text> <xsl:value-of select="substring-before($f,'-')"/> <xsl:text>}, </xsl:text> <xsl:call-template name="convert-u-compact-remainder"> <xsl:with-param name="f" select="substring-after($f,'-')"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:text>{</xsl:text> <xsl:value-of select="$f"/> <xsl:text>}</xsl:text> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="convert-u-compact"> <xsl:param name="f"/> <xsl:choose> <xsl:when test="contains($f,'-')"> <xsl:text>{</xsl:text> <xsl:value-of select="substring-before($f,'-')"/> <xsl:text>}</xsl:text> </xsl:when> <xsl:otherwise> <xsl:text>{</xsl:text> <xsl:value-of select="$f"/> <xsl:text>}</xsl:text> </xsl:otherwise> </xsl:choose> <xsl:if test="contains($f,'-')"> <xsl:text> (</xsl:text> <xsl:call-template name="convert-u-compact-remainder"> <xsl:with-param name="f" select="substring-after($f,'-')"/> </xsl:call-template> <xsl:text>)</xsl:text> </xsl:if> </xsl:template> <xsl:template name="u-hex2"> <xsl:param name="n"/> <xsl:variable name="hex">0123456789ABCDEF</xsl:variable> <xsl:if test="$n >= 16"> <xsl:call-template name="u-hex2"> <xsl:with-param name="n" select="floor($n div 16)"/> </xsl:call-template> </xsl:if> <xsl:value-of select="substring($hex, 1 + ($n mod 16), 1)"/> </xsl:template> <xsl:template name="u-hex"> <xsl:param name="n"/> <xsl:variable name="t"> <xsl:call-template name="u-hex2"> <xsl:with-param name="n" select="$n"/> </xsl:call-template> </xsl:variable> <xsl:if test="string-length($t) < 4"> <xsl:value-of select="substring('0000',1,4-string-length($t))"/> </xsl:if> <xsl:value-of select="$t"/> </xsl:template> <xsl:template name="u-expanded-name"> <xsl:param name="lit"/> <xsl:choose> <xsl:when test="string-length($lit)=0"></xsl:when> <xsl:otherwise> <xsl:call-template name="name-of-first-char"> <xsl:with-param name="lit" select="$lit"/> </xsl:call-template> <xsl:if test="string-length($lit)!=1"> <xsl:text>, </xsl:text> <xsl:call-template name="u-expanded-name"> <xsl:with-param name="lit" select="substring($lit,2)"/> </xsl:call-template> </xsl:if> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="name-of-first-char"> <xsl:param name="lit"/> <xsl:variable name="c" select="substring($lit,1,1)"/> <xsl:variable name="map" select="//x:u-map/x:c[@c=$c][@d]"/> <xsl:choose> <xsl:when test="$map"> <xsl:value-of select="$map/@d"/> </xsl:when> <xsl:when test="$xml2rfc-ext-ucd-file!='' and document($xml2rfc-ext-ucd-file)/x:u-map/x:c[@c=$c]"> <xsl:value-of select="document($xml2rfc-ext-ucd-file)/x:u-map/x:c[@c=$c]/@d"/> </xsl:when> <xsl:otherwise> <xsl:text>???</xsl:text> <xsl:call-template name="error"> <xsl:with-param name="msg"> <xsl:text>'name' expansion for <u>: character '</xsl:text> <xsl:value-of select="$c"/> <xsl:text>' requires local definition using x:u-map or local UCD mapping file </xsl:text> <xsl:choose> <xsl:when test="$xml2rfc-ext-ucd-file=''">which can be specified using the 'ucd-file' directive</xsl:when> <xsl:otherwise>'<xsl:value-of select="$xml2rfc-ext-ucd-file"/>'</xsl:otherwise> </xsl:choose> </xsl:with-param> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="u-expanded-num"> <xsl:param name="lit"/> <xsl:choose> <xsl:when test="string-length($lit)=0"></xsl:when> <xsl:otherwise> <xsl:text>U+</xsl:text> <xsl:variable name="n"> <xsl:call-template name="codepoint-of-first-char"> <xsl:with-param name="lit" select="$lit"/> </xsl:call-template> </xsl:variable> <xsl:call-template name="u-hex"> <xsl:with-param name="n" select="$n"/> </xsl:call-template> <xsl:if test="string-length($lit)!=1"> <xsl:text> </xsl:text> <xsl:call-template name="u-expanded-num"> <xsl:with-param name="lit" select="substring($lit,2)"/> </xsl:call-template> </xsl:if> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="codepoint-of-first-char"> <xsl:param name="lit"/> <xsl:variable name="c" select="substring($lit,1,1)"/> <xsl:choose> <xsl:when test="not(function-available('string-to-codepoints'))"> <xsl:variable name="map" select="//x:u-map/x:c[@c=$c]"/> <xsl:variable name="asciistring"> !"#$%&'()*+,-./<xsl:value-of select="$digits"/>:;<=>?@<xsl:value-of select="$ucase"/>[\]^_`<xsl:value-of select="$lcase"/>{|}~</xsl:variable> <xsl:choose> <xsl:when test="contains($asciistring,$c)"> <xsl:value-of select="32 + string-length(substring-before($asciistring,$c))"/> </xsl:when> <xsl:when test="$map"> <xsl:value-of select="number($map/@n)"/> </xsl:when> <xsl:when test="$xml2rfc-ext-ucd-file!='' and document($xml2rfc-ext-ucd-file)/x:u-map/x:c[@c=substring($lit,1,1)]"> <xsl:value-of select="document($xml2rfc-ext-ucd-file)/x:u-map/x:c[@c=substring($lit,1,1)]/@n"/> </xsl:when> <xsl:otherwise> <xsl:call-template name="error"> <xsl:with-param name="msg">'<xsl:value-of select="$xml2rfc-ext-ucd-file"/>' <xsl:text>'num' expansion for <u>: character '</xsl:text> <xsl:value-of select="$c"/> <xsl:text>' requires XSLT 2, local definition using x:u-map, or local UCD mapping file </xsl:text> <xsl:choose> <xsl:when test="$xml2rfc-ext-ucd-file=''">which can be specified using the 'ucd-file' directive</xsl:when> <xsl:otherwise>'<xsl:value-of select="$xml2rfc-ext-ucd-file"/>'</xsl:otherwise> </xsl:choose> </xsl:with-param> </xsl:call-template> <xsl:value-of select="number(65533)"/> </xsl:otherwise> </xsl:choose> </xsl:when> <xsl:otherwise> <xsl:value-of select="number(string-to-codepoints($c))"/> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="u-expanded"> <xsl:param name="format"/> <xsl:param name="lit"/> <xsl:param name="ascii"/> <xsl:choose> <xsl:when test="starts-with($format,'{') and contains($format,'}')"> <xsl:variable name="tok" select="substring(substring-before($format,'}'),2)"/> <xsl:choose> <xsl:when test="$tok='lit'"> <xsl:text>"</xsl:text> <xsl:value-of select="$lit"/> <xsl:text>"</xsl:text> </xsl:when> <xsl:when test="$tok='ascii'"> <xsl:text>"</xsl:text> <xsl:value-of select="$ascii"/> <xsl:text>"</xsl:text> </xsl:when> <xsl:when test="$tok='name'"> <xsl:call-template name="u-expanded-name"> <xsl:with-param name="lit" select="$lit"/> </xsl:call-template> </xsl:when> <xsl:when test="$tok='num'"> <xsl:call-template name="u-expanded-num"> <xsl:with-param name="lit" select="$lit"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:call-template name="warning"> <xsl:with-param name="msg">unknown expansion for <u>: <xsl:value-of select="$tok"/></xsl:with-param> </xsl:call-template> </xsl:otherwise> </xsl:choose> <xsl:call-template name="u-expanded"> <xsl:with-param name="format" select="substring-after($format,'}')"/> <xsl:with-param name="lit" select="$lit"/> </xsl:call-template> </xsl:when> <xsl:when test="starts-with($format,'{')"> <xsl:call-template name="warning"> <xsl:with-param name="msg">Broken format string for <u>: <xsl:value-of select="$format"/></xsl:with-param> </xsl:call-template> </xsl:when> <xsl:when test="not(contains($format,'{'))"> <xsl:value-of select="$format"/> </xsl:when> <xsl:otherwise> <xsl:variable name="s" select="substring-before($format,'{')"/> <xsl:value-of select="$s"/> <xsl:call-template name="u-expanded"> <xsl:with-param name="format" select="substring($format, 1+string-length($s))"/> <xsl:with-param name="lit" select="$lit"/> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="emit-u"> <xsl:variable name="format"> <xsl:choose> <xsl:when test="@format!=''"> <xsl:value-of select="@format"/> </xsl:when> <xsl:otherwise>lit-name-num</xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:variable name="f"> <xsl:choose> <xsl:when test="translate($format,concat($lcase,'-'),'')=''"> <!-- compact notation --> <xsl:call-template name="convert-u-compact"> <xsl:with-param name="f" select="$format"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:value-of select="$format"/> </xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:call-template name="u-expanded"> <xsl:with-param name="format" select="$f"/> <xsl:with-param name="lit" select="."/> <xsl:with-param name="ascii" select="@ascii"/> </xsl:call-template> </xsl:template> <xsl:template match="u"> <xsl:call-template name="emit-u"/> </xsl:template> <xsl:template match="x:u-map"/> <!-- simple validation support --> <xsl:template match="*" mode="validate"> <xsl:apply-templates select="@*|*" mode="validate"/> </xsl:template> <xsl:template match="@*" mode="validate"/> <xsl:template name="validation-error"> <xsl:param name="additionalDiagnostics"/> <xsl:variable name="pname"> <xsl:if test="namespace-uri(..)!=''"> <xsl:value-of select="concat('{',namespace-uri(..),'}')"/> </xsl:if> <xsl:value-of select="local-name(..)"/> </xsl:variable> <xsl:variable name="cname"> <xsl:if test="namespace-uri(.)!=''"> <xsl:value-of select="concat('{',namespace-uri(.),'}')"/> </xsl:if> <xsl:value-of select="local-name(.)"/> </xsl:variable> <xsl:call-template name="error"> <xsl:with-param name="msg" select="concat($cname,' not allowed inside ',$pname,$additionalDiagnostics)"/> <xsl:with-param name="inline" select="'no'"/> </xsl:call-template> </xsl:template> <!-- artwork/sourcecode element --> <xsl:template match="blockquote/artwork | figure/artwork | figure/ed:replace/ed:*/artwork | section/artwork | li/artwork | dd/artwork | artset/artwork" mode="validate" priority="9"> <xsl:apply-templates select="@*|*" mode="validate"/> </xsl:template> <xsl:template match="blockquote/sourcecode | figure/sourcecode | figure/ed:replace/ed:*/sourcecode | section/sourcecode | li/sourcecode | dd/sourcecode | td/sourcecode" mode="validate" priority="9"> <xsl:apply-templates select="@*|*" mode="validate"/> </xsl:template> <xsl:template match="artwork|sourcecode" mode="validate"> <xsl:call-template name="validation-error"/> <xsl:apply-templates select="@*|*" mode="validate"/> </xsl:template> <!-- author element --> <xsl:template match="front/author" mode="validate" priority="9"> <xsl:apply-templates select="@*|*" mode="validate"/> </xsl:template> <xsl:template match="author" mode="validate"> <xsl:call-template name="validation-error"/> <xsl:apply-templates select="@*|*" mode="validate"/> </xsl:template> <!-- li element --> <xsl:template match="ol/li | ul/li" mode="validate" priority="9"> <xsl:apply-templates select="@*|*" mode="validate"/> </xsl:template> <xsl:template match="li" mode="validate"> <xsl:call-template name="validation-error"/> <xsl:apply-templates select="@*|*" mode="validate"/> </xsl:template> <!-- list element --> <xsl:template match="t/list | t/ed:replace/ed:*/list" mode="validate" priority="9"> <xsl:apply-templates select="@*|*" mode="validate"/> </xsl:template> <xsl:template match="list" mode="validate"> <xsl:call-template name="validation-error"/> <xsl:apply-templates select="@*|*" mode="validate"/> </xsl:template> <!-- dl element --> <xsl:template match="abstract/dl | aside/dl | blockquote/dl | dd/dl | li/dl | note/dl | section/dl | td/dl | th/dl" mode="validate" priority="9"> <xsl:apply-templates select="@*|*" mode="validate"/> </xsl:template> <xsl:template match="dl" mode="validate"> <xsl:call-template name="validation-error"/> <xsl:apply-templates select="@*|*" mode="validate"/> </xsl:template> <!-- t element --> <xsl:template match="abstract/t | abstract/ed:replace/ed:*/t | list/t | list/ed:replace/ed:*/t | note/t | note/ed:replace/ed:*/t | section/t | section/ed:replace/ed:*/t | blockquote/t | x:blockquote/t | x:blockquote/ed:replace/ed:*/t | x:note/t | x:note/ed:replace/ed:*/t | aside/t | td/t | th/t | x:lt/t | li/t | x:lt/ed:replace/ed:*/t | dd/t" mode="validate" priority="9"> <xsl:apply-templates select="@*|*" mode="validate"/> </xsl:template> <xsl:template match="t" mode="validate"> <xsl:call-template name="validation-error"/> <xsl:apply-templates select="@*|*" mode="validate"/> </xsl:template> <!-- xref element --> <xsl:template match="abstract//xref" mode="validate"> <xsl:call-template name="validation-error"> <xsl:with-param name="additionalDiagnostics"> (inside <abstract>)</xsl:with-param> </xsl:call-template> <xsl:apply-templates select="@*|*" mode="validate"/> </xsl:template> <xsl:template name="check-no-text-content"> <xsl:for-each select="text()"> <xsl:if test="normalize-space(.)!=''"> <xsl:call-template name="warning"> <xsl:with-param name="msg">No text content allowed inside <<xsl:value-of select="local-name(..)"/>>, but found: '<xsl:value-of select="."/>'</xsl:with-param> </xsl:call-template> </xsl:if> </xsl:for-each> </xsl:template> <xsl:template name="render-name"> <xsl:param name="n"/> <xsl:param name="strip-links" select="true()"/> <xsl:variable name="t"> <xsl:apply-templates select="$n"/> </xsl:variable> <xsl:choose> <xsl:when test="not($strip-links)"> <xsl:copy-of select="exslt:node-set($t)"/> </xsl:when> <xsl:otherwise> <xsl:apply-templates select="exslt:node-set($t)" mode="strip-links"/> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="render-name-ref"> <xsl:param name="n"/> <xsl:variable name="t"> <xsl:call-template name="render-name"> <xsl:with-param name="n" select="$n"/> </xsl:call-template> </xsl:variable> <xsl:apply-templates select="exslt:node-set($t)" mode="strip-ids-and-linebreaks"/> </xsl:template> <!-- clean up links from HTML --> <xsl:template match="comment()|@*" mode="strip-links"><xsl:copy/></xsl:template> <xsl:template match="text()" mode="strip-links"><xsl:copy/></xsl:template> <xsl:template match="*" mode="strip-links"> <xsl:element name="{local-name()}"> <xsl:apply-templates select="@*|node()" mode="strip-links" /> </xsl:element> </xsl:template> <xsl:template match="a|xhtml:a" mode="strip-links" xmlns:xhtml="http://www.w3.org/1999/xhtml"> <xsl:choose> <xsl:when test="@id"> <span id="{@id}"> <xsl:apply-templates select="node()" mode="strip-links" /> </span> </xsl:when> <xsl:otherwise> <xsl:apply-templates select="node()" mode="strip-links" /> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="node()|@*" mode="strip-ids-and-linebreaks"> <xsl:copy> <xsl:apply-templates select="node()|@*" mode="strip-ids-and-linebreaks" /> </xsl:copy> </xsl:template> <xsl:template match="xhtml:br" mode="strip-ids-and-linebreaks"> <xsl:text> </xsl:text> </xsl:template> <xsl:template match="@id" mode="strip-ids-and-linebreaks"/> <!-- customization: these templates can be overridden in an XSLT that imports from this one --> <xsl:template name="add-start-material"/> <xsl:template name="add-end-material"/> </xsl:transform> �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������kramdown-rfc2629-1.7.31/data/kramdown-rfc2629.erb���������������������������������������������������0000644�0000041�0000041�00000016020�15142163665�021100� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="<%=ps[:coding]||"UTF-8"%>"?> <?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?> <!-- generated by https://github.com/cabo/kramdown-rfc version <%= Gem.loaded_specs["kramdown-rfc2629"].version rescue nil %> (Ruby <%= RUBY_VERSION %>) --> <% if $options.v3 %> <!DOCTYPE rfc <%= ps["doctype-reference"] %> [ <!ENTITY nbsp " "> <!ENTITY zwsp "​"> <!ENTITY nbhy "‑"> <!ENTITY wj "⁠"> <% else %> <!DOCTYPE rfc SYSTEM "rfc2629.dtd" [ <% end %> <% ps.arr("bibxml") do |tag, sys| -%> <!ENTITY <%= tag %> SYSTEM "<%= sys %>"> <% end -%> <% ps.arr("entity", false) do |en, ev| -%> <!ENTITY <%=en%> "<%=ev%>"> <% end -%> ]> <% ps.rest.fetch("consensus") do # consensus not given -- default intelligently cat = ps.has("category") || ps.has("cat") MUST_CONSENSUS = {"std" => true, "bcp" => true} ps["consensus"] = true if MUST_CONSENSUS[cat] end rfcattrs = ps.attrs("ipr", "docName=docname", "category=cat", "consensus", "submissionType=submissiontype=stream", "xml:lang=lang", "number", "obsoletes", "updates", "seriesNo=seriesno") TRUE_FALSE = {nil => "true", false => "false", true => "true", "yes" => "true", "no" => "false"} YES_NO = {"true" => "yes", "false" => "no"} pis = KramdownRFC::ParameterSet.new({}) ps.arr("pi", false) do |pi, val| pis[pi] = TRUE_FALSE[val] || val end if $options.v3 piattrs = pis.attrs("tocDepth=tocdepth", "tocInclude=toc", "sortRefs=sortrefs", "symRefs=symrefs", "indexInclude=index") if piattrs != "" rfcattrs << " " << piattrs end end pis.rest.each do |pi, val| v = YES_NO[val] || pis.escattr(val) -%> <?rfc <%=pi%>="<%=v%>"?> <% end -%> <rfc <%=rfcattrs%>> <% ps.arr("v3xml2rfc", false) do |pi, val| Array(val).each do |el| -%> <?v3xml2rfc <%=pi%>="<%=ps.escattr(el)%>"?> <% end end -%> <front> <%= ps.ele("title", ps.attr("abbrev=titleabbrev")) %> <% ps.arr("author") do |au| aups = KramdownRFC::authorps_from_hash(au) -%> <%= KramdownRFC::person_element_from_aups("author", aups) -%> <% aups.warn_if_leftovers -%> <% end -%> <date <%= KramdownRFC::dateattrs(ps[:date]||Date.today) %>/> <%= ps.ele("area") %> <%= ps.ele("workgroup=wg") %> <%= ps.ele("keyword=kw") %> <abstract> <%= sechash.delete("abstract") %> </abstract> <% if $options.v3 -%> <% venue = ps[:venue] -%> <% if venue -%> <% venue = KramdownRFC::ParameterSet.new(venue) -%> <note title="About This Document" removeInRFC="true"> <% if (dn = ps.av[:docName]) && (dt = dn.rpartition('-')[0]) != "" -%> <t> <% if latest = venue[:latest] -%> The latest revision of this draft can be found at <eref target="<%=latest%>"/>. <% end -%> Status information for this document may be found at <eref target="https://datatracker.ietf.org/doc/<%=dt%>/"/>. </t> <% end -%> <% mail = venue[:mail] -%> <% homepage = venue[:home] -%> <% gtype = venue[:type] -%> <% if mail || homepage -%> <t> <% end -%> <% if mail mail_local, mail_host = mail.split("@", 2) end if mail_host -%> <% default_links = { "iab.org" => true, "ietf.org" => true, "irtf.org" => true, }[mail_host] mail_subdomain, mail_domain = mail_host.split(".", 2) group = venue[:group] || mail_local # XXX arch = venue[:arch] || default_links && "https://mailarchive.ietf.org/arch/browse/#{mail_local}/" subscribe = venue[:subscribe] || default_links && "https://www.ietf.org/mailman/listinfo/#{mail_local}/" GROUPS = {"ietf" => "Working ", "irtf" => "Research "} gtype ||= "#{GROUPS[mail_subdomain]}Group" -%> Discussion of this document takes place on the <%=group%> <%=gtype%> mailing list (<eref target="mailto:<%=mail%>"/>)<% if arch -%>, which is archived at <eref target="<%=arch%>"/><% end -%>. <% if subscribe -%> Subscribe at <eref target="<%=subscribe%>"/>. <% end -%> <% end -%> <% if homepage -%> <%=gtype%> information can be found at <eref target="<%=homepage%>"/>. <% end -%> <% if mail || homepage -%> </t> <% end -%> <% if repo = venue[:repo] || ((gh = venue[:github]) && "https://github.com/#{gh}") -%> <t>Source for this draft and an issue tracker can be found at <eref target="<%=repo%>"/>.</t> <% end -%> <%= venue.ele("t=text", nil, nil, true) -%> </note> <% venue.warn_if_leftovers -%> <% end -%> <% end -%> <% sechash.keys.each do |k| -%> <% if k =~ /\A(to_be_removed_)?note_(.*)/ -%> <% option = "" text = "" if $1 if $options.v3 option = " removeInRFC=\"true\"" else text = " <t>[This note is to be removed before publishing as an RFC.]</t>\n" end end -%> <note title="<%= $2.gsub("_", " ")%>"<%= option %>> <%= text -%> <%= sechash.delete(k) -%> </note> <% end -%> <% end -%> </front> <middle> {:/nomarkdown} {:quote: gi="blockquote"} {:aside: gi="aside"} {:cref: gi="cref"} {:markers: sourcecode-markers="true"} {:unnumbered: numbered="false"} {:vspace: vspace="0"} {:removeinrfc: removeinrfc="true"} {:notoc: toc="exclude"} {:compact: spacing="compact"} {:noabbrev: noabbrev="true"} {::nomarkdown} <%= sechash.delete("middle") %> </middle> <back> <% displayref.each do |k, v| -%> <displayreference target="<%=k%>" to="<%=v%>"/> <% end -%> <% shn = sechash.delete("normative") shi = sechash.delete("informative") shc = shn && shi if shc -%> <references title='References' anchor="sec-combined-references"> <% end -%> <% if shn -%> <references title='Normative References' anchor="sec-normative-references"> <%= shn %> </references> <% end -%> <% if shi -%> <references title='Informative References' anchor="sec-informative-references"> <%= shi %> </references> <% end -%> <% if shc -%> </references> <% end -%> <%= sechash.delete("back") %> <% sh = sechash.delete("contributor") -%> <% consec = ps.has("contributor") -%> <% if sh || consec -%> <% if $options.v3 -%> <section anchor="contributors" numbered="false" toc="include" removeInRFC="false"> <name>Contributors</name> <% else -%> <section anchor="contributors" numbered="false" title="Contributors"> <% warn "*** To use YAML contributors, use --v3 (kdrfc -3)" if consec -%> <% end -%> <%= sh -%> <% if $options.v3 && consec ps.arr("contributor") do |au| if Hash === au aups = KramdownRFC::authorps_from_hash(au) -%> <%= KramdownRFC::person_element_from_aups("contact", aups) -%> <%= if contrib = aups["contribution"] <<CONTRIBUTION {:/nomarkdown} #{contrib} {::nomarkdown} CONTRIBUTION end -%> <% aups.warn_if_leftovers -%> <% else -%> <%= <<TEXT {:/nomarkdown} #{au} {::nomarkdown} TEXT -%> <% end -%> <% end -%> <% end -%> </section> <% end -%> </back> <% if $source -%> <!-- ##markdown-source: <%= $source %> --> <% end -%> </rfc> ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������kramdown-rfc2629-1.7.31/bin/������������������������������������������������������������������������0000755�0000041�0000041�00000000000�15142163665�015331� 5����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������kramdown-rfc2629-1.7.31/bin/kramdown-rfc������������������������������������������������������������0000755�0000041�0000041�00000000217�15142163665�017651� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/usr/bin/env ruby # -*- coding: utf-8 -*- require 'ostruct' $options ||= OpenStruct.new $options.v3 = true require 'kramdown-rfc/command' ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������kramdown-rfc2629-1.7.31/bin/kramdown-rfc-clean-svg-ids����������������������������������������������0000755�0000041�0000041�00000000764�15142163665�022312� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/usr/bin/env ruby # -*- coding: utf-8 -*- require 'rexml/document' require 'kramdown-rfc/rexml-formatters-conservative' require 'kramdown-rfc/svg-id-cleanup' def svg_clean_ids(s) d = REXML::Document.new(s) d.context[:attribute_quote] = :quote # Set double-quote as the attribute value delimiter svg_id_cleanup(d) tr = REXML::Formatters::Conservative.new o = '' tr.write(d, o) o rescue => detail warn "*** Can't clean SVG: #{detail}" d.to_s end puts svg_clean_ids(ARGF.read) ������������kramdown-rfc2629-1.7.31/bin/kramdown-rfc2629��������������������������������������������������������0000755�0000041�0000041�00000000114�15142163665�020170� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/usr/bin/env ruby # -*- coding: utf-8 -*- require 'kramdown-rfc/command' ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������kramdown-rfc2629-1.7.31/bin/kramdown-rfc-cache-subseries-bibxml�������������������������������������0000755�0000041�0000041�00000007104�15142163665�024171� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/usr/bin/env ruby # prerequisite: # gem install net-http-persistent # # generates referencegroup files for BCP and STD series (like bibxml9) # unfortunately, needs to re-fetch rfc-index.xml # uses pretty slow built-in XML parser, so it will take a while even on regen # # uses ENV["KRAMDOWN_REFCACHEDIR"] for where you want to have your bibxml9 data # require 'rexml/document' require 'fileutils' begin require 'net/http/persistent' rescue LoadError warn "*** please install net-http-persistent:" warn " gem install net-http-persistent" warn "(prefix by sudo only if required)." exit 72 # EX_OSFILE end TARGET_DIR = ENV["KRAMDOWN_REFCACHEDIR"] || ( path = File.expand_path("~/.cache/xml2rfc") warn "*** set environment variable KRAMDOWN_REFCACHEDIR to #{path} to actually use the cache" path ) FileUtils.mkdir_p(TARGET_DIR) FileUtils.chdir(TARGET_DIR) $http = Net::HTTP::Persistent.new name: 'subseries' KRAMDOWN_PERSISTENT_VERBOSE = true def get_and_write_resource_persistently(url, fn, age_verbose=false) t1 = Time.now response = $http.request(URI(url)) if response.code != "200" raise "*** Status code #{response.code} while fetching #{url}" else File.write(fn, response.body) end t2 = Time.now warn "#{url} -> #{fn} (#{"%.3f" % (t2 - t1)} s)" if KRAMDOWN_PERSISTENT_VERBOSE if age_verbose if age = response.get_fields("age") warn "(working from a web cache, index is #{age.first} seconds stale)" end end end CLEAR_RET = "\e[K\r" # XXX all the world is ECMA-48 (ISO 6429), no? def noisy(name) print "#{name}...#{CLEAR_RET}" end def clear_noise print CLEAR_RET end def normalize_name(n) n.sub(/([A-Z])0+/) {$1} end def regress_name(n) n.sub(/([A-Z])(\d+)/) {"#$1#{"%04d" % $2.to_i}"} end def regress_name_dot(n) n.sub(/([A-Z])(\d+)/) {"#$1.#{"%04d" % $2.to_i}"} end def get_ref(rfcname) name = "reference.#{regress_name_dot(rfcname)}.xml" begin file = File.read(name) # no age check rescue Errno::ENOENT get_and_write_resource_persistently("https://www.rfc-editor.org/refs/bibxml/" << name, name) file = File.read(name) end d = REXML::Document.new(file) d.xml_decl.nowrite "<!-- #{name} -->\n" << d.to_s.lstrip end def create_bib(series, subname, rfcnames) p [series, subname, rfcnames] subname_norm = normalize_name(subname) refs = %{<?xml version='1.0' encoding='UTF-8'?>\n} refs << %{<referencegroup anchor='#{subname_norm}' target='https://www.rfc-editor.org/info/#{subname_norm.downcase}'>\n} refs << rfcnames.map {|x| get_ref(x)}.join refs << "</referencegroup>\n" File.write("reference.#{regress_name_dot(subname)}.xml", refs) end def handle_sub(series, entry) ids = entry.get_elements("doc-id") warn "** ids #{ids} #{entry}" unless ids.size == 1 subname = ids.first.text isalso = entry.get_elements("is-also") if isalso.size == 1 rfcs = isalso.first.get_elements("doc-id") if rfcs.size > 0 rfcnames = rfcs.map {|r| r.text} create_bib(series, subname, rfcnames) end end end RFCINDEX_SOURCE = "https://www.rfc-editor.org/rfc/rfc-index.xml" RFCINDEX_COPY = File.basename(RFCINDEX_SOURCE) get_and_write_resource_persistently(RFCINDEX_SOURCE, RFCINDEX_COPY, true) unless ENV["KRAMDOWN_DONT_REFRESH_RFCINDEX"] doc = REXML::Document.new(File.read(RFCINDEX_COPY)) REXML::XPath.each(doc.root, "/rfc-index/bcp-entry") { |e| handle_sub("BCP", e) } REXML::XPath.each(doc.root, "/rfc-index/std-entry") { |e| handle_sub("STD", e) } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������kramdown-rfc2629-1.7.31/bin/kramdown-rfc-extract-sourcecode�����������������������������������������0000755�0000041�0000041�00000013050�15142163665�023451� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/usr/bin/env ruby -KU require 'rexml/document' # for SVG and bibxml acrobatics require 'yaml' require 'shellwords' require 'fileutils' require_relative '../lib/kramdown-rfc/rfc8792' require_relative '../lib/kramdown-rfc/rexml-all-text.rb' def clean(s) s.gsub!(/\//, ":") s.gsub!(/\A([-.]+)/) {"_" * $1.size } s.gsub!(/[^-.:\w]+/, "-") s end $seen_slugs = {} def slugify_like_xml2rfc(s, delta = 0) s = s.unicode_normalize(:nfkd).force_encoding(Encoding::ASCII).scrub('').downcase s.gsub!(/[^-\w\s\/]/, '') s = s.strip s.gsub!(/[-\s\/]/, '-') n = 32 - delta nmax = [s.size, 40 - delta].min while $seen_slugs[slugex = s[0...n]] && n < nmax n += 1 end if $seen_slugs[slugex] m = 2 while $seen_slugs[slugex = "#{s[0...n]}-#{m}"] m += 1 if m == 1000 raise ArgumentError, "Can't build distinguishable slug for '#{s}'" end end end $seen_slugs[slugex] = s slugex end target = nil dir = nil out_type = out_name = nil unfold = true targets = [:list, :files, :zip, :yaml] require 'optparse' begin op = OptionParser.new do |opts| opts.banner = "Usage: kramdown-rfc-extract-sourcecode [options] document.xml" opts.on("-tFMT", "--to=FMT", targets, "Target format #{targets.map(&:to_s)}") do |v| target = v end opts.on("-dDIR", "--dir=DIR", "Target directory (default: sourcecode)") do |v| dir = v end opts.on("-xTYPE/NAME", "--extract=TYPE/NAME", "Extract single item to stdout") do |v| target = :stdout out_type, out_name = v.split("/", 2) end opts.on("-f", "--[no-]unfold", "RFC8792-unfold (default: yes)") do |v| unfold = v end end op.parse! rescue Exception => e warn e exit 1 end if dir target ||= :files unless [:files, :zip].include? target warn "** Unused argument --dir=#{dir}" end end dir ||= "sourcecode" target ||= :list gensym = "unnamed-000" taken = Hash.new { |h, k| h[k] = Hash.new } warned = Hash.new { |h, k| h[k] = Hash.new } filenames = ARGV.inspect begin d = REXML::Document.new(ARGF) dr = d.root unless dr warn "*** Can't parse: #{filenames}" exit(1) end rescue Errno::ENOENT warn "*** Not found: #{filenames}" exit(1) rescue => e begin warn "*** Can't parse: #{filenames} (#{e.to_s[0..120]})" rescue => e warn "*** Can't parse: #{filenames} (#{e.to_s[0..120]})" end exit(1) end REXML::XPath.each(dr, "//sourcecode|//artwork") do |x| if ty = x[:type] is_svg = false REXML::XPath.each(x, "svg") do is_svg = true end ty = clean(ty) if is_svg && ty != "svg" warn "** replacing SVG type '#{ty}' by type 'svg'" ty = "svg" end ext = ty if ty.empty? ty = "=txt" ext = "txt" end name = x[:name] name_is_from_slug = false if !name || name.empty? REXML::XPath.each(x, "ancestor::*/name[position() = 1]") do |nameel| unless sname = nameel['slugifiedName'] alltext = nameel.all_text nameel.add_attribute('slugifiedName', sname = clean("name-" << slugify_like_xml2rfc(alltext, 5))) end name = clean(sname.to_s.sub(/^name-/, '')) name_is_from_slug = true end if !name || name.empty? name = gensym.succ!.dup end name = "#{name}.#{ext}" end name = clean(name) if taken[ty][name] if name_is_from_slug || is_svg # rename old entry as well if it was from slug? nameparts = name.split(".") if is_svg && nameparts[-1] != "svg" nameparts << "svg" end ext1 = nameparts.pop || "txt" suffix = "b" while taken[ty][name = [*nameparts[0...-1], "#{nameparts[-1]}-#{suffix}", ext1].join(".")] suffix.succ! end taken[ty][name] = '' else unless warned[ty][name] warn "Concatenating to #{ty}/#{name}." warned[ty][name] = true end end else taken[ty][name] = '' end extracted = false REXML::XPath.each(x, "svg") do |svg| # According to v3.rnc, there should be only one... taken[ty][name] << svg.to_s extracted = true end unless extracted taken[ty][name] << handle_artwork_sourcecode(x.all_text, unfold) end end end def make_directory_from(dir, taken) if File.exist?(dir) bak = "#{dir}.bak" begin FileUtils.mv(dir, bak) rescue Errno::EEXIST bak.succ! retry end end FileUtils.mkdir_p(dir) taken.each { |dir1, v| FileUtils.mkdir_p("#{dir}/#{dir1}") v.each { |fn, value| IO.write("#{dir}/#{dir1}/#{fn}", value) } } end case target when :stdout if dataset = taken[out_type] unless out_name case dataset.size when 0 warn "No sourcecodes under #{out_type}" exit(1) when 1 out_name ||= dataset.keys.first else warn "Multiple sourcecodes under #{out_type}: #{dataset.keys}" exit(1) end end if data = dataset[out_name] puts data exit end end warn "*** Cannot find sourcecode #{out_type}/#{out_name}" exit(1) when :yaml puts taken.to_yaml when :list puts Hash[ taken.map {|k, v| [k, v.keys] } ].to_yaml when :files make_directory_from(dir, taken) when :zip make_directory_from(dir, taken) zip = "#{dir}.zip" if File.exist?(zip) bak = "#{zip}.bak" begin FileUtils.mv(zip, bak) rescue Errno::EEXIST # This doesn't actually happen. XXX bak.succ! retry end end cmd = ["zip", "-mr", zip, dir].shelljoin warn cmd system(cmd) end ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������kramdown-rfc2629-1.7.31/bin/de-gfm������������������������������������������������������������������0000755�0000041�0000041�00000001634�15142163665�016422� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/usr/bin/env ruby -Ku Encoding.default_external = "UTF-8" # wake up, smell the coffee require 'kramdown' require 'kramdown-parser-gfm' options = '' while /\A-([4bck]+)\z/ === ARGV[0] ARGV.shift options << $1 end if /k/ === options # kramdown MARKDOWN_BR = "\\\\\n" end if /c/ === options # commonmark MARKDOWN_BR = "\\\n" end if /b/ === options # universal HTML MARKDOWN_BR = "<br/>\n" end MARKDOWN_BR ||= " \n" # original Gruber module Kramdown module Converter # Converts an element tree to the kramdown format. class Kramdown < Base # Argh def convert_br(_el, _opts) MARKDOWN_BR end end end end list_indent = 2 list_indent = 4 if /4/ === options doc = Kramdown::Document.new(ARGF.read, input: 'GFM', gfm_quirks: 'paragraph_end', list_indent: list_indent) puts doc.to_kramdown ����������������������������������������������������������������������������������������������������kramdown-rfc2629-1.7.31/bin/kramdown-rfc-lsr��������������������������������������������������������0000755�0000041�0000041�00000016615�15142163665�020460� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/usr/bin/env ruby -KU # frozen_string_literal: true # List Section References from a RFCXML document # # (PoC, in urgent need of refactoring) # Requires xml2rfc and tidy commands in path # Use without open-uri-cached is untested require 'rexml/document' require 'yaml' require 'json' require 'shellwords' require 'fileutils' begin require 'open-uri/cached' rescue LoadError warn '*** please "gem install open-uri-cached" to enable caching' require 'open-uri' end require_relative '../lib/kramdown-rfc/rexml-all-text.rb' target = :shortname require 'optparse' begin op = OptionParser.new do |opts| opts.banner = "Usage: kramdown-rfc-lsr [options] xml-source" opts.on("-u", "--url", "Source is URL") do |v| target = :url end opts.on("-s", "--shortname", "Source is shortname (default)") do |v| target = :shortname end opts.on("-f", "--file", "Source is filename") do |v| target = :file end end op.parse! rescue Exception => e warn e exit 1 end $exit_code = 0 if target != :file && ARGV.size != 1 puts op exit 1 end xmlsource = ARGV[0] if target == :shortname xmlsource = case xmlsource when /^(?:rfc)?(\d+)$/i "https://www.rfc-editor.org/rfc/rfc#{$1.to_i.to_s}.xml" when /^(?:draft-|I-D.|)(.*-\d\d)$/ "https://www.ietf.org/archive/id/draft-#$1.xml" # XXX find xml source for most recent version! else warn "*** Can't parse shortname #{xmlsource.inspect}" puts op exit 1 end target = :url end begin xml = case target when :file ARGF.read when :url URI(xmlsource).open.read else fail end rescue Exception => e warn "#{xmlsource.inspect}: #{e}" exit 1 end doc = REXML::Document.new(xml) REXML::XPath.match(doc.root, '//xi:include').each do |el| begin refdoc = REXML::Document.new(URI(el[:href]).open.read) el.replace_with(refdoc.root) rescue => e warn "*** error getting xinclude #{el} resolved: #{e}" end end def series_info_to_URI(si) case si[:name] when "RFC" "https://www.rfc-editor.org/rfc/rfc#{si[:value]}.xml" when "Internet-Draft" "https://www.ietf.org/archive/id/#{si[:value]}.xml" end end def series_info_to_name(si) case si[:name] when "RFC" "RFC#{si[:value]}" when "Internet-Draft" si[:value] end end def section_number_to_pn_candidates(s) if /^[0-9]/ =~ s ["section-#{s}"] elsif /[.]/ =~ s ["section-#{s.downcase}", "section-appendix.#{s.downcase}"] else ["section-appendix.#{s.downcase}"] end end def section_number_to_htmlid(s) if /^[0-9]/ =~ s "section-#{s}" else "appendix-#{s.upcase}" end end references = Hash[REXML::XPath.match(doc.root, "//reference").map {|r| si = REXML::XPath.match(r, "seriesInfo").map {|s| series_info_to_URI(s)}.compact.first sn = REXML::XPath.match(r, "seriesInfo").map {|s| series_info_to_name(s)}.compact.first [r[:anchor], si ? [si, sn] : nil] }] # XXX duplicates? heading1 = "# #{xmlsource}" title = REXML::XPath.first(doc.root, "//title") heading1 << "\n(#{title.all_text})" if title puts heading1 per_reference = Hash.new { |h, k| h[k] = Set[]} REXML::XPath.each(doc.root, "//xref[@section]") do |x| trg = x[:target] if x[:relative] puts "\n## #{x[:target]}#{x[:relative]}: #{x[:section]}" else # p x per_reference[trg] << x[:section] end end def error_out(s) warn "" warn s warn "" $exit_code = 1 end def num_expand(s) s.gsub(/\d+/) {|n| "%09d" % n.to_i} end def want_one(secs, what) case secs.size when 0 error_out "*** cannot match #{what}" "*** DOESN'T EXIST ***" when 1 yield secs.first else error_out "*** multiple matches for #{what}" "*** MULTIPLE MATCHES ***" end end require 'open3' module OpenURI class << self def processed(uri, old, camo, *rest) newuri = uri.to_s.sub(old, camo) # camo name for processed data response = Cache.get(newuri) || ( unprocessed = open_uri(uri, *rest).read fn = [OpenURI::Cache.cache_path, uri.sub(/.*\//, '')].join('/') File.open(fn, 'wb'){|f| f.write unprocessed } new_fn = yield newuri, fn Cache.set(newuri, File.open(new_fn)) ) response end def prepped(uri) processed(uri, /\.xml$/, ".prepped.xml") do |newuri, fn| _prep_out, s = Open3.capture2("xml2rfc", "--prep", fn) fail s.inspect unless s.success? fn.sub(/\.xml$/, ".prepped.xml") # xml2rfc creates new file end end def tidied(uri) processed(uri, /\.html$/, ".tidied.html") do |newuri, fn| _prep_out, s = Open3.capture2("tidy", "-mq", "-asxml", "-f", "/dev/null", fn) fail s.inspect unless s.exited? # can't check success fn # -m makes in-place change end end end end # go through section-referenced documents in sequence per_reference.keys.sort_by {|x| num_expand(x)}.each do |trg| uri, sname = references[trg] add = +'' if sname != trg add << " [#{sname}]" end begin ref = URI(uri).open.read refdoc = REXML::Document.new(ref) if REXML::XPath.match(refdoc.root, "/rfc/front/abstract[@pn]").size == 0 ref = OpenURI.prepped(uri).read refdoc = REXML::Document.new(ref) add << " [+prep]" end add << " (#{REXML::XPath.match(refdoc.root, "//title").first.all_text})" rescue OpenURI::HTTPError => e begin jsonuri = uri.sub(/\.xml$/, ".json") refjson = URI(jsonuri).open.read refdata = JSON.load(refjson) add << " (#{refdata["title"].strip})" rescue OpenURI::HTTPError => e add << " [No XML or JSON]" rescue Exception => e warn "*** error getting #{jsonuri.inspect}: #{e}" end rescue Exception => e warn "*** error getting #{uri.inspect}: #{e}" end puts "\n## #{trg}#{add}" unless refdoc begin htmluri = uri.sub(/\.xml$/, ".html") refhtml = OpenURI.tidied(htmluri).read refhtmldoc = REXML::Document.new(refhtml) rescue Exception => e warn "*** error tidying up HTML for #{htmluri.inspect}: #{e}" end end # go through individual section references in sequence per_reference[trg].to_a.sort_by {|x| num_expand(x)}.each do |s| add = +'' if refdoc # find section name in XML from anchor s secpn = section_number_to_pn_candidates(s) secs = secpn.flat_map{ |c| REXML::XPath.match(refdoc.root, "//section[@pn=$pn]", {}, {"pn" => c})} what = "#{secpn.join(" or ")} in #{trg}" add << " (#{want_one(secs, what) do |sec| sec[:title] || sec.elements["name"].all_text end})" elsif refhtmldoc # find section name in HTML from anchor s secpn = section_number_to_htmlid(s) secs = REXML::XPath.match(refhtmldoc.root, "//xmlns:a[@id=$pn]/ancestor::xmlns:span", {"xmlns" => "http://www.w3.org/1999/xhtml"}, {"pn" => secpn}) what = "#{secpn} in #{trg}" add << " (#{want_one(secs, what) do |sec| sec.text.sub(/^\.\s+/, '') end})" end puts "* #{/^[0-9]/ =~ s ? "Section" : "Appendix"} #{s}#{add}" end end exit $exit_code �������������������������������������������������������������������������������������������������������������������kramdown-rfc2629-1.7.31/bin/kdrfc�������������������������������������������������������������������0000755�0000041�0000041�00000005026�15142163665�016353� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/usr/bin/env ruby -KU require 'kramdown-rfc/kdrfc-processor' require 'optparse' # try to get this from gemspec. KDRFC_VERSION=Gem.loaded_specs["kramdown-rfc2629"].version rescue "unknown-version" kdrfc = KramdownRFC::KDRFC.new kdrfc.options.txt = true # default op = OptionParser.new do |opts| opts.banner = <<BANNER Usage: kdrfc [options] file.md|file.xml Version: #{KDRFC_VERSION} BANNER opts.on("-V", "--version", "Show version and exit") do |v| puts "kdrfc, from kramdown-rfc2629 #{KDRFC_VERSION}" exit end opts.on("-H", "--help", "Show option summary and exit") do |v| puts opts exit end opts.on("-v", "--[no-]verbose", "Run verbosely") do |v| kdrfc.options.verbose = v end opts.on("-r", "--[no-]remote", "Run xml2rfc remotely even if there is a local one") do |v| kdrfc.options.remote = v end opts.on("-x", "--[no-]xml", "Convert to xml only") do |v| kdrfc.options.xml_only = v end opts.on("-p", "--[no-]prep", "Convert xml to prepped xml") do |v| kdrfc.options.prep = v end opts.on("-P", "-f", "--[no-]pdf", "Convert xml to PDF") do |v| kdrfc.options.pdf = v end opts.on("-c", "--[no-]convert", "Convert xml to v3 xml") do |v| kdrfc.options.v2v3 = v end opts.on("-i", "--[no-]idnits", "Run idnits on the resulting text") do |v| kdrfc.options.idnits = v end opts.on("-h", "--[no-]html", "Convert to html as well") do |v| kdrfc.options.html = v end opts.on("-t", "--[no-]txt", "Convert to txt as well (default)") do |v| kdrfc.options.txt = v end opts.on("-n", "Do not convert to txt (--no-txt)") do |v| kdrfc.options.txt = !v end opts.on("-3", "--[no-]v3", "Use RFCXML v3 processing rules") do |v| kdrfc.options.v3 = v end opts.on("-2", "--[no-]v2", "Use RFCXML v2 processing rules") do |v| kdrfc.options.v2 = v end opts.on("-dNN", "--docrev=NN", /[0-9][0-9]/, "Replace -latest by -NN in docname") do |v| ENV["KRAMDOWN_RFC_DOCREV"] = v end end op.parse! if kdrfc.options.v2 && kdrfc.options.v3 warn "*** can't have v2 and eat v3 cake" kdrfc.options.v2 = false end if kdrfc.options.v3.nil? && !kdrfc.options.v2 if Time.now.to_i >= 1645567342 # Time.parse("2022-02-22T22:02:22Z").to_i kdrfc.options.v3 = true # new default from the above date end end warn "*** v2 #{kdrfc.options.v2.inspect} v3 #{kdrfc.options.v3.inspect}" if kdrfc.options.verbose case ARGV.size when 1 fn = ARGV[0] begin kdrfc.process(fn) rescue StandardError => e warn e.to_s exit 1 end else puts op exit 1 end ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������kramdown-rfc2629-1.7.31/bin/doilit������������������������������������������������������������������0000755�0000041�0000041�00000002500�15142163665�016540� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/usr/bin/env ruby require 'yaml' require 'kramdown-rfc2629' require 'kramdown-rfc/parameterset' require 'kramdown-rfc/refxml' require 'kramdown-rfc/doi' # doilit -c 10.6028/NIST.SP.800-183 10.1016/j.adhoc.2015.04.007 10.1109/MIC.2012.29 10.1145/2507924.2507954 $verbose = false $fuzzy = false $handle = "a" $xml = false $site = "https://dx.doi.org" $global_markdown_options ||= {} # work around uninitialized litent = {} ARGV.each do |doi| case doi when "-c" begin require 'open-uri/cached' rescue LoadError warn '*** please "gem install open-uri-cached" to enable caching' end next when "-f" $fuzzy = true next when "-v" $verbose = true next when /\A-s=(.*)/ $site = $1 next when /\A-h=(.*)/ $handle = $1 next when /\A-x=(.*)/ $handle = $1 $xml = true # make all come out as XML next when /\A-/ warn "*** Usage: doilit [-c] [-f] [-v] [-h=handle|-x=xmlhandle] doi..." exit 1 end lit = doi_fetch_and_convert(doi, fuzzy: $fuzzy, verbose: $verbose, site: $site) while litent[$handle] $handle.succ! end litent[$handle] = lit end if $xml litent.each do |k, v| puts KramdownRFC::ref_to_xml(k, v) end else # 1.9 compat: s/lines/each_line.to_a/ puts litent.to_yaml.gsub(/^/, " ").each_line.to_a[1..-1] end ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������kramdown-rfc2629-1.7.31/bin/kramdown-rfc-extract-figures-tables�������������������������������������0000755�0000041�0000041�00000004170�15142163665�024235� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/usr/bin/env ruby -KU require 'rexml/document' require 'yaml' require 'optparse' PROGNAME = $0 # "kramdown-rfc-extract-figures-tables" target = :section targets = [:section, :note, :rfc] require 'optparse' begin op = OptionParser.new do |opts| opts.banner = "Usage: #{PROGNAME} [options] [-|document.xml]" opts.on("-tFMT", "--to=FMT", targets, "Target format #{targets.map(&:to_s)}") do |v| target = v end end op.parse! rescue Exception => e warn e exit 1 end class String def spacify gsub(/\s+/, " ") end end lists = Hash.new { |h, k| h[k] = [] } d = REXML::Document.new(ARGF) unless d.root warn "** #{PROGNAME}: Cannot parse input" exit 1 end REXML::XPath.each(d.root, %{//figure|//*[name()="table" or name()="texttable"]}) do |x| gi = x.name ref = x[:anchor] # p [gi, ref] out = [] REXML::XPath.each(x, "name") do |nm| out << nm.children.map{|ch| ch.to_s}.join # p [gi, out.last] end REXML::XPath.each(x, "@title") do |ttl| out << ttl.to_s.spacify # p [gi, out.last] end gi1 = if gi == "texttable"; "table" else gi end if out == [] # nameless # nameless, anchorless fig doesn't get a number; ignore next if gi == "figure" && !ref # Synthesize name (if not redundant) out = ["#{gi1.capitalize} #{lists[gi1].size + 1}"] if !ref end # p [gi, out] lists[gi1] << [ref, out.join(" ")] end lists.each do |k, v| item = k.capitalize title = "List of #{item}s" case target when :note puts puts "--- note_#{title.gsub(" ", "_")}" puts when :section, :rfc puts puts "# #{title}" puts "{:unnumbered}" puts puts "{:compact#{" hangindent=\"11\"" if target == :rfc}}" else fail end v.each_with_index do |(ref, ti), n| ti.sub!(/,?[\p{Zl}\p{Zp}\p{Cc}].*/, "") # first line of caption only if target == :rfc if ref puts "{{#{ref}}}:" puts ": {{<<#{ref}}}" else puts "#{item} #{n+1}:" puts ": #{ti}" warn "** No anchor on #{item} #{n+1} \"#{ti}\"" end puts else ti = "[#{ti}](##{ref})" if ref puts "#{n+1}. #{ti}" end end end ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������kramdown-rfc2629-1.7.31/bin/kramdown-rfc-extract-markdown�������������������������������������������0000755�0000041�0000041�00000000476�15142163665�023150� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/usr/bin/env ruby -KU require 'kramdown-rfc/gzip-clone' require 'base64' EMBEDDED_RE = %r{<!-- ##markdown-source:\s*([A-Za-z0-9+/=\s]+)-->} embedded = ARGF.read.scan(EMBEDDED_RE) unless embedded.empty? puts Gzip.decompress(Base64.decode64(embedded[0][0])) else warn "*** No embedded markdown source found!" end ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������kramdown-rfc2629-1.7.31/bin/kramdown-rfc-cache-i-d-bibxml�������������������������������������������0000755�0000041�0000041�00000006056�15142163665�022643� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/usr/bin/env ruby # prerequisite: # gem install net-http-persistent # # dumps all bibxml for current, "Active" I-Ds in cache # reasonably efficient after initial call if the output is retained # # requires Ruby 2.4 or above because of "liberal_parsing" option # # uses ENV["KRAMDOWN_REFCACHEDIR"] for where you want to have your bibxml3 data # require 'csv' require 'fileutils' begin require 'net/http/persistent' rescue LoadError warn "*** please install net-http-persistent:" warn " gem install net-http-persistent" warn "(prefix by sudo only if required)." exit 72 # EX_OSFILE end TARGET_DIR = ENV["KRAMDOWN_REFCACHEDIR"] || ( path = File.expand_path("~/.cache/xml2rfc") warn "*** set environment variable KRAMDOWN_REFCACHEDIR to #{path} to actually use the cache" path ) FileUtils.mkdir_p(TARGET_DIR) FileUtils.chdir(TARGET_DIR) $http = Net::HTTP::Persistent.new name: 'allid' KRAMDOWN_PERSISTENT_VERBOSE = true def get_and_write_resource_persistently(url, fn, age_verbose=false) t1 = Time.now response = $http.request(URI(url)) if response.code != "200" raise "*** Status code #{response.code} while fetching #{url}" else File.write(fn, response.body) end t2 = Time.now warn "#{url} -> #{fn} (#{"%.3f" % (t2 - t1)} s)" if KRAMDOWN_PERSISTENT_VERBOSE if age_verbose if age = response.get_fields("age") warn "(working from a web cache, index is #{age.first} seconds stale)" end end end CLEAR_RET = "\e[K\r" # XXX all the world is ECMA-48 (ISO 6429), no? def noisy(name) print "#{name}...#{CLEAR_RET}" end def clear_noise print CLEAR_RET end ALL_ID2_SOURCE = "https://www.ietf.org/id/all_id2.txt" ALL_ID2_COPY = ".all_id2.txt" get_and_write_resource_persistently(ALL_ID2_SOURCE, ALL_ID2_COPY, true) unless ENV["KRAMDOWN_DONT_REFRESH_ALL_ID2"] ix = File.read(ALL_ID2_COPY).lines.grep_v(/^#/).join csv = CSV.new(ix, col_sep: "\t", liberal_parsing: true) drafts = csv.read active = drafts.select { |d| d[2] == "Active" } active_names = active.map { |a| a[0] } puts "#{active_names.size} active drafts" active_names.each do |name| if name =~ /\Adraft-(.*)-(\d\d)\z/ namepart = $1 version = $2 name0 = "reference.I-D.#{namepart}.xml" noisy(name0) if File.exist?(name0) name1 = "reference.I-D.draft-#{namepart}-#{version}.xml" if File.exist?(name1) noisy(name1) FileUtils.touch(name0) # because name1 already exists, we believe name0 is fresh else begin url0 = "https://datatracker.ietf.org/doc/bibxml3/draft-#{namepart}.xml" get_and_write_resource_persistently(url0, name0) # get name0 first url1 = "https://datatracker.ietf.org/doc/bibxml3/draft-#{namepart}-#{version}.xml" get_and_write_resource_persistently(url1, name1) # then name1 to mark this as updated rescue => e warn "*** #{name0}: #{e}" end end else warn "*** Malformed draft name: #{name}" end end clear_noise ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������kramdown-rfc2629-1.7.31/bin/kramdown-rfc-autolink-iref-cleanup��������������������������������������0000755�0000041�0000041�00000000273�15142163665�024047� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/usr/bin/env ruby # -*- coding: utf-8 -*- require 'rexml/document' require 'kramdown-rfc/autolink-iref-cleanup' d = REXML::Document.new(ARGF.read) autolink_iref_cleanup(d) puts d.to_s �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������kramdown-rfc2629-1.7.31/bin/echars������������������������������������������������������������������0000755�0000041�0000041�00000003137�15142163665�016530� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/usr/bin/env ruby require 'unicode/name' require 'unicode/scripts' require 'unicode/blocks' require 'json' require 'differ' module Differ module Format module Color class << self def as_change(change) # monkey patch as_insert(change) << "\n" << as_delete(change) end end end end end def readable(c) j = c.to_json if j.size == 3 j[1...-1] else j end end def explain(s) ret = '' hist = Hash.new(0) s.each_char do |c| hist[c] += 1 unless c.ord.between?(32, 126) end hist.delete("\n") hist.keys.sort.group_by {|c| Unicode::Blocks.block(c)}.each do |block, l| scripts = Set[] l.each do |c| scripts << Unicode::Scripts.scripts(c) end ret << "*** #{block}" ret << " (#{scripts.join})" if scripts.size == 1 ret << "\n" l.each do |c| ret << "#{readable(c)}: U+#{"%04X %4d" % [c.ord, hist[c]] } #{Unicode::Name.correct(c) || Unicode::Name.label(c) }" ret << " (#{Unicode::Scripts.scripts(c).join(", ")})" if scripts.size != 1 ret << "\n" end end ret end s = ARGF.read es = explain(s) n = s.unicode_normalize en = explain(n) if es == en puts es else puts "*** Warning: some characters are not normalized and are shown in red." puts " ...showing a normalized variant (NFC) in green." puts " Lack of normalization may or may not be a problem." puts " (Characters may appear to be under wrong block heading.)" puts Differ.diff_by_line(en, es).format_as(:color) end ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������kramdown-rfc2629-1.7.31/kramdown-rfc2629.gemspec����������������������������������������������������0000644�0000041�0000041�00000004173�15142163665�021050� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������spec = Gem::Specification.new do |s| s.name = 'kramdown-rfc2629' s.version = '1.7.31' s.summary = "Kramdown extension for generating RFCXML (RFC 799x)." s.description = %{An RFCXML (RFC 799x) generating backend for Thomas Leitner's "kramdown" markdown parser. Mostly useful for RFC writers.} s.add_dependency('kramdown', '~> 2.4.0') s.add_dependency('kramdown-parser-gfm', '~> 1.1') s.add_dependency('certified', '~> 1.0') s.add_dependency('json_pure', '~> 2.0') s.add_dependency('unicode-name', '~> 1.0') s.add_dependency('unicode-blocks', '~> 1.0') s.add_dependency('unicode-scripts', '~> 1.0') s.add_dependency('net-http-persistent', '~> 4.0') s.add_dependency('differ', '~> 0.1') s.add_dependency('base64', '~> 0.2') s.add_dependency('ostruct', '~> 0.6') s.files = Dir['lib/**/*.rb'] + %w(README.md LICENSE kramdown-rfc2629.gemspec bin/kdrfc bin/kramdown-rfc bin/kramdown-rfc2629 bin/doilit bin/echars bin/kramdown-rfc-extract-markdown bin/kramdown-rfc-extract-sourcecode bin/kramdown-rfc-extract-figures-tables bin/kramdown-rfc-lsr data/kramdown-rfc2629.erb data/encoding-fallbacks.txt data/math.json data/rfcxml.xslt bin/kramdown-rfc-cache-subseries-bibxml bin/kramdown-rfc-autolink-iref-cleanup bin/de-gfm bin/kramdown-rfc-clean-svg-ids) s.require_path = 'lib' s.executables = ['kramdown-rfc', 'kramdown-rfc2629', 'doilit', 'echars', 'kramdown-rfc-extract-markdown', 'kramdown-rfc-extract-sourcecode', 'kramdown-rfc-extract-figures-tables', 'kramdown-rfc-lsr', 'kdrfc', 'kramdown-rfc-cache-i-d-bibxml', 'kramdown-rfc-cache-subseries-bibxml', 'kramdown-rfc-autolink-iref-cleanup', 'de-gfm', 'kramdown-rfc-clean-svg-ids'] s.required_ruby_version = '>= 2.5.0' s.author = "Carsten Bormann" s.email = "cabo@tzi.org" s.homepage = "http://github.com/cabo/kramdown-rfc" s.license = 'MIT' end �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������kramdown-rfc2629-1.7.31/lib/������������������������������������������������������������������������0000755�0000041�0000041�00000000000�15142163665�015327� 5����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������kramdown-rfc2629-1.7.31/lib/kramdown-rfc/�����������������������������������������������������������0000755�0000041�0000041�00000000000�15142163665�017721� 5����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������kramdown-rfc2629-1.7.31/lib/kramdown-rfc/gzip-clone.rb����������������������������������������������0000644�0000041�0000041�00000001771�15142163665�022323� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������require 'zlib' require 'stringio' # cloned from module ActiveSupport # A convenient wrapper for the zlib standard library that allows # compression/decompression of strings with gzip. # # gzip = Gzip.compress('compress me!') # # => "\x1F\x8B\b\x00o\x8D\xCDO\x00\x03K\xCE\xCF-(J-.V\xC8MU\x04\x00R>n\x83\f\x00\x00\x00" # # Gzip.decompress(gzip) # # => "compress me!" module Gzip class Stream < StringIO def initialize(*) super set_encoding "BINARY" end def close; rewind; end end # Decompresses a gzipped string. def self.decompress(source) Zlib::GzipReader.new(StringIO.new(source)).read end # Compresses a string using gzip, setting mtime to 0 def self.compress_m0(source, level=Zlib::DEFAULT_COMPRESSION, strategy=Zlib::DEFAULT_STRATEGY) output = Stream.new gz = Zlib::GzipWriter.new(output, level, strategy) gz.mtime = 0 gz.write(source) gz.close output.string end end # end �������kramdown-rfc2629-1.7.31/lib/kramdown-rfc/parameterset.rb��������������������������������������������0000644�0000041�0000041�00000004624�15142163665�022750� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������module KramdownRFC class ParameterSet include Kramdown::Utils::Html attr_reader :f def initialize(y) raise "*** invalid parameter set #{y.inspect}" unless Hash === y @f = y @av = {} end attr :av def [](pn) @f.delete(pn.to_s) end def []=(pn, val) @f[pn.to_s] = val end def default(pn, &block) @f.fetch(pn.to_s, &block) end def default!(pn, value) default(pn) { @f[pn.to_s] = value } end def has(pn) @f[pn.to_s] end def has?(pn) @f.key?(pn.to_s) end def escattr(str) escape_html(str.to_s, :attribute) end def van(pn) # pn is a parameter name, possibly with =aliases names = pn.to_s.split("=") [self[names.reverse.find{|nm| has?(nm)}], names.first] end def attr(pn) val, an = van(pn) @av[an.intern] = val %{#{an}="#{escattr(val)}"} if val # see attrtf below end def attrs(*pns) pns.map{ |pn| attr(pn) if pn }.compact.join(" ") end def attrtf(pn) # can do an overriding false value val, an = van(pn) @av[an.intern] = val %{#{an}="#{escattr(val)}"} unless val.nil? end def attrstf(*pns) pns.map{ |pn| attrtf(pn) if pn }.compact.join(" ") end def ele(pn, attr=nil, defcontent=nil, markdown=false) val, an = van(pn) val ||= defcontent val = [val] if Hash === val Array(val).map do |val1| a = Array(attr).dup if Hash === val1 val1.each do |k, v| if k == ":" val1 = v else k = Kramdown::Element.attrmangle(k) || k a.unshift(%{#{k}="#{escattr(v)}"}) end end end v = val1.to_s.strip contents = if markdown ::Kramdown::Converter::Rfc2629::process_markdown(v) else escape_html(v) end %{<#{[an, *a.map(&:to_s)].join(" ").strip}>#{contents}</#{an}>} end.join(" ") end def arr(an, converthash=true, must_have_one=false, &block) arr = self[an] || [] arr = [arr] if Hash === arr && converthash arr << { } if must_have_one && arr.empty? Array(arr).each(&block) end def rest @f end def warn_if_leftovers if !@f.empty? warn "*** attributes left #{@f.inspect}!" end end end end ������������������������������������������������������������������������������������������������������������kramdown-rfc2629-1.7.31/lib/kramdown-rfc/rfc8792.rb�������������������������������������������������0000644�0000041�0000041�00000005674�15142163665�021366� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� # Note that this doesn't attempt to handle HT characters def remove_indentation(s) l = s.lines indent = l.grep(/\S/).map {|l| l[/^\s*/].size}.min l.map {|li| li.sub(/^ {0,#{indent}}/, "")}.join end def trim_empty_lines_around(s) # this deletes the trailing newline, which may need to be reconstructed s.sub(/\A(\r?\n)*/, '').sub(/(\r?\n)*\z/, '') end def fix_unterminated_line(s) s.sub(/[^\n]\z/) { "#$&\n" } # XXX end def handle_artwork_sourcecode(s, unfold = true) s = trim_empty_lines_around(s) s = unfold8792(s) if unfold fix_unterminated_line(s) end FOLD_MSG = "NOTE: '\\' line wrapping per RFC 8792".freeze UNFOLD_RE = /\A.*#{FOLD_MSG.sub("\\", "(\\\\\\\\\\\\\\\\?)")}.*\n\r?\n/ def unfold8792(s) if s =~ UNFOLD_RE indicator = $1 s = $' sub = case indicator when "\\" s.gsub!(/\\\n[ \t]*/, '') when "\\\\" s.gsub!(/\\\n[ \t]*\\/, '') else fail "indicator" # Cannot happen end warn "** encountered RFC 8792 header without folded lines" unless sub end s end MIN_FOLD_COLUMNS = FOLD_MSG.size FOLD_COLUMNS = 69 RE_IDENT = /\A[A-Za-z0-9_]\z/ def fold8792_1(s, columns = FOLD_COLUMNS, left = false, dry = false) if s.index("\t") warn "*** HT (\"TAB\") in text to be folded. Giving up." return s end if columns < MIN_FOLD_COLUMNS columns = if columns == 0 FOLD_COLUMNS else warn "*** folding to #{MIN_FOLD_COLUMNS}, not #{columns}" MIN_FOLD_COLUMNS end end lines = s.lines.map(&:chomp) did_fold = false ix = 0 while li = lines[ix] col = columns if li[col].nil? if li[-1] == "\\" lines[ix..ix] = [li << "\\", ""] ix += 1 end ix += 1 else did_fold = true min_indent = left || 0 col -= 1 # space for "\\" while li[col] == " " # can't start new line with " " col -= 1 end if col <= min_indent warn "*** Cannot RFC8792-fold1 to #{columns} cols #{"with indent #{left}" if left} |#{li.inspect}|" else if RE_IDENT === li[col] # Don't split IDs col2 = col while col2 > min_indent && RE_IDENT === li[col2-1] col2 -= 1 end if col2 > min_indent col = col2 end end rest = li[col..-1] indent = left || columns - rest.size if !left && li[-1] == "\\" indent -= 1 # leave space for next round end if indent > 0 rest = " " * indent + rest end lines[ix..ix] = [li[0...col] << "\\", rest] end ix += 1 end end if did_fold msg = FOLD_MSG.dup if !dry && columns >= msg.size + 4 delta = columns - msg.size - 2 # 2 spaces half = delta/2 msg = "#{"=" * half} #{msg} #{"=" * (delta - half)}" end lines[0...0] = [msg, ""] lines.map{|x| x << "\n"}.join else s end end ��������������������������������������������������������������������kramdown-rfc2629-1.7.31/lib/kramdown-rfc/yamlcheck.rb�����������������������������������������������0000644�0000041�0000041�00000002246�15142163665�022212� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������require 'yaml' module KramdownRFC module YAMLcheck def self.short_name(node) if node.scalar? node.value else node.children&.map {|nm| short_name(nm)}&.join("_") end end # Does not follow aliases. def self.check_dup_keys1(node, path) if YAML::Nodes::Mapping === node children = node.children.each_slice(2) duplicates = children.map { |key_node, _value_node| key_node }.group_by{|nm| short_name(nm)}.select { |_value, nodes| nodes.size > 1 } duplicates.each do |key, nodes| name = (path + [key]).join("/") lines = nodes.map { |occurrence| occurrence.start_line + 1 }.join(", ") warn "** duplicate map key >#{name}< in YAML, lines #{lines}" end children.each do |key_node, value_node| newname = short_name(key_node) check_dup_keys1(value_node, path + Array(newname)) end else node.children.to_a.each { |child| check_dup_keys1(child, path) } end end def self.check_dup_keys(data) ast = YAML.parse_stream(data) check_dup_keys1(ast, []) end # check_dup_keys(DATA) end end ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������kramdown-rfc2629-1.7.31/lib/kramdown-rfc/autolink-iref-cleanup.rb�����������������������������������0000644�0000041�0000041�00000001543�15142163665�024447� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������require 'rexml/document' def autolink_iref_cleanup(d) d.root.get_elements("//section[@anchor]").each do |sec| anchor = sec['anchor'] irefs = {} sec.get_elements(".//xref[@target='#{anchor}'][@format='none']").each do |xr| ne = xr.previous_element # 9c87e84 iref now before xref if ne && ne.name == "iref" && (item = ne['item']) irefs[item] = ne['subitem'] # XXX one subitem only ne.remove chi = xr.children chi[1..-1].reverse.each do |ch| xr.parent.insert_after(xr, ch) end xr.replace_with(chi[0]) end end irefs.each do |k, v| sec.insert_after(sec.get_elements("name").first, e = REXML::Element.new("iref", sec)) e.attributes["item"] = k e.attributes["subitem"] = v e.attributes["primary"] = 'true' end end end �������������������������������������������������������������������������������������������������������������������������������������������������������������kramdown-rfc2629-1.7.31/lib/kramdown-rfc/rexml-all-text.rb������������������������������������������0000644�0000041�0000041�00000000542�15142163665�023126� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������require 'rexml/document' module REXML # all_text: Get all text from descendants that are Text or CData class Element def all_text @children.map {|c| c.all_text}.join end end class Text # also: ancestor of CData def all_text value end end class Child def all_text '' end end end ��������������������������������������������������������������������������������������������������������������������������������������������������������������kramdown-rfc2629-1.7.31/lib/kramdown-rfc/command.rb�������������������������������������������������0000755�0000041�0000041�00000054164�15142163665�021701� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/usr/bin/env ruby # -*- coding: utf-8 -*- require 'kramdown-rfc2629' require 'kramdown-rfc/parameterset' require 'kramdown-rfc/refxml' require 'kramdown-rfc/rfc8792' require 'yaml' require 'kramdown-rfc/erb' require 'date' # try to get this from gemspec. KDRFC_VERSION=Gem.loaded_specs["kramdown-rfc2629"].version rescue "unknown-version" Encoding.default_external = "UTF-8" # wake up, smell the coffee def add_quote(s) l = s.lines l.map {|li| "> #{li}"}.join end def process_chunk(s, nested, dedent, fold, quote) process_includes(s) if nested s = remove_indentation(s) if dedent s = fold8792_1(s, *fold) if fold s = add_quote(s) if quote s end def process_includes(input) input.gsub!(/^\{::include((?:-[a-z0-9]+)*)\s+(.*?)\}/) { include_flags = $1 fn = [$2] chunks = false nested = false dedent = false fold = false quote = false include_flags.split("-") do |flag| case flag when "" when "nested" nested = true when "quote" quote = true when "dedent" dedent = true when /\Afold(\d*)(left(\d*))?(dry)?\z/ fold = [$1.to_i, # col 0 for '' ($3.to_i if $2), # left 0 for '', nil if no "left" $4] # dry when "all", "last" fn = fn.flat_map{|n| Dir[n]} fn = [fn.last] if flag == "last" chunks = fn.map{ |f| ret = process_chunk(File.read(f), nested, dedent, fold, quote) nested = false; dedent = false; fold = false; quote = false ret } else warn "** unknown include flag #{flag}" end end chunks = fn.map{|f| File.read(f)} unless chunks # no all/last chunks = chunks.map {|ch| process_chunk(ch, nested, dedent, fold, quote)} chunks.join.chomp } end def boilerplate(key) ret = '' case key.downcase when /\Abcp14(info)?(\+)?(-tagged)?(-bcp(14)?)?\z/i # $1 $2 $3 $4 $5 if $1 ret << <<RFC8174ise Although this document is not an IETF Standards Track publication, it adopts the conventions for normative language to provide clarity of instructions to the implementer. RFC8174ise end ret << <<RFC8174 The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 {{!RFC2119}} {{!RFC8174}} when, and only when, they appear in all capitals, as shown here. RFC8174 if $2 ret << <<PLUS These words may also appear in this document in lower case as plain English words, absent their normative meanings. PLUS end if $3 ($options.v3_used ||= []) << "** need --v3 to tag bcp14" ret << <<TAGGED *[MUST]: <bcp14> *[MUST NOT]: <bcp14> *[REQUIRED]: <bcp14> *[SHALL]: <bcp14> *[SHALL NOT]: <bcp14> *[SHOULD]: <bcp14> *[SHOULD NOT]: <bcp14> *[RECOMMENDED]: <bcp14> *[NOT RECOMMENDED]: <bcp14> *[MAY]: <bcp14> *[OPTIONAL]: <bcp14> TAGGED end if $4 # experimental; idnits complains: if $5 # ** The document contains RFC2119-like boilerplate, but doesn't seem to # mention RFC 2119. The boilerplate contains a reference [BCP14], but that # reference does not seem to mention RFC 2119 either. ret.sub!("BCP 14 {{!RFC2119}} {{!RFC8174}}", "{{!BCP14}} ({{RFC2119}}) ({{RFC8174}})") else # ** The document seems to lack a both a reference to RFC 2119 and the # recommended RFC 2119 boilerplate, even if it appears to use RFC 2119 # keywords -- however, there's a paragraph with a matching beginning. # Boilerplate error? ret.sub!("{{!RFC2119}} {{!RFC8174}}", "{{!BCP14}}") end end ret when /\Arfc\s*7942(info)?\z/i if $1 ret << <<INFO (Boilerplate as per {{Section 2.1 of RFC7942}}:) INFO end ret << <<RFC7942 This section records the status of known implementations of the protocol defined by this specification at the time of posting of this Internet-Draft, and is based on a proposal described in {{?RFC7942}}. The description of implementations in this section is intended to assist the IETF in its decision processes in progressing drafts to RFCs. Please note that the listing of any individual implementation here does not imply endorsement by the IETF. Furthermore, no effort has been spent to verify the information presented here that was supplied by IETF contributors. This is not intended as, and must not be construed to be, a catalog of available implementations or their features. Readers are advised to note that other implementations may exist. According to {{?RFC7942}}, "this will allow reviewers and working groups to assign due consideration to documents that have the benefit of running code, which may serve as evidence of valuable experimentation and feedback that have made the implemented protocols more mature. It is up to the individual working groups to use this information as they see fit". RFC7942 else warn "** Unknown boilerplate key: #{key}" "{::boilerplate #{key}}" end end def do_the_tls_dance begin require 'openssl' File.open(OpenSSL::X509::DEFAULT_CERT_FILE) do end # This guards against having an unreadable cert file (yes, that appears to happen a lot). rescue if Dir[File.join(OpenSSL::X509::DEFAULT_CERT_DIR, "*.pem")].empty? # This guards against having no certs at all, not against missing the right one for IETF. # Oh well. warn "** Configuration problem with OpenSSL certificate store." warn "** You may want to examine #{OpenSSL::X509::DEFAULT_CERT_FILE}" warn "** and #{OpenSSL::X509::DEFAULT_CERT_DIR}." warn "** Activating suboptimal workaround." warn "** Occasionally run `certified-update` to maintain that workaround." require 'certified' end end end RE_NL = /(?:\r\n|\n|\r)/ RE_SECTION = /---(?: +(\w+)(-?))? *#{RE_NL}(.*?#{RE_NL})(?=---(?:\s+\w+-?)?\s*#{RE_NL}|\Z)/m NMDTAGS = ["{:/nomarkdown}\n\n", "\n\n{::nomarkdown}\n"] NORMINFORM = { "!" => :normative, "?" => :informative } def yaml_load(input, *args) begin if YAML.respond_to?(:safe_load) begin YAML.safe_load(input, *args) rescue ArgumentError YAML.safe_load(input, permitted_classes: args[0], permitted_symbols: args[1], aliases: args[2]) end else YAML.load(input) end rescue Psych::SyntaxError => e warn "*** YAML syntax error: #{e}" exit 65 # EX_DATAERR end end def process_kramdown_options(coding_override = nil, smart_quotes = nil, typographic_symbols = nil, header_kramdown_options = nil) ascii_target = coding_override && coding_override =~ /ascii/ suppress_typography = ascii_target || $options.v3 entity_output = ascii_target ? :numeric : :as_char; options = {input: 'RFC2629Kramdown', entity_output: entity_output, link_defs: {}} if smart_quotes.nil? && suppress_typography smart_quotes = false end if smart_quotes == false smart_quotes = ["'".ord, "'".ord, '"'.ord, '"'.ord] end case smart_quotes when Array options[:smart_quotes] = smart_quotes when nil, true # nothin else warn "*** Can't deal with smart_quotes value #{smart_quotes.inspect}" end if typographic_symbols.nil? && suppress_typography typographic_symbols = false end if typographic_symbols == false typographic_symbols = Hash[::Kramdown::Parser::Kramdown::TYPOGRAPHIC_SYMS.map { |k, v| if Symbol === v [v.intern, k] end }.compact] end # warn [:TYPOGRAPHIC_SYMBOLS, typographic_symbols].to_yaml case typographic_symbols when Hash options[:typographic_symbols] = typographic_symbols when nil, true # nothin else warn "*** Can't deal with typographic_symbols value #{typographic_symbols.inspect}" end if header_kramdown_options options.merge! header_kramdown_options end $global_markdown_options = options # For nested calls in bibref annotation processing and xref text options end XREF_SECTIONS_RE = ::Kramdown::Parser::RFC2629Kramdown::SECTIONS_RE XSR_PREFIX = "#{XREF_SECTIONS_RE} of " XSR_SUFFIX = ", (#{XREF_SECTIONS_RE})| \\((#{XREF_SECTIONS_RE})\\)" XREF_TXT = ::Kramdown::Parser::RFC2629Kramdown::XREF_TXT XREF_TXT_SUFFIX = " \\(#{XREF_TXT}\\)" def spacify_re(s) s.gsub(' ', '[\u00A0\s]+') end include ::Kramdown::Utils::Html # Make this a method so there is a more speaking traceback if this fails def read_erbfile erbfilename = ENV["KRAMDOWN_ERB_FILE"] || File.expand_path('../../../data/kramdown-rfc2629.erb', __FILE__) File.read(erbfilename, coding: "UTF-8") end def xml_from_sections(input) unless ENV["KRAMDOWN_NO_SOURCE"] require 'kramdown-rfc/gzip-clone' require 'base64' compressed_input = Gzip.compress_m0(input) $source = Base64.encode64(compressed_input) end sections = input.scan(RE_SECTION) # resulting in an array; each section is [section-label, nomarkdown-flag, section-text] line = 1 # skip "---" sections.each do |section| section << line line += 1 + section[2].lines.count end # warn "#{line-1} lines" # the first section is a YAML with front matter parameters (don't put a label here) # We put back the "---" plus gratuitous blank lines to hack the line number in errors yaml_in = input[/---\s*/] << sections.shift[2] begin require 'kramdown-rfc/yamlcheck' KramdownRFC::YAMLcheck.check_dup_keys(yaml_in) rescue => e warn "** Cannot check for duplicate keys in YAML header (#{e})" end ps = KramdownRFC::ParameterSet.new(yaml_load(yaml_in, [Date], [], true)) if v = ps[:v] warn "*** unsupported RFCXML version #{v}" if v != 3 if $options.v2 warn "*** command line --v2 wins over document's 'v: #{v}'" else $options.v3 = true $options.v = 3 ps.default!(:stand_alone, true) ps.default!(:ipr, "trust200902") ps.default!(:pi, {"toc" => true, "sortrefs" => true, "symrefs" => true}) end end if r = ENV["KRAMDOWN_RFC_DOCREV"] warn "** building document revision -#{r}" unless n = ps.has(:docname) and n.sub!(/-latest\z/, "-#{r}") warn "** -d#{r}: docname #{n.inspect} doesn't have a '-latest' suffix" end end if o = ps[:'autolink-iref-cleanup'] $options.autolink_iref_cleanup = o end if o = ps[:'svg-id-cleanup'] $options.svg_id_cleanup = o end coding_override = ps.has(:coding) smart_quotes = ps[:smart_quotes] || ps[:"smart-quotes"] typographic_symbols = ps[:typographic_symbols] header_kramdown_options = ps[:kramdown_options] kramdown_options = process_kramdown_options(coding_override, smart_quotes, typographic_symbols, header_kramdown_options) # all the other sections are put in a Hash, possibly concatenated from parts there sechash = Hash.new{ |h,k| h[k] = ""} snames = [] # a stack of section names sections.each do |sname, nmdflag, text, line| # warn [:SNAME, sname, nmdflag, text[0..10]].inspect nmdin, nmdout = { "-" => ["", ""], # stay in nomarkdown "" => NMDTAGS, # pop out temporarily }[nmdflag || ""] if sname snames << sname # "--- label" -> push label (now current) else snames.pop # just "---" -> pop label (previous now current) end sechash[snames.last] << "#{nmdin}<?line #{line}?>\n#{text}#{nmdout}" end ref_replacements = { } anchor_to_bibref = { } displayref = {} [:ref, :normative, :informative].each do |sn| if refs = ps.has(sn) warn "*** bad section #{sn}: #{refs.inspect}" unless refs.respond_to? :each refs.each do |k, v| if v.respond_to? :to_str if bibtagsys(v) # enable "foo: RFC4711" as a custom anchor definition anchor_to_bibref[k] = v.to_str end ref_replacements[v.to_str] = k end if Hash === v if aliasname = v.delete("-") ref_replacements[aliasname] = k end if bibref = v.delete("=") anchor_to_bibref[k] = bibref end if dr = v.delete("display") displayref[k.gsub("/", "_")] = dr end end end end end open_refs = ps[:ref] || { } # consumed norm_ref = { } # convenience replacement of {{-coap}} with {{I-D.ietf-core-coap}} # collect normative/informative tagging {{!RFC2119}} {{?RFC4711}} sechash.each do |k, v| next if k == "fluff" v.gsub!(/{{(#{ spacify_re(XSR_PREFIX) })?([\w.\/_\-]+@)?(?:([?!])(-)?|(-))([\w._\-]+)(?:=([\w.\/_\-]+))?(#{ # 2 3 4 5 6 7 XREF_TXT_SUFFIX })?(#{ spacify_re(XSR_SUFFIX) })?}}/) do |match| xsr_prefix = $1 subref = $2 norminform = $3 replacing = $4 || $5 word = $6 bibref = $7 xrt_suffix = $8 xsr_suffix = $9 if replacing if new = ref_replacements[word] word = new else warn "*** no alias replacement for {{-#{word}}}" word = "-#{word}" end end # now, word is the anchor if bibref if old = anchor_to_bibref[word] if bibref != old warn "*** conflicting definitions for xref #{word}: #{old} != #{bibref}" end else anchor_to_bibref[word] = bibref end end # things can be normative in one place and informative in another -> normative # collect norm/inform above and assign it by priority here if norminform norm_ref[word] ||= norminform == '!' # one normative ref is enough end "{{#{xsr_prefix}#{subref}#{word}#{xrt_suffix}#{xsr_suffix}}}" end end [:normative, :informative].each do |k| ps.rest[k.to_s] ||= { } end norm_ref.each do |k, v| # could check bibtagsys here: needed if open_refs is nil or string kind = v ? :normative : :informative target = ps.has(kind) warn "** (#{kind} reference #{k} is both inline and in YAML header)" if target.has_key?(k) target[k] = open_refs[k] # add reference to normative/informative end # note that unused items from ref are considered OK, therefore no check for that here # also should allow norm/inform check of other references # {{?coap}} vs. {{!coap}} vs. {{-coap}} (undecided) # or {{?-coap}} vs. {{!-coap}} vs. {{-coap}} (undecided) # could require all references to be decided by a global flag overlap = [:normative, :informative].map { |s| (ps.has(s) || { }).keys }.reduce(:&) unless overlap.empty? warn "*** #{overlap.join(', ')}: both normative and informative" end stand_alone = ps[:stand_alone] [:normative, :informative].each do |sn| if refs = ps[sn] refs.each do |k, v| href = ::Kramdown::Parser::RFC2629Kramdown.idref_cleanup(k) kramdown_options[:link_defs][k] = ["##{href}", nil] # allow [RFC2119] in addition to {{RFC2119}} bibref = anchor_to_bibref[k] || k bts, url = bibtagsys(bibref, k, stand_alone) ann = v.delete("annotation") || v.delete("ann") if Hash === v if bts && (!v || v == {} || v.respond_to?(:to_str)) if stand_alone a = %{{: anchor="#{k}"}} a[-1...-1] = %{ ann="#{escape_html(ann, :attribute)}"} if ann sechash[sn.to_s] << %{\n#{NMDTAGS[0]}\n![:include:](#{bts})#{a}\n#{NMDTAGS[1]}\n} else warn "*** please use standalone mode for adding annotations to references" if ann bts.gsub!('/', '_') (ps.rest["bibxml"] ||= []) << [bts, url] sechash[sn.to_s] << %{&#{bts};\n} # ??? end else if v.nil? && (bri = bibref.to_i) != 0 v = bri end # hack in {{?Err6543=8610}} if v && Integer === v case href when /\AErr(.*)/ epno = $1 rfcno = v.to_s v = { "target" => "https://www.rfc-editor.org/errata/eid#{epno}", "title" => "RFC Errata Report #{epno}", "quote-title" => false, "seriesinfo" => { "RFC" => rfcno }, "date" => false } else # superfluous -- would be caught by next "unless" warn "*** don't know how to expand numeric ref #{k}" next end end unless v && Hash === v warn "*** don't know how to expand ref #{k} #{v.inspect}" next end if bts && !v.delete("override") warn "*** warning: explicit settings completely override canned bibxml in reference #{k}" end v["ann"] = ann if ann sechash[sn.to_s] << KramdownRFC::ref_to_xml(href, v) end end end end erbfile = read_erbfile erb = ERB.trim_new(erbfile, '-') # remove redundant nomarkdown pop outs/pop ins as they confuse kramdown input = erb.result(binding).gsub(%r"{::nomarkdown}\s*{:/nomarkdown}"m, "") ps.warn_if_leftovers sechash.delete("fluff") # fluff is a "commented out" section if !sechash.empty? # any sections unused by the ERb file? warn "*** sections left #{sechash.keys.inspect}!" end [input, kramdown_options, coding_override] end XML_RESOURCE_ORG_PREFIX = Kramdown::Converter::Rfc2629::XML_RESOURCE_ORG_PREFIX # return XML entity name, url, rewrite_anchor flag def bibtagsys(bib, anchor=nil, stand_alone=true) if bib =~ /\Arfc(\d+)/i rfc4d = "%04d" % $1.to_i [bib.upcase, "#{XML_RESOURCE_ORG_PREFIX}/bibxml/reference.RFC.#{rfc4d}.xml"] elsif $options.v3 && bib =~ /\A(bcp|std)(\d+)/i n4d = "%04d" % $2.to_i [bib.upcase, "#{XML_RESOURCE_ORG_PREFIX}/bibxml-rfcsubseries-new/reference.#{$1.upcase}.#{n4d}.xml"] elsif bib =~ /\A([-A-Z0-9]+)\./ && (xro = Kramdown::Converter::Rfc2629::XML_RESOURCE_ORG_MAP[$1]) dir, _ttl, rewrite_anchor = xro bib1 = ::Kramdown::Parser::RFC2629Kramdown.idref_cleanup(bib) if anchor && bib1 != anchor if rewrite_anchor a = %{?anchor=#{anchor}} else if !stand_alone warn "*** selecting a custom anchor '#{anchor}' for '#{bib1}' requires stand_alone mode" warn " the output will need manual editing to correct this" end end end [bib1, "#{XML_RESOURCE_ORG_PREFIX}/#{dir}/reference.#{bib}.xml#{a}"] end end def read_encodings encfilename = File.expand_path '../../../data/encoding-fallbacks.txt', __FILE__ encfile = File.read(encfilename, coding: "UTF-8") Hash[encfile.lines.map{|l| l.chomp!; x, s = l.split(" ", 2) [x.hex.chr(Encoding::UTF_8), s || " "]}] end FALLBACK = read_encodings def expand_tabs(s, tab_stops = 8) s.gsub(/([^\t\n]*)\t/) do $1 + " " * (tab_stops - ($1.size % tab_stops)) end end require 'optparse' require 'ostruct' $options ||= OpenStruct.new op = OptionParser.new do |opts| opts.banner = <<BANNER Usage: kramdown-rfc2629 [options] [file.md] > file.xml Version: #{KDRFC_VERSION} BANNER opts.on("-V", "--version", "Show version and exit") do |v| puts "kramdown-rfc #{KDRFC_VERSION}" exit end opts.on("-H", "--help", "Show option summary and exit") do |v| puts opts exit end opts.on("-v", "--[no-]verbose", "Run verbosely") do |v| $options.verbose = v end opts.on("-3", "--[no-]v3", "Use RFCXML v3 processing rules") do |v| $options.v3 = v end opts.on("-2", "--[no-]v2", "Use RFCXML v2 processing rules") do |v| $options.v2 = v end end op.parse! if $options.v2 && $options.v3 warn "*** can't have v2 and eat v3 cake" $options.v2 = false end if $options.v3.nil? && !$options.v2 if Time.now.to_i >= 1645567342 # Time.parse("2022-02-22T22:02:22Z").to_i $options.v3 = true # new default from the above date end end warn "*** v2 #{$options.v2.inspect} v3 #{$options.v3.inspect}" if $options.verbose input = ARGF.read input.scrub! do |c| warn "*** replaced invalid UTF-8 byte sequence #{c.inspect} by U+FFFD REPLACEMENT CHARACTER" 0xFFFD.chr(Encoding::UTF_8) end if input[0] == "\uFEFF" warn "*** There is a leading byte order mark. Ignored." input[0..0] = '' end if input[-1] != "\n" # warn "*** added missing newline at end" input << "\n" # fix #26 end process_includes(input) unless ENV["KRAMDOWN_SAFE"] input.gsub!(/^\{::boilerplate\s+(.*?)\}/) { bp = boilerplate($1) delta = bp.lines.count bp + "<?line -#{delta+1}?>\n" } if input =~ /[\t]/ warn "*** Input contains HT (\"tab\") characters. Undefined behavior will ensue." input = expand_tabs(input) end if input =~ /\A---/ # this is a sectionized file do_the_tls_dance unless ENV["KRAMDOWN_DONT_VERIFY_HTTPS"] input, options, coding_override = xml_from_sections(input) else options = process_kramdown_options # all default end if input =~ /\A<\?xml/ # if this is a whole XML file, protect it input = "{::nomarkdown}\n#{input}\n{:/nomarkdown}\n" end if $options.v3_used && !$options.v3 warn $options.v3_used $options.v3_used = nil $options.v3 = true end if coding_override input = input.encode(Encoding.find(coding_override), fallback: FALLBACK) end # 1.4.17: because of UTF-8 bibxml files, kramdown always needs to see UTF-8 (!) if input.encoding != Encoding::UTF_8 input = input.encode(Encoding::UTF_8) end # warn "options: #{options.inspect}" doc = Kramdown::Document.new(input, options) $stderr.puts doc.warnings.to_yaml unless doc.warnings.empty? output = doc.to_rfc2629 if $options.v3_used && !$options.v3 warn $options.v3_used $options.v3 = true end # only reparse output document if cleanup actions required if $options.autolink_iref_cleanup || $options.svg_id_cleanup require 'rexml/document' d = REXML::Document.new(output) d.context[:attribute_quote] = :quote # Set double-quote as the attribute value delimiter if $options.autolink_iref_cleanup require 'kramdown-rfc/autolink-iref-cleanup' autolink_iref_cleanup(d) end if $options.svg_id_cleanup require 'kramdown-rfc/svg-id-cleanup' svg_id_cleanup(d) end output = d.to_s end if coding_override output = output.encode(Encoding.find(coding_override), fallback: FALLBACK) end puts output ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������kramdown-rfc2629-1.7.31/lib/kramdown-rfc/svg-id-cleanup.rb������������������������������������������0000644�0000041�0000041�00000002253�15142163665�023066� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������require 'rexml/document' SVG_NAMESPACES = {"svg"=>"http://www.w3.org/2000/svg", "xlink"=>"http://www.w3.org/1999/xlink"} def svg_id_cleanup(d) gensym = "gensym000" REXML::XPath.each(d.root, "//svg:svg", SVG_NAMESPACES) do |x| gensym = gensym.succ # warn "*** SVG" # warn "*** SVG: #{x.to_s.size}" found_as_id = Set[] found_as_href = Set[] REXML::XPath.each(x, ".//*[@id]", SVG_NAMESPACES) do |y| # warn "*** ID: #{y}" name = y.attributes["id"] if found_as_id === name warn "*** duplicate ID #{name}" end found_as_id.add(name) y.attributes["id"] = "#{name}-#{gensym}" end REXML::XPath.each(x, ".//*[@xlink:href]", SVG_NAMESPACES) do |y| # warn "*** HREF: #{y}" name = y.attributes["href"] name1 = name[1..-1] if !found_as_id === name1 warn "*** unknown HREF #{name}" end found_as_href.add(name1) y.attributes["xlink:href"] = "#{name}-#{gensym}" end found_as_id -= found_as_href warn "*** warning: unused ID: #{found_as_id.to_a.join(", ")}" unless found_as_id.empty? end rescue => detail warn "*** Can't clean SVG: #{detail}" end �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������kramdown-rfc2629-1.7.31/lib/kramdown-rfc/doi.rb�����������������������������������������������������0000644�0000041�0000041�00000006430�15142163665�021024� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������require 'open-uri' require 'json' require 'yaml' ACCEPT_CITE_JSON = {"Accept" => "application/citeproc+json"} def doi_fetch_and_convert(doi, fuzzy: false, verbose: false, site: "https://dx.doi.org") doipath = doi.sub(/^([0-9.]+)_/) {"#$1/"} # convert initial _ back to / # warn "** SUB #{doi} #{doipath}" if doi != doipath begin cite = JSON.parse(URI("#{site}/#{doipath}").open(ACCEPT_CITE_JSON).read) puts cite.to_yaml if verbose doi_citeproc_to_lit(cite, fuzzy) rescue OpenURI::HTTPError => e begin site = "https://dl.acm.org" percent_escaped = doipath.gsub("/", "%2F") path = "#{site}/action/exportCiteProcCitation?targetFile=custom-bibtex&format=bibTex&dois=#{percent_escaped}" op = URI(path).open # first get a cookie, ignore result # warn [:META, op.meta].inspect cook = op.meta['set-cookie'].split('; ', 2)[0] cite = JSON.parse(URI(path).open("Cookie" => cook).read) cite = cite["items"].first[doipath] puts cite.to_yaml if verbose doi_citeproc_to_lit(cite, fuzzy) rescue raise e end end end def doi_citeproc_to_lit(cite, fuzzy) lit = {} ser = lit["seriesinfo"] = {} refcontent = [] lit["title"] = cite["title"] if (st = cite["subtitle"]) && Array === st # defensive st.delete('') if st != [] lit["title"] << ": " << st.join("; ") end end if authors = cite["author"] lit["author"] = authors.map do |au| lau = {} if (f = au["family"]) if (g = au["given"]) lau["name"] = "#{g} #{f}" lau["ins"] = "#{g[0]}. #{f}" else lau["name"] = "#{f}" # lau["ins"] = "#{g[0]}. #{f}" end end if (f = au["affiliation"]) && Array === f names = f.map { |affn| if Hash === affn && (n = affn["name"]) && String === n n end }.compact if names.size > 0 lau["org"] = names.join("; ") end end lau end end if iss = cite["issued"] if dp = iss["date-parts"] if Integer === (dp = dp[0])[0] lit["date"] = ["%04d" % dp[0], *dp[1..-1].map {|p| "%02d" % p}].join("-") end end end if !lit.key?("date") && fuzzy && (iss = cite["created"]) if dp = iss["date-parts"] if Integer === (dp = dp[0])[0] lit["date"] = ["%04d" % dp[0], *dp[1..-1].map {|p| "%02d" % p}].join("-") end end end if (ct = cite["container-title"]) && ct != [] info = [] if v = cite["volume"] vi = "vol. #{v}" if (v = cite["journal-issue"]) && (issue = v["issue"]) vi << ", no. #{issue}" end info << vi end if p = cite["page"] info << "pp. #{p}" end rhs = info.join(", ") if info != [] ser[ct] = rhs else spl = ct.split(" ") ser[spl[0..-2].join(" ")] = spl[-1] end end if pub = cite["publisher"] refcontent << pub # info = [] # if t = cite["type"] # info << t # end # rhs = info.join(", ") # if info != [] # ser[pub] = rhs # else # spl = pub.split(" ") # ser[spl[0..-2].join(" ")] = spl[-1] # end end ["DOI", "ISBN"].each do |st| if a = cite[st] ser[st] = a end end if refcontent != [] lit["refcontent"] = refcontent.join(", ") end lit end ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������kramdown-rfc2629-1.7.31/lib/kramdown-rfc/erb.rb�����������������������������������������������������0000644�0000041�0000041�00000000423�15142163665�021015� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������require 'erb' class ERB case version.sub("erb.rb [", "") when /\A2.1/ # works back to 1.9.1 def self.trim_new(s, trim) ERB.new(s, nil, trim) end else def self.trim_new(s, trim) ERB.new(s, trim_mode: trim) end end end ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������kramdown-rfc2629-1.7.31/lib/kramdown-rfc/kdrfc-processor.rb�����������������������������������������0000644�0000041�0000041�00000016100�15142163665�023352� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������require 'uri' require 'net/http' require 'net/http/persistent' require 'open3' require 'ostruct' require 'json' module KramdownRFC class KDRFC attr_reader :options def initialize @options = OpenStruct.new end # ))) KDRFC_PREPEND = [ENV["KDRFC_PREPEND"]].compact KDRFC_XML2RFC_FLAGS = Array(ENV["KDRFC_XML2RFC_FLAGS"]&.split(",")) def v3_flag? [*(@options.v3 ? ["--v3"] : []), *(@options.v2 ? ["--v2"] : [])] end def process_mkd(input, output) warn "* converting locally from markdown #{input} to xml #{output}" if @options.verbose o, s = Open3.capture2(*KDRFC_PREPEND, "kramdown-rfc2629", *v3_flag?, input) if s.success? File.open(output, "w") do |fo| fo.print(o) end warn "* #{output} written" if @options.verbose else raise IOError.new("*** kramdown-rfc failed, status #{s.exitstatus}") end end def filename_ct(fn, ext) bn = File.basename(fn, ".*") if r = ENV["KRAMDOWN_RFC_DOCREV"] bn << "-#{r}" end {filename: "#{bn}.#{ext}", content_type: "text/plain"} end def run_idnits(*args) if @options.remote run_idnits_remotely(*args) else run_idnits_locally(*args) end end def run_idnits_locally(txt_fn) warn "* running idnits locally in txt #{txt_fn}" if @options.verbose unless system("idnits", txt_fn) warn "*** problem #$? running idnits" if @options.verbose warn "*** problem running idnits -- falling back to remote idnits processing" run_idnits_remotely(txt_fn) end end # curl -s https://author-tools.ietf.org/api/idnits -X POST -F file=@draft-ietf-core-comi.txt -F hidetext=true IDNITS_WEBSERVICE = ENV["KRAMDOWN_IDNITS_WEBSERVICE"] || 'https://author-tools.ietf.org/api/idnits' def run_idnits_remotely(txt_fn) url = URI(IDNITS_WEBSERVICE) req = Net::HTTP::Post.new(url) form = [["file", File.open(txt_fn), filename_ct(txt_fn, "txt")], ["hidetext", "true"]] diag = ["url/form: ", url, form].inspect req.set_form(form, 'multipart/form-data') warn "* requesting idnits at #{url}" if @options.verbose t0 = Time.now res = persistent_http.request(url, req) warn "* elapsed time: #{Time.now - t0}" if @options.verbose case res when Net::HTTPBadRequest result = checked_json(res.body) raise IOError.new("*** Remote Error: #{result["error"]}") when Net::HTTPOK case res.content_type when 'text/plain' if res.body == '' raise IOError.new("*** HTTP response is empty with status #{res.code}, not written") end puts res.body else warning = "*** HTTP response has unexpected content_type #{res.content_type} with status #{res.code}, #{diag}" warning << "\n" warning << res.body raise IOError.new(warning) end else raise IOError.new("*** HTTP response: #{res.code}, #{diag}") end end def process_xml(*args) if @options.remote process_xml_remotely(*args) else process_xml_locally(*args) end end def process_xml_locally(input, output, *flags) warn "* converting locally from xml #{input} to txt #{output}" if @options.verbose begin o, s = Open3.capture2(*KDRFC_PREPEND, "xml2rfc", *v3_flag?, *flags, *KDRFC_XML2RFC_FLAGS, input) puts o if s.success? warn "* #{output} written" if @options.verbose else raise IOError.new("*** xml2rfc failed, status #{s.exitstatus} (possibly try with -r)") end rescue Errno::ENOENT warn "*** falling back to remote xml2rfc processing (web service)" # if @options.verbose process_xml_remotely(input, output, *flags) end end # curl https://author-tools.ietf.org/api/render/text -X POST -F "file=@..." XML2RFC_WEBSERVICE = ENV["KRAMDOWN_XML2RFC_WEBSERVICE"] || 'https://author-tools.ietf.org/api/render/' MODE_AS_FORMAT = { "--text" => "text", "--html" => "html", "--v2v3" => "xml", "--pdf" => "pdf", } def checked_json(t) begin JSON.load(t) rescue => e raise IOError.new("*** JSON result: #{e.detailed_message}, #{diag}") end end def persistent_http $http ||= Net::HTTP::Persistent.new name: 'kramdown-rfc' end def process_xml_remotely(input, output, *flags) format = flags[0] || "--text" warn "* converting remotely from xml #{input} to #{format} #{output}" if @options.verbose maf = MODE_AS_FORMAT[format] unless maf raise ArgumentError.new("*** don't know how to convert remotely from xml #{input} to #{format} #{output}") end url = URI(XML2RFC_WEBSERVICE + maf) req = Net::HTTP::Post.new(url) form = [["file", File.open(input), filename_ct(input, "xml")]] diag = ["url/form: ", url, form].inspect req.set_form(form, 'multipart/form-data') warn "* requesting at #{url}" if @options.verbose t0 = Time.now res = persistent_http.request(url, req) warn "* elapsed time: #{Time.now - t0}" if @options.verbose case res when Net::HTTPBadRequest result = checked_json(res.body) raise IOError.new("*** Remote Error: #{result["error"]}") when Net::HTTPOK case res.content_type when 'application/json' if res.body == '' raise IOError.new("*** HTTP response is empty with status #{res.code}, not written") end # warn "* res.body #{res.body}" if @options.verbose result = checked_json(res.body) if logs = result["logs"] if errors = logs["errors"] errors.each do |err| warn("*** Error: #{err}") end end if warnings = logs["warnings"] warnings.each do |w| warn("** Warning: #{w}") end end end raise IOError.new("*** No useful result from remote") unless result["url"] res = persistent_http.request(URI(result["url"])) warn "* result content type #{res.content_type}" if @options.verbose if res.body == '' raise IOError.new("*** Second HTTP response is empty with status #{res.code}, not written") end File.open(output, "w") do |fo| fo.print(res.body) end warn "* #{output} written" if @options.verbose else warning = "*** HTTP response has unexpected content_type #{res.content_type} with status #{res.code}, #{diag}" warning << "\n" warning << res.body raise IOError.new(warning) end else raise IOError.new("*** HTTP response: #{res.code}, #{diag}") end end def process_the_xml(fn, base) process_xml(fn, "#{base}.prepped.xml", "--preptool") if @options.prep process_xml(fn, "#{base}.v2v3.xml", "--v2v3") if @options.v2v3 process_xml(fn, "#{base}.txt") if @options.txt || @options.idnits process_xml(fn, "#{base}.html", "--html") if @options.html process_xml(fn, "#{base}.pdf", "--pdf") if @options.pdf run_idnits("#{base}.txt") if @options.idnits end def process(fn) case fn when /(.*)\.xml\z/ if @options.xml_only warn "*** You already have XML" else # FIXME: copy/paste process_the_xml(fn, $1) end when /(.*)\.mk?d\z/ xml = "#$1.xml" process_mkd(fn, xml) process_the_xml(xml, $1) unless @options.xml_only when /(.*)\.txt\z/ run_idnits(fn) if @options.idnits else raise ArgumentError.new("Unknown file type: #{fn}") end end # ((( end end ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������kramdown-rfc2629-1.7.31/lib/kramdown-rfc/refxml.rb��������������������������������������������������0000644�0000041�0000041�00000015622�15142163665�021551� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������require 'kramdown-rfc/erb' module KramdownRFC extend Kramdown::Utils::Html def self.escattr(str) escape_html(str.to_s, :attribute) end AUTHOR_ATTRIBUTES = %w{ initials surname fullname asciiInitials asciiSurname asciiFullname role } def self.ref_to_xml(k, v) vps = KramdownRFC::ParameterSet.new(v) erb = ERB.trim_new <<-REFERB, '-' <reference anchor="<%= escattr(k) %>" <%= vps.attrstf("target", "quoteTitle=quote-title=quotetitle=qt") %>> <front> <%= vps.ele("title") -%> <% vps.arr("author", true, true) do |au| aups = authorps_from_hash(au) -%> <author <%=aups.attrs(*AUTHOR_ATTRIBUTES)%>> <%= aups.ele("organization=org", aups.attr("abbrev=orgabbrev"), "") %> </author> <% aups.warn_if_leftovers -%> <% end -%> <date <%= dateattrs(vps[:date]) %>/> </front> <% vps.arr("seriesinfo", false) do |k, v| -%> <seriesInfo name="<%=escattr(k)%>" value="<%=escattr(v)%>"/> <% end -%> <% vps.arr("format", false) do |k, v| -%> <format type="<%=escattr(k)%>" target="<%=escattr(v)%>"/> <% end -%> <%= vps.ele("annotation=ann", nil, nil, true) -%> <%= vps.ele("refcontent=rc", nil, nil, true) -%> </reference> REFERB ret = erb.result(binding) vps.warn_if_leftovers ret end def self.treat_multi_attribute_member(ps, an) value = ps.rest[an] if Hash === value value.each do |k, v| ps.rest[if k == ':' an else Kramdown::Element.attrmangle(k + an) || Kramdown::Element.attrmangle(k) || k end] = v end end end def self.initializify(s) # XXX Jean-Pierre w = '\p{Lu}\p{Lo}' if s =~ /\A[-.#{w}]+[.]/u $& elsif s =~ /\A([#{w}])[^-]*/u ret = "#$1." while (s = $') && s =~ /\A(-[\p{L}])[^-]*/u ret << "#$1." end ret else warn "*** Can't initializify #{s}" s end end def self.looks_like_initial(s) s =~ /\A[\p{Lu}\p{Lo}]([-.][\p{Lu}\p{Lo}]?)*\z/u end def self.initials_from_parts_and_surname(aups, parts, s) ssz = s.size nonsurname = parts[0...-ssz] if (ns = parts[-ssz..-1]) != s warn "*** inconsistent surnames #{ns} and #{s}" end nonsurname.map{|x| initializify(x)}.join(" ") end def self.handle_ins(aups, ins_k, initials_k, surname_k) if ins = aups[ins_k] parts = ins.split('.').map(&:strip) # split on dots first if parts == [] warn "*** an empty '#{ins_k}:' value is not useful, try leaving it out" return end # Coalesce H.-P. i = 1; while i < parts.size if parts[i][0] == "-" parts[i-1..i] = [parts[i-1] + "." + parts[i]] else i += 1 end end # Multiple surnames in ins? parts[-1..-1] = parts[-1].split s = if surname = aups.rest[surname_k] surname.split else parts.reverse.take_while{|x| !looks_like_initial(x)}.reverse end aups.rest[initials_k] = initials_from_parts_and_surname(aups, parts, s) aups.rest[surname_k] = s.join(" ") end end def self.handle_name(aups, fn_k, initials_k, surname_k) if name = aups.rest[fn_k] names = name.split(/ *\| */, 2) # boundary for given/last name if names == [] warn "*** an empty '#{fn_k}:' value is not useful, try leaving it out" return end if names[1] aups.rest[fn_k] = name = names.join(" ") # remove boundary if surname = aups.rest[surname_k] if surname != names[1] warn "*** inconsistent embedded surname #{names[1]} and surname #{surname}" end end aups.rest[surname_k] = names[1] end parts = name.split if parts == [] warn "*** a blank '#{fn_k}:' value is not useful, try leaving it out" return end surname = aups.rest[surname_k] || parts[-1] s = surname.split aups.rest[initials_k] ||= initials_from_parts_and_surname(aups, parts, s) aups.rest[surname_k] = s.join(" ") end end def self.authorps_from_hash(au) aups = KramdownRFC::ParameterSet.new(au) if n = aups[:name] warn "** both name #{n} and fullname #{fn} are set on one author" if fn = aups.rest["fullname"] aups.rest["fullname"] = n usename = true end ["fullname", "ins", "initials", "surname"].each do |an| treat_multi_attribute_member(aups, an) end handle_ins(aups, :ins, "initials", "surname") handle_ins(aups, :asciiIns, "asciiInitials", "asciiSurname") # hack ("heuristic for") initials and surname from name # -- only works for people with exactly one last name and uncomplicated first names # -- add surname for people with more than one last name if usename handle_name(aups, "fullname", "initials", "surname") handle_name(aups, "asciiFullname", "asciiInitials", "asciiSurname") end aups end # The below anticipates the "postalLine" changes. # If a postalLine is used (abbreviated "postal" in YAML), # non-postalLine elements are appended as further postalLines. # This prepares for how "country" is expected to be handled # specially with the next schema update. # So an address is now best keyboarded as: # postal: # - Foo Street # - 28359 Bar # country: Germany PERSON_ERB = <<~ERB <<%= element_name%> <%=aups.attrs(*AUTHOR_ATTRIBUTES)%>> <%= aups.ele("organization=org", aups.attrs("abbrev=orgabbrev", *[$options.v3 && "ascii=orgascii"]), "") %> <address> <% postal_elements = %w{extaddr pobox street cityarea city region code sortingcode country postal}.select{|gi| aups.has(gi)} if postal_elements != [] -%> <postal> <% if pl = postal_elements.delete("postal") -%> <%= aups.ele("postalLine=postal") %> <% postal_elements.each do |gi| -%> <%= aups.ele("postalLine=" << gi) %> <% end -%> <% else -%> <% postal_elements.each do |gi| -%> <%= aups.ele(gi) %> <% end -%> <% end -%> </postal> <% end -%> <% %w{phone facsimile email uri}.select{|gi| aups.has(gi)}.each do |gi| -%> <%= aups.ele(gi) %> <% end -%> </address> </<%= element_name%>> ERB def self.person_element_from_aups(element_name, aups) erb = ERB.trim_new(PERSON_ERB, '-') erb.result(binding) end def self.dateattrs(date) begin case date when /\A\d\d\d\d\z/ %{year="#{date}"} when Integer %{year="#{"%04d" % date}"} when String Date.parse("#{date}-01").strftime(%{year="%Y" month="%B"}) when Date date.strftime(%{year="%Y" month="%B" day="%d"}) when Array # this allows to explicitly give a string %{year="#{date.join(" ")}"} when nil %{year="n.d."} end rescue ArgumentError warn "*** Invalid date: #{date} -- use 2012, 2012-07, or 2012-07-28" end end end ��������������������������������������������������������������������������������������������������������������kramdown-rfc2629-1.7.31/lib/kramdown-rfc/rexml-formatters-conservative.rb���������������������������0000644�0000041�0000041�00000001742�15142163665�026273� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������require 'rexml/document' module REXML module Formatters # The Conservative formatter writes an XML document that parses to an # identical document as the source document. This means that no extra # whitespace nodes are inserted, and whitespace within text nodes is # preserved. Attributes are not sorted. class Conservative < Default def initialize @indentation = 0 @level = 0 @ie_hack = false end protected def write_element( node, output ) output << "<#{node.expanded_name}" node.attributes.each_attribute do |attr| output << " " attr.write( output ) end unless node.attributes.empty? if node.children.empty? output << "/" else output << ">" node.children.each { |child| write( child, output ) } output << "</#{node.expanded_name}" end output << ">" end end end end ������������������������������kramdown-rfc2629-1.7.31/lib/kramdown-rfc2629.rb�����������������������������������������������������0000644�0000041�0000041�00000173647�15142163665�020613� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at> # Copyright (C) 2010-2014 Carsten Bormann <cabo@tzi.org> # # This file was derived from a part of the kramdown gem which is licensed under the MIT license. # This derived work is also licensed under the MIT license, see LICENSE. #++ # require 'shellwords' raise "sorry, 1.8 was last decade" unless RUBY_VERSION >= '1.9' gem 'kramdown', '~> 2.4.0' require 'kramdown' my_span_elements = %w{list xref eref iref cref spanx vspace} Kramdown::Parser::Html::Constants::HTML_SPAN_ELEMENTS.concat my_span_elements require 'rexml/parsers/baseparser' require 'open3' # for math require 'json' # for math require 'rexml/document' # for SVG and bibxml acrobatics require 'kramdown-rfc/doi' # for fetching information for a DOI require 'kramdown-rfc/rfc8792' class Object def deep_clone Marshal.load(Marshal.dump(self)) end end module Kramdown RFCXML_SPAN_ELEMENTS = Set.new(Kramdown::Parser::Html::Constants::HTML_SPAN_ELEMENTS) Kramdown::Options.define(:ol_start_at_first_marker, Kramdown::Options::Boolean, false, <<~EOF) If this option is `true`, an ordered list (<ol) will use the number in its first marker (1 for 1. etc.) as the default value of the start= attribute. Default: false (for backward compatibility) Used by: RFCXML converter EOF Kramdown::Options.define(:nested_ol_types, Object, %w[1], <<~EOF) do |val| Values for type= attribute for nested ordered lists (ol). The value needs to be an array of <ol type= values, expressed as one of: 1. A YAML array 2. A string that will be split on commas (with optional blank space following) 3. A string that will be split on blank space Default: ["1"] Used by: RFCXML converter EOF val = case val when String if val[0] == "[" && val[-1] == "]" begin val = YAML.safe_load(val) rescue Psych::SyntaxError warn "** YAML syntax error in nested_ol_types=#{val.inspect}" val = %w[1] end else val = val.split(/, */) val = val[0].split(/ +/) if val.size == 1 end Kramdown::Options.simple_array_validator(val, :nested_ol_types) when Array val.map!{ |x| x.to_s } val = Kramdown::Options.simple_array_validator(val, :nested_ol_types) else raise Kramdown::Error, "Invalid value for option '#{:nested_ol_types}': '#{val.inspect}'" end if val == [] val = %w[1] warn "** Option #{:nested_ol_types} cannot be empty, defaulting to #{val.inspect}" end val end module Parser class RFC2629Kramdown < Kramdown def replace_abbreviations(el, regexps = nil) unless regexps # DUPLICATED AND MODIFIED CODE FROM UPSTREAM, CHECK ON UPSTREAM UPGRADE sorted_abbrevs = @root.options[:abbrev_defs].keys.sort {|a, b| b.length <=> a.length } regexps = [Regexp.union(*sorted_abbrevs.map {|k| /#{Regexp.escape(k).gsub(/\\\s/, "[\\s\\p{Z}]+").force_encoding(Encoding::UTF_8)}/})] regexps << /(?=(?:\W|^)#{regexps.first}(?!\w))/ # regexp should only match on word boundaries # warn regexps.inspect end super(el, regexps) end def initialize(*doc) super @span_parsers.unshift(:xref) @span_parsers.unshift(:iref) @span_parsers.unshift(:span_pi) @block_parsers.unshift(:block_pi) end XREF_BASE = /#{REXML::XMLTokens::NAME_CHAR}+/ # a token for a reference XREF_TXT = /(?:[^\(]|\([^\)]*\))+/ # parenthesized text XREF_RE = /#{XREF_BASE}(?: \(#{XREF_TXT}\))?/ XREF_RE_M = /\A(#{XREF_BASE})(?: \((#{XREF_TXT})\))?/ # matching version of XREF_RE XREF_SINGLE = /(?:Section|Appendix) #{XREF_RE}/ XREF_MULTI = /(?:Sections|Appendices) (?:#{XREF_RE}, )*#{XREF_RE},? and #{XREF_RE}/ XREF_ANY = /(?:#{XREF_SINGLE}|#{XREF_MULTI})/ SECTIONS_RE = /(?:#{XREF_ANY} and )?#{XREF_ANY}/ def self.idref_cleanup(href) # can't start an IDREF with a number or reserved start if href =~ / / if $options.v3 warn "** space(s) in cross-reference '#{href}' -- are you trying to use section references?" else warn "** space(s) in cross-reference '#{href}' -- note that section references are supported in v3 mode only." end end href.gsub(/\A(?:[0-9]|section-|u-|figure-|table-|iref-)/) { "_#{$&}" } end def rfc_mention(target1) # only works for RFCnnnn target1 =~ /\A([A-Z]*)(.*)\z/ "#$1 #$2 " end def handle_bares(s, attr, format, href, last_join = nil) if s.match(/\A(#{XREF_ANY}) and (#{XREF_ANY})\z/) handle_bares($1, {}, nil, href, " and ") handle_bares($2, {}, nil, href, " of ") return end href = href.split(' ')[0] # Remove any trailing (...) target1, target2 = href.split("@", 2) multi = last_join != nil (sn, s) = s.split(' ', 2) loop do m = s.match(/\A#{XREF_RE_M}(, (?:and )?| and )?/) break if not m if not multi and not m[2] and not m[3] and not target2 # Modify |attr| if there is a single reference. This can only be # used if there is only one section reference and the section part # has no title. attr['section'] = m[1] attr['sectionFormat'] = format attr['text'] = m[2] return end if sn @tree.children << Element.new(:text, "#{sn} ", {}) sn = nil end multi = true s[m[0]] = '' attr1 = { 'target' => target1, 'section' => m[1], 'sectionFormat' => 'bare', 'text' => m[2] } @tree.children << Element.new(:xref, nil, attr1) andof = m[3] || last_join || " of " if andof == " of " && target2 andof += rfc_mention(target1) end @tree.children << Element.new(:text, andof, {}) end end XREF_START = /\{\{(?:(?:\{(.*?\n??.*?)\}(?:\{(.*?\n??.*?)\})?)|(\X*?))((?:\}\})|\})/u # Introduce new {{target}} syntax for empty xrefs, which would # otherwise be an ugly ![!](target) or ![ ](target) # (I'd rather use [[target]], but that somehow clashes with links.) def parse_xref @src.pos += @src.matched_size unless @src[4] == "}}" warn "*** #{@src[0]}: unmatched braces #{@src[4].inspect}" end if contact_name = @src[1] attr = {'fullname' => contact_name.gsub("\n", " ")} if ascii_name = @src[2] attr["asciiFullname"] = ascii_name.gsub("\n", " ") end el = Element.new(:contact, nil, attr) else href = @src[3] attr = {} handled_subref = false if $options.v3 # match Section ... of ...; set section, sectionFormat case href.gsub(/[\u00A0\s]+/, ' ') # may need nbsp and/or newlines when /\A(#{SECTIONS_RE}) of (.*)\z/ href = $2 handle_bares($1, attr, "of", href) handled_subref = true when /\A(.*), (#{SECTIONS_RE})\z/ href = $1 handle_bares($2, attr, "comma", href) handled_subref = true when /\A(.*) \((#{SECTIONS_RE})\)\z/ href = $1 handle_bares($2, attr, "parens", href) handled_subref = true when /#{XREF_RE_M}<(.+)\z/ href = $3 if $2 attr['section'] = $2 attr['relative'] = "#" << $1 else attr['section'] = $1 end attr['sectionFormat'] = 'bare' when /\A<<(.+)\z/ href = $1 attr['format'] = 'title' when /\A<(.+)\z/ href = $1 attr['format'] = 'counter' end end if href.match(/#{XREF_RE_M}\z/) href = $1 attr['text'] = $2 end target1, target2 = href.split("@", 2) # should do this only for sectionref... if target2 href = target2 unless handled_subref @tree.children << Element.new(:text, rfc_mention(target1), {}) end end href = self.class.idref_cleanup(href) attr['target'] = href el = Element.new(:xref, nil, attr) end @tree.children << el end define_parser(:xref, XREF_START, '\{\{') IREF_START = /\(\(\((.*?)\)\)\)/u # Introduce new (((target))) syntax for irefs def parse_iref @src.pos += @src.matched_size href = @src[1] el = Element.new(:iref, nil, {'target' => href}) # XXX @tree.children << el end define_parser(:iref, IREF_START, '\(\(\(') # HTML_INSTRUCTION_RE = /<\?(.*?)\?>/m # still defined! # warn [:OPT_SPACE, OPT_SPACE, HTML_INSTRUCTION_RE].inspect PI_BLOCK_START = /^#{OPT_SPACE}<\?/u def parse_block_pi # warn [:BLOCK].inspect line = @src.current_line_number if (result = @src.scan(HTML_INSTRUCTION_RE)) @tree.children << Element.new(:xml_pi, result, nil, category: :block, location: line) @src.scan(TRAILING_WHITESPACE) true else false end end define_parser(:block_pi, PI_BLOCK_START) PI_SPAN_START = /<\?/u def parse_span_pi # warn [:SPAN].inspect line = @src.current_line_number if (result = @src.scan(HTML_INSTRUCTION_RE)) @tree.children << Element.new(:xml_pi, result, nil, category: :span, location: line) else add_text(@src.getch) end end define_parser(:span_pi, PI_SPAN_START, '<\?') # warn [:HERE, @@parsers.keys].inspect end end class Element # Not fixing studly element names postalLine and seriesInfo yet # occasionally regenerate the studly attribute name list via # script in data/studly.rb STUDLY_ATTR = %w( asciiAbbrev asciiFullname asciiInitials asciiName asciiSurname asciiValue blankLines derivedAnchor derivedContent derivedCounter derivedLink displayFormat docName expiresDate hangIndent hangText indexInclude iprExtract keepWithNext keepWithPrevious originalSrc prepTime quoteTitle quotedFrom removeInRFC sectionFormat seriesNo showOnFrontPage slugifiedName sortRefs submissionType symRefs tocDepth tocInclude ) STUDLY_ATTR_MAP = Hash[STUDLY_ATTR.map {|s| [s.downcase, s]}] TRUTHY = Hash.new {|h, k| k} TRUTHY["false"] = false TRUTHY["no"] = false # explicit or automatic studlification # note that explicit (including trailing "_") opts out of automatic def self.attrmangle(k) if (d = k.gsub(/_(.|$)/) { $1.upcase }) != k or d = STUDLY_ATTR_MAP[k] d end end def rfc2629_fix(opts) if a = attr if !opts[:noanchor] && (anchor = a.delete('id')) a['anchor'] = ::Kramdown::Parser::RFC2629Kramdown.idref_cleanup(anchor) end if anchor = a.delete('href') a['target'] = ::Kramdown::Parser::RFC2629Kramdown.idref_cleanup(anchor) end if lang = a.delete('lang-') a['xml:lang'] = lang end if av = a.delete('noabbrev') # pseudo attribute -> opts opts = opts.merge(noabbrev: TRUTHY[av]) # updated copy end attr.keys.each do |k| if d = self.class.attrmangle(k) a[d] = a.delete(k) end end end opts end end module Converter # Converts a Kramdown::Document to HTML. class Rfc2629 < Base # we use these to do XML stuff, too include ::Kramdown::Utils::Html def el_html_attributes(el) html_attributes(el.attr) end def el_html_attributes_with(el, defattr) html_attributes(defattr.merge(el.attr)) end # :stopdoc: KRAMDOWN_PERSISTENT = ENV["KRAMDOWN_PERSISTENT"] KRAMDOWN_PERSISTENT_VERBOSE = /v/ === KRAMDOWN_PERSISTENT if KRAMDOWN_PERSISTENT begin require 'net/http/persistent' $http = Net::HTTP::Persistent.new name: 'kramdown-rfc', proxy: :ENV rescue Exception => e warn "** Not using persistent HTTP -- #{e}" warn "** To silence this message and get full speed, try:" warn "** gem install net-http-persistent" warn "** If this doesn't work, you can ignore this warning." end end # Defines the amount of indentation used when nesting XML tags. INDENTATION = 2 # Initialize the XML converter with the given Kramdown document +doc+. def initialize(*doc) super @sec_level = 1 @location_delta = 100000 # until reset @location_correction = 0 # pre-scanning corrections @in_dt = 0 @footnote_names_in_use = {} end def correct_location(location) location + @location_delta + @location_correction end def convert(el) opts = el.options[:options] # warn "** tree opts #{opts.inspect}" if nested_ol_types = @options[:nested_ol_types] opts[:nested_ol_types] ||= nested_ol_types # warn "** tree opts out #{opts.inspect}" end indent = -INDENTATION if el.children[-1].type == :raw raw = convert1(el.children.pop, indent, opts) end "#{convert1(el, indent, opts)}#{end_sections(1, indent, el.options[:location])}#{raw}" end def convert1(el, indent, opts = {}) nopts = el.rfc2629_fix(opts) send("convert_#{el.type}", el, indent, nopts) end def inner_a(el, indent, opts) indent += INDENTATION el.children.map do |inner_el| nopts = inner_el.rfc2629_fix(opts) send("convert_#{inner_el.type}", inner_el, indent, nopts) end end def inner(el, indent, opts) inner_a(el, indent, opts).join('') end def convert_blank(el, indent, opts) "\n" end def convert_text(el, indent, opts) escape_html(el.value, :text) end def convert_p(el, indent, opts) if (el.children.size == 1 && el.children[0].type == :img) || opts[:unpacked] inner(el, indent, opts) # Part of the bad reference hack else "#{' '*indent}<t#{el_html_attributes(el)}>#{inner(el, indent, opts)}</t>\n" end end def saner_generate_id(value) generate_id(value).gsub(/-+/, '-') end def self.process_markdown1(v) # Uuh. Heavy coupling. doc = ::Kramdown::Document.new(v, $global_markdown_options) $stderr.puts doc.warnings.to_yaml unless doc.warnings.empty? doc.to_rfc2629 end def self.process_markdown(v) process_markdown1(v)[3..-6] # skip <t>...</t>\n end def self.process_markdown_to_rexml(v) s = process_markdown1(v) REXML::Document.new(s) end SVG_COLORS = Hash.new {|h, k| k} <<COLORS.each_line {|l| k, v = l.chomp.split; SVG_COLORS[k] = v} black #000000 silver #C0C0C0 gray #808080 white #FFFFFF maroon #800000 red #FF0000 purple #800080 fuchsia #FF00FF green #008000 lime #00FF00 olive #808000 yellow #FFFF00 navy #000080 blue #0000FF teal #008080 aqua #00FFFF COLORS def svg_munch_id(id) id.gsub(/[^-._A-Za-z0-9]/) {|x| "_%02X" % x.ord} end def self.hex_to_lin(h) h.to_i(16)**2.22 # approximating sRGB gamma end define_method :hex_to_lin, &method(:hex_to_lin) B_W_THRESHOLD = hex_to_lin("a4") # a little brighter than 1/2 0xFF -> white def svg_munch_color(c, fill) c = SVG_COLORS[c] case c when /\A#(..)(..)(..)\z/ if hex_to_lin($1)*0.2126 + hex_to_lin($2)*0.7152 + hex_to_lin($3)*0.0722 >= B_W_THRESHOLD 'white' else 'black' end when 'none' 'none' if fill # delete for stroke else c end end SVG_NAMESPACES = {"xmlns"=>"http://www.w3.org/2000/svg", "xlink"=>"http://www.w3.org/1999/xlink"} def svg_clean_kgt(s) d = REXML::Document.new(s) REXML::XPath.each(d.root, "/xmlns:svg", SVG_NAMESPACES) do |x| if (w = x.attributes["width"]) && (h = x.attributes["height"]) x.attributes["viewBox"] = "0 0 %d %d" % [w, h] end if x.attributes["viewBox"] x.attributes["width"] = nil x.attributes["height"] = nil end end REXML::XPath.each(d.root, "//rect|//line|//path") do |x| x.attributes["fill"] = "none" x.attributes["stroke"] = "black" x.attributes["stroke-width"] = "1.5" end d.to_s rescue => detail warn "*** Can't clean SVG: #{detail}" d end def svg_clean(s) # expensive, risky d = REXML::Document.new(s) REXML::XPath.each(d.root, "//*[@shape-rendering]") { |x| x.attributes["shape-rendering"] = nil } #; warn x.inspect } REXML::XPath.each(d.root, "//*[@text-rendering]") { |x| x.attributes["text-rendering"] = nil } #; warn x.inspect } REXML::XPath.each(d.root, "//*[@stroke]") { |x| x.attributes["stroke"] = svg_munch_color(x.attributes["stroke"], false) } REXML::XPath.each(d.root, "//*[@fill]") { |x| x.attributes["fill"] = svg_munch_color(x.attributes["fill"], true) } REXML::XPath.each(d.root, "//*[@id]") { |x| x.attributes["id"] = svg_munch_id(x.attributes["id"]) } ## REXML::XPath.each(d.root, "//rect") { |x| x.attributes["style"] = "fill:none;stroke:black;stroke-width:1" unless x.attributes["style"] } # Fix for mermaid: REXML::XPath.each(d.root, "//polygon") { |x| x.attributes["rx"] = nil; x.attributes["ry"] = nil } d.to_s rescue => detail warn "*** Can't clean SVG: #{detail}" d end def memoize(meth, *args) require 'digest' Dir.mkdir(REFCACHEDIR) unless Dir.exist?(REFCACHEDIR) kdrfc_version = Gem.loaded_specs["kramdown-rfc2629"].version.to_s.gsub('.', '_') rescue "UNKNOWN" fn = "#{REFCACHEDIR}/kdrfc-#{kdrfc_version}-#{meth}-#{Digest::SHA256.hexdigest(Marshal.dump(args))[0...40]}.cache" begin out = Marshal.load(File.binread(fn)) rescue StandardError => e # warn e.inspect out = method(meth).call(*args) File.binwrite(fn, Marshal.dump(out)) end out end def capture_croak(t, err) if err != '' err.lines do |l| warn "*** [#{t}:] #{l.chomp}" end end end def shell_prepare(opt) " " << opt.shellsplit.shelljoin end DEFAULT_AASVG="aasvg --spaces=1" def svg_tool_process(t, svg_opt, txt_opt, result) require 'tempfile' file = Tempfile.new("kramdown-rfc") file.write(result) file.close dont_clean = false dont_check = false svg_opt = shell_prepare(svg_opt) if svg_opt txt_opt = shell_prepare(txt_opt) if txt_opt case t when "protocol", "protocol-goat", "protocol-aasvg" cmdparm = result.lines.map(&:strip).select {|x| x != ''}.join(',') result, err, _s = Open3.capture3("protocol #{Shellwords.escape(cmdparm)}#{txt_opt}", stdin_data: '') if t == "protocol-goat" file.unlink file = Tempfile.new("kramdown-rfc") file.write(result) file.close result1, err, _s = Open3.capture3("goat#{svg_opt} #{file.path}", stdin_data: result); dont_clean = true elsif t == "protocol-aasvg" result1, err, _s = Open3.capture3("#{DEFAULT_AASVG}#{svg_opt}", stdin_data: result); dont_clean = true dont_check = true else result1 = nil end when "goat" result1, err, _s = Open3.capture3("goat#{svg_opt} #{file.path}", stdin_data: result); dont_clean = true when "aasvg" result1, err, _s = Open3.capture3("#{DEFAULT_AASVG}#{svg_opt}", stdin_data: result); dont_clean = true dont_check = true when "ditaa" # XXX: This needs some form of option-setting result1, err, _s = Open3.capture3("ditaa #{file.path} --svg -o -#{svg_opt}", stdin_data: result); when "mscgen" result1, err, _s = Open3.capture3("mscgen -T svg -i #{file.path} -o -#{svg_opt}", stdin_data: result); when "mermaid" result1, err, _s = Open3.capture3("mmdc -i #{file.path}#{svg_opt}", stdin_data: result); # -b transparent outpath = file.path + ".svg" result1 = File.read(outpath) rescue '' # don't die before providing error message File.unlink(outpath) rescue nil # ditto when "plantuml", "plantuml-utxt", "plantuml-ascii-art" if t == "plantuml-ascii-art" result, ascii_art = result.split(/^~{3,} ascii-art\n/, 2) unless ascii_art warn "*** Didn't find ascii-art in plantuml-ascii-art #{result.inspect}" ascii_art = result.to_s end end plantuml = "@startuml\n#{result}\n@enduml" result1, err, _s = Open3.capture3("plantuml -pipe -tsvg#{svg_opt}", stdin_data: plantuml); case t when "plantuml-utxt" result, err1, _s = Open3.capture3("plantuml -pipe -tutxt#{txt_opt}", stdin_data: plantuml) err << err1.to_s when "plantuml-ascii-art" result = ascii_art end when "railroad", "railroad-utf8" result1, err1, _s = Open3.capture3("kgt -l abnf -e svg#{svg_opt}", stdin_data: result); result1 = svg_clean_kgt(result1); dont_clean = true result, err, _s = Open3.capture3("kgt -l abnf -e rr#{t == "railroad" ? "text" : "utf8"}#{txt_opt}", stdin_data: result); err << err1.to_s when "math", "math-asciitex" result1, err, _s = Open3.capture3("tex2svg --font STIX --speech=false#{svg_opt} #{Shellwords.escape(' ' << result)}"); begin raise Errno::ENOENT if t == "math-asciitex" result, err1, s = Open3.capture3("utftex -m #{txt_opt}", stdin_data: result) if s.exitstatus != 0 warn "** utftex: #{err1.inspect}" raise Errno::ENOENT end rescue Errno::ENOENT warn "** utftex not working, falling back to asciitex" unless t == "math-asciitex" result, err1, _s = Open3.capture3("asciitex -f #{file.path}#{txt_opt}") end err << err1 end capture_croak(t, err) # warn ["text:", result.inspect] # warn ["svg:", result1.inspect] file.unlink if result1 result1 = svg_clean(result1) unless dont_clean unless dont_check file = Tempfile.new("kramdown-rfc") file.write(result1) file.close result1, err, _s = Open3.capture3("svgcheck -qa #{file.path}"); file.unlink # warn ["svgcheck:", result1.inspect] capture_croak("svgcheck", err) end if result1 == '' warn "*** could not create svg for #{result.inspect[0...20]}..." exit 65 # EX_DATAERR end end [result, result1] # text, svg end ARTWORK_TYPES = %w(ascii-art binary-art call-flow hex-dump svg) def convert_codeblock(el, indent, opts) # el.attr['anchor'] ||= saner_generate_id(el.value) -- no longer in 1.0.6 result = el.value gi = el.attr.delete('gi') blockclass = el.attr.delete('class') if blockclass == 'language-tbreak' result = result.lines.map {|line| [line.chomp, 0]} spaceind = 0 result.each_with_index {|pair, index| if pair[0] == '' result[spaceind][1] += 1 pair[0] = nil unless index == spaceind else spaceind = index end } # $stderr.puts(result.inspect) result = result.map {|line, space| "<![CDATA[#{line.gsub(/^\s+/) {|s| "\u00A0" * s.size}}]]><vspace blankLines=\"#{space}\"/>" if line }.compact.join("\n") "#{' '*indent}<t>#{result}</t>\n" else artwork_attr = {} t = nil if blockclass classes = blockclass.split(' ') classes.each do |cl| if md = cl.match(/\Alanguage-(.*)/) t = artwork_attr["type"] = md[1] # XXX overwrite else $stderr.puts "*** Unimplemented codeblock class: #{cl}" end end end # compensate for XML2RFC idiosyncrasy by insisting on a blank line unless el.attr.delete('tight') result[0,0] = "\n" unless result[0,1] == "\n" end el.attr.each do |k, v| if md = k.match(/\A(?:artwork|sourcecode)-(.*)/) el.attr.delete(k) artwork_attr[md[1]] = v end end case t when "aasvg", "ditaa", "goat", "math", "math-asciitex", "mermaid", "mscgen", "plantuml", "plantuml-utxt", "plantuml-ascii-art", "protocol", "protocol-aasvg", "protocol-goat", "railroad", "railroad-utf8" if gi warn "*** Can't set GI #{gi} for composite SVG artset" end result, result1 = memoize(:svg_tool_process, t, artwork_attr.delete("svg-options"), artwork_attr.delete("txt-options"), result) retart = mk_artwork(artwork_attr, "ascii-art", "<![CDATA[#{result}#{result =~ /\n\Z/ ? '' : "\n"}]]>") if result1 # nest TXT in artset with SVG retsvg = mk_artwork(artwork_attr, "svg", result1.sub(/.*?<svg/m, "<svg")) retart = "<artset>#{retsvg}#{retart}</artset>" end "#{' '*indent}<figure#{el_html_attributes(el)}>#{retart}</figure>\n" else gi ||= ( if !$options.v3 || !t || ARTWORK_TYPES.include?(t) "artwork" elsif artwork_attr["align"] warn "** RFXCMLv3 does not yet allow setting align= for <sourcecode, falling back to <artwork" "artwork" else "sourcecode" end ) loc_str = if anchor = el.attr['anchor'] "##{anchor}" elsif lineno = el.options[:location] "#{correct_location(lineno)}" else "UNKNOWN" end preprocs = el.attr.delete("pre") checks = el.attr.delete("check") postprocs = el.attr.delete("post") case t when "cbor" warn "** There is no sourcecode-type “cbor”." warn "** Do you mean “cbor-diag” (diagnostic notation)" warn "** or “cbor-pretty” (annotated hex-dump)?" when "json" checks ||= "json" when /\A(.*)-from-yaml\z/ t = $1 preprocs ||= "yaml2json" end preprocs = (preprocs || '').split("-") checks = (checks || '').split("-") postprocs = (postprocs || '').split("-") result = sourcecode_checkproc(preprocs, checks, postprocs, loc_str, result) "#{' '*indent}<figure#{el_html_attributes(el)}><#{gi}#{html_attributes(artwork_attr)}><![CDATA[#{result}#{result =~ /\n\Z/ ? '' : "\n"}]]></#{gi}></figure>\n" end end end def sourcecode_proc(proc, loc_str, result) case proc when "dedent" result = remove_indentation(result) when /\Afold(\d*)(left(\d*))?(dry)?\z/ fold = [$1.to_i, # col 0 for '' ($3.to_i if $2), # left 0 for '', nil if no "left" $4] # dry result = fix_unterminated_line(fold8792_1(trim_empty_lines_around(result), *fold)) # XXX when "yaml2json" begin y = YAML.safe_load(result, aliases: true, filename: loc_str) result = JSON.pretty_generate(y) rescue => e warn "*** #{loc_str}: YAML isn't: #{e.message}\n" end else warn "*** #{loc_str}: unknown proc '#{proc}'" end result end def sourcecode_checkproc(preprocs, checks, postprocs, loc_str, result) preprocs.each do |proc| result = sourcecode_proc(proc, loc_str, result) end if preprocs check_input = result checks.each do |check| case check when "skipheader" check_input = handle_artwork_sourcecode(check_input).sub(/.*?\n\n/m, '') when "json" # check for 8792; undo if needed: begin JSON.load(handle_artwork_sourcecode(check_input)) rescue => e err1 = "*** #{loc_str}: JSON isn't: #{JSON.dump(e.message[0..40])}\n" begin JSON.load("{" << check_input << "}") rescue => e warn err1 << "*** not even with braces added around: #{JSON.dump(e.message[0..40])}" end end else warn "*** #{loc_str}: unknown check '#{check}'" end end if checks postprocs.each do |proc| result = sourcecode_proc(proc, loc_str, result) end if postprocs result end def mk_artwork(artwork_attr, typ, content) "<artwork #{html_attributes(artwork_attr.merge("type" => typ))}>#{content}</artwork>" end def convert_blockquote(el, indent, opts) text = inner(el, indent, opts) if $options.v3 gi = el.attr.delete('gi') if gi && gi != 'ul' if RFCXML_SPAN_ELEMENTS === gi text.sub!(/\A\s*<t>(.*)<\/t>\s*\z/) {$1} # XXX unwrap inner text from block "#{' '*indent}<t><#{gi}#{el_html_attributes(el)}>#{text}</#{gi}></t>\n" else "#{' '*indent}<#{gi}#{el_html_attributes(el)}>\n#{text}#{' '*indent}</#{gi}>\n" end else "#{' '*indent}<ul#{el_html_attributes_with(el, {"empty" => 'true'})}><li>\n#{text}#{' '*indent}</li></ul>\n" end else text = "<t></t>" unless text =~ /</ # empty block quote "#{' '*indent}<t><list style='empty'#{el_html_attributes(el)}>\n#{text}#{' '*indent}</list></t>\n" end end def end_sections(to_level, indent, location) if indent < 0 indent = 0 end if @sec_level >= to_level delta = (@sec_level - to_level) @sec_level = to_level "#{' '*indent}</section>\n" * delta else $stderr.puts "** #{correct_location(location)}: Bad section nesting: start heading level at 1 and increment by 1" end end def clean_pcdata(parts) # hack, will become unnecessary with XML2RFCv3 clean = '' irefs = '' # warn "clean_parts: #{parts.inspect}" parts.each do |p| md = p.match(%r{([^<]*)(.*)}) clean << md[1] irefs << md[2] # breaks for spanx... don't emphasize in headings! end [clean, irefs] end def clean_pcdatav3(parts) # hack, will become unnecessary with v3 tables clean = '' parts.each do |p| next if p.empty? if p == "<br />" p = "\u2028" # XXX end d = REXML::Document.new("<foo>#{p}</foo>") t = REXML::XPath.each(d.root, "//text()").to_a.join if t != p warn "** simplified markup #{p.inspect} into #{t.inspect} in table heading" end clean << t end clean end def convert_header(el, indent, opts) # todo: handle appendix tags el = el.deep_clone options = @doc ? @doc.options : @options # XXX: 0.11 vs. 0.12 if options[:auto_ids] && !el.attr['anchor'] el.attr['anchor'] = saner_generate_id(el.options[:raw_text]) end if $options.v3 if sl = el.attr.delete('slugifiedName') # could do general name- play attrstring = html_attributes({'slugifiedName' => sl}) end # noabbrev: true -- Workaround for https://github.com/ietf-tools/xml2rfc/issues/683 nm = inner(el, indent, opts.merge(noabbrev: true)) if ttl = el.attr['title'] warn "*** Section has two titles: >>#{ttl}<< and >>#{nm}<<" warn "*** Do you maybe have a loose IAL?" end irefs = "<name#{attrstring}>#{nm}</name>" # else clean, irefs = clean_pcdata(inner_a(el, indent, opts)) el.attr['title'] = clean end "#{end_sections(el.options[:level], indent, el.options[:location])}#{' '*indent}<section#{@sec_level += 1; el_html_attributes(el)}>#{irefs}\n" end def convert_hr(el, indent, opts) # misuse for page break "#{' '*indent}<t><vspace blankLines='999' /></t>\n" end STYLES = {ul: 'symbols', ol: 'numbers', dl: 'hanging'} def convert_ul(el, indent, opts) opts = opts.merge(vspace: el.attr.delete('vspace')) attrstring = el_html_attributes_with(el, {"style" => STYLES[el.type]}) if opts[:unpacked] "#{' '*indent}<list#{attrstring}>\n#{inner(el, indent, opts)}#{' '*indent}</list>\n" else "#{' '*indent}<t><list#{attrstring}>\n#{inner(el, indent, opts)}#{' '*indent}</list></t>\n" end end def convert_ol(el, indent, opts) if @options[:ol_start_at_first_marker] and (first_list_marker = el.options[:first_list_marker]) el.attr['start'] ||= first_list_marker[/\d+/] end nested_types = opts[:nested_ol_types] || ["1"] # warn "** ol opts #{opts.inspect} types #{nested_types.inspect}" if nested_attr = el.attr.delete('nestedOlTypes') nested_types = ::Kramdown::Options.parse(:nested_ol_types, nested_attr) end if nested_types = nested_types.dup # warn "** nested_types #{nested_types.inspect}" nested_here = nested_types.shift opts = opts.merge(nested_ol_types: nested_types << nested_here) el.attr['type'] ||= nested_here # warn "** actual ol type #{el.attr['type'].inspect}" end convert_ul(el, indent, opts) end def convert_dl(el, indent, opts) if $options.v3 if hangindent = el.attr.delete('hangIndent') el.attr['indent'] ||= hangindent # new attribute name wins end vspace = el.attr.delete('vspace') if vspace && !el.attr['newline'] el.attr['newline'] = 'true' end "#{' '*indent}<dl#{el_html_attributes(el)}>\n#{inner(el, indent, opts.dup)}#{' '*indent}</dl>\n" else convert_ul(el, indent, opts) end end def convert_li(el, indent, opts) res_a = inner_a(el, indent, opts) if el.children.empty? || el.children.first.options[:category] == :span res = res_a.join('') else # merge multiple <t> elements res = res_a.select { |x| x.strip != '' }.map { |x| x.sub(/\A\s*<t>(.*)<\/t>\s*\Z/m) { $1} }.join("#{' '*indent}<vspace blankLines='1'/>\n").gsub(%r{(</list>)\s*<vspace blankLines='1'/>}) { $1 }.gsub(%r{<vspace blankLines='1'/>\s*(<list)}) { $1 } end "#{' '*indent}<t#{el_html_attributes(el)}>#{res}#{(res =~ /\n\Z/ ? ' '*indent : '')}</t>\n" end def convert_dd(el, indent, opts) if $options.v3 out = '' if !opts[:haddt] out ="#{' '*indent}<dt/>\n" # you can't make this one up end opts[:haddt] = false out << "#{' '*indent}<dd#{el_html_attributes(el)}>\n#{inner(el, indent, opts)}#{' '*indent}</dd>\n" else output = ' '*indent if @in_dt == 1 @in_dt = 0 else output << "<t#{el_html_attributes(el)}>" end res = inner(el, indent+INDENTATION, opts.merge(unpacked: true)) # if el.children.empty? || el.children.first.options[:category] != :block output << res << (res =~ /\n\Z/ ? ' '*indent : '') # else FIXME: The latter case is needed for more complex cases # output << "\n" << res << ' '*indent # end output << "</t>\n" end end def convert_dt(el, indent, opts) # SERIOUSLY BAD HACK: if $options.v3 out = '' if opts[:haddt] out ="#{' '*indent}<dd><t/></dd>\n" # you can't make this one up end opts[:haddt] = true out << "#{' '*indent}<dt#{el_html_attributes(el)}>#{inner(el, indent, opts)}</dt>\n" else close = "#{' '*indent}</t>\n" * @in_dt @in_dt = 1 vspace = opts[:vspace] vspaceel = "<vspace blankLines='#{vspace}'/>" if vspace ht = escape_html(inner(el, indent, opts), :attribute) # XXX this may leave gunk "#{close}#{' '*indent}<t#{el_html_attributes(el)} hangText=\"#{ht}\">#{vspaceel}\n" end end HTML_TAGS_WITH_BODY=['div', 'script'] def convert_html_element(el, indent, opts) if el.value == "svg" # do not meddle with id= in SVG opts = opts.merge({noanchor: true}) end res = inner(el, indent, opts) if el.options[:category] == :span "<#{el.value}#{el_html_attributes(el)}" << (!res.empty? ? ">#{res}</#{el.value}>" : " />") else output = '' output << ' '*indent if !el.options[:parent_is_raw] output << "<#{el.value}#{el_html_attributes(el)}" if !res.empty? && el.options[:parse_type] != :block output << ">#{res}</#{el.value}>" elsif !res.empty? output << ">\n#{res}" << ' '*indent << "</#{el.value}>" elsif HTML_TAGS_WITH_BODY.include?(el.value) output << "></#{el.value}>" else output << " />" end output << "\n" if el.options[:outer_element] || !el.options[:parent_is_raw] output end end def convert_xml_comment(el, indent, opts) if el.value =~ /\A<\?line (([-+]?)[0-9]+)\?>\z/ lineno = $1.to_i case $2 when '' # absolute @location_delta = lineno - el.options[:location] when '+', '-' # correction (pre-scanning!) @location_correction += lineno end end if el.options[:category] == :block && !el.options[:parent_is_raw] ' '*indent + el.value + "\n" else el.value end end alias :convert_xml_pi :convert_xml_comment alias :convert_html_doctype :convert_xml_comment ALIGNMENTS = { default: :left, left: :left, right: :right, center: :center} COLS_ALIGN = { "l" => :left, "c" => :center, "r" => :right} def convert_table(el, indent, opts) # This only works for tables with headers alignment = el.options[:alignment].map { |al| ALIGNMENTS[al]} cols = (el.attr.delete("cols") || "").split(' ') "#{' '*indent}<texttable#{el_html_attributes(el)}>\n#{inner(el, indent, opts.merge(table_alignment: alignment, table_cols: cols))}#{' '*indent}</texttable>\n" end def convert_thead(el, indent, opts) inner(el, indent, opts) end alias :convert_tbody :convert_thead alias :convert_tfoot :convert_thead alias :convert_tr :convert_thead def convert_td(el, indent, opts) if alignment = opts[:table_alignment] alignment = alignment.shift if cols = opts[:table_cols].shift md = cols.match(/(\d*(|em|[%*]))([lrc])/) if md[1].to_i != 0 widthval = md[1] widthval << "em" if md[2].empty? widthopt = "width='#{widthval}' " end alignment = COLS_ALIGN[md[3]] || :left end end if alignment xmlres = inner_a(el, indent, opts) if $options.v3 res = clean_pcdatav3(xmlres) else res, irefs = clean_pcdata(xmlres) warn "*** lost markup #{irefs} in table heading" unless irefs.empty? end "#{' '*indent}<ttcol #{widthopt}align='#{alignment}'#{el_html_attributes(el)}>#{res.empty? ? " " : res}</ttcol>\n" # XXX need clean_pcdata else res = inner(el, indent, opts) "#{' '*indent}<c#{el_html_attributes(el)}>#{res.empty? ? " " : res}</c>\n" end end alias :convert_th :convert_td def convert_comment(el, indent, opts) ## Don't actually output all those comments into the XML: # if el.options[:category] == :block # "#{' '*indent}<!-- #{el.value} -->\n" # else # "<!-- #{el.value} -->" # end end def convert_br(el, indent, opts) if $options.v3 "<br />" else "<vspace />" end end def convert_a(el, indent, opts) gi = el.attr.delete('gi') res = inner(el, indent, opts) target = el.attr['target'] if target[0..1] == "{{" # XXX ignoring all attributes and content s = ::Kramdown::Converter::Rfc2629::process_markdown(target) # if res != '' && s[-2..-1] == '/>' # if s =~ /\A<([-A-Za-z0-9_.]+) / # gi ||= $1 # end # s[-2..-1] = ">#{res}</#{gi}>" # end return s end if target[0] == "#" # handle [](#foo) as xref as in RFC 7328 el.attr['target'] = target = target[1..-1] if target.downcase == res.downcase res = '' # get rid of raw anchors leaking through end gi ||= "xref" else gi ||= "eref" end "<#{gi}#{el_html_attributes(el)}>#{res}</#{gi}>" end def convert_xref(el, indent, opts) gi = el.attr.delete('gi') text = el.attr.delete('text') target = el.attr['target'] if target[0] == "&" "#{target};" else if target =~ %r{\A\w+:(?://|.*@)} gi ||= "eref" else gi ||= "xref" end if text tail = ">#{Rfc2629::process_markdown(text)}</#{gi}>" else tail = "/>" end "<#{gi}#{el_html_attributes(el)}#{tail}" end end def convert_contact(el, indent, opts) "<contact#{el_html_attributes(el)}/>" end REFCACHEDIR = ENV["KRAMDOWN_REFCACHEDIR"] || ".refcache" # warn "*** REFCACHEDIR #{REFCACHEDIR}" KRAMDOWN_OFFLINE = ENV["KRAMDOWN_OFFLINE"] KRAMDOWN_REFCACHE_REFETCH = ENV["KRAMDOWN_REFCACHE_REFETCH"] KRAMDOWN_REFCACHE_QUIET = ENV["KRAMDOWN_REFCACHE_QUIET"] def get_and_write_resource(url, fn) options = {} if ENV["KRAMDOWN_DONT_VERIFY_HTTPS"] options[:ssl_verify_mode] = OpenSSL::SSL::VERIFY_NONE end # workaround for OpenSSL on Windows... # URI.open(url, **options) do |uf| # not portable to older versions OpenURI.open_uri(url, **options) do |uf| s = uf.read if uf.status[0] != "200" warn "*** Status code #{status} while fetching #{url}" else File.write(fn, s) end end end def get_and_write_resource_persistently(url, fn) t1 = Time.now response = $http.request(URI(url)) if response.code != "200" raise "Status code #{response.code} while fetching #{url}" else File.write(fn, response.body) end t2 = Time.now warn "(#{"%.3f" % (t2 - t1)} s)" if KRAMDOWN_PERSISTENT_VERBOSE end def get_doi(refname) lit = doi_fetch_and_convert(refname, fuzzy: true) anchor = "DOI_#{refname.gsub("/", "_")}" KramdownRFC::ref_to_xml(anchor, lit) end # this is now slightly dangerous as multiple urls could map to the same cachefile def get_and_cache_resource(url, cachefile, tvalid = 7200, tn = Time.now) fn = "#{REFCACHEDIR}/#{cachefile}" Dir.mkdir(REFCACHEDIR) unless Dir.exist?(REFCACHEDIR) f = File.stat(fn) rescue nil unless KRAMDOWN_REFCACHE_REFETCH if !KRAMDOWN_OFFLINE && (!f || tn - f.mtime >= tvalid) if f message = "renewing (stale by #{"%.1f" % ((tn-f.mtime)/86400)} days)" fetch_timeout = 10 # seconds, give up quickly if just renewing else message = "fetching" fetch_timeout = 60 # seconds; long timeout needed for Travis end $stderr.puts "#{fn}: #{message} from #{url}" unless KRAMDOWN_REFCACHE_QUIET if Array === url begin case url[0] when :DOI ref = get_doi(url[1]) File.write(fn, ref) end rescue Exception => e warn "*** Error fetching #{url[0]} #{url[1].inspect}: #{e}" end elsif ENV["HAVE_WGET"] `cd #{REFCACHEDIR}; wget -t 3 -T #{fetch_timeout} -Nnv "#{url}"` # ignore errors if offline (hack) begin File.utime nil, nil, fn rescue Errno::ENOENT warn "Can't fetch #{url} -- is wget in path?" end else require 'open-uri' require 'socket' require 'openssl' require 'timeout' begin Timeout::timeout(fetch_timeout) do if $http begin # belt and suspenders get_and_write_resource_persistently(url, fn) rescue Exception => e warn "*** Can't get with persistent HTTP: #{e}" get_and_write_resource(url, fn) end else get_and_write_resource(url, fn) end end rescue OpenURI::HTTPError, Errno::EHOSTUNREACH, Errno::ECONNREFUSED, SocketError, Timeout::Error => e warn "*** #{e} while fetching #{url}" end end end begin File.read(fn) # this blows up if no cache available after fetch attempt rescue Errno::ENOENT => e warn "*** #{e} for #{fn}" end end def self.bcp_std_ref(t, n) warn "*** #{t} anchors not supported in v2 format" unless $options.v3 [name = "reference.#{t}.#{"%04d" % n.to_i}.xml", "#{XML_RESOURCE_ORG_PREFIX}/bibxml-rfcsubseries/#{name}"] # FOR NOW end KRAMDOWN_REFCACHETTL = (e = ENV["KRAMDOWN_REFCACHETTL"]) ? e.to_i : 3600 KRAMDOWN_REFCACHETTL_RFC = (e = ENV["KRAMDOWN_REFCACHETTL_RFC"]) ? e.to_i : 86400*7 KRAMDOWN_REFCACHETTL_DOI_IANA = (e = ENV["KRAMDOWN_REFCACHETTL_DOI_IANA"]) ? e.to_i : 86400 KRAMDOWN_REFCACHETTL_DOI = (e = ENV["KRAMDOWN_REFCACHETTL_DOI"]) ? e.to_i : KRAMDOWN_REFCACHETTL_DOI_IANA KRAMDOWN_REFCACHETTL_IANA = (e = ENV["KRAMDOWN_REFCACHETTL_IANA"]) ? e.to_i : KRAMDOWN_REFCACHETTL_DOI_IANA # [subdirectory name, cache ttl in seconds, does it provide for ?anchor=] XML_RESOURCE_ORG_MAP = { "RFC" => ["bibxml", KRAMDOWN_REFCACHETTL_RFC, false, ->(fn, n){ [name = "reference.RFC.#{"%04d" % n.to_i}.xml", "https://bib.ietf.org/public/rfc/bibxml/#{name}"] } # was "https://www.rfc-editor.org/refs/bibxml/#{name}"] } ], "I-D" => ["bibxml3", false, false, ->(fn, n){ [fn, "https://datatracker.ietf.org/doc/bibxml3/draft-#{n.sub(/\Adraft-/, '')}.xml"] } ], "BCP" => ["bibxml-rfcsubseries", KRAMDOWN_REFCACHETTL_RFC, false, ->(fn, n){ Rfc2629::bcp_std_ref("BCP", n) } ], "STD" => ["bibxml-rfcsubseries", KRAMDOWN_REFCACHETTL_RFC, false, ->(fn, n){ Rfc2629::bcp_std_ref("STD", n) } ], "W3C" => "bibxml4", "3GPP" => "bibxml5", "SDO-3GPP" => "bibxml5", "ANSI" => "bibxml2", "CCITT" => "bibxml2", "FIPS" => "bibxml2", # "IANA" => "bibxml2", overtaken by bibxml8 "IEEE" => "bibxml6", # copied over to bibxml6 2019-02-27 "ISO" => "bibxml2", "ITU" => "bibxml2", "NIST" => "bibxml2", "OASIS" => "bibxml2", "PKCS" => "bibxml2", "DOI" => ["bibxml7", KRAMDOWN_REFCACHETTL_DOI, true, ->(fn, n){ ["computed-#{fn}", [:DOI, n] ] }, true # always_altproc ], # emulate old 24 h cache "IANA" => ["bibxml8", KRAMDOWN_REFCACHETTL_IANA, true], # ditto } # XML_RESOURCE_ORG_HOST = ENV["XML_RESOURCE_ORG_HOST"] || "xml.resource.org" # XML_RESOURCE_ORG_HOST = ENV["XML_RESOURCE_ORG_HOST"] || "xml2rfc.tools.ietf.org" XML_RESOURCE_ORG_HOST = ENV["XML_RESOURCE_ORG_HOST"] || "bib.ietf.org" XML_RESOURCE_ORG_PREFIX = ENV["XML_RESOURCE_ORG_PREFIX"] || "https://#{XML_RESOURCE_ORG_HOST}/public/rfc" KRAMDOWN_USE_TOOLS_SERVER = ENV["KRAMDOWN_USE_TOOLS_SERVER"] KRAMDOWN_NO_TARGETS = ENV['KRAMDOWN_NO_TARGETS'] KRAMDOWN_KEEP_TARGETS = ENV['KRAMDOWN_KEEP_TARGETS'] def convert_img(el, indent, opts) # misuse the tag! if a = el.attr alt = a.delete('alt').strip alt = '' if alt == '!' # work around re-wrap uglyness if src = a.delete('src') a['target'] = src end end if alt == ":include:" # Really bad misuse of tag... ann = el.attr.delete('ann') anchor = el.attr.delete('anchor') || ( # not yet warn "*** missing anchor for '#{src}'" src ) anchor = ::Kramdown::Parser::RFC2629Kramdown.idref_cleanup(anchor) anchor.gsub!('/', '_') # should take out all illegals to_insert = "" src.scan(/(W3C|3GPP|[A-Z-]+)[.]?([A-Za-z_0-9.\(\)\/\+-]+)/) do |t, n| never_altproc = n.sub!(/^[.]/, "") fn = "reference.#{t}.#{n}.xml" sub, ttl, _can_anchor, altproc, always_altproc = XML_RESOURCE_ORG_MAP[t] ttl ||= KRAMDOWN_REFCACHETTL # everything but RFCs might change a lot puts "*** Huh: #{fn}" unless sub if altproc && !never_altproc && (!KRAMDOWN_USE_TOOLS_SERVER || always_altproc) fn, url = altproc.call(fn, n) else url = "#{XML_RESOURCE_ORG_PREFIX}/#{sub}/#{fn}" fn = "alt-#{fn}" if never_altproc || KRAMDOWN_USE_TOOLS_SERVER end # if can_anchor # create anchor server-side for stand_alone: false # url << "?anchor=#{anchor}" # fn[/.xml$/] = "--anchor=#{anchor}.xml" # end to_insert = get_and_cache_resource(url, fn.gsub('/', '_'), ttl) to_insert.scrub! rescue nil # only do this for Ruby >= 2.1 begin d = REXML::Document.new(to_insert) d.xml_decl.nowrite d.delete d.doctype d.context[:attribute_quote] = :quote # Set double-quote as the attribute value delimiter d.root.attributes["anchor"] = anchor if t == "RFC" or t == "I-D" if KRAMDOWN_NO_TARGETS || !KRAMDOWN_KEEP_TARGETS d.root.attributes["target"] = nil REXML::XPath.each(d.root, "/reference/format") { |x| d.root.delete_element(x) } else REXML::XPath.each(d.root, "/reference/format") { |x| x.attributes["target"].sub!(%r{https?://www.ietf.org/internet-drafts/}, %{https://www.ietf.org/archive/id/}) if t == "I-D" } end elsif t == "IANA" d.root.attributes["target"].sub!(%r{\Ahttp://www.iana.org/assignments/}, 'https://www.iana.org/assignments/') end if ann el = ::Kramdown::Converter::Rfc2629::process_markdown_to_rexml(ann).root el.name = "annotation" d.root.add_element(el) end to_insert = d.to_s rescue Exception => e warn "** Can't manipulate reference XML: #{e}" broken = true to_insert = nil end # this may be a bit controversial: Don't break the build if reference is broken if KRAMDOWN_OFFLINE || broken unless to_insert to_insert = "<reference anchor='#{anchor}'> <front> <title>*** BROKEN REFERENCE *** " warn "*** KRAMDOWN_OFFLINE: Inserting broken reference for #{fn}" end else exit 66 unless to_insert # EX_NOINPUT end end to_insert else "#{alt}" end end def convert_codespan(el, indent, opts) attrstring = el_html_attributes_with(el, {"style" => 'verb'}) "#{escape_html(el.value)}" end def convert_footnote(el, indent, opts) # XXX: footnotes into crefs??? # this would be more like xml2rfc v3: # "\n#{' '*indent}\n#{inner(el.value, indent, opts).rstrip}\n#{' '*indent}" content = inner(el.value, indent, opts).strip content = content.sub(/\A(.*)<\/t>\z/m) {$1} name = ::Kramdown::Parser::RFC2629Kramdown.idref_cleanup(el.options[:name]) o_name = name.dup while @footnote_names_in_use[name] do if name =~ /_\d+\z/ name.succ! else name << "_1" end end @footnote_names_in_use[name] = true attrstring = el_html_attributes_with(el, {"anchor" => name}) if $options.v3 if o_name[-1] == "-" # Ignore HTML attributes. Hmm. content else # do not indent span-level so we can stick to previous word. Good? "#{content}" end else content = escape_html(content, :text) # text only... "\n#{' '*indent}#{content}" end end def convert_raw(el, indent, opts) end_sections(1, indent, el.options[:location]) + el.value + (el.options[:category] == :block ? "\n" : '') end EMPH = { em: "emph", strong: "strong"} def convert_em(el, indent, opts) if $options.v3 gi = el.type "<#{gi}#{el_html_attributes(el)}>#{inner(el, indent, opts)}" else attrstring = el_html_attributes_with(el, {"style" => EMPH[el.type]}) span, irefs = clean_pcdata(inner_a(el, indent, opts)) "#{span}#{irefs}" end end alias :convert_strong :convert_em def convert_entity(el, indent, opts) entity_to_str(el.value) end TYPOGRAPHIC_SYMS = { :mdash => [::Kramdown::Utils::Entities.entity('mdash')], :ndash => [::Kramdown::Utils::Entities.entity('ndash')], :hellip => [::Kramdown::Utils::Entities.entity('hellip')], :laquo_space => [::Kramdown::Utils::Entities.entity('laquo'), ::Kramdown::Utils::Entities.entity('nbsp')], :raquo_space => [::Kramdown::Utils::Entities.entity('nbsp'), ::Kramdown::Utils::Entities.entity('raquo')], :laquo => [::Kramdown::Utils::Entities.entity('laquo')], :raquo => [::Kramdown::Utils::Entities.entity('raquo')] } def convert_typographic_sym(el, indent, opts) if (result = @options[:typographic_symbols][el.value]) escape_html(result, :text) else TYPOGRAPHIC_SYMS[el.value].map {|e| entity_to_str(e) }.join('') end end def convert_smart_quote(el, indent, opts) entity_to_str(smart_quote_entity(el)) end MATH_LATEX_FILENAME = File.expand_path '../../data/math.json', __FILE__ MATH_LATEX = JSON.parse(File.read(MATH_LATEX_FILENAME, encoding: Encoding::UTF_8)) MATH_REPLACEMENTS = MATH_LATEX["replacements"] MATH_COMBININGMARKS = MATH_LATEX["combiningmarks"] def munge_latex(s) MATH_REPLACEMENTS.each do |o, n| s.gsub!(o, n) end MATH_COMBININGMARKS.each do |m, n| re = /\\#{m[1..-1]}\{(\X)\}/ s.gsub!(re) { "#$1#{n}" } end s end # XXX: This is missing sup/sub support, which needs to be added def convert_math(el, indent, opts) # XXX: This is wrong el = el.deep_clone if el.options[:category] == :block el.attr['artwork-type'] ||= '' el.attr['artwork-type'] += (el.attr['artwork-type'].empty? ? '' : ' ') + 'math' artwork_attr = {} el.attr.each do |k, v| if md = k.match(/\Aartwork-(.*)/) el.attr.delete(k) artwork_attr[md[1]] = v end end result, err, _s = Open3.capture3("tex2mail -noindent -ragged -by_par -linelength=69", stdin_data: el.value); # warn "*** tex2mail not in path?" unless s.success? -- doesn't have useful status capture_croak("tex2mail", err) "#{' '*indent}\n" else type = 'spanx' if $options.v3 # could use utftex if present content = escape_html(munge_latex(el.value).chomp, :text) attrstring = el_html_attributes_with(el, {"style" => 'none'}) else warn "*** no support for inline math in XML2RFCv2" content = escape_html(el.value, :text) attrstring = el_html_attributes_with(el, {"style" => 'verb'}) end if attrstring == ' style="none"' content else "<#{type}#{attrstring}>#{content}" # this might get a style=none... end end end ITEM_RE = '\s*(?:"([^"]*)"|([^,]*?))\s*' IREF_RE = %r{\A(!\s*)?#{ITEM_RE}(?:,#{ITEM_RE})?\z} def iref_attr(s) md = s.match(IREF_RE) attr = { item: md[2] || md[3], subitem: md[4] || md[5], primary: md[1] && 'true', } "" end def nobr_hack(s) # replace this by actual once that exists # https://github.com/ietf-tools/xml2rfc/blob/main/xml2rfc/utils.py#L42 s.gsub(/([-\s\/])(?!\s)/) { case rep = $1 when /\A\s\z/ "\u00A0" # nbsp when "-" "\u2011" # nbhy -- XXX this might mangle dashes else "#{rep}\u2060" end } end def convert_iref(el, indent, opts) iref_attr(el.attr['target']) end def convert_abbreviation(el, indent, opts) # XXX: This is wrong if opts[:noabbrev] return el.value end value = el.value ix = value.gsub(/[\s\p{Z}]+/, " ") title = @root.options[:abbrev_defs][ix] if title.nil? warn "*** abbrev mismatch: value = #{value.inspect} ix = #{ix.inspect}" else title = nil if title.empty? end if title == "" && $options.v3 return "#{value}" end hacked_value = value nobr = false if title && title =~ /\A(\z|\s)/ nobr = true _nobr, title = title.split(' ', 2) hacked_value = nobr_hack(value) if title.nil? || title.empty? return hacked_value # we have "exhausted" this abbrev -- suppress normal meaning end end if title && title[0] == "#" target, title = title.split(' ', 2) if target == "#" target = value else target = target[1..-1] end else target = nil end if item = title pairs = title.split(Parser::RFC2629Kramdown::IREF_START).each_slice(2).to_a replacement = pairs.map {|x,| s = x.strip; s unless s.empty?}.compact.join(" ") irefs = pairs.map {|_,x| x && [x]}.compact warn "@@@ ABBREV MISMATCH #{irefs}" if title.scan(Parser::RFC2629Kramdown::IREF_START) != irefs if irefs.empty? subitem = value else iref = irefs.map{|a,| iref_attr(a)}.join('') end unless replacement.empty? replacement = nobr_hack(replacement) if nobr # XXX this can break XML replacement = ::Kramdown::Converter::Rfc2629::process_markdown(replacement) hacked_value = replacement end else item = value end iref ||= "" if target "#{iref}#{hacked_value}" else "#{iref}#{hacked_value}" end end def convert_root(el, indent, opts) result = inner(el, indent, opts) end end end end kramdown-rfc2629-1.7.31/LICENSE0000644000004100000410000000206715142163665015573 0ustar www-datawww-dataCopyright (c) 2010-2015 Carsten Bormann Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. kramdown-rfc2629-1.7.31/README.md0000644000004100000410000006000015142163665016034 0ustar www-datawww-data# kramdown-rfc [kramdown][] is a [markdown][] parser by Thomas Leitner, which has a number of backends for generating HTML, Latex, and markdown again. **kramdown-rfc** is an additional backend to that: It allows the generation of [XML2RFC][] XML markup (originally known as [RFC 2629][] compliant markup, with a newer version documented in [RFC 7749][]; version 3 now documented in [RFC 7991][] etc. and [v3][]). Who would care? Anybody who is writing Internet-Drafts and RFCs in the [IETF][] and prefers (or has co-authors who prefer) to do part of their work in markdown. kramdown-rfc is documented on this page, and also on [the wiki][]. [the wiki]: https://github.com/cabo/kramdown-rfc/wiki # Usage Start by installing the kramdown-rfc gem (this automatically installs appropriate versions of referenced gems such as kramdown as well): gem install kramdown-rfc (Add a `sudo` and a space in front of that command if you don't have all the permissions needed.) The guts of kramdown-rfc are in one Ruby file, `lib/kramdown-rfc2629.rb` --- this melds nicely into the extension structure provided by kramdown. `bin/kramdown-rfc` started out as a simple command-line program showing how to use this, but can now do much more (see below). To use kramdown-rfc, you'll need Ruby (at least version 2.3, but preferably a current version), and maybe [XML2RFC][] if you want to see the fruits of your work. kramdown-rfc mydraft.md >mydraft.xml xml2rfc mydraft.xml (The most popular file name extension that IETF people have for markdown is .md -- for those who tend to think about GNU machine descriptions here, any extension such as .mkd will do, too.) A more brief interface for both calling kramdown-rfc and XML2RFC is provided by `kdrfc`: kdrfc mydraft.md `kdrfc` can also use a remote installation of XML2RFC if needed: kdrfc -r mydraft.md # Versions of RFCXML Since RFC 8650, RFCs are using an updated grammar as defined in RFC 7991 to 7998 and further updated informally since, colloquially called "[v3][]". As RFC 2629 is no longer the governing standard, what was called kramdown-rfc2629 is now called kramdown-rfc. The latter command defaults to v3 processing rules; from 2022-02-22T22:02:22 on, the old kramdown-rfc2629 driver program does as well (1.6.1). (-3/--v3 and -2/--v2 select v3 and v2 explicitly; the latter should only be needed if there is a reason to to make a document look like it's 2016.) See also [v3 announcement mail][]. [v3 announcement mail]: https://mailarchive.ietf.org/arch/msg/rfc-markdown/JC__LDDGuUbSFqyaEntF9r4kwKw # Examples For historical interest `stupid.mkd` was an early markdown version of an actual Internet-Draft (for a protocol called [STuPiD][] \[sic!]). This demonstrated some, but not all features of kramdown-rfc. Since markdown/kramdown does not cater for all the structure of an RFC 7991 style document, some of the markup is in XML, and the example switches between XML and markdown using kramdown's `{::nomarkdown}` and `{:/nomarkdown}` (this is ugly, but works well enough). `stupid.xml` and `stupid.txt` show what kramdown-rfc and xml2rfc make out of this. `stupid-s.mkd` is the same document in the new sectionized format supported by kramdown-rfc. The document metadata are in a short piece of YAML at the start, and from there, `abstract`, `middle`, references (`normative` and `informative`) and `back` are sections delimited in the markdown file. See the example for how this works. The sections `normative` and `informative` can be populated right from the metadata, so there is never a need to write XML any more. Much less scary, and no `{:/nomarkdown}` etc. is needed any more. Similarly, `stupid-s.xml` and `stupid-s.txt` show what kramdown-rfc and xml2rfc make out of this. `draft-ietf-core-block-xx.mkd` is a real-world example of a current Internet-Draft done this way. For RFC and Internet-Draft references, it uses document prolog entities instead of caching the references in the XML (i.e., not standalone mode, this is easier to handle when collaborating with XML-only co-authors). See the `bibxml` metadata. # The YAML header Please consult the examples for the structure of the YAML header, this should be mostly obvious. The `stand_alone` attribute controls whether the RFC/I-D references are inserted into the document (yes) or entity-referenced (no), the latter leads to increased build time, but may be more palatable for a final XML conversion. The author entry can be a single hash or a list, as in: author: ins: C. Bormann name: Carsten Bormann org: Universität Bremen TZI abbrev: TZI street: Bibliothekstr. 1 city: Bremen code: D-28359 country: Germany phone: +49-421-218-63921 email: cabo@tzi.org or author: - ins: C. Bormann name: Carsten Bormann org: Universität Bremen TZI email: cabo@tzi.org - ins: Z. Shelby name: Zach Shelby org: Sensinode role: editor street: Kidekuja 2 city: Vuokatti code: 88600 country: Finland phone: "+358407796297" email: zach@sensinode.com - role: editor ins: P. Thubert name: Pascal Thubert org: Cisco Systems abbrev: Cisco street: - Village d'Entreprises Green Side - 400, Avenue de Roumanille - Batiment T3 city: Biot - Sophia Antipolis code: '06410' country: FRANCE phone: "+33 4 97 23 26 34" email: pthubert@cisco.com (the hash keys are the XML GIs from RFC 7749, with a flattened structure. As RFC 7749 requires giving both the full name and surname/initials, we use `ins` as an abbreviation for "initials/surname". Yes, the toolchain is Unicode-capable, even if the final RFC output is still in ASCII.) Note that the YAML header needs to be syntactically valid YAML. Where there is a potential for triggering some further YAML feature, a string should be put in quotes (like the "+358407796297" above, which might otherwise be interpreted as a number, losing the + sign). ## References The references section is built from the references listed in the YAML header and from references made inline to RFCs and I-Ds in the markdown text. Since kramdown-rfc cannot know whether a reference is normative or informative, no entry is generated by default in the references section. By indicating a normative reference as in `{{!RFC2119}}` or an informative one as in `{{?RFC1925}}`, you can completely automate the referencing, without the need to write anything in the header. Alternatively, you can write something like: informative: RFC1925: normative: RFC2119: and then just write `{{RFC2119}}` or `{{RFC1925}}`. (Yes, there is a colon in the YAML, because this is a hash that could provide other information.) Since version 1.1, references imported from the [BibXML][] databases can be supplied with a replacement label (anchor name). E.g., RFC 793 could be referenced as `{{!TCP=RFC0793}}`, further references then just can say `{{TCP}}`; both will get `[TCP]` as the label. In the YAML, the same replacement can be expressed as in the first example: normative: TCP: RFC0793 informative: SST: DOI.10.1145/1282427.1282421 Notes about this feature: * Thank you, Martin Thomson, for supplying an implementation and insisting this be done. * While this feature is now available, you are not forced to use it for everything: readers of documents often benefit from not having to look up references, so continuing to use the draft names and RFC numbers as labels may be the preferable style in many cases. * As a final caveat, renaming anchors does not work in the `stand_alone: no` mode (except for IANA and DOI), as there is no such mechanism in XML entity referencing; exporting to XML while maintaining live references then may require some manual editing to get rid of the custom anchors. If your references are not in the [BibXML][] databases and do not have a DOI (that also happens to have correct data) either, you need to spell it out like in the examples below: informative: RFC1925: WEI: title: "6LoWPAN: the Wireless Embedded Internet" # see the quotes above? Needed because of the embedded colon. author: - ins: Z. Shelby name: Zach Shelby - ins: C. Bormann name: Carsten Bormann date: 2009 seriesinfo: ISBN: 9780470747995 ann: This is a really good reference on 6LoWPAN. ASN.1: title: > Information Technology — ASN.1 encoding rules: Specification of Basic Encoding Rules (BER), Canonical Encoding Rules (CER) and Distinguished Encoding Rules (DER) # YAML's ">" syntax used above is a good way to write longer titles author: org: International Telecommunications Union date: 1994 seriesinfo: ITU-T: Recommendation X.690 REST: target: http://www.ics.uci.edu/~fielding/pubs/dissertation/fielding_dissertation.pdf title: Architectural Styles and the Design of Network-based Software Architectures author: ins: R. Fielding name: Roy Thomas Fielding org: University of California, Irvine date: 2000 seriesinfo: "Ph.D.": "Dissertation, University of California, Irvine" format: PDF: http://www.ics.uci.edu/~fielding/pubs/dissertation/fielding_dissertation.pdf COAP: title: "CoAP: An Application Protocol for Billions of Tiny Internet Nodes" seriesinfo: DOI: 10.1109/MIC.2012.29 date: 2012 author: - ins: C. Bormann name: Carsten Bormann - ins: A. P. Castellani name: Angelo P. Castellani - ins: Z. Shelby name: Zach Shelby IPSO: title: IP for Smart Objects (IPSO) author: - org: date: false seriesinfo: Web: http://ipso-alliance.github.io/pub/ normative: ECMA262: author: org: European Computer Manufacturers Association title: ECMAScript Language Specification 5.1 Edition date: 2011-06 target: http://www.ecma-international.org/publications/files/ecma-st/ECMA-262.pdf seriesinfo: ECMA: Standard ECMA-262 RFC2119: RFC6690: (as in the author list, `ins` is an abbreviation for "initials/surname"; note that the first title had to be put in double quotes as it contains a colon which is special syntax in YAML.) Then you can simply reference `{{ASN.1}}` and `{{ECMA262}}` in the text. (Make sure the reference keys are valid XML names, though.) # Experimental features Most of the [kramdown syntax][kdsyntax] is supported and does something useful; with the exception of the math syntax (math has no special support in XML2RFC), and HTML syntax of course. A number of more esoteric features have recently been added. (The minimum required version for each full feature is indicated.) (1.3.x) Slowly improving support for SVG generating tools for XML2RFCv3 (i.e., with `-3` flag). These tools must be installed and callable from the command line. The basic idea is to mark an input code block with one of the following labels (language types), yielding some plaintext form in the .TXT output and a graphical form in the .HTML output. The plaintext is the input in some cases (e.g., ASCII art, `mscgen`), or some plaintext output generated by the tool (e.g., `plantuml-utxt`). Currently supported labels as of 1.3.9: * [goat][], [ditaa][]: ASCII (plaintext) art to figure conversion * [mscgen][]: Message Sequence Charts * [plantuml][]: widely used multi-purpose diagram generator * plantuml-utxt: Like plantuml, except that a plantuml-generated plaintext form is used * [mermaid][]: Very experimental; the conversion to SVG is prone to generate black-on-black text in this version * math: display math using [tex2svg][] for HTML/PDF and [utftex][] for plaintext [goat]: https://github.com/blampe/goat [ditaa]: https://github.com/stathissideris/ditaa [mscgen]: http://www.mcternan.me.uk/mscgen/ [plantuml]: https://plantuml.com [mermaid]: https://github.com/mermaid-js/mermaid-cli [tex2svg]: https://github.com/mathjax/MathJax-demos-node/blob/master/direct/tex2svg [utftex]: https://github.com/bartp5/libtexprintf Note that this feature does not play well with the CI (continuous integration) support in Martin Thomson's [I-D Template][], as that may not have the tools installed in its docker instance. More details have been collected on the [wiki][svg]. [svg]: https://github.com/cabo/kramdown-rfc/wiki/SVG (1.2.9:) The YAML header now allows specifying [kramdown_options][]. [kramdown_options]: https://kramdown.gettalong.org/options.html This was added specifically to provide easier access to the kramdown `auto_id_prefix` feature, which prefixes by some distinguishing string the anchors that are auto-generated for sections, avoiding conflicts: ```yaml kramdown_options: auto_id_prefix: sec- ``` (1.2.8:) An experimental feature was added to include [BCP 14] boilerplate: ```markdown {::boilerplate bcp14} ``` which saves some typing. Saying "bcp14+" instead of "bcp14" adds some random clarifications at the end of the [standard boilerplate text][] that you may or may not want to have. (Do we need other boilerplate items beyond BCP14?) [BCP 14]: https://www.rfc-editor.org/info/bcp14 [standard boilerplate text]: https://tools.ietf.org/html/rfc8174#page-3 (1.0.35:) An experimental command `doilit` has been added. It can be used to convert DOIs given on the command line into references entries for kramdown-rfc YAML, saving a lot of typing. Note that the DOI database is not of very consistent quality, so you likely have to hand-edit the result before including it into the document (use `-v` to see raw JSON data from the DOI database, made somewhat readable by converting it into YAML). Use `-c` to enable caching (requires `open-uri-cached` gem). Use `-h=handle` in front of a DOI to set a handle different from the default `a`, `b`, etc. Similarly, use `-x=handle` to generate XML2RFCv2 XML instead of kramdown-rfc YAML. (1.0.31:) The kramdown `smart_quotes` feature can be controlled better. By default, it is on (with default kramdown settings), unless `coding: us-ascii` is in effect (1.3.14: or --v3 is given), in which case it is off by default. It also can be explicitly set on (`true`) or off (`false`) in the YAML header, or to a specific value (an array of four kramdown entity names or character numbers). E.g., for a German text (that is not intended to become an Internet-Draft), one might write: ```yaml smart_quotes: [sbquo, lsquo, bdquo, ldquo] pi: topblock: no private: yes ``` (1.0.30:) kramdown-rfc now uses kramdown 1.10, which leads to two notable updates: * Support for empty link texts in the standard markdown reference syntax, as in `[](#RFC7744)`. * Language names in fenced code blocks now support all characters except whitespace, so you can go wild with `asn.1` and `C#`. A heuristic generates missing initials/surname from the `name` entry in author information. This should save a lot of redundant typing. You'll need to continue using the `ins` entry as well if that heuristic fails (e.g., for Spanish names). Also, there is some rather experimental support for markdown display math (blocks between `$$` pairs) if the `tex2mail` tool is available. (1.0.23:) Move up to kramdown 1.6.0. This inherits a number of fixes and one nice feature: Markdown footnote definitions that turn into `cref`s can have their attributes in the footnote definition: ```markdown {:cabo: source="cabo"} (This section to be removed by the RFC editor.)[^1] [^1]: here is my editorial comment: warble warble. {:cabo} Another questionable paragraph.[^2] [^2]: so why not delete it? {: source="observer"} ``` (1.0.23:) As before, IAL attributes on a codeblock go to the figure element. Language attributes on the code block now become the artwork type, and any attribute with a name that starts "artwork-" is moved over to the artwork. So this snippet now does the obvious things: ```markdown ~~~ abnf a = b / %s"foo" / %x0D.0A ~~~ {: artwork-align="center" artwork-name="syntax"} ``` (1.0.22:) Index entries can be created with `(((item)))` or `(((item, subitem)))`; use quotes for weird entries: `(((",", comma)))`. If the index entry is to be marked "primary", prefix an (unquoted) `!` as in `(((!item)))`. In addition, auto-indexing is supported by hijacking the kramdown "abbrev" syntax: *[IANA]: *[MUST]: BCP14 *[CBOR]: (((Object Representation, Concise Binary))) (((CBOR))) The word in square brackets (which must match exactly, case-sensitively) is entered into the index automatically for each place where it occurs. If no title is given, just the word is entered (first example). If one is given, that becomes the main item (the auto-indexed word becomes the subitem, second example). If full control is desired (e.g., for multiple entries per occurrence), just write down the full index entries instead (third example). (1.0.20:) As an alternative referencing syntax for references with text, `{{ref}}` can be expressed as `[text](#ref)`. As a special case, a simple `[ref]` is interpreted as `[](#ref)` (except that the latter syntax is not actually allowed by kramdown). This syntax does not allow for automatic entry of items as normative/informative. (1.0.16:) Markdown footnotes are converted into `cref`s (XML2RFC formal comments; note that these are only visible if the pi "comments" is set to yes). The anchor is taken from the markdown footnote name. The source, if needed, can be supplied by an [IAL][], as in (first example also uses an [ALD][]): ```markdown {:cabo: source="cabo"} (This section to be removed by the RFC editor.)[^1]{:cabo} [^1]: here is my editorial comment Another questionable paragraph.[^2]{: source="observer"} [^2]: so why not delete it ``` Note that XML2RFC v2 doesn't allow structure in crefs. If you put any, you get the escaped verbatim XML... (1.0.11:) Allow overriding "style" attribute (via IAL = [inline attribute list][IAL]) in lists and spans as in: ```markdown {:req: counter="bar" style="format R(%d)"} {: req} * Foo * Bar * Bax Text outside the list, so a new IAL is needed. * Foof * Barf * Barx {: req} ``` (1.0.5:) An IAL attribute "cols" can be added to tables to override the column layout. For example, `cols="* 20 30c r"` sets the width attributes to 20 and 30 for the middle columns and sets the right two columns to center and right alignment, respectively. The alignment from `cols` overrides that from the kramdown table, if present. (1.0.2:) An IAL attribute "vspace" can be added to a definition list to break after the definition term: ```markdown {: vspace="0"} word: : definition anotherword: : another definition ``` (0.x:) Files can be included with the syntax `{::include fn}` (needs to be in column 1 since 1.0.22; can be suppressed for use in servers by setting environment variable KRAMDOWN_SAFE since 1.0.22). A typical example from a recent RFC, where the contents of a figure was machine-generated: ```markdown ~~~~~~~~~~ {::include ../ghc/packets-new/p4.out} ~~~~~~~~~~ {: #example2 title="A longer RPL example"} ``` (0.x:) A page break can be forced by adding a horizontal rule (`----`, note that this creates ugly blank space in some HTML converters). # Risks and Side-Effects The code is not very polished, but now quite stable; it has been successfully used for hundreds of non-trivial Internet-Drafts and RFCs. You probably still need to skim [v3][] if you want to write an Internet-Draft, but you don't really need to understand XML very much. Knowing the basics of YAML helps with the metadata (but you'll understand it from the examples). Occasionally, you do need to reach through to the XML arcana, e.g. by setting attribute values using kramdown's ["IAL" syntax][IAL]. This can for instance be used to obtain unnumbered appendices: ```markdown Acknowledgements ================ {: numbered="false"} John Mattsson was nice enough to point out the need for this being documented. ``` Note that this specific example is covered by a predefined kramdown-rfc ["attribute list definition" (ALD)][ALD]: ```markdown {:unnumbered: numbered="false"} ``` so the conventional way to write this example would be the somewhat simpler: ```markdown Acknowledgements ================ {:unnumbered} John Mattsson was nice enough to point out the need for this being documented. ``` # Upconversion If you have an old RFC and want to convert it to markdown, try just using that RFC, it is 80 % there. It may be possible to automate the remaining 20 % some more, but that hasn't been done. If you have XML, there is an experimental upconverter that does 99 % of the work. Please [contact the author](mailto:cabo@tzi.org?subject=Markdown%20for%20RFCXML) if you want to try it. Actually, if the XML was generated by kramdown-rfc, you can simply extract the input markdown from that XML file (but will of course lose any edits that have been made to the XML file after generation): kramdown-rfc-extract-markdown myfile.xml >myfile.md # Tools Joe Hildebrand has a [grunt][] plugin for kramdown-rfc at: https://github.com/hildjj/grunt-kramdown-rfc2629 . Get started with it at: https://github.com/hildjj/grunt-init-rfc . This provides a self-refreshing web page with the kramdown-rfc/xml2rfc rendition of the draft you are editing. [grunt]: http://gruntjs.com Martin Thomson has an [I-D Template][] for github repositories that enable collaboration on draft development. This supports kramdown-rfc out of the box. Just name your draft like `draft-ietf-unicorn-protocol.md` and follow the installation instructions. [I-D Template]: https://github.com/martinthomson/i-d-template # Related Work Moving from XML to Markdown for RFC writing apparently is a no-brainer, so I'm not the only one who has written code for this. [Miek Gieben][] has done a [similar thing][pandoc2rfc] employing pandoc, now documented in [RFC 7328][]. He uses multiple input files instead of kramdown-rfc's sectionized input format. He keeps the metadata in a separate XML file, similar to the way the previous version of kramdown-rfc stored (and still can store) the metadata in XML in the markdown document. He also uses a slightly different referencing syntax, which is closer to what markdown does elsewhere but more verbose (this syntax is now also supported in kramdown-rfc). (Miek now also has a new thing going on with mostly different syntax, see [mmark][] and its [github repository][mmark-git].) Other human-oriented markup input languages that are being used for authoring RFCXML include: * [asciidoc][], with the [asciidoctor-rfc][] tool, as documented in [draft-ribose-asciirfc][]. * [orgmode][] (please help supply a more specific link here). # License Since kramdown version 1.0, kramdown itself is MIT licensed, which made it possible to license kramdown-rfc under the same license. [kramdown]: https://kramdown.gettalong.org [kdsyntax]: http://kramdown.gettalong.org/syntax.html [IAL]: https://kramdown.gettalong.org/syntax.html#inline-attribute-lists [ALD]: https://kramdown.gettalong.org/syntax.html#attribute-list-definitions [stupid]: http://tools.ietf.org/id/draft-hartke-xmpp-stupid-00 [RFC 2629]: https://www.rfc-editor.org/rfc/rfc2629.html [RFC 7749]: https://www.rfc-editor.org/rfc/rfc7749.html [RFC 7991]: https://www.rfc-editor.org/rfc/rfc7991.html [v3]: https://authors.ietf.org/rfcxml-vocabulary [markdown]: http://en.wikipedia.org/wiki/Markdown [IETF]: http://www.ietf.org [Miek Gieben]: http://www.miek.nl/ [pandoc2rfc]: https://github.com/miekg/pandoc2rfc/ [XML2RFC]: https://github.com/ietf-tools/xml2rfc [RFC 7328]: http://tools.ietf.org/html/rfc7328 [mmark-git]: https://github.com/miekg/mmark [mmark]: https://mmark.nl [YAML]: http://www.yaml.org/spec/1.2/spec.html [draft-ribose-asciirfc]: https://tools.ietf.org/html/draft-ribose-asciirfc [asciidoctor-rfc]: https://github.com/metanorma/asciidoctor-rfc [asciidoc]: http://www.methods.co.nz/asciidoc/ [orgmode]: http://orgmode.org [BibXML]: https://bib.ietf.org/