Easy, powerful boxes and arrows diagrams using text

Simple diagrams are easy, complex diagrams are possible. Easy to update, version control, and collaborate on. All using a text-based language for humans.

Simple diagrams are easy
     arrow "source" "code"
LA:  box "lexical" "analyzer"
     arrow "tokens" above
P:   box "parser"
     arrow "AST"
Sem: box "semantic" "checker"
     arrow

     arrow <-> up from top of LA
LC:  box "lexical" "corrector"
     arrow <-> up from top of P
Syn: box "syntactic" "corrector"
     arrow up
DMP: box "diagnostic" "message" "printer"
     arrow <-> right from right of DMP
ST:  box "symbol" "table"
     arrow from LC.ne to DMP.sw
     arrow from Sem.nw to DMP.se
     arrow <-> from Sem.top to ST.bot
Complex diagrams are possible
# Source: https://docs.microsoft.com/en-us/azure/architecture/solution-ideas/media/advanced-analytics-on-big-data.png
# Source: https://docs.microsoft.com/en-us/azure/architecture/icons/

ILogs:          icon name "azure_10801-icon-service-Files" "Logs, files and" "media (unstructured)"
IBrowser:       icon name "azure_10783-icon-service-Browser" "Business/custom" "apps (structured)" \
                with .n at ILogs.s + (0, 200)
IDataFactory:   icon name "azure_10126-icon-service-Data-Factory" "Azure" "Data Factory" \
                with .c at (ILogs.e.x + 200, (ILogs.c.y + IBrowser.c.y) / 2)
IStorage:       icon name "azure_10090-icon-service-Data-Lake-Storage-Gen1" "Azure Data" "Lake Storage" \
                with .c at IDataFactory.c + (150, 0)
IDataBricks:    icon name "azure_10787-icon-service-Azure-Databricks" "Azure" "Databricks" \
                with .c at IStorage.c + (150, 0)
ICosmosDB:      icon name "azure_10121-icon-service-Azure-Cosmos-DB" "Azure" "Cosmos DB" \
                with .c at IDataBricks.c + (150, 150)
IWebApp:        icon name "azure_10803-icon-service-Folder-Website" "Web" "Application" \
                with .c at ICosmosDB.c + (150, 0)
IPowerBI:       icon name "azure_10148-icon-service-Analysis-Services" "Power BI" \
                with .c at IWebApp - (0, 150)
ISynAna:        icon name "azure_00606-icon-service-Azure-Synapse-Analytics" "Azure Synapse" "Analytics" \
                with .c at IDataBricks - (-150, 150)
IAnalysis:      icon name "azure_10148-icon-service-Analysis-Services" "Azure Analysis" "Services" \
                with .c at ISynAna + (150, 0)

A0a: arrow from ILogs.e + (20, 0) right 100 then down (IDataFactory.w.y - ILogs.e.y) to IDataFactory.w - (10, 0) \
        stroke darkgray
A0b: arrow from IBrowser.e + (20, 0) right 100 then up (IBrowser.e.y - IDataFactory.w.y) to IDataFactory.w - (10, 0) \
        stroke darkgray
A1: arrow "(1)" from IDataFactory.e + (20, 0) to IStorage.w - (10, 0) stroke darkgray
A2: arrow "(2)" from IStorage.e + (20, 0) to IDataBricks.w - (10, 0) stroke darkgray
text "(3)" with .nw at IDataBricks.nw - (20, 10)
A4: arrow <- from IDataBricks.e + (35, -20) right (ICosmosDB.n.y - IDataBricks.e.y - 35) up to ISynAna.s + (0, 40) stroke darkgrey
text "(4)" with .c at (A4.end.x, A4.end.y + 30) fill white

A5: arrow "(5)" from IDataBricks.e + (20, 0) to IPowerBI.w - (20, 0) stroke darkgray
A6: arrow "(6)" from IAnalysis.s + (0, 30) down to IPowerBI.n stroke darkgray
A7: arrow <-> from A4.start + (0, 40) right (ICosmosDB.n.y - IDataBricks.e.y - 35) down to ICosmosDB.n - (0, 10) stroke darkgrey
text "(7)" with .c at (A7.end.x, A7.end.y - 30) fill white

Ingest: box \
    from IDataFactory.nw - (30, 10) \
    to IDataFactory.se + (30, 40) \
    fill grey 0.1 stroke none
text "Ingest" with .nw at Ingest.nw - (0, 25)

Store: box \
    with .nw at IStorage.nw - (30, 10) \
    width Ingest.width \
    height Ingest.height \
    fill grey 0.1 stroke none
text "Store" with .nw at Store.nw - (0, 20)

PrepAndTrain: box \
    with .nw at IDataBricks.nw - (30, 10) \
    width Ingest.width \
    height Ingest.height \
    fill grey 0.1 stroke none
text "Prep and train" with .nw at PrepAndTrain.nw - (0, 25)

CosmosDBBackground: box \
    with .nw at ICosmosDB.nw - (30, 10) \
    width Ingest.width \
    height Ingest.height \
    fill grey 0.1 stroke none

PowerBIBackground: box \
    with .nw at IPowerBI.nw - (30, 10) \
    width Ingest.width \
    height Ingest.height \
    fill grey 0.1 stroke none

ModelAndServeBackground: box \
    from ISynAna.nw - (40, 10) \
    to IAnalysis.se + (50, 50)\
    width Ingest.width \
    height Ingest.height \
    fill grey 0.1 stroke none
text "Model and serve" with .nw at ModelAndServeBackground.nw - (0, 20)