lexxy 0.9.29 → 0.9.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3c6392cdd1a3fd5cc9535778cb84e544b5864e6d75378af4e19b6d7c6c0a5628
4
- data.tar.gz: 88bccc783d7e3de2f7650e2d80ad7899369053182de3fbe4b51c50f7566421fc
3
+ metadata.gz: 29ffce96e1428f47448c9dd8dba203d14209fed8614c09319de418275e7d7c4b
4
+ data.tar.gz: 54b507d1fa6cbbb69e0c34ae60fe9d2ffca21b3f9a9312cb11d690c9a46bd39d
5
5
  SHA512:
6
- metadata.gz: 0aa7bf890d287539720cb79cd58cee9e32833c26ed4bd0d6418ab7f94c0bed4fee739a14299093a3333e8337d23a0d4cd00fe1524defefa8f14842ceb0b278a9
7
- data.tar.gz: c0dfc34fee283b34b76281b77b9dd24a57fcd7ef8d488e70628107fb1aa7a537c8811986e1a5f77d5df2573e6d040214a62f037c5f3845de136f44b813f2e71c
6
+ metadata.gz: a018d5b7719927ffa23b3dd7f83487c1988899b32cb14178415e460358bc86e908a583ec8e064f9692b0deee3f2a7c57f85c0f2dcf761b01653783749ab2c498
7
+ data.tar.gz: d9c7cf6b9653ec1938009ad6c6b6d341dbe6fa79a202432ea3b49090f30d054cf29ec6b580fdb31228868f55fe1b114a1e746dc2a806531cba84bc6fc070a636
@@ -6479,6 +6479,22 @@ function styleFilterHook(_currentNode, hookEvent) {
6479
6479
 
6480
6480
  purify.addHook("uponSanitizeAttribute", styleFilterHook);
6481
6481
 
6482
+ const FORBIDDEN_STIMULUS_ATTRIBUTES = [ "data-controller", "data-action" ];
6483
+
6484
+ // Stimulus behavior attributes must never survive sanitization, whatever an
6485
+ // extension's allowedElements declares. FORBID_ATTR alone isn't enough: in
6486
+ // DOMPurify 3.x the functional ADD_ATTR — which Lexxy builds from the public
6487
+ // allowedElements API — is evaluated ahead of FORBID_ATTR, so an extension that
6488
+ // listed one of these on a tag would otherwise reinstate it. This hook drops
6489
+ // them unconditionally, keeping the class-level prohibition config-independent.
6490
+ function stimulusAttributeFilterHook(_currentNode, hookEvent) {
6491
+ if (FORBIDDEN_STIMULUS_ATTRIBUTES.includes(hookEvent.attrName)) {
6492
+ hookEvent.keepAttr = false;
6493
+ }
6494
+ }
6495
+
6496
+ purify.addHook("uponSanitizeAttribute", stimulusAttributeFilterHook);
6497
+
6482
6498
  purify.addHook("uponSanitizeElement", (node, data) => {
6483
6499
  if (data.tagName === "strong" || data.tagName === "em") {
6484
6500
  node.removeAttribute("class");
@@ -6502,7 +6518,12 @@ function buildConfig(allowedElements ) {
6502
6518
  ALLOWED_ATTR: ALLOWED_HTML_ATTRIBUTES,
6503
6519
  ADD_ATTR: (attribute, tag) => tagAttributes[tag]?.includes(attribute),
6504
6520
  ADD_URI_SAFE_ATTR: [ "caption", "filename" ],
6505
- SAFE_FOR_XML: false // So that it does not strip attributes that contains serialized HTML (like content)
6521
+ SAFE_FOR_XML: false, // So that it does not strip attributes that contains serialized HTML (like content)
6522
+ // Stimulus behavior attributes must never survive sanitization: they let stored content
6523
+ // wire up arbitrary controllers/actions in the viewer's session. FORBID_ATTR wins over
6524
+ // ALLOWED_ATTR/ADD_ATTR/ALLOW_DATA_ATTR in DOMPurify, so this holds even though other
6525
+ // data-* attributes (data-language, data-trix-*, etc.) are otherwise allowed through.
6526
+ FORBID_ATTR: [ "data-controller", "data-action" ]
6506
6527
  }
6507
6528
  }
6508
6529
 
@@ -12910,7 +12931,7 @@ class Contents {
12910
12931
  insertText(text, { tag } = {}) {
12911
12932
  this.editor.update(() => {
12912
12933
  const paragraph = eo();
12913
- text.split("\n").forEach((line, index) => {
12934
+ text.split(/\r\n|\r|\n/).forEach((line, index) => {
12914
12935
  if (index > 0) paragraph.append(or());
12915
12936
  paragraph.append(kr(line));
12916
12937
  });
@@ -13624,6 +13645,12 @@ ${e}</tr>
13624
13645
  `+this.renderer.text(o);t?n+=this.renderer.paragraph({type:"paragraph",raw:a,text:a,tokens:[{type:"text",raw:a,text:a,escaped:true}]}):n+=a;continue}default:{let o='Token with "'+s.type+'" type was not found.';if(this.options.silent)return console.error(o),"";throw new Error(o)}}}return n}parseInline(e,t=this.renderer){let n="";for(let r=0;r<e.length;r++){let i=e[r];if(this.options.extensions?.renderers?.[i.type]){let o=this.options.extensions.renderers[i.type].call({parser:this},i);if(o!==false||!["escape","html","link","image","strong","em","codespan","br","del","text"].includes(i.type)){n+=o||"";continue}}let s=i;switch(s.type){case "escape":{n+=t.text(s);break}case "html":{n+=t.html(s);break}case "link":{n+=t.link(s);break}case "image":{n+=t.image(s);break}case "strong":{n+=t.strong(s);break}case "em":{n+=t.em(s);break}case "codespan":{n+=t.codespan(s);break}case "br":{n+=t.br(s);break}case "del":{n+=t.del(s);break}case "text":{n+=t.text(s);break}default:{let o='Token with "'+s.type+'" type was not found.';if(this.options.silent)return console.error(o),"";throw new Error(o)}}}return n}};var S=class{options;block;constructor(e){this.options=e||T;}static passThroughHooks=new Set(["preprocess","postprocess","processAllTokens","emStrongMask"]);static passThroughHooksRespectAsync=new Set(["preprocess","postprocess","processAllTokens"]);preprocess(e){return e}postprocess(e){return e}processAllTokens(e){return e}emStrongMask(e){return e}provideLexer(){return this.block?x.lex:x.lexInline}provideParser(){return this.block?b.parse:b.parseInline}};var B=class{defaults=L();options=this.setOptions;parse=this.parseMarkdown(true);parseInline=this.parseMarkdown(false);Parser=b;Renderer=P;TextRenderer=$;Lexer=x;Tokenizer=y;Hooks=S;constructor(...e){this.use(...e);}walkTokens(e,t){let n=[];for(let r of e)switch(n=n.concat(t.call(this,r)),r.type){case "table":{let i=r;for(let s of i.header)n=n.concat(this.walkTokens(s.tokens,t));for(let s of i.rows)for(let o of s)n=n.concat(this.walkTokens(o.tokens,t));break}case "list":{let i=r;n=n.concat(this.walkTokens(i.items,t));break}default:{let i=r;this.defaults.extensions?.childTokens?.[i.type]?this.defaults.extensions.childTokens[i.type].forEach(s=>{let o=i[s].flat(1/0);n=n.concat(this.walkTokens(o,t));}):i.tokens&&(n=n.concat(this.walkTokens(i.tokens,t)));}}return n}use(...e){let t=this.defaults.extensions||{renderers:{},childTokens:{}};return e.forEach(n=>{let r={...n};if(r.async=this.defaults.async||r.async||false,n.extensions&&(n.extensions.forEach(i=>{if(!i.name)throw new Error("extension name required");if("renderer"in i){let s=t.renderers[i.name];s?t.renderers[i.name]=function(...o){let a=i.renderer.apply(this,o);return a===false&&(a=s.apply(this,o)),a}:t.renderers[i.name]=i.renderer;}if("tokenizer"in i){if(!i.level||i.level!=="block"&&i.level!=="inline")throw new Error("extension level must be 'block' or 'inline'");let s=t[i.level];s?s.unshift(i.tokenizer):t[i.level]=[i.tokenizer],i.start&&(i.level==="block"?t.startBlock?t.startBlock.push(i.start):t.startBlock=[i.start]:i.level==="inline"&&(t.startInline?t.startInline.push(i.start):t.startInline=[i.start]));}"childTokens"in i&&i.childTokens&&(t.childTokens[i.name]=i.childTokens);}),r.extensions=t),n.renderer){let i=this.defaults.renderer||new P(this.defaults);for(let s in n.renderer){if(!(s in i))throw new Error(`renderer '${s}' does not exist`);if(["options","parser"].includes(s))continue;let o=s,a=n.renderer[o],l=i[o];i[o]=(...c)=>{let p=a.apply(i,c);return p===false&&(p=l.apply(i,c)),p||""};}r.renderer=i;}if(n.tokenizer){let i=this.defaults.tokenizer||new y(this.defaults);for(let s in n.tokenizer){if(!(s in i))throw new Error(`tokenizer '${s}' does not exist`);if(["options","rules","lexer"].includes(s))continue;let o=s,a=n.tokenizer[o],l=i[o];i[o]=(...c)=>{let p=a.apply(i,c);return p===false&&(p=l.apply(i,c)),p};}r.tokenizer=i;}if(n.hooks){let i=this.defaults.hooks||new S;for(let s in n.hooks){if(!(s in i))throw new Error(`hook '${s}' does not exist`);if(["options","block"].includes(s))continue;let o=s,a=n.hooks[o],l=i[o];S.passThroughHooks.has(s)?i[o]=c=>{if(this.defaults.async&&S.passThroughHooksRespectAsync.has(s))return (async()=>{let g=await a.call(i,c);return l.call(i,g)})();let p=a.call(i,c);return l.call(i,p)}:i[o]=(...c)=>{if(this.defaults.async)return (async()=>{let g=await a.apply(i,c);return g===false&&(g=await l.apply(i,c)),g})();let p=a.apply(i,c);return p===false&&(p=l.apply(i,c)),p};}r.hooks=i;}if(n.walkTokens){let i=this.defaults.walkTokens,s=n.walkTokens;r.walkTokens=function(o){let a=[];return a.push(s.call(this,o)),i&&(a=a.concat(i.call(this,o))),a};}this.defaults={...this.defaults,...r};}),this}setOptions(e){return this.defaults={...this.defaults,...e},this}lexer(e,t){return x.lex(e,t??this.defaults)}parser(e,t){return b.parse(e,t??this.defaults)}parseMarkdown(e){return (n,r)=>{let i={...r},s={...this.defaults,...i},o=this.onError(!!s.silent,!!s.async);if(this.defaults.async===true&&i.async===false)return o(new Error("marked(): The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise."));if(typeof n>"u"||n===null)return o(new Error("marked(): input parameter is undefined or null"));if(typeof n!="string")return o(new Error("marked(): input parameter is of type "+Object.prototype.toString.call(n)+", string expected"));if(s.hooks&&(s.hooks.options=s,s.hooks.block=e),s.async)return (async()=>{let a=s.hooks?await s.hooks.preprocess(n):n,c=await(s.hooks?await s.hooks.provideLexer():e?x.lex:x.lexInline)(a,s),p=s.hooks?await s.hooks.processAllTokens(c):c;s.walkTokens&&await Promise.all(this.walkTokens(p,s.walkTokens));let d=await(s.hooks?await s.hooks.provideParser():e?b.parse:b.parseInline)(p,s);return s.hooks?await s.hooks.postprocess(d):d})().catch(o);try{s.hooks&&(n=s.hooks.preprocess(n));let l=(s.hooks?s.hooks.provideLexer():e?x.lex:x.lexInline)(n,s);s.hooks&&(l=s.hooks.processAllTokens(l)),s.walkTokens&&this.walkTokens(l,s.walkTokens);let p=(s.hooks?s.hooks.provideParser():e?b.parse:b.parseInline)(l,s);return s.hooks&&(p=s.hooks.postprocess(p)),p}catch(a){return o(a)}}}onError(e,t){return n=>{if(n.message+=`
13625
13646
  Please report this to https://github.com/markedjs/marked.`,e){let r="<p>An error occurred:</p><pre>"+w(n.message+"",true)+"</pre>";return t?Promise.resolve(r):r}if(t)return Promise.reject(n);throw n}}};var _=new B;function k(u,e){return _.parse(u,e)}k.options=k.setOptions=function(u){return _.setOptions(u),k.defaults=_.defaults,G(k.defaults),k};k.getDefaults=L;k.defaults=T;k.use=function(...u){return _.use(...u),k.defaults=_.defaults,G(k.defaults),k};k.walkTokens=function(u,e){return _.walkTokens(u,e)};k.parseInline=_.parseInline;k.Parser=b;k.parser=b.parse;k.Renderer=P;k.TextRenderer=$;k.Lexer=x;k.lexer=x.lex;k.Tokenizer=y;k.Hooks=S;k.parse=k;k.options;k.setOptions;k.use;k.walkTokens;k.parseInline;b.parse;x.lex;
13626
13647
 
13648
+ // Markdown reads any line indented by a tab or four spaces as a code block. Pasted
13649
+ // plain text is full of incidental indentation — outlines, notes, logs — and nobody
13650
+ // indents a note meaning "this is code"; they fence it. Keep fences, drop the
13651
+ // indentation rule.
13652
+ const pastedMarkdown = new B({ breaks: true }).use({ tokenizer: { code: () => undefined } });
13653
+
13627
13654
  class Clipboard {
13628
13655
  #listeners = new ListenerBin()
13629
13656
 
@@ -13810,7 +13837,7 @@ class Clipboard {
13810
13837
  }
13811
13838
 
13812
13839
  #pasteMarkdown(text) {
13813
- const html = k(text, { breaks: true });
13840
+ const html = pastedMarkdown.parse(text);
13814
13841
  const doc = parseHtml(html);
13815
13842
 
13816
13843
  if (this.#isPlainTextWithoutMarkdown(doc)) {
Binary file
Binary file