1- import { DiffFile } from "@git-diff-view/core" ;
2- import { type JSXElement , type JSX , createSignal , createRenderEffect } from "solid-js" ;
1+ /* eslint-disable @typescript-eslint/no-unnecessary-type-constraint */
2+ import { _cacheMap , DiffFile , SplitSide } from "@git-diff-view/core" ;
3+ import { diffFontSizeName , DiffModeEnum } from "@git-diff-view/utils" ;
4+ import { type JSXElement , type JSX , createSignal , createEffect , createMemo , onCleanup } from "solid-js" ;
5+
6+ import { DiffViewContext } from "./DiffViewContext" ;
7+ import { DiffWidgetContext } from "./DiffWidgetContext" ;
8+ import { createDiffConfigStore } from "./tools" ;
39
410import type { DiffHighlighter , DiffHighlighterLang } from "@git-diff-view/core" ;
511
6- export enum DiffModeEnum {
7- // github like
8- SplitGitHub = 1 ,
9- // gitlab like
10- SplitGitLab = 2 ,
11- Split = 1 | 2 ,
12- Unified = 4 ,
13- }
12+ _cacheMap . name = "@git-diff-view/solid" ;
13+
14+ export { SplitSide , DiffModeEnum } ;
1415
1516export type DiffViewProps < T > = {
1617 data ?: {
1718 oldFile ?: { fileName ?: string | null ; fileLang ?: DiffHighlighterLang | string | null ; content ?: string | null } ;
1819 newFile ?: { fileName ?: string | null ; fileLang ?: DiffHighlighterLang | string | null ; content ?: string | null } ;
1920 hunks : string [ ] ;
2021 } ;
21- extendData ?: { oldFile ?: Record < string , { data : T } > ; newFile ?: Record < string , { data : T } > } ;
22+ extendData ?: { oldFile ?: Record < string , { data : T } | undefined > ; newFile ?: Record < string , { data : T } | undefined > } ;
23+ initialWidgetState ?: { side : SplitSide ; lineNumber : number } ;
2224 diffFile ?: DiffFile ;
2325 class ?: string ;
2426 style ?: JSX . CSSProperties ;
@@ -56,15 +58,30 @@ export type DiffViewProps<T> = {
5658 onAddWidgetClick ?: ( lineNumber : number , side : SplitSide ) => void ;
5759} ;
5860
59- export const DiffView = < T extends unknown > ( props : DiffViewProps < T > ) => {
61+ type DiffViewProps_1 < T > = Omit < DiffViewProps < T > , "data" > & {
62+ data ?: {
63+ oldFile ?: { fileName ?: string | null ; fileLang ?: DiffHighlighterLang | null ; content ?: string | null } ;
64+ newFile ?: { fileName ?: string | null ; fileLang ?: DiffHighlighterLang | null ; content ?: string | null } ;
65+ hunks : string [ ] ;
66+ } ;
67+ } ;
68+
69+ type DiffViewProps_2 < T > = Omit < DiffViewProps < T > , "data" > & {
70+ data ?: {
71+ oldFile ?: { fileName ?: string | null ; fileLang ?: string | null ; content ?: string | null } ;
72+ newFile ?: { fileName ?: string | null ; fileLang ?: string | null ; content ?: string | null } ;
73+ hunks : string [ ] ;
74+ } ;
75+ } ;
76+
77+ const InternalDiffView = < T extends unknown > ( props : DiffViewProps < T > ) => {
6078 const getInstance = ( ) => {
79+ let diffFile : DiffFile | null = null ;
6180 if ( props . diffFile ) {
62- const diffFile = DiffFile . createInstance ( { } ) ;
81+ diffFile = DiffFile . createInstance ( { } ) ;
6382 diffFile . _mergeFullBundle ( props . diffFile . _getFullBundle ( ) ) ;
64- return diffFile ;
65- }
66- if ( props . data )
67- return new DiffFile (
83+ } else if ( props . data ) {
84+ diffFile = new DiffFile (
6885 props . data . oldFile ?. fileName || "" ,
6986 props . data . oldFile ?. content || "" ,
7087 props . data . newFile ?. fileName || "" ,
@@ -73,16 +90,164 @@ export const DiffView = <T extends unknown>(props: DiffViewProps<T>) => {
7390 props . data . oldFile ?. fileLang || "" ,
7491 props . data . newFile ?. fileLang || ""
7592 ) ;
76- return null ;
93+ }
94+
95+ onCleanup ( ( ) => diffFile ?. clear ?.( ) ) ;
96+
97+ return diffFile ;
7798 } ;
7899
79- const [ diffFile , setDiffFile ] = createSignal ( getInstance ( ) ) ;
100+ let wrapperRef : HTMLDivElement | undefined ;
101+
102+ const diffFile = createMemo ( getInstance ) ;
103+
104+ const [ isMounted , setIsMounted ] = createSignal ( false ) ;
105+
106+ createEffect ( ( ) => {
107+ setIsMounted ( true ) ;
108+ } ) ;
109+
110+ const [ widgetState , setWidgetState ] = createSignal < { side ?: SplitSide ; lineNumber ?: number } > ( {
111+ side : props . initialWidgetState ?. side ,
112+ lineNumber : props . initialWidgetState ?. lineNumber ,
113+ } ) ;
114+
115+ const reactiveHook = createDiffConfigStore ( props , diffFile ( ) ?. getId ( ) || "" ) ;
116+
117+ createEffect ( ( ) => {
118+ const {
119+ setId,
120+ setEnableAddWidget,
121+ setEnableHighlight,
122+ setEnableWrap,
123+ setExtendData,
124+ setFontSize,
125+ setIsIsMounted,
126+ setMode,
127+ setOnAddWidgetClick,
128+ setRenderExtendLine,
129+ setRenderWidgetLine,
130+ } = reactiveHook . getReadonlyState ( ) ;
131+ const currentDiffFile = diffFile ( ) ;
132+
133+ setId ( currentDiffFile ?. getId ( ) || "" ) ;
134+
135+ setEnableAddWidget ( ! ! props . diffViewAddWidget ) ;
136+
137+ setEnableHighlight ( ! ! props . diffViewHighlight ) ;
138+
139+ setEnableWrap ( ! ! props . diffViewWrap ) ;
80140
81- createRenderEffect ( ( ) => {
82- diffFile ( ) ?. clear ( ) ;
141+ setFontSize ( props . diffViewFontSize || 14 ) ;
83142
84- setDiffFile ( getInstance ( ) ) ;
143+ setIsIsMounted ( isMounted ( ) ) ;
144+
145+ setMode ( props . diffViewMode || DiffModeEnum . Split ) ;
146+
147+ setOnAddWidgetClick ( { current : props . onAddWidgetClick } ) ;
148+
149+ setRenderExtendLine ( props . renderExtendLine ) ;
150+
151+ setRenderWidgetLine ( props . renderWidgetLine ) ;
152+
153+ setExtendData ( props . extendData ) ;
154+ } ) ;
155+
156+ createEffect ( ( ) => {
157+ if ( props . initialWidgetState ) {
158+ setWidgetState ( {
159+ side : props . initialWidgetState . side ,
160+ lineNumber : props . initialWidgetState . lineNumber ,
161+ } ) ;
162+ }
85163 } ) ;
86164
87- return < div > DiffView</ div > ;
165+ const initSubscribe = ( ) => {
166+ const mounted = isMounted ( ) ;
167+ const currentDiffFile = diffFile ( ) ;
168+ if ( mounted && props . diffFile && currentDiffFile ) {
169+ props . diffFile . _addClonedInstance ( currentDiffFile ) ;
170+ onCleanup ( ( ) => props . diffFile ?. _delClonedInstance ( currentDiffFile ) ) ;
171+ }
172+ } ;
173+
174+ const initDiff = ( ) => {
175+ const mounted = isMounted ( ) ;
176+ const currentDiffFile = diffFile ( ) ;
177+ if ( mounted && currentDiffFile ) {
178+ currentDiffFile . initTheme ( props . diffViewTheme ) ;
179+ currentDiffFile . initRaw ( ) ;
180+ currentDiffFile . buildSplitDiffLines ( ) ;
181+ currentDiffFile . buildUnifiedDiffLines ( ) ;
182+ }
183+ } ;
184+
185+ const initSyntax = ( ) => {
186+ const mounted = isMounted ( ) ;
187+ const currentDiffFile = diffFile ( ) ;
188+ if ( mounted && currentDiffFile && props . diffViewHighlight ) {
189+ currentDiffFile . initSyntax ( { registerHighlighter : props . registerHighlighter } ) ;
190+ currentDiffFile . notifyAll ( ) ;
191+ }
192+ } ;
193+
194+ const initAttribute = ( ) => {
195+ const mounted = isMounted ( ) ;
196+ const currentDiffFile = diffFile ( ) ;
197+ if ( mounted && currentDiffFile && wrapperRef ) {
198+ const cb = currentDiffFile . subscribe ( ( ) => {
199+ wrapperRef ?. setAttribute ( "data-theme" , currentDiffFile . _getTheme ( ) || "light" ) ;
200+ wrapperRef ?. setAttribute ( "data-highlighter" , currentDiffFile . _getHighlighterName ( ) ) ;
201+ } ) ;
202+
203+ onCleanup ( ( ) => cb ( ) ) ;
204+ }
205+ } ;
206+
207+ createEffect ( initSubscribe ) ;
208+
209+ createEffect ( initDiff ) ;
210+
211+ createEffect ( initSyntax ) ;
212+
213+ createEffect ( initAttribute ) ;
214+
215+ onCleanup ( ( ) => reactiveHook . clear ( ) ) ;
216+
217+ return (
218+ < div
219+ class = "diff-tailwindcss-wrapper"
220+ data-component = "git-diff-view"
221+ data-theme = { diffFile ( ) ?. _getTheme ?.( ) || "light" }
222+ data-version = { __VERSION__ }
223+ data-highlighter = { diffFile ( ) ?. _getHighlighterName ?.( ) }
224+ ref = { wrapperRef }
225+ >
226+ < DiffViewContext . Provider value = { reactiveHook } >
227+ < DiffWidgetContext . Provider value = { widgetState } >
228+ < div class = "diff-style-root" style = { { [ diffFontSizeName ] : ( props . diffViewFontSize || 14 ) + "px" } } >
229+ < div
230+ id = { isMounted ( ) ? `diff-root${ diffFile ( ) ?. getId ( ) } ` : undefined }
231+ class = { "diff-view-wrapper" + ( props . class ? ` ${ props . class } ` : "" ) }
232+ style = { props . style }
233+ >
234+ { /* {!props.diffViewMode || props.diffViewMode & DiffModeEnum.Split ? (
235+ <DiffSplitView key={DiffModeEnum.Split} diffFile={diffFile.value as DiffFile} />
236+ ) : (
237+ <DiffUnifiedView key={DiffModeEnum.Unified} diffFile={diffFile.value as DiffFile} />
238+ )} */ }
239+ </ div >
240+ </ div >
241+ </ DiffWidgetContext . Provider >
242+ </ DiffViewContext . Provider >
243+ </ div >
244+ ) ;
88245} ;
246+
247+ function SolidDiffView < T > ( props : DiffViewProps_1 < T > ) : JSXElement ;
248+ function SolidDiffView < T > ( props : DiffViewProps_2 < T > ) : JSXElement ;
249+ function SolidDiffView < T > ( props : DiffViewProps < T > ) : JSXElement {
250+ return < InternalDiffView { ...props } /> ;
251+ }
252+
253+ export const DiffView = SolidDiffView ;
0 commit comments