difit 2.2.0 → 2.2.1
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.
- package/dist/client/assets/{index-BG6tLkMt.js → index-KydrgTN-.js} +49 -50
- package/dist/client/assets/{prism-csharp-B-CFRzGF.js → prism-csharp-R5PE7dGT.js} +1 -1
- package/dist/client/assets/{prism-java-IqkDgVxE.js → prism-java-BvQgUZlL.js} +1 -1
- package/dist/client/assets/{prism-php-COdrRzRl.js → prism-php-sGBBrTD-.js} +1 -1
- package/dist/client/assets/{prism-ruby-ig7xCRi-.js → prism-ruby-CBz5QFG3.js} +1 -1
- package/dist/client/assets/{prism-solidity-lkGQYrB_.js → prism-solidity-Ck6Q6Nkr.js} +1 -1
- package/dist/client/index.html +1 -1
- package/dist/server/schemas/commentSchema.d.ts +22 -0
- package/dist/server/schemas/commentSchema.js +16 -0
- package/dist/server/schemas/commentSchema.test.d.ts +1 -0
- package/dist/server/schemas/commentSchema.test.js +229 -0
- package/dist/server/server.js +1 -13
- package/dist/server/server.test.js +103 -0
- package/dist/utils/commentFormatter.d.ts +26 -0
- package/dist/utils/commentFormatter.js +50 -0
- package/dist/utils/commentFormatting.d.ts +4 -0
- package/dist/utils/commentFormatting.js +24 -0
- package/dist/utils/commentFormatting.test.d.ts +1 -0
- package/dist/utils/commentFormatting.test.js +220 -0
- package/package.json +2 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
import{g as U}from"./index-
|
|
1
|
+
import{g as U}from"./index-KydrgTN-.js";function W(r,t){for(var e=0;e<t.length;e++){const a=t[e];if(typeof a!="string"&&!Array.isArray(a)){for(const s in a)if(s!=="default"&&!(s in r)){const u=Object.getOwnPropertyDescriptor(a,s);u&&Object.defineProperty(r,s,u.get?u:{enumerable:!0,get:()=>a[s]})}}}return Object.freeze(Object.defineProperty(r,Symbol.toStringTag,{value:"Module"}))}var I={},O;function Z(){return O||(O=1,function(r){function t(n,l){return n.replace(/<<(\d+)>>/g,function(f,M){return"(?:"+l[+M]+")"})}function e(n,l,f){return RegExp(t(n,l),"")}function a(n,l){for(var f=0;f<l;f++)n=n.replace(/<<self>>/g,function(){return"(?:"+n+")"});return n.replace(/<<self>>/g,"[^\\s\\S]")}var s={type:"bool byte char decimal double dynamic float int long object sbyte short string uint ulong ushort var void",typeDeclaration:"class enum interface record struct",contextual:"add alias and ascending async await by descending from(?=\\s*(?:\\w|$)) get global group into init(?=\\s*;) join let nameof not notnull on or orderby partial remove select set unmanaged value when where with(?=\\s*{)",other:"abstract as base break case catch checked const continue default delegate do else event explicit extern finally fixed for foreach goto if implicit in internal is lock namespace new null operator out override params private protected public readonly ref return sealed sizeof stackalloc static switch this throw try typeof unchecked unsafe using virtual volatile while yield"};function u(n){return"\\b(?:"+n.trim().replace(/ /g,"|")+")\\b"}var v=u(s.typeDeclaration),d=RegExp(u(s.type+" "+s.typeDeclaration+" "+s.contextual+" "+s.other)),T=u(s.typeDeclaration+" "+s.contextual+" "+s.other),z=u(s.type+" "+s.typeDeclaration+" "+s.other),g=a(/<(?:[^<>;=+\-*/%&|^]|<<self>>)*>/.source,2),h=a(/\((?:[^()]|<<self>>)*\)/.source,2),i=/@?\b[A-Za-z_]\w*\b/.source,b=t(/<<0>>(?:\s*<<1>>)?/.source,[i,g]),c=t(/(?!<<0>>)<<1>>(?:\s*\.\s*<<1>>)*/.source,[T,b]),y=/\[\s*(?:,\s*)*\]/.source,A=t(/<<0>>(?:\s*(?:\?\s*)?<<1>>)*(?:\s*\?)?/.source,[c,y]),K=t(/[^,()<>[\];=+\-*/%&|^]|<<0>>|<<1>>|<<2>>/.source,[g,h,y]),q=t(/\(<<0>>+(?:,<<0>>+)+\)/.source,[K]),p=t(/(?:<<0>>|<<1>>)(?:\s*(?:\?\s*)?<<2>>)*(?:\s*\?)?/.source,[q,c,y]),o={keyword:d,punctuation:/[<>()?,.:[\]]/},k=/'(?:[^\r\n'\\]|\\.|\\[Uux][\da-fA-F]{1,8})'/.source,w=/"(?:\\.|[^\\"\r\n])*"/.source,F=/@"(?:""|\\[\s\S]|[^\\"])*"(?!")/.source;r.languages.csharp=r.languages.extend("clike",{string:[{pattern:e(/(^|[^$\\])<<0>>/.source,[F]),lookbehind:!0,greedy:!0},{pattern:e(/(^|[^@$\\])<<0>>/.source,[w]),lookbehind:!0,greedy:!0}],"class-name":[{pattern:e(/(\busing\s+static\s+)<<0>>(?=\s*;)/.source,[c]),lookbehind:!0,inside:o},{pattern:e(/(\busing\s+<<0>>\s*=\s*)<<1>>(?=\s*;)/.source,[i,p]),lookbehind:!0,inside:o},{pattern:e(/(\busing\s+)<<0>>(?=\s*=)/.source,[i]),lookbehind:!0},{pattern:e(/(\b<<0>>\s+)<<1>>/.source,[v,b]),lookbehind:!0,inside:o},{pattern:e(/(\bcatch\s*\(\s*)<<0>>/.source,[c]),lookbehind:!0,inside:o},{pattern:e(/(\bwhere\s+)<<0>>/.source,[i]),lookbehind:!0},{pattern:e(/(\b(?:is(?:\s+not)?|as)\s+)<<0>>/.source,[A]),lookbehind:!0,inside:o},{pattern:e(/\b<<0>>(?=\s+(?!<<1>>|with\s*\{)<<2>>(?:\s*[=,;:{)\]]|\s+(?:in|when)\b))/.source,[p,z,i]),inside:o}],keyword:d,number:/(?:\b0(?:x[\da-f_]*[\da-f]|b[01_]*[01])|(?:\B\.\d+(?:_+\d+)*|\b\d+(?:_+\d+)*(?:\.\d+(?:_+\d+)*)?)(?:e[-+]?\d+(?:_+\d+)*)?)(?:[dflmu]|lu|ul)?\b/i,operator:/>>=?|<<=?|[-=]>|([-+&|])\1|~|\?\?=?|[-+*/%&|^!=<>]=?/,punctuation:/\?\.?|::|[{}[\];(),.:]/}),r.languages.insertBefore("csharp","number",{range:{pattern:/\.\./,alias:"operator"}}),r.languages.insertBefore("csharp","punctuation",{"named-parameter":{pattern:e(/([(,]\s*)<<0>>(?=\s*:)/.source,[i]),lookbehind:!0,alias:"punctuation"}}),r.languages.insertBefore("csharp","class-name",{namespace:{pattern:e(/(\b(?:namespace|using)\s+)<<0>>(?:\s*\.\s*<<0>>)*(?=\s*[;{])/.source,[i]),lookbehind:!0,inside:{punctuation:/\./}},"type-expression":{pattern:e(/(\b(?:default|sizeof|typeof)\s*\(\s*(?!\s))(?:[^()\s]|\s(?!\s)|<<0>>)*(?=\s*\))/.source,[h]),lookbehind:!0,alias:"class-name",inside:o},"return-type":{pattern:e(/<<0>>(?=\s+(?:<<1>>\s*(?:=>|[({]|\.\s*this\s*\[)|this\s*\[))/.source,[p,c]),inside:o,alias:"class-name"},"constructor-invocation":{pattern:e(/(\bnew\s+)<<0>>(?=\s*[[({])/.source,[p]),lookbehind:!0,inside:o,alias:"class-name"},"generic-method":{pattern:e(/<<0>>\s*<<1>>(?=\s*\()/.source,[i,g]),inside:{function:e(/^<<0>>/.source,[i]),generic:{pattern:RegExp(g),alias:"class-name",inside:o}}},"type-list":{pattern:e(/\b((?:<<0>>\s+<<1>>|record\s+<<1>>\s*<<5>>|where\s+<<2>>)\s*:\s*)(?:<<3>>|<<4>>|<<1>>\s*<<5>>|<<6>>)(?:\s*,\s*(?:<<3>>|<<4>>|<<6>>))*(?=\s*(?:where|[{;]|=>|$))/.source,[v,b,i,p,d.source,h,/\bnew\s*\(\s*\)/.source]),lookbehind:!0,inside:{"record-arguments":{pattern:e(/(^(?!new\s*\()<<0>>\s*)<<1>>/.source,[b,h]),lookbehind:!0,greedy:!0,inside:r.languages.csharp},keyword:d,"class-name":{pattern:RegExp(p),greedy:!0,inside:o},punctuation:/[,()]/}},preprocessor:{pattern:/(^[\t ]*)#.*/m,lookbehind:!0,alias:"property",inside:{directive:{pattern:/(#)\b(?:define|elif|else|endif|endregion|error|if|line|nullable|pragma|region|undef|warning)\b/,lookbehind:!0,alias:"keyword"}}}});var x=w+"|"+k,E=t(/\/(?![*/])|\/\/[^\r\n]*[\r\n]|\/\*(?:[^*]|\*(?!\/))*\*\/|<<0>>/.source,[x]),S=a(t(/[^"'/()]|<<0>>|\(<<self>>*\)/.source,[E]),2),_=/\b(?:assembly|event|field|method|module|param|property|return|type)\b/.source,N=t(/<<0>>(?:\s*\(<<1>>*\))?/.source,[c,S]);r.languages.insertBefore("csharp","class-name",{attribute:{pattern:e(/((?:^|[^\s\w>)?])\s*\[\s*)(?:<<0>>\s*:\s*)?<<1>>(?:\s*,\s*<<1>>)*(?=\s*\])/.source,[_,N]),lookbehind:!0,greedy:!0,inside:{target:{pattern:e(/^<<0>>(?=\s*:)/.source,[_]),alias:"keyword"},"attribute-arguments":{pattern:e(/\(<<0>>*\)/.source,[S]),inside:r.languages.csharp},"class-name":{pattern:RegExp(c),inside:{punctuation:/\./}},punctuation:/[:,]/}}});var m=/:[^}\r\n]+/.source,C=a(t(/[^"'/()]|<<0>>|\(<<self>>*\)/.source,[E]),2),$=t(/\{(?!\{)(?:(?![}:])<<0>>)*<<1>>?\}/.source,[C,m]),R=a(t(/[^"'/()]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|<<0>>|\(<<self>>*\)/.source,[x]),2),D=t(/\{(?!\{)(?:(?![}:])<<0>>)*<<1>>?\}/.source,[R,m]);function j(n,l){return{interpolation:{pattern:e(/((?:^|[^{])(?:\{\{)*)<<0>>/.source,[n]),lookbehind:!0,inside:{"format-string":{pattern:e(/(^\{(?:(?![}:])<<0>>)*)<<1>>(?=\}$)/.source,[l,m]),lookbehind:!0,inside:{punctuation:/^:/}},punctuation:/^\{|\}$/,expression:{pattern:/[\s\S]+/,alias:"language-csharp",inside:r.languages.csharp}}},string:/[\s\S]+/}}r.languages.insertBefore("csharp","string",{"interpolation-string":[{pattern:e(/(^|[^\\])(?:\$@|@\$)"(?:""|\\[\s\S]|\{\{|<<0>>|[^\\{"])*"/.source,[$]),lookbehind:!0,greedy:!0,inside:j($,C)},{pattern:e(/(^|[^@\\])\$"(?:\\.|\{\{|<<0>>|[^\\"{])*"/.source,[D]),lookbehind:!0,greedy:!0,inside:j(D,R)}],char:{pattern:RegExp(k),greedy:!0}}),r.languages.dotnet=r.languages.cs=r.languages.csharp}(Prism)),I}var B=Z();const G=U(B),J=W({__proto__:null,default:G},[B]);export{J as p};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{g as u}from"./index-
|
|
1
|
+
import{g as u}from"./index-KydrgTN-.js";function p(t,a){for(var r=0;r<a.length;r++){const e=a[r];if(typeof e!="string"&&!Array.isArray(e)){for(const s in e)if(s!=="default"&&!(s in t)){const n=Object.getOwnPropertyDescriptor(e,s);n&&Object.defineProperty(t,s,n.get?n:{enumerable:!0,get:()=>e[s]})}}}return Object.freeze(Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}))}var o={},i;function d(){return i||(i=1,function(t){var a=/\b(?:abstract|assert|boolean|break|byte|case|catch|char|class|const|continue|default|do|double|else|enum|exports|extends|final|finally|float|for|goto|if|implements|import|instanceof|int|interface|long|module|native|new|non-sealed|null|open|opens|package|permits|private|protected|provides|public|record(?!\s*[(){}[\]<>=%~.:,;?+\-*/&|^])|requires|return|sealed|short|static|strictfp|super|switch|synchronized|this|throw|throws|to|transient|transitive|try|uses|var|void|volatile|while|with|yield)\b/,r=/(?:[a-z]\w*\s*\.\s*)*(?:[A-Z]\w*\s*\.\s*)*/.source,e={pattern:RegExp(/(^|[^\w.])/.source+r+/[A-Z](?:[\d_A-Z]*[a-z]\w*)?\b/.source),lookbehind:!0,inside:{namespace:{pattern:/^[a-z]\w*(?:\s*\.\s*[a-z]\w*)*(?:\s*\.)?/,inside:{punctuation:/\./}},punctuation:/\./}};t.languages.java=t.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"/,lookbehind:!0,greedy:!0},"class-name":[e,{pattern:RegExp(/(^|[^\w.])/.source+r+/[A-Z]\w*(?=\s+\w+\s*[;,=()]|\s*(?:\[[\s,]*\]\s*)?::\s*new\b)/.source),lookbehind:!0,inside:e.inside},{pattern:RegExp(/(\b(?:class|enum|extends|implements|instanceof|interface|new|record|throws)\s+)/.source+r+/[A-Z]\w*\b/.source),lookbehind:!0,inside:e.inside}],keyword:a,function:[t.languages.clike.function,{pattern:/(::\s*)[a-z_]\w*/,lookbehind:!0}],number:/\b0b[01][01_]*L?\b|\b0x(?:\.[\da-f_p+-]+|[\da-f_]+(?:\.[\da-f_p+-]+)?)\b|(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?\d[\d_]*)?[dfl]?/i,operator:{pattern:/(^|[^.])(?:<<=?|>>>?=?|->|--|\+\+|&&|\|\||::|[?:~]|[-+*/%&|^!=<>]=?)/m,lookbehind:!0},constant:/\b[A-Z][A-Z_\d]+\b/}),t.languages.insertBefore("java","string",{"triple-quoted-string":{pattern:/"""[ \t]*[\r\n](?:(?:"|"")?(?:\\.|[^"\\]))*"""/,greedy:!0,alias:"string"},char:{pattern:/'(?:\\.|[^'\\\r\n]){1,6}'/,greedy:!0}}),t.languages.insertBefore("java","class-name",{annotation:{pattern:/(^|[^.])@\w+(?:\s*\.\s*\w+)*/,lookbehind:!0,alias:"punctuation"},generics:{pattern:/<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&))*>)*>)*>)*>/,inside:{"class-name":e,keyword:a,punctuation:/[<>(),.:]/,operator:/[?&|]/}},import:[{pattern:RegExp(/(\bimport\s+)/.source+r+/(?:[A-Z]\w*|\*)(?=\s*;)/.source),lookbehind:!0,inside:{namespace:e.inside.namespace,punctuation:/\./,operator:/\*/,"class-name":/\w+/}},{pattern:RegExp(/(\bimport\s+static\s+)/.source+r+/(?:\w+|\*)(?=\s*;)/.source),lookbehind:!0,alias:"static",inside:{namespace:e.inside.namespace,static:/\b\w+$/,punctuation:/\./,operator:/\*/,"class-name":/\w+/}}],namespace:{pattern:RegExp(/(\b(?:exports|import(?:\s+static)?|module|open|opens|package|provides|requires|to|transitive|uses|with)\s+)(?!<keyword>)[a-z]\w*(?:\.[a-z]\w*)*\.?/.source.replace(/<keyword>/g,function(){return a.source})),lookbehind:!0,inside:{punctuation:/\./}}})}(Prism)),o}var c=d();const l=u(c),w=p({__proto__:null,default:l},[c]);export{w as p};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{g as c}from"./index-
|
|
1
|
+
import{g as c}from"./index-KydrgTN-.js";function f(e,r){for(var n=0;n<r.length;n++){const t=r[n];if(typeof t!="string"&&!Array.isArray(t)){for(const a in t)if(a!=="default"&&!(a in e)){const i=Object.getOwnPropertyDescriptor(t,a);i&&Object.defineProperty(e,a,i.get?i:{enumerable:!0,get:()=>t[a]})}}}return Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}var u={},d;function g(){return d||(d=1,function(e){var r=/\/\*[\s\S]*?\*\/|\/\/.*|#(?!\[).*/,n=[{pattern:/\b(?:false|true)\b/i,alias:"boolean"},{pattern:/(::\s*)\b[a-z_]\w*\b(?!\s*\()/i,greedy:!0,lookbehind:!0},{pattern:/(\b(?:case|const)\s+)\b[a-z_]\w*(?=\s*[;=])/i,greedy:!0,lookbehind:!0},/\b(?:null)\b/i,/\b[A-Z_][A-Z0-9_]*\b(?!\s*\()/],t=/\b0b[01]+(?:_[01]+)*\b|\b0o[0-7]+(?:_[0-7]+)*\b|\b0x[\da-f]+(?:_[\da-f]+)*\b|(?:\b\d+(?:_\d+)*\.?(?:\d+(?:_\d+)*)?|\B\.\d+)(?:e[+-]?\d+)?/i,a=/<?=>|\?\?=?|\.{3}|\??->|[!=]=?=?|::|\*\*=?|--|\+\+|&&|\|\||<<|>>|[?~]|[/^|%*&<>.+-]=?/,i=/[{}\[\](),:;]/;e.languages.php={delimiter:{pattern:/\?>$|^<\?(?:php(?=\s)|=)?/i,alias:"important"},comment:r,variable:/\$+(?:\w+\b|(?=\{))/,package:{pattern:/(namespace\s+|use\s+(?:function\s+)?)(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,lookbehind:!0,inside:{punctuation:/\\/}},"class-name-definition":{pattern:/(\b(?:class|enum|interface|trait)\s+)\b[a-z_]\w*(?!\\)\b/i,lookbehind:!0,alias:"class-name"},"function-definition":{pattern:/(\bfunction\s+)[a-z_]\w*(?=\s*\()/i,lookbehind:!0,alias:"function"},keyword:[{pattern:/(\(\s*)\b(?:array|bool|boolean|float|int|integer|object|string)\b(?=\s*\))/i,alias:"type-casting",greedy:!0,lookbehind:!0},{pattern:/([(,?]\s*)\b(?:array(?!\s*\()|bool|callable|(?:false|null)(?=\s*\|)|float|int|iterable|mixed|object|self|static|string)\b(?=\s*\$)/i,alias:"type-hint",greedy:!0,lookbehind:!0},{pattern:/(\)\s*:\s*(?:\?\s*)?)\b(?:array(?!\s*\()|bool|callable|(?:false|null)(?=\s*\|)|float|int|iterable|mixed|never|object|self|static|string|void)\b/i,alias:"return-type",greedy:!0,lookbehind:!0},{pattern:/\b(?:array(?!\s*\()|bool|float|int|iterable|mixed|object|string|void)\b/i,alias:"type-declaration",greedy:!0},{pattern:/(\|\s*)(?:false|null)\b|\b(?:false|null)(?=\s*\|)/i,alias:"type-declaration",greedy:!0,lookbehind:!0},{pattern:/\b(?:parent|self|static)(?=\s*::)/i,alias:"static-context",greedy:!0},{pattern:/(\byield\s+)from\b/i,lookbehind:!0},/\bclass\b/i,{pattern:/((?:^|[^\s>:]|(?:^|[^-])>|(?:^|[^:]):)\s*)\b(?:abstract|and|array|as|break|callable|case|catch|clone|const|continue|declare|default|die|do|echo|else|elseif|empty|enddeclare|endfor|endforeach|endif|endswitch|endwhile|enum|eval|exit|extends|final|finally|fn|for|foreach|function|global|goto|if|implements|include|include_once|instanceof|insteadof|interface|isset|list|match|namespace|never|new|or|parent|print|private|protected|public|readonly|require|require_once|return|self|static|switch|throw|trait|try|unset|use|var|while|xor|yield|__halt_compiler)\b/i,lookbehind:!0}],"argument-name":{pattern:/([(,]\s*)\b[a-z_]\w*(?=\s*:(?!:))/i,lookbehind:!0},"class-name":[{pattern:/(\b(?:extends|implements|instanceof|new(?!\s+self|\s+static))\s+|\bcatch\s*\()\b[a-z_]\w*(?!\\)\b/i,greedy:!0,lookbehind:!0},{pattern:/(\|\s*)\b[a-z_]\w*(?!\\)\b/i,greedy:!0,lookbehind:!0},{pattern:/\b[a-z_]\w*(?!\\)\b(?=\s*\|)/i,greedy:!0},{pattern:/(\|\s*)(?:\\?\b[a-z_]\w*)+\b/i,alias:"class-name-fully-qualified",greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/(?:\\?\b[a-z_]\w*)+\b(?=\s*\|)/i,alias:"class-name-fully-qualified",greedy:!0,inside:{punctuation:/\\/}},{pattern:/(\b(?:extends|implements|instanceof|new(?!\s+self\b|\s+static\b))\s+|\bcatch\s*\()(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,alias:"class-name-fully-qualified",greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/\b[a-z_]\w*(?=\s*\$)/i,alias:"type-declaration",greedy:!0},{pattern:/(?:\\?\b[a-z_]\w*)+(?=\s*\$)/i,alias:["class-name-fully-qualified","type-declaration"],greedy:!0,inside:{punctuation:/\\/}},{pattern:/\b[a-z_]\w*(?=\s*::)/i,alias:"static-context",greedy:!0},{pattern:/(?:\\?\b[a-z_]\w*)+(?=\s*::)/i,alias:["class-name-fully-qualified","static-context"],greedy:!0,inside:{punctuation:/\\/}},{pattern:/([(,?]\s*)[a-z_]\w*(?=\s*\$)/i,alias:"type-hint",greedy:!0,lookbehind:!0},{pattern:/([(,?]\s*)(?:\\?\b[a-z_]\w*)+(?=\s*\$)/i,alias:["class-name-fully-qualified","type-hint"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/(\)\s*:\s*(?:\?\s*)?)\b[a-z_]\w*(?!\\)\b/i,alias:"return-type",greedy:!0,lookbehind:!0},{pattern:/(\)\s*:\s*(?:\?\s*)?)(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,alias:["class-name-fully-qualified","return-type"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}}],constant:n,function:{pattern:/(^|[^\\\w])\\?[a-z_](?:[\w\\]*\w)?(?=\s*\()/i,lookbehind:!0,inside:{punctuation:/\\/}},property:{pattern:/(->\s*)\w+/,lookbehind:!0},number:t,operator:a,punctuation:i};var l={pattern:/\{\$(?:\{(?:\{[^{}]+\}|[^{}]+)\}|[^{}])+\}|(^|[^\\{])\$+(?:\w+(?:\[[^\r\n\[\]]+\]|->\w+)?)/,lookbehind:!0,inside:e.languages.php},o=[{pattern:/<<<'([^']+)'[\r\n](?:.*[\r\n])*?\1;/,alias:"nowdoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<<'[^']+'|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<'?|[';]$/}}}},{pattern:/<<<(?:"([^"]+)"[\r\n](?:.*[\r\n])*?\1;|([a-z_]\w*)[\r\n](?:.*[\r\n])*?\2;)/i,alias:"heredoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<<(?:"[^"]+"|[a-z_]\w*)|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<"?|[";]$/}},interpolation:l}},{pattern:/`(?:\\[\s\S]|[^\\`])*`/,alias:"backtick-quoted-string",greedy:!0},{pattern:/'(?:\\[\s\S]|[^\\'])*'/,alias:"single-quoted-string",greedy:!0},{pattern:/"(?:\\[\s\S]|[^\\"])*"/,alias:"double-quoted-string",greedy:!0,inside:{interpolation:l}}];e.languages.insertBefore("php","variable",{string:o,attribute:{pattern:/#\[(?:[^"'\/#]|\/(?![*/])|\/\/.*$|#(?!\[).*$|\/\*(?:[^*]|\*(?!\/))*\*\/|"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*')+\](?=\s*[a-z$#])/im,greedy:!0,inside:{"attribute-content":{pattern:/^(#\[)[\s\S]+(?=\]$)/,lookbehind:!0,inside:{comment:r,string:o,"attribute-class-name":[{pattern:/([^:]|^)\b[a-z_]\w*(?!\\)\b/i,alias:"class-name",greedy:!0,lookbehind:!0},{pattern:/([^:]|^)(?:\\?\b[a-z_]\w*)+/i,alias:["class-name","class-name-fully-qualified"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}}],constant:n,number:t,operator:a,punctuation:i}},delimiter:{pattern:/^#\[|\]$/,alias:"punctuation"}}}}),e.hooks.add("before-tokenize",function(s){if(/<\?/.test(s.code)){var p=/<\?(?:[^"'/#]|\/(?![*/])|("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|(?:\/\/|#(?!\[))(?:[^?\n\r]|\?(?!>))*(?=$|\?>|[\r\n])|#\[|\/\*(?:[^*]|\*(?!\/))*(?:\*\/|$))*?(?:\?>|$)/g;e.languages["markup-templating"].buildPlaceholders(s,"php",p)}}),e.hooks.add("after-tokenize",function(s){e.languages["markup-templating"].tokenizePlaceholders(s,"php")})}(Prism)),u}var b=g();const y=c(b),m=f({__proto__:null,default:y},[b]);export{m as p};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{g as l}from"./index-
|
|
1
|
+
import{g as l}from"./index-KydrgTN-.js";function d(e,r){for(var n=0;n<r.length;n++){const t=r[n];if(typeof t!="string"&&!Array.isArray(t)){for(const i in t)if(i!=="default"&&!(i in e)){const s=Object.getOwnPropertyDescriptor(t,i);s&&Object.defineProperty(e,i,s.get?s:{enumerable:!0,get:()=>t[i]})}}}return Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}var a={},o;function g(){return o||(o=1,function(e){e.languages.ruby=e.languages.extend("clike",{comment:{pattern:/#.*|^=begin\s[\s\S]*?^=end/m,greedy:!0},"class-name":{pattern:/(\b(?:class|module)\s+|\bcatch\s+\()[\w.\\]+|\b[A-Z_]\w*(?=\s*\.\s*new\b)/,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:BEGIN|END|alias|and|begin|break|case|class|def|define_method|defined|do|each|else|elsif|end|ensure|extend|for|if|in|include|module|new|next|nil|not|or|prepend|private|protected|public|raise|redo|require|rescue|retry|return|self|super|then|throw|undef|unless|until|when|while|yield)\b/,operator:/\.{2,3}|&\.|===|<?=>|[!=]?~|(?:&&|\|\||<<|>>|\*\*|[+\-*/%<>!^&|=])=?|[?:]/,punctuation:/[(){}[\].,;]/}),e.languages.insertBefore("ruby","operator",{"double-colon":{pattern:/::/,alias:"punctuation"}});var r={pattern:/((?:^|[^\\])(?:\\{2})*)#\{(?:[^{}]|\{[^{}]*\})*\}/,lookbehind:!0,inside:{content:{pattern:/^(#\{)[\s\S]+(?=\}$)/,lookbehind:!0,inside:e.languages.ruby},delimiter:{pattern:/^#\{|\}$/,alias:"punctuation"}}};delete e.languages.ruby.function;var n="(?:"+[/([^a-zA-Z0-9\s{(\[<=])(?:(?!\1)[^\\]|\\[\s\S])*\1/.source,/\((?:[^()\\]|\\[\s\S]|\((?:[^()\\]|\\[\s\S])*\))*\)/.source,/\{(?:[^{}\\]|\\[\s\S]|\{(?:[^{}\\]|\\[\s\S])*\})*\}/.source,/\[(?:[^\[\]\\]|\\[\s\S]|\[(?:[^\[\]\\]|\\[\s\S])*\])*\]/.source,/<(?:[^<>\\]|\\[\s\S]|<(?:[^<>\\]|\\[\s\S])*>)*>/.source].join("|")+")",t=/(?:"(?:\\.|[^"\\\r\n])*"|(?:\b[a-zA-Z_]\w*|[^\s\0-\x7F]+)[?!]?|\$.)/.source;e.languages.insertBefore("ruby","keyword",{"regex-literal":[{pattern:RegExp(/%r/.source+n+/[egimnosux]{0,6}/.source),greedy:!0,inside:{interpolation:r,regex:/[\s\S]+/}},{pattern:/(^|[^/])\/(?!\/)(?:\[[^\r\n\]]+\]|\\.|[^[/\\\r\n])+\/[egimnosux]{0,6}(?=\s*(?:$|[\r\n,.;})#]))/,lookbehind:!0,greedy:!0,inside:{interpolation:r,regex:/[\s\S]+/}}],variable:/[@$]+[a-zA-Z_]\w*(?:[?!]|\b)/,symbol:[{pattern:RegExp(/(^|[^:]):/.source+t),lookbehind:!0,greedy:!0},{pattern:RegExp(/([\r\n{(,][ \t]*)/.source+t+/(?=:(?!:))/.source),lookbehind:!0,greedy:!0}],"method-definition":{pattern:/(\bdef\s+)\w+(?:\s*\.\s*\w+)?/,lookbehind:!0,inside:{function:/\b\w+$/,keyword:/^self\b/,"class-name":/^\w+/,punctuation:/\./}}}),e.languages.insertBefore("ruby","string",{"string-literal":[{pattern:RegExp(/%[qQiIwWs]?/.source+n),greedy:!0,inside:{interpolation:r,string:/[\s\S]+/}},{pattern:/("|')(?:#\{[^}]+\}|#(?!\{)|\\(?:\r\n|[\s\S])|(?!\1)[^\\#\r\n])*\1/,greedy:!0,inside:{interpolation:r,string:/[\s\S]+/}},{pattern:/<<[-~]?([a-z_]\w*)[\r\n](?:.*[\r\n])*?[\t ]*\1/i,alias:"heredoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<[-~]?[a-z_]\w*|\b[a-z_]\w*$/i,inside:{symbol:/\b\w+/,punctuation:/^<<[-~]?/}},interpolation:r,string:/[\s\S]+/}},{pattern:/<<[-~]?'([a-z_]\w*)'[\r\n](?:.*[\r\n])*?[\t ]*\1/i,alias:"heredoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<[-~]?'[a-z_]\w*'|\b[a-z_]\w*$/i,inside:{symbol:/\b\w+/,punctuation:/^<<[-~]?'|'$/}},string:/[\s\S]+/}}],"command-literal":[{pattern:RegExp(/%x/.source+n),greedy:!0,inside:{interpolation:r,command:{pattern:/[\s\S]+/,alias:"string"}}},{pattern:/`(?:#\{[^}]+\}|#(?!\{)|\\(?:\r\n|[\s\S])|[^\\`#\r\n])*`/,greedy:!0,inside:{interpolation:r,command:{pattern:/[\s\S]+/,alias:"string"}}}]}),delete e.languages.ruby.string,e.languages.insertBefore("ruby","number",{builtin:/\b(?:Array|Bignum|Binding|Class|Continuation|Dir|Exception|FalseClass|File|Fixnum|Float|Hash|IO|Integer|MatchData|Method|Module|NilClass|Numeric|Object|Proc|Range|Regexp|Stat|String|Struct|Symbol|TMS|Thread|ThreadGroup|Time|TrueClass)\b/,constant:/\b[A-Z][A-Z0-9_]*(?:[?!]|\b)/}),e.languages.rb=e.languages.ruby}(Prism)),a}var u=g();const p=l(u),b=d({__proto__:null,default:p},[u]);export{b as p};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{g as u}from"./index-
|
|
1
|
+
import{g as u}from"./index-KydrgTN-.js";function d(t,n){for(var i=0;i<n.length;i++){const e=n[i];if(typeof e!="string"&&!Array.isArray(e)){for(const r in e)if(r!=="default"&&!(r in t)){const s=Object.getOwnPropertyDescriptor(e,r);s&&Object.defineProperty(t,r,s.get?s:{enumerable:!0,get:()=>e[r]})}}}return Object.freeze(Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}))}var o={},a;function c(){return a||(a=1,Prism.languages.solidity=Prism.languages.extend("clike",{"class-name":{pattern:/(\b(?:contract|enum|interface|library|new|struct|using)\s+)(?!\d)[\w$]+/,lookbehind:!0},keyword:/\b(?:_|anonymous|as|assembly|assert|break|calldata|case|constant|constructor|continue|contract|default|delete|do|else|emit|enum|event|external|for|from|function|if|import|indexed|inherited|interface|internal|is|let|library|mapping|memory|modifier|new|payable|pragma|private|public|pure|require|returns?|revert|selfdestruct|solidity|storage|struct|suicide|switch|this|throw|using|var|view|while)\b/,operator:/=>|->|:=|=:|\*\*|\+\+|--|\|\||&&|<<=?|>>=?|[-+*/%^&|<>!=]=?|[~?]/}),Prism.languages.insertBefore("solidity","keyword",{builtin:/\b(?:address|bool|byte|u?int(?:8|16|24|32|40|48|56|64|72|80|88|96|104|112|120|128|136|144|152|160|168|176|184|192|200|208|216|224|232|240|248|256)?|string|bytes(?:[1-9]|[12]\d|3[0-2])?)\b/}),Prism.languages.insertBefore("solidity","number",{version:{pattern:/([<>]=?|\^)\d+\.\d+\.\d+\b/,lookbehind:!0,alias:"number"}}),Prism.languages.sol=Prism.languages.solidity),o}var l=c();const m=u(l),y=d({__proto__:null,default:m},[l]);export{y as p};
|
package/dist/client/index.html
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
<link rel="icon" href="/favicon-white.svg" media="(prefers-color-scheme: dark)" />
|
|
8
8
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
9
9
|
<title>difit - Git Diff Viewer</title>
|
|
10
|
-
<script type="module" crossorigin src="/assets/index-
|
|
10
|
+
<script type="module" crossorigin src="/assets/index-KydrgTN-.js"></script>
|
|
11
11
|
<link rel="stylesheet" crossorigin href="/assets/index-Bz9yRRZ7.css">
|
|
12
12
|
</head>
|
|
13
13
|
<body>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const LineNumberSchema: z.ZodUnion<readonly [z.ZodNumber, z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>]>;
|
|
3
|
+
export declare const CommentSchema: z.ZodObject<{
|
|
4
|
+
id: z.ZodString;
|
|
5
|
+
file: z.ZodString;
|
|
6
|
+
line: z.ZodUnion<readonly [z.ZodNumber, z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>]>;
|
|
7
|
+
body: z.ZodString;
|
|
8
|
+
timestamp: z.ZodString;
|
|
9
|
+
codeContent: z.ZodOptional<z.ZodString>;
|
|
10
|
+
}, z.core.$strip>;
|
|
11
|
+
export declare const CommentsPayloadSchema: z.ZodObject<{
|
|
12
|
+
comments: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
13
|
+
id: z.ZodString;
|
|
14
|
+
file: z.ZodString;
|
|
15
|
+
line: z.ZodUnion<readonly [z.ZodNumber, z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>]>;
|
|
16
|
+
body: z.ZodString;
|
|
17
|
+
timestamp: z.ZodString;
|
|
18
|
+
codeContent: z.ZodOptional<z.ZodString>;
|
|
19
|
+
}, z.core.$strip>>>;
|
|
20
|
+
}, z.core.$strip>;
|
|
21
|
+
export type ValidatedComment = z.infer<typeof CommentSchema>;
|
|
22
|
+
export type ValidatedCommentsPayload = z.infer<typeof CommentsPayloadSchema>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
// Schema for line number: either a single number or a tuple of two numbers
|
|
3
|
+
export const LineNumberSchema = z.union([z.number(), z.tuple([z.number(), z.number()])]);
|
|
4
|
+
// Schema for a single comment
|
|
5
|
+
export const CommentSchema = z.object({
|
|
6
|
+
id: z.string(),
|
|
7
|
+
file: z.string(),
|
|
8
|
+
line: LineNumberSchema,
|
|
9
|
+
body: z.string(),
|
|
10
|
+
timestamp: z.string(),
|
|
11
|
+
codeContent: z.string().optional(),
|
|
12
|
+
});
|
|
13
|
+
// Schema for the comments payload sent from client
|
|
14
|
+
export const CommentsPayloadSchema = z.object({
|
|
15
|
+
comments: z.array(CommentSchema).optional(),
|
|
16
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { CommentSchema, CommentsPayloadSchema, LineNumberSchema } from './commentSchema';
|
|
3
|
+
describe('Comment Schema Validation', () => {
|
|
4
|
+
describe('LineNumberSchema', () => {
|
|
5
|
+
it('should accept single number', () => {
|
|
6
|
+
const result = LineNumberSchema.safeParse(42);
|
|
7
|
+
expect(result.success).toBe(true);
|
|
8
|
+
if (result.success) {
|
|
9
|
+
expect(result.data).toBe(42);
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
it('should accept tuple of two numbers', () => {
|
|
13
|
+
const result = LineNumberSchema.safeParse([10, 20]);
|
|
14
|
+
expect(result.success).toBe(true);
|
|
15
|
+
if (result.success) {
|
|
16
|
+
expect(result.data).toEqual([10, 20]);
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
it('should reject string', () => {
|
|
20
|
+
const result = LineNumberSchema.safeParse('42');
|
|
21
|
+
expect(result.success).toBe(false);
|
|
22
|
+
});
|
|
23
|
+
it('should reject array with more than 2 numbers', () => {
|
|
24
|
+
const result = LineNumberSchema.safeParse([1, 2, 3]);
|
|
25
|
+
expect(result.success).toBe(false);
|
|
26
|
+
});
|
|
27
|
+
it('should reject array with less than 2 numbers', () => {
|
|
28
|
+
const result = LineNumberSchema.safeParse([1]);
|
|
29
|
+
expect(result.success).toBe(false);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
describe('CommentSchema', () => {
|
|
33
|
+
it('should accept valid comment with single line number', () => {
|
|
34
|
+
const comment = {
|
|
35
|
+
id: '123',
|
|
36
|
+
file: 'src/app.ts',
|
|
37
|
+
line: 42,
|
|
38
|
+
body: 'Test comment',
|
|
39
|
+
timestamp: '2024-01-01T00:00:00Z',
|
|
40
|
+
};
|
|
41
|
+
const result = CommentSchema.safeParse(comment);
|
|
42
|
+
expect(result.success).toBe(true);
|
|
43
|
+
if (result.success) {
|
|
44
|
+
expect(result.data).toEqual(comment);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
it('should accept valid comment with line range', () => {
|
|
48
|
+
const comment = {
|
|
49
|
+
id: '456',
|
|
50
|
+
file: 'src/utils.ts',
|
|
51
|
+
line: [10, 20],
|
|
52
|
+
body: 'Range comment',
|
|
53
|
+
timestamp: '2024-01-01T00:00:00Z',
|
|
54
|
+
};
|
|
55
|
+
const result = CommentSchema.safeParse(comment);
|
|
56
|
+
expect(result.success).toBe(true);
|
|
57
|
+
if (result.success) {
|
|
58
|
+
expect(result.data).toEqual(comment);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
it('should accept comment with optional codeContent', () => {
|
|
62
|
+
const comment = {
|
|
63
|
+
id: '789',
|
|
64
|
+
file: 'src/index.ts',
|
|
65
|
+
line: 1,
|
|
66
|
+
body: 'Comment with code',
|
|
67
|
+
timestamp: '2024-01-01T00:00:00Z',
|
|
68
|
+
codeContent: 'const x = 42;',
|
|
69
|
+
};
|
|
70
|
+
const result = CommentSchema.safeParse(comment);
|
|
71
|
+
expect(result.success).toBe(true);
|
|
72
|
+
if (result.success) {
|
|
73
|
+
expect(result.data.codeContent).toBe('const x = 42;');
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
it('should reject comment without required fields', () => {
|
|
77
|
+
const invalidComment = {
|
|
78
|
+
id: '123',
|
|
79
|
+
// missing file
|
|
80
|
+
line: 42,
|
|
81
|
+
body: 'Test',
|
|
82
|
+
timestamp: '2024-01-01T00:00:00Z',
|
|
83
|
+
};
|
|
84
|
+
const result = CommentSchema.safeParse(invalidComment);
|
|
85
|
+
expect(result.success).toBe(false);
|
|
86
|
+
if (!result.success) {
|
|
87
|
+
expect(result.error.issues[0]?.path).toContain('file');
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
it('should reject comment with wrong type for file', () => {
|
|
91
|
+
const invalidComment = {
|
|
92
|
+
id: '123',
|
|
93
|
+
file: 123, // should be string
|
|
94
|
+
line: 42,
|
|
95
|
+
body: 'Test',
|
|
96
|
+
timestamp: '2024-01-01T00:00:00Z',
|
|
97
|
+
};
|
|
98
|
+
const result = CommentSchema.safeParse(invalidComment);
|
|
99
|
+
expect(result.success).toBe(false);
|
|
100
|
+
});
|
|
101
|
+
it('should reject comment with invalid line format', () => {
|
|
102
|
+
const invalidComment = {
|
|
103
|
+
id: '123',
|
|
104
|
+
file: 'test.ts',
|
|
105
|
+
line: 'invalid', // should be number or [number, number]
|
|
106
|
+
body: 'Test',
|
|
107
|
+
timestamp: '2024-01-01T00:00:00Z',
|
|
108
|
+
};
|
|
109
|
+
const result = CommentSchema.safeParse(invalidComment);
|
|
110
|
+
expect(result.success).toBe(false);
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
describe('CommentsPayloadSchema', () => {
|
|
114
|
+
it('should accept valid payload with comments array', () => {
|
|
115
|
+
const payload = {
|
|
116
|
+
comments: [
|
|
117
|
+
{
|
|
118
|
+
id: '1',
|
|
119
|
+
file: 'file1.ts',
|
|
120
|
+
line: 10,
|
|
121
|
+
body: 'Comment 1',
|
|
122
|
+
timestamp: '2024-01-01T00:00:00Z',
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
id: '2',
|
|
126
|
+
file: 'file2.ts',
|
|
127
|
+
line: [20, 30],
|
|
128
|
+
body: 'Comment 2',
|
|
129
|
+
timestamp: '2024-01-01T00:01:00Z',
|
|
130
|
+
},
|
|
131
|
+
],
|
|
132
|
+
};
|
|
133
|
+
const result = CommentsPayloadSchema.safeParse(payload);
|
|
134
|
+
expect(result.success).toBe(true);
|
|
135
|
+
if (result.success) {
|
|
136
|
+
expect(result.data.comments).toHaveLength(2);
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
it('should accept empty comments array', () => {
|
|
140
|
+
const payload = { comments: [] };
|
|
141
|
+
const result = CommentsPayloadSchema.safeParse(payload);
|
|
142
|
+
expect(result.success).toBe(true);
|
|
143
|
+
if (result.success) {
|
|
144
|
+
expect(result.data.comments).toEqual([]);
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
it('should accept payload without comments property', () => {
|
|
148
|
+
const payload = {};
|
|
149
|
+
const result = CommentsPayloadSchema.safeParse(payload);
|
|
150
|
+
expect(result.success).toBe(true);
|
|
151
|
+
if (result.success) {
|
|
152
|
+
expect(result.data.comments).toBeUndefined();
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
it('should reject payload with invalid comment in array', () => {
|
|
156
|
+
const payload = {
|
|
157
|
+
comments: [
|
|
158
|
+
{
|
|
159
|
+
id: '1',
|
|
160
|
+
file: 'file1.ts',
|
|
161
|
+
line: 10,
|
|
162
|
+
body: 'Valid comment',
|
|
163
|
+
timestamp: '2024-01-01T00:00:00Z',
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
id: '2',
|
|
167
|
+
// missing file property
|
|
168
|
+
line: 20,
|
|
169
|
+
body: 'Invalid comment',
|
|
170
|
+
timestamp: '2024-01-01T00:01:00Z',
|
|
171
|
+
},
|
|
172
|
+
],
|
|
173
|
+
};
|
|
174
|
+
const result = CommentsPayloadSchema.safeParse(payload);
|
|
175
|
+
expect(result.success).toBe(false);
|
|
176
|
+
});
|
|
177
|
+
it('should reject payload with comments as non-array', () => {
|
|
178
|
+
const payload = {
|
|
179
|
+
comments: 'not an array',
|
|
180
|
+
};
|
|
181
|
+
const result = CommentsPayloadSchema.safeParse(payload);
|
|
182
|
+
expect(result.success).toBe(false);
|
|
183
|
+
});
|
|
184
|
+
it('should handle real-world DiffComment format from client', () => {
|
|
185
|
+
// This simulates the actual DiffComment format sent from client
|
|
186
|
+
const diffCommentPayload = {
|
|
187
|
+
comments: [
|
|
188
|
+
{
|
|
189
|
+
id: 'abc123',
|
|
190
|
+
filePath: 'src/components/Button.tsx', // Note: 'filePath' instead of 'file'
|
|
191
|
+
position: {
|
|
192
|
+
line: 42,
|
|
193
|
+
side: 'new',
|
|
194
|
+
},
|
|
195
|
+
body: 'Fix this button',
|
|
196
|
+
createdAt: '2024-01-01T00:00:00Z',
|
|
197
|
+
},
|
|
198
|
+
],
|
|
199
|
+
};
|
|
200
|
+
const result = CommentsPayloadSchema.safeParse(diffCommentPayload);
|
|
201
|
+
expect(result.success).toBe(false); // Should fail because of incorrect property names
|
|
202
|
+
if (!result.success) {
|
|
203
|
+
// Check that it fails because 'file' is missing
|
|
204
|
+
const fileIssue = result.error.issues.find((issue) => issue.path.includes('file'));
|
|
205
|
+
expect(fileIssue).toBeDefined();
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
it('should accept properly transformed comments from client', () => {
|
|
209
|
+
// This is what the client should send after transformation
|
|
210
|
+
const transformedPayload = {
|
|
211
|
+
comments: [
|
|
212
|
+
{
|
|
213
|
+
id: 'abc123',
|
|
214
|
+
file: 'src/components/Button.tsx', // Correct property name
|
|
215
|
+
line: 42, // Extracted from position.line
|
|
216
|
+
body: 'Fix this button',
|
|
217
|
+
timestamp: '2024-01-01T00:00:00Z', // Renamed from createdAt
|
|
218
|
+
},
|
|
219
|
+
],
|
|
220
|
+
};
|
|
221
|
+
const result = CommentsPayloadSchema.safeParse(transformedPayload);
|
|
222
|
+
expect(result.success).toBe(true);
|
|
223
|
+
if (result.success) {
|
|
224
|
+
expect(result.data.comments).toHaveLength(1);
|
|
225
|
+
expect(result.data.comments[0].file).toBe('src/components/Button.tsx');
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
});
|
package/dist/server/server.js
CHANGED
|
@@ -4,6 +4,7 @@ import express from 'express';
|
|
|
4
4
|
import open from 'open';
|
|
5
5
|
const __filename = fileURLToPath(import.meta.url);
|
|
6
6
|
const __dirname = dirname(__filename);
|
|
7
|
+
import { formatCommentsOutput } from '../utils/commentFormatting.js';
|
|
7
8
|
import { getFileExtension } from '../utils/fileUtils.js';
|
|
8
9
|
import { FileWatcherService } from './file-watcher.js';
|
|
9
10
|
import { GitDiffParser } from './git-diff.js';
|
|
@@ -124,19 +125,6 @@ export async function startServer(options) {
|
|
|
124
125
|
res.send('');
|
|
125
126
|
}
|
|
126
127
|
});
|
|
127
|
-
// Function to format comments for output
|
|
128
|
-
function formatCommentsOutput(comments) {
|
|
129
|
-
const prompts = comments.map((comment) => {
|
|
130
|
-
return `${comment.file}:${Array.isArray(comment.line) ? `L${comment.line[0]}-L${comment.line[1]}` : `L${comment.line}`}\n${comment.body}`;
|
|
131
|
-
});
|
|
132
|
-
return [
|
|
133
|
-
'\n📝 Comments from review session:',
|
|
134
|
-
'='.repeat(50),
|
|
135
|
-
prompts.join('\n=====\n'),
|
|
136
|
-
'='.repeat(50),
|
|
137
|
-
`Total comments: ${comments.length}\n`,
|
|
138
|
-
].join('\n');
|
|
139
|
-
}
|
|
140
128
|
// Function to output comments when server shuts down
|
|
141
129
|
function outputFinalComments() {
|
|
142
130
|
if (finalComments.length > 0) {
|
|
@@ -5,6 +5,23 @@ import { startServer } from './server.js';
|
|
|
5
5
|
// Add fetch polyfill for Node.js test environment
|
|
6
6
|
const { fetch } = await import('undici');
|
|
7
7
|
globalThis.fetch = fetch;
|
|
8
|
+
// Helper function to get available port
|
|
9
|
+
async function getAvailablePort(preferredPort) {
|
|
10
|
+
let port = preferredPort;
|
|
11
|
+
const maxAttempts = 10;
|
|
12
|
+
for (let i = 0; i < maxAttempts; i++) {
|
|
13
|
+
try {
|
|
14
|
+
await fetch(`http://localhost:${port}`);
|
|
15
|
+
// If we get here, port is in use, try next one
|
|
16
|
+
port++;
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
// Port is available
|
|
20
|
+
return port;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return port;
|
|
24
|
+
}
|
|
8
25
|
// Mock GitDiffParser
|
|
9
26
|
vi.mock('./git-diff.js', () => ({
|
|
10
27
|
GitDiffParser: vi.fn().mockImplementation(() => ({
|
|
@@ -29,6 +46,92 @@ vi.mock('./git-diff.js', () => ({
|
|
|
29
46
|
})),
|
|
30
47
|
}));
|
|
31
48
|
describe('Server Integration Tests', () => {
|
|
49
|
+
describe('Comments API', () => {
|
|
50
|
+
it('should accept properly formatted comments', async () => {
|
|
51
|
+
const port = await getAvailablePort(4966);
|
|
52
|
+
const result = await startServer({
|
|
53
|
+
preferredPort: port,
|
|
54
|
+
openBrowser: false,
|
|
55
|
+
});
|
|
56
|
+
try {
|
|
57
|
+
const comments = [
|
|
58
|
+
{
|
|
59
|
+
id: '1',
|
|
60
|
+
file: 'src/App.tsx',
|
|
61
|
+
line: 10,
|
|
62
|
+
body: 'Test comment',
|
|
63
|
+
timestamp: '2024-01-01T00:00:00Z',
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
id: '2',
|
|
67
|
+
file: 'src/utils/helper.ts',
|
|
68
|
+
line: [20, 30],
|
|
69
|
+
body: 'Another comment',
|
|
70
|
+
timestamp: '2024-01-01T00:01:00Z',
|
|
71
|
+
},
|
|
72
|
+
];
|
|
73
|
+
const response = await fetch(`http://localhost:${result.port}/api/comments`, {
|
|
74
|
+
method: 'POST',
|
|
75
|
+
headers: { 'Content-Type': 'application/json' },
|
|
76
|
+
body: JSON.stringify({ comments }),
|
|
77
|
+
});
|
|
78
|
+
expect(response.status).toBe(200);
|
|
79
|
+
const apiResult = await response.json();
|
|
80
|
+
expect(apiResult).toEqual({ success: true });
|
|
81
|
+
// Verify the formatted output
|
|
82
|
+
const outputResponse = await fetch(`http://localhost:${result.port}/api/comments-output`);
|
|
83
|
+
const output = await outputResponse.text();
|
|
84
|
+
expect(output).toContain('src/App.tsx:L10');
|
|
85
|
+
expect(output).toContain('Test comment');
|
|
86
|
+
expect(output).toContain('src/utils/helper.ts:L20-L30');
|
|
87
|
+
expect(output).toContain('Another comment');
|
|
88
|
+
expect(output).not.toContain('undefined');
|
|
89
|
+
}
|
|
90
|
+
finally {
|
|
91
|
+
if (result.server) {
|
|
92
|
+
await new Promise((resolve) => {
|
|
93
|
+
result.server.close(() => resolve());
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
it('should handle comments with missing file property gracefully', async () => {
|
|
99
|
+
const port = await getAvailablePort(4966);
|
|
100
|
+
const result = await startServer({
|
|
101
|
+
preferredPort: port,
|
|
102
|
+
openBrowser: false,
|
|
103
|
+
});
|
|
104
|
+
try {
|
|
105
|
+
const commentsWithMissingFile = [
|
|
106
|
+
{
|
|
107
|
+
id: '1',
|
|
108
|
+
// file property is missing/undefined
|
|
109
|
+
line: 10,
|
|
110
|
+
body: 'Comment without file',
|
|
111
|
+
timestamp: '2024-01-01T00:00:00Z',
|
|
112
|
+
},
|
|
113
|
+
];
|
|
114
|
+
const response = await fetch(`http://localhost:${result.port}/api/comments`, {
|
|
115
|
+
method: 'POST',
|
|
116
|
+
headers: { 'Content-Type': 'application/json' },
|
|
117
|
+
body: JSON.stringify({ comments: commentsWithMissingFile }),
|
|
118
|
+
});
|
|
119
|
+
expect(response.status).toBe(200);
|
|
120
|
+
// Check the output handles undefined file gracefully
|
|
121
|
+
const outputResponse = await fetch(`http://localhost:${result.port}/api/comments-output`);
|
|
122
|
+
const output = await outputResponse.text();
|
|
123
|
+
expect(output).toContain('<unknown file>:L10');
|
|
124
|
+
expect(output).toContain('Comment without file');
|
|
125
|
+
}
|
|
126
|
+
finally {
|
|
127
|
+
if (result.server) {
|
|
128
|
+
await new Promise((resolve) => {
|
|
129
|
+
result.server.close(() => resolve());
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
});
|
|
32
135
|
let servers = [];
|
|
33
136
|
let originalProcessExit;
|
|
34
137
|
beforeEach(() => {
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type Comment, type LineNumber } from '../types/diff';
|
|
2
|
+
/**
|
|
3
|
+
* Formats a line number or range for display
|
|
4
|
+
* @param line - Single line number or line range
|
|
5
|
+
* @returns Formatted string like "L10" or "L10-L20", or empty string if line is undefined
|
|
6
|
+
*/
|
|
7
|
+
export declare function formatLineNumber(line: LineNumber | undefined): string;
|
|
8
|
+
/**
|
|
9
|
+
* Formats a single comment for prompt output
|
|
10
|
+
* @param comment - The comment to format
|
|
11
|
+
* @returns Formatted string like "file.ts:L10\nComment body"
|
|
12
|
+
*/
|
|
13
|
+
export declare function formatCommentPrompt(comment: Comment): string;
|
|
14
|
+
/**
|
|
15
|
+
* Formats multiple comments for batch output
|
|
16
|
+
* @param comments - Array of comments to format
|
|
17
|
+
* @param separator - Separator between comments (default: "=====")
|
|
18
|
+
* @returns Formatted string with all comments separated
|
|
19
|
+
*/
|
|
20
|
+
export declare function formatCommentsPrompt(comments: Comment[], separator?: string): string;
|
|
21
|
+
/**
|
|
22
|
+
* Formats comments for server output with decorative elements
|
|
23
|
+
* @param comments - Array of comments to format
|
|
24
|
+
* @returns Formatted string with header and footer
|
|
25
|
+
*/
|
|
26
|
+
export declare function formatCommentsOutput(comments: Comment[]): string;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formats a line number or range for display
|
|
3
|
+
* @param line - Single line number or line range
|
|
4
|
+
* @returns Formatted string like "L10" or "L10-L20", or empty string if line is undefined
|
|
5
|
+
*/
|
|
6
|
+
export function formatLineNumber(line) {
|
|
7
|
+
if (!line)
|
|
8
|
+
return '';
|
|
9
|
+
if (Array.isArray(line)) {
|
|
10
|
+
return `L${line[0]}-L${line[1]}`;
|
|
11
|
+
}
|
|
12
|
+
return `L${line}`;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Formats a single comment for prompt output
|
|
16
|
+
* @param comment - The comment to format
|
|
17
|
+
* @returns Formatted string like "file.ts:L10\nComment body"
|
|
18
|
+
*/
|
|
19
|
+
export function formatCommentPrompt(comment) {
|
|
20
|
+
const lineDisplay = formatLineNumber(comment.line);
|
|
21
|
+
const location = lineDisplay ? `${comment.file}:${lineDisplay}` : comment.file;
|
|
22
|
+
return `${location}\n${comment.body}`;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Formats multiple comments for batch output
|
|
26
|
+
* @param comments - Array of comments to format
|
|
27
|
+
* @param separator - Separator between comments (default: "=====")
|
|
28
|
+
* @returns Formatted string with all comments separated
|
|
29
|
+
*/
|
|
30
|
+
export function formatCommentsPrompt(comments, separator = '=====') {
|
|
31
|
+
if (comments.length === 0) {
|
|
32
|
+
return 'No comments available.';
|
|
33
|
+
}
|
|
34
|
+
return comments.map(formatCommentPrompt).join(`\n${separator}\n`);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Formats comments for server output with decorative elements
|
|
38
|
+
* @param comments - Array of comments to format
|
|
39
|
+
* @returns Formatted string with header and footer
|
|
40
|
+
*/
|
|
41
|
+
export function formatCommentsOutput(comments) {
|
|
42
|
+
const prompts = formatCommentsPrompt(comments);
|
|
43
|
+
return [
|
|
44
|
+
'\n📝 Comments from review session:',
|
|
45
|
+
'='.repeat(50),
|
|
46
|
+
prompts,
|
|
47
|
+
'='.repeat(50),
|
|
48
|
+
`Total comments: ${comments.length}\n`,
|
|
49
|
+
].join('\n');
|
|
50
|
+
}
|