@@ -394,6 +394,102 @@ func (b *Builder) renderEntityPage(
394394 title := e .GetString ("title" )
395395 description := e .GetString ("description" )
396396
397+ // Entity profile chart data (compact format for JS)
398+ profileData := map [string ]interface {}{}
399+ if lc := e .GetInt ("line_count" ); lc > 0 {
400+ profileData ["lc" ] = lc
401+ }
402+ if co := e .GetInt ("call_count" ); co > 0 {
403+ profileData ["co" ] = co
404+ }
405+ if cb := e .GetInt ("called_by_count" ); cb > 0 {
406+ profileData ["cb" ] = cb
407+ }
408+ if ic := e .GetInt ("import_count" ); ic > 0 {
409+ profileData ["ic" ] = ic
410+ }
411+ if ib := e .GetInt ("imported_by_count" ); ib > 0 {
412+ profileData ["ib" ] = ib
413+ }
414+ if fn := e .GetInt ("function_count" ); fn > 0 {
415+ profileData ["fn" ] = fn
416+ }
417+ if cl := e .GetInt ("class_count" ); cl > 0 {
418+ profileData ["cl" ] = cl
419+ }
420+ if tc := e .GetInt ("type_count" ); tc > 0 {
421+ profileData ["tc" ] = tc
422+ }
423+ if fc := e .GetInt ("file_count" ); fc > 0 {
424+ profileData ["fc" ] = fc
425+ }
426+ if sl := e .GetInt ("start_line" ); sl > 0 {
427+ profileData ["sl" ] = sl
428+ }
429+ if el := e .GetInt ("end_line" ); el > 0 {
430+ profileData ["el" ] = el
431+ }
432+ // Edge type breakdown
433+ edgeTypes := map [string ]int {}
434+ if v := e .GetInt ("import_count" ); v > 0 {
435+ edgeTypes ["imports" ] = v
436+ }
437+ if v := e .GetInt ("imported_by_count" ); v > 0 {
438+ edgeTypes ["imports" ] += v
439+ }
440+ if v := e .GetInt ("call_count" ); v > 0 {
441+ edgeTypes ["calls" ] = v
442+ }
443+ if v := e .GetInt ("called_by_count" ); v > 0 {
444+ edgeTypes ["calls" ] += v
445+ }
446+ if v := e .GetInt ("function_count" ); v > 0 {
447+ edgeTypes ["defines" ] += v
448+ }
449+ if v := e .GetInt ("class_count" ); v > 0 {
450+ edgeTypes ["defines" ] += v
451+ }
452+ if v := e .GetInt ("type_count" ); v > 0 {
453+ edgeTypes ["defines" ] += v
454+ }
455+ if len (edgeTypes ) > 0 {
456+ profileData ["et" ] = edgeTypes
457+ }
458+ var entityChartJSON []byte
459+ if len (profileData ) > 0 {
460+ entityChartJSON , _ = json .Marshal (profileData )
461+ }
462+
463+ // Source code (read from workspace if available)
464+ var sourceCode , sourceLang string
465+ if filePath := e .GetString ("file_path" ); filePath != "" {
466+ if sl := e .GetInt ("start_line" ); sl > 0 {
467+ if el := e .GetInt ("end_line" ); el > 0 {
468+ sourceDir := b .cfg .Paths .SourceDir
469+ if sourceDir != "" {
470+ fullPath := filepath .Join (sourceDir , filePath )
471+ if data , err := os .ReadFile (fullPath ); err == nil {
472+ lines := strings .Split (string (data ), "\n " )
473+ if sl <= len (lines ) && el <= len (lines ) {
474+ sourceCode = strings .Join (lines [sl - 1 :el ], "\n " )
475+ }
476+ }
477+ }
478+ }
479+ }
480+ sourceLang = e .GetString ("language" )
481+ if sourceLang == "" {
482+ ext := filepath .Ext (filePath )
483+ langMap := map [string ]string {
484+ ".js" : "javascript" , ".ts" : "typescript" , ".tsx" : "typescript" ,
485+ ".py" : "python" , ".go" : "go" , ".rs" : "rust" , ".java" : "java" ,
486+ ".rb" : "ruby" , ".php" : "php" , ".c" : "c" , ".cpp" : "cpp" ,
487+ ".cs" : "csharp" , ".swift" : "swift" , ".kt" : "kotlin" ,
488+ }
489+ sourceLang = langMap [ext ]
490+ }
491+ }
492+
397493 ctx := render.EntityPageContext {
398494 Site : b .cfg .Site ,
399495 Entity : e ,
@@ -410,6 +506,9 @@ func (b *Builder) renderEntityPage(
410506 AllTaxonomies : taxonomies ,
411507 ValidSlugs : validSlugs ,
412508 Contributors : contributors ,
509+ ChartData : template .JS (entityChartJSON ),
510+ SourceCode : sourceCode ,
511+ SourceLang : sourceLang ,
413512 CTA : b .cfg .Extra .CTA ,
414513 OG : render.OGMeta {
415514 Title : title + " \u2014 " + b .cfg .Site .Name ,
@@ -551,7 +650,7 @@ func (b *Builder) renderTaxonomyPages(
551650 Type : "article" ,
552651 SiteName : b .cfg .Site .Name ,
553652 },
554- ChartData : template .HTML (hubChartJSON ),
653+ ChartData : template .JS (hubChartJSON ),
555654 CTA : b .cfg .Extra .CTA ,
556655 }
557656
@@ -650,7 +749,7 @@ func (b *Builder) renderTaxonomyPages(
650749 Type : "article" ,
651750 SiteName : b .cfg .Site .Name ,
652751 },
653- ChartData : template .HTML (taxChartJSON ),
752+ ChartData : template .JS (taxChartJSON ),
654753 CTA : b .cfg .Extra .CTA ,
655754 }
656755
@@ -724,7 +823,7 @@ func (b *Builder) renderTaxonomyPages(
724823 Type : "article" ,
725824 SiteName : b .cfg .Site .Name ,
726825 },
727- ChartData : template .HTML (letterChartJSON ),
826+ ChartData : template .JS (letterChartJSON ),
728827 CTA : b .cfg .Extra .CTA ,
729828 }
730829
@@ -845,9 +944,9 @@ func (b *Builder) renderAllEntitiesPages(
845944 jsonLD := schema .MarshalSchemas (collectionSchema , breadcrumbSchema )
846945
847946 // Only include chart data on page 1
848- var pageChartData template.HTML
947+ var pageChartData template.JS
849948 if page == 1 {
850- pageChartData = template .HTML (chartJSON )
949+ pageChartData = template .JS (chartJSON )
851950 }
852951
853952 ctx := render.AllEntitiesPageContext {
@@ -911,30 +1010,112 @@ func (b *Builder) renderHomepage(
9111010 }
9121011 imageURL := shareImageURL (b .cfg .Site .BaseURL , "homepage.svg" )
9131012
914- // Chart data: treemap of taxonomies -> entries
915- type chartEntry struct {
1013+ // Chart data: treemap of taxonomies
1014+ type chartTax struct {
9161015 Name string `json:"name"`
9171016 Count int `json:"count"`
918- }
919- type chartTax struct {
920- Label string `json:"label"`
921- TopEntries []chartEntry `json:"topEntries"`
1017+ Slug string `json:"slug"`
9221018 }
9231019 type homepageChart struct {
9241020 Taxonomies []chartTax `json:"taxonomies"`
9251021 TotalEntities int `json:"totalEntities"`
9261022 }
9271023 var chartTaxonomies []chartTax
9281024 for _ , tax := range taxonomies {
929- top := taxonomy .TopEntries (tax .Entries , 10 )
930- var entries []chartEntry
931- for _ , e := range top {
932- entries = append (entries , chartEntry {Name : e .Name , Count : len (e .Entities )})
1025+ totalCount := 0
1026+ for _ , entry := range tax .Entries {
1027+ totalCount += len (entry .Entities )
9331028 }
934- chartTaxonomies = append (chartTaxonomies , chartTax {Label : tax .Label , TopEntries : entries })
1029+ chartTaxonomies = append (chartTaxonomies , chartTax {
1030+ Name : tax .Label ,
1031+ Count : totalCount ,
1032+ Slug : tax .Name ,
1033+ })
9351034 }
9361035 chartJSON , _ := json .Marshal (homepageChart {Taxonomies : chartTaxonomies , TotalEntities : len (entities )})
9371036
1037+ // Architecture overview: domain/subdomain force graph
1038+ type archNode struct {
1039+ ID string `json:"id"`
1040+ Name string `json:"name"`
1041+ Type string `json:"type"`
1042+ Count int `json:"count"`
1043+ Slug string `json:"slug,omitempty"`
1044+ }
1045+ type archLink struct {
1046+ Source string `json:"source"`
1047+ Target string `json:"target"`
1048+ }
1049+ type archOverview struct {
1050+ Nodes []archNode `json:"nodes"`
1051+ Links []archLink `json:"links"`
1052+ }
1053+
1054+ var archNodes []archNode
1055+ var archLinks []archLink
1056+
1057+ // Root node is the repo/site
1058+ rootID := "__root__"
1059+ archNodes = append (archNodes , archNode {ID : rootID , Name : b .cfg .Site .Name , Type : "root" , Count : len (entities )})
1060+
1061+ // Find subdomain -> domain parent relationships
1062+ subdomainParent := make (map [string ]string ) // subdomain name -> domain name
1063+ for _ , tax := range taxonomies {
1064+ if tax .Name == "subdomain" {
1065+ for _ , entry := range tax .Entries {
1066+ parentDomain := ""
1067+ if len (entry .Entities ) > 0 {
1068+ parentDomain = entry .Entities [0 ].GetString ("domain" )
1069+ }
1070+ subdomainParent [entry .Name ] = parentDomain
1071+ }
1072+ }
1073+ }
1074+
1075+ // Add domain nodes
1076+ for _ , tax := range taxonomies {
1077+ if tax .Name == "domain" {
1078+ for _ , entry := range tax .Entries {
1079+ nodeID := "domain:" + entry .Slug
1080+ archNodes = append (archNodes , archNode {
1081+ ID : nodeID ,
1082+ Name : entry .Name ,
1083+ Type : "domain" ,
1084+ Count : len (entry .Entities ),
1085+ Slug : "domain/" + entry .Slug ,
1086+ })
1087+ archLinks = append (archLinks , archLink {Source : rootID , Target : nodeID })
1088+ }
1089+ }
1090+ }
1091+ // Add subdomain nodes
1092+ for _ , tax := range taxonomies {
1093+ if tax .Name == "subdomain" {
1094+ for _ , entry := range tax .Entries {
1095+ nodeID := "subdomain:" + entry .Slug
1096+ archNodes = append (archNodes , archNode {
1097+ ID : nodeID ,
1098+ Name : entry .Name ,
1099+ Type : "subdomain" ,
1100+ Count : len (entry .Entities ),
1101+ Slug : "subdomain/" + entry .Slug ,
1102+ })
1103+ parentDomain := subdomainParent [entry .Name ]
1104+ if parentDomain != "" {
1105+ parentSlug := entity .ToSlug (parentDomain )
1106+ archLinks = append (archLinks , archLink {Source : "domain:" + parentSlug , Target : nodeID })
1107+ } else {
1108+ archLinks = append (archLinks , archLink {Source : rootID , Target : nodeID })
1109+ }
1110+ }
1111+ }
1112+ }
1113+
1114+ var archJSON []byte
1115+ if len (archNodes ) > 1 {
1116+ archJSON , _ = json .Marshal (archOverview {Nodes : archNodes , Links : archLinks })
1117+ }
1118+
9381119 // JSON-LD
9391120 websiteSchema := schemaGen .GenerateWebSiteSchema (imageURL )
9401121
@@ -970,7 +1151,8 @@ func (b *Builder) renderHomepage(
9701151 Type : "website" ,
9711152 SiteName : b .cfg .Site .Name ,
9721153 },
973- ChartData : template .HTML (chartJSON ),
1154+ ChartData : template .JS (chartJSON ),
1155+ ArchData : template .JS (archJSON ),
9741156 CTA : b .cfg .Extra .CTA ,
9751157 }
9761158
0 commit comments