### Install golangci-lint using curl Source: https://github.com/dimelords/idmllib/blob/main/LINTING.md Install the golangci-lint tool by downloading and executing the official installation script. This method is suitable for quick local setup. ```bash curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.55.2 ``` -------------------------------- ### Install golangci-lint Source: https://github.com/dimelords/idmllib/blob/main/README.md Instructions for installing the golangci-lint tool using different methods, including Go, Homebrew, and a shell script. ```bash # Install golangci-lint go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest # Or using homebrew on macOS brew install golangci-lint # Or using the install script curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.55.2 ``` -------------------------------- ### Install IDML Library Source: https://github.com/dimelords/idmllib/blob/main/README.md Install the IDML library using the Go get command. This command fetches the latest version of the library. ```bash go get github.com/dimelords/idmllib/v2 ``` -------------------------------- ### Install golangci-lint using go install Source: https://github.com/dimelords/idmllib/blob/main/LINTING.md Install the golangci-lint tool using the Go toolchain. This method integrates with your existing Go environment. ```bash go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.55.2 ``` -------------------------------- ### Verify golangci-lint Installation Source: https://github.com/dimelords/idmllib/blob/main/LINTING.md Check if golangci-lint has been installed correctly by displaying its version. This command confirms the installation and shows the active version. ```bash golangci-lint --version ``` -------------------------------- ### Run golangci-lint Source: https://github.com/dimelords/idmllib/blob/main/README.md Examples of how to run golangci-lint for code quality checks, including specifying timeouts, targeting specific files, and fixing auto-fixable issues. ```bash # Run all linting checks golangci-lint run # Run with specific timeout golangci-lint run --timeout=10m # Run on specific files or directories golangci-lint run ./pkg/idml/ # Fix auto-fixable issues golangci-lint run --fix ``` -------------------------------- ### Documented Go Struct Example Source: https://github.com/dimelords/idmllib/blob/main/ARCHITECTURE.md Example of a Go struct with detailed documentation for fields, including identification, configuration, child elements, and catch-all. ```go // MyElement represents a document element for XYZ. // This element controls ABC and is used for DEF. type MyElement struct { // Identification Self string `xml:"Self,attr"` // Unique identifier (e.g., "abc123") Name string `xml:"Name,attr"` // Display name // Configuration Enabled string `xml:"Enabled,attr,omitempty"` // Enable feature ("true"/"false") // Child elements Properties *Properties `xml:"Properties,omitempty"` // Optional properties // Catch-all OtherElements []RawXMLElement `xml:",any"` } ``` -------------------------------- ### Go Golden File Assertions Source: https://github.com/dimelords/idmllib/blob/main/testdata/golden/README.md Example of using the `testutil.NewGoldenFile` to assert actual output against a golden file, and how to update the golden file when the `-update` flag is present. ```go golden := testutil.NewGoldenFile(t, "testdata/golden") // Compare output against golden file golden.Assert(t, "my_test", actualOutput) // Update golden file (run with -update flag) golden.Update(t, "my_test", actualOutput) ``` -------------------------------- ### Debug XML Generation for ZIP Files Source: https://github.com/dimelords/idmllib/blob/main/docs/TEST_DEBUG.md This example shows how to create a debug-enabled ZIP archive using `testutil.CreateTestZIPWithDebug` for testing XML generation. The generated ZIP file will be preserved for inspection if the debug flag is enabled. ```go func TestXMLGeneration(t *testing.T) { files := map[string][]byte{ "designmap.xml": generateDesignmap(), "Stories/Story_u1d8.xml": generateStory(), } // Create debug ZIP zipPath := testutil.CreateTestZIPWithDebug(t, files, "generated.idml") // Test the generated ZIP... } ``` -------------------------------- ### Debug a Roundtrip Test Source: https://github.com/dimelords/idmllib/blob/main/docs/TEST_DEBUG.md This example demonstrates how to use `writeTestIDMLWithDebug` to preserve output during a roundtrip test. The output file is written with debug support, allowing for inspection if the `-preserve-test-output` flag is active. ```go func TestMyRoundtrip(t *testing.T) { pkg := loadTestIDML(t, "example.idml") // Write with debug preservation outputPath := writeTestIDMLWithDebug(t, pkg, "roundtrip_output.idml") // Read back pkg2, err := Read(outputPath) if err != nil { t.Fatalf("Failed to read back: %v", err) } // Compare... } ``` -------------------------------- ### Golden File Roundtrip Test Example Source: https://github.com/dimelords/idmllib/blob/main/ARCHITECTURE.md Verify byte-perfect IDML roundtrips by comparing the original file with the re-written output. This test ensures no data corruption during parsing and marshaling. ```Go func TestGoldenRoundtrip(t *testing.T) { // Read original IDML original := readIDML("plain.idml") // Parse and re-write pkg, _ := idml.OpenIDML("plain.idml") idml.WriteIDML(pkg, "output.idml") // Compare byte-for-byte assertIdentical(t, original, output) } ``` -------------------------------- ### Migrate from Old CLI to New TUI Menu Selection Source: https://github.com/dimelords/idmllib/blob/main/docs/CLI_TUI_ARCHITECTURE.md Demonstrates the transition from using `fmt.Println` for menu options and `reader.ReadString` for choice to the TUI `Menu` component. ```go fmt.Println("1. Option A") fmt.Println("2. Option B") fmt.Print("Choice: ") choice, _ := reader.ReadString('\n') ``` ```go menu := tui.NewMenu([]MenuItem{ {Title: "Option A"}, {Title: "Option B"}, }) p := tea.NewProgram(menu) m, _ := p.Run() selected := m.(*tui.Menu).GetSelected() ``` -------------------------------- ### Create New IDML Document from Template Source: https://github.com/dimelords/idmllib/blob/main/pkg/idml/templates/README.md Demonstrates how to create a new IDML package using default templates or with custom options. The generated package can then be modified and written to a file. ```Go pkg, err := idml.NewFromTemplate(nil) // uses defaults // Or with custom options pkg, err := idml.NewFromTemplate(&idml.TemplateOptions{ DOMVersion: "20.4", UseMinimalTemplates: true, }) // Modify the document as needed doc, _ := pkg.Document() // ... make changes ... // Write to file err = idml.Write(pkg, "output.idml") ``` -------------------------------- ### Run Go Tests Source: https://github.com/dimelords/idmllib/blob/main/ARCHITECTURE.md Execute the Go test suite to verify the implementation of new elements and other changes. ```bash go test ./pkg/idml/ ``` -------------------------------- ### Run Go Tests for Project Source: https://github.com/dimelords/idmllib/blob/main/ARCHITECTURE.md Execute all Go tests within the project. ```bash # Test go test ./... ``` -------------------------------- ### Run Linting with Specific Configuration Source: https://github.com/dimelords/idmllib/blob/main/LINTING.md Run the linting process using a specified configuration file. This is useful for testing or using a different configuration than the default. ```bash golangci-lint run --config=.golangci.yml ``` -------------------------------- ### Progressive Enhancement with Alt-Screen Source: https://github.com/dimelords/idmllib/blob/main/docs/CLI_TUI_ARCHITECTURE.md Demonstrates two ways to run a Bubbletea program: using an alternative screen for immersive experiences or the regular screen for simpler flows. This allows for graceful degradation based on terminal capabilities. ```go // Use alt-screen for immersive experiences p := tea.NewProgram(model, tea.WithAltScreen()) // Regular screen for simple flows p := tea.NewProgram(model) ``` -------------------------------- ### Reusable Text Input Component Source: https://github.com/dimelords/idmllib/blob/main/docs/CLI_TUI_ARCHITECTURE.md Demonstrates the creation and usage of a reusable text input component. It initializes the component with a prompt and placeholder, runs it through the Bubbletea program, and retrieves the final value. ```go input := tui.NewTextInput("Enter filename:", "output.idml") p := tea.NewProgram(input) m, _ := p.Run() finalInput := m.(*tui.TextInput) value := finalInput.GetValue() ``` -------------------------------- ### Run Go Tests Source: https://github.com/dimelords/idmllib/blob/main/README.md Commands for running Go tests, including options for coverage, race detection, generating HTML reports, and targeting specific packages. ```bash # Run all tests go test ./... # Run with coverage go test -cover ./... # Run with race detection and coverage go test -v -race -coverprofile=coverage.out ./... # Generate HTML coverage report go tool cover -html=coverage.out -o coverage.html # Run specific package tests go test ./pkg/idml -v # Update golden files when intentionally changing output UPDATE_GOLDEN=1 go test ./pkg/idml ``` -------------------------------- ### Build and Run CLI Tool Source: https://github.com/dimelords/idmllib/blob/main/README.md Commands to build the project's CLI tool and run it interactively for exploring and manipulating IDML files. ```bash # Build the CLI go build -o bin/idmllib ./cmd/cli # Run interactively ./bin/idmllib ``` -------------------------------- ### Create New IDML Document Source: https://github.com/dimelords/idmllib/blob/main/ARCHITECTURE.md Initialize a new IDML document using the `idml.NewDocument()` function. ```go // Create new document doc := idml.NewDocument() ``` -------------------------------- ### Running IDMLib Tests Source: https://github.com/dimelords/idmllib/blob/main/ARCHITECTURE.md Execute tests using standard Go commands. Options include running all tests, verbose output, targeting specific tests, and checking code coverage. ```Bash # All tests go test ./pkg/idml/ # Verbose output go test -v ./pkg/idml/ # Specific test go test -v -run TestDocumentRoundtrip ./pkg/idml/ # Coverage go test -cover ./pkg/idml/ ``` -------------------------------- ### Lint Project with GolangCI-Lint Source: https://github.com/dimelords/idmllib/blob/main/ARCHITECTURE.md Run the golangci-lint tool to check for code style and potential issues. ```bash # Lint (if golangci-lint installed) golangci-lint run ``` -------------------------------- ### Create New Paragraph Style Source: https://github.com/dimelords/idmllib/blob/main/ARCHITECTURE.md Create a new paragraph style with specified options. ```go // Create style doc.CreateParagraphStyle("Custom", styleOpts) ``` -------------------------------- ### IDML Build Layered Architecture Diagram Source: https://github.com/dimelords/idmllib/blob/main/ARCHITECTURE.md Illustrates the layered design of the IDML Build project, showing the progression from the Go standard library to internal utilities and the core pkg/idml package, with future high-level APIs planned. ```text ┌─────────────────────────────────────┐ │ High-Level APIs (Future) │ │ - Document manipulation │ │ - Style management │ │ - Content creation │ └─────────────────────────────────────┘ ↓ ┌─────────────────────────────────────┐ │ pkg/idml (Current Focus) │ │ - Document struct (designmap.xml) │ │ - Parse/Marshal functions │ │ - Type-safe element access │ └─────────────────────────────────────┘ ↓ ┌─────────────────────────────────────┐ │ internal/xmlutil │ │ - XML utilities │ │ - Namespace handling │ └─────────────────────────────────────┘ ↓ ┌─────────────────────────────────────┐ │ Go Standard Library │ │ - encoding/xml │ │ - archive/zip │ └─────────────────────────────────────┘ ``` -------------------------------- ### Modify IDML Content and Save Source: https://github.com/dimelords/idmllib/blob/main/README.md Shows how to create a new story, add it to an existing IDML package, and then write the modified package to a new IDML file. Ensure correct file paths for reading and writing. ```go package main import ( "log" "github.com/dimelords/idmllib/v2/pkg/idml" "github.com/dimelords/idmllib/v2/pkg/story" ) func main() { pkg, err := idml.Read("document.idml") if err != nil { log.Fatal(err) } // Create a new story newStory := &story.Story{} newStory.StoryElement.Self = "u1234" newStory.StoryElement.ParagraphStyleRanges = []story.ParagraphStyleRange{ { AppliedParagraphStyle: "ParagraphStyle/$ID/NormalParagraphStyle", CharacterStyleRanges: []story.CharacterStyleRange{ story.NewCharacterStyleRange( "CharacterStyle/$ID/[No character style]", "Hello, World!", ), }, }, } // Add the story to the package err = pkg.AddStory("Stories/Story_u1234.xml", newStory) if err != nil { log.Fatal(err) } // Save the modified document err = idml.Write(pkg, "output.idml") if err != nil { log.Fatal(err) } } ``` -------------------------------- ### Read and Inspect IDML Files Source: https://github.com/dimelords/idmllib/blob/main/README.md Demonstrates how to read an IDML file, access its document structure, and inspect properties of stories and spreads. Ensure the file path is correct. ```go package main import ( "log" "github.com/dimelords/idmllib/v2/pkg/idml" ) func main() { // Read an IDML file pkg, err := idml.Read("document.idml") if err != nil { log.Fatal(err) } // Access parsed document structure doc, err := pkg.Document() if err != nil { log.Fatal(err) } // Inspect document properties log.Printf("Document version: %s", doc.Version) log.Printf("Stories: %d", len(doc.Stories)) log.Printf("Spreads: %d", len(doc.Spreads)) // Access a story story, err := pkg.Story("Stories/Story_u123.xml") if err != nil { log.Fatal(err) } log.Printf("Story has %d paragraph ranges", len(story.StoryElement.ParagraphStyleRanges)) // Access a spread spread, err := pkg.Spread("Spreads/Spread_ue6.xml") if err != nil { log.Fatal(err) } log.Printf("Spread has %d text frames", len(spread.InnerSpread.TextFrames)) } ``` -------------------------------- ### Migrate from Old CLI to New TUI Text Input Source: https://github.com/dimelords/idmllib/blob/main/docs/CLI_TUI_ARCHITECTURE.md Shows how to replace the old `fmt.Scan` pattern for reading string input with the new TUI `TextInput` component. ```go fmt.Print("Enter value: ") value, _ := reader.ReadString('\n') value = strings.TrimSpace(value) ``` ```go input := tui.NewTextInput("Enter value:", "default") p := tea.NewProgram(input) m, _ := p.Run() value := m.(*tui.TextInput).GetValue() ``` -------------------------------- ### Embed Standard Templates Source: https://github.com/dimelords/idmllib/blob/main/pkg/idml/templates/README.md Shows how to embed standard IDML template files into a Go binary using `go:embed` directives. This makes the templates available at compile time without external file dependencies. ```Go //go:embed templates/standard/Preferences.xml var standardPreferences []byte //go:embed templates/standard/Styles.xml var standardStyles []byte ``` -------------------------------- ### Struct Tags for Catch-all XML Elements Source: https://github.com/dimelords/idmllib/blob/main/ARCHITECTURE.md Use `xml:",any"` to capture any unmarshalled XML elements into a slice. ```go // Catch-all OtherElements []RawXMLElement `xml:",any"` ``` -------------------------------- ### Create temporary IDML file with debug support Source: https://github.com/dimelords/idmllib/blob/main/docs/TEST_DEBUG.md Use `testutil.TempIDMLWithDebug` to create a temporary IDML file that will be preserved if the debug flag is set. This contrasts with `testutil.TempIDML` which cleans up automatically. ```go // Regular temporary file (auto-cleanup) outputPath := testutil.TempIDML(t, "output.idml") // Debug-enabled file (preserved if flag is set) outputPath := testutil.TempIDMLWithDebug(t, "output.idml") // Write IDML with debug support outputPath := writeTestIDMLWithDebug(t, pkg, "debug_output.idml") ``` -------------------------------- ### Add Page to Document Source: https://github.com/dimelords/idmllib/blob/main/ARCHITECTURE.md Add a new spread and a page to the document. ```go // Add page spread := doc.AddSpread() page := spread.AddPage() ``` -------------------------------- ### Search for Specific Content Source: https://github.com/dimelords/idmllib/blob/main/ARCHITECTURE.md Search the document for specific keywords or content. ```go // Find specific content results := doc.Search("keyword") ``` -------------------------------- ### Wizard Pattern with State Machine Source: https://github.com/dimelords/idmllib/blob/main/docs/CLI_TUI_ARCHITECTURE.md Implements a multi-step workflow using an enum-based state machine. The Update function handles user input to transition between different steps of the wizard. ```go type Step int const ( step1 Step = iota step2 step3 stepDone ) type Wizard struct { step Step // ... fields for each step } func (w *Wizard) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg := msg.(type) { case tea.KeyMsg: if msg.String() == "enter" { switch w.step { case step1: w.step = step2 case step2: w.step = step3 // ... } } } return w, nil } ``` -------------------------------- ### Create Document Wizard States Source: https://github.com/dimelords/idmllib/blob/main/docs/CLI_TUI_ARCHITECTURE.md Defines the enumerated states for the Create Document Wizard, representing each step in the multi-step process of creating a new document. ```go const ( stepPreset // Page size selection stepOrientation // Portrait/Landscape stepColumns // Column count stepGutter // Column spacing stepFilename // Output path stepCreating // Processing stepDone // Results ) ``` -------------------------------- ### Run All Linters Locally Source: https://github.com/dimelords/idmllib/blob/main/LINTING.md Execute all configured linters to check the codebase for quality issues. This command is the primary way to run linting checks locally. ```bash golangci-lint run ``` -------------------------------- ### Open IDML Package Source: https://github.com/dimelords/idmllib/blob/main/ARCHITECTURE.md Opens an IDML file, handling ZIP extraction and MIME type validation. Use this function to load an IDML package for further processing. ```go func OpenIDML(path string) (*Package, error) ``` -------------------------------- ### Write Document Tests Source: https://github.com/dimelords/idmllib/blob/main/ARCHITECTURE.md Implement Go tests for new elements, including roundtrip testing to ensure data integrity. ```go func TestDocumentNewElements(t *testing.T) { /* ... */ } func TestDocumentNewElementsRoundtrip(t *testing.T) { /* ... */ } ``` -------------------------------- ### Create and Update Golden Files Source: https://github.com/dimelords/idmllib/blob/main/testdata/golden/README.md Use this command to create or update golden files with the current test output. This is typically done on the first run or after intentional changes. ```bash go test ./pkg/idml/... -run TestGolden -update ``` -------------------------------- ### Compare Against Golden Files Source: https://github.com/dimelords/idmllib/blob/main/testdata/golden/README.md Run tests to compare current output against existing golden files. Failures indicate discrepancies that need review. ```bash go test ./pkg/idml/... -run TestGolden ``` -------------------------------- ### Result Display Pattern with Boxed Summary Source: https://github.com/dimelords/idmllib/blob/main/docs/CLI_TUI_ARCHITECTURE.md Renders a success screen using styled text and a bordered box to display summary details. It utilizes predefined styles for success messages and box borders. ```go func (w *Wizard) viewSuccess() string { var s strings.Builder s.WriteString(SuccessStyle.Render("✅ Success!")) s.WriteString("\n\n") details := fmt.Sprintf( "Info:\n"+ " Field 1: %s\n"+ " Field 2: %s\n", w.field1, w.field2, ) s.WriteString(BoxStyle.Render(details)) return s.String() } ``` -------------------------------- ### Unit Test for Wizard Navigation Source: https://github.com/dimelords/idmllib/blob/main/docs/CLI_TUI_ARCHITECTURE.md Tests the navigation logic of the wizard component, ensuring it correctly advances through steps upon user interaction. ```go func TestWizardNavigation(t *testing.T) { w := NewWizard() // Test initial state if w.step != step1 { t.Error("Wrong initial step") } // Simulate key press msg := tea.KeyMsg{Type: tea.KeyEnter} updated, _ := w.Update(msg) finalWizard := updated.(*Wizard) if finalWizard.step != step2 { t.Error("Should advance to step2") } } ``` -------------------------------- ### IDMLib Package Structure Source: https://github.com/dimelords/idmllib/blob/main/ARCHITECTURE.md The package structure follows a domain-driven design, with each directory representing a domain mirroring the IDML file structure. The 'pkg/idml' directory acts as the coordinator. ```treeview idmlbuild/ ├── pkg/ │ ├── idml/ # Core coordinator + public API │ │ ├── package.go # Package coordinator (file I/O, caching) │ │ ├── read.go # ZIP reading │ │ ├── write.go # ZIP writing │ │ ├── selection.go # Selection API for IDMS export │ │ ├── resourcemgr*.go # Resource management │ │ ├── errors.go # Error types │ │ └── *_test.go # Tests │ │ │ ├── common/ # Shared types across all domains │ │ └── types.go # RawXMLElement, Properties, PathGeometry │ │ │ ├── document/ # Document types (designmap.xml) │ │ ├── document.go # Document + 30 types (Language, Layer, etc.) │ │ ├── metadata.go # ProcessingInstruction, DocumentWithMetadata │ │ ├── parse.go # ParseDocument*(), MarshalDocument*() │ │ └── designmap.go # Legacy Designmap types (deprecated) │ │ │ ├── spread/ # Spread types (Spreads/*.xml) │ │ ├── spread.go # Spread, SpreadElement, Page │ │ ├── pageitems.go # TextFrame, Rectangle, Oval, Image, etc. │ │ ├── graphicline.go # GraphicLine │ │ └── parse.go # ParseSpread(), MarshalSpread() │ │ │ ├── story/ # Story types (Stories/*.xml) │ │ ├── story.go # Story, StoryElement, ParagraphStyleRange │ │ └── parse.go # ParseStory(), MarshalStory() │ │ │ ├── resources/ # Resource types (Resources/*.xml) │ │ ├── graphics.go # GraphicFile, Color, Swatch, Gradient, etc. │ │ ├── fonts.go # FontsFile, FontFamily, Font, etc. │ │ ├── styles.go # StylesFile, CharacterStyle, ParagraphStyle │ │ ├── parse_*.go # Parsing functions for each resource type │ │ └── errors.go # Resource-specific errors │ │ │ ├── analysis/ # Dependency tracking for IDMS export │ │ └── tracker.go # DependencyTracker, DependencySet │ │ │ └── idms/ # IDMS snippet export functionality │ ├── package.go # IDMS Package (single XML file) │ ├── exporter.go # Exporter, selection → IDMS │ └── *.go # IDMS-specific I/O and marshaling │ ├── internal/ │ ├── xmlutil/ # XML utilities │ └── testutil/ # Test helpers │ ├── cmd/cli/ # Interactive CLI tool with Bubbletea TUI │ ├── testdata/ │ ├── *.idml # Sample IDML files │ ├── *.xml # Sample XML files │ └── golden/ # Expected outputs │ └── docs/ ├── ARCHITECTURE.md # This file └── EPIC*.md # Epic documentation ``` -------------------------------- ### Manage and Clean IDML Resources Source: https://github.com/dimelords/idmllib/blob/main/README.md This Go snippet demonstrates how to read an IDML document, find and clean up orphaned resources (like unused styles and colors), and save the modified document. ```go package main import ( "log" "github.com/dimelords/idmllib/v2/pkg/idml" ) func main() { pkg, err := idml.Read("document.idml") if err != nil { log.Fatal(err) } // Create a resource manager rm := idml.NewResourceManager(pkg) // Find orphaned resources (unused styles, colors, etc.) report := rm.FindOrphans() log.Printf("Found %d orphaned styles", len(report.OrphanedStyles)) log.Printf("Found %d orphaned colors", len(report.OrphanedColors)) // Clean up orphaned resources cleanupReport := rm.CleanupOrphans() log.Printf("Removed %d unused resources", cleanupReport.TotalRemoved) // Save the cleaned document err = idml.Write(pkg, "cleaned.idml") if err != nil { log.Fatal(err) } } ``` -------------------------------- ### Resource Reference Pattern for External Files Source: https://github.com/dimelords/idmllib/blob/main/ARCHITECTURE.md Implement ResourceRef for type-safe, namespaced references to external XML files like graphics. The 'src' attribute points to the resource file. ```Go type ResourceRef struct { XMLName xml.Name Src string `xml:"src,attr"` } // In Document: GraphicResource *ResourceRef `xml:"http://ns.adobe.com/AdobeInDesign/idml/1.0/packaging Graphic,omitempty"` ``` -------------------------------- ### Apply Paragraph Style Source: https://github.com/dimelords/idmllib/blob/main/ARCHITECTURE.md Apply a specific paragraph style to a paragraph. ```go // Apply style paragraph.ApplyStyle("Heading 1") ``` -------------------------------- ### Create temporary ZIP file with debug support Source: https://github.com/dimelords/idmllib/blob/main/docs/TEST_DEBUG.md Use `testutil.CreateTestZIPWithDebug` to create a debug-enabled ZIP archive. This function preserves the archive if the debug flag is set, unlike `testutil.CreateTestZIP`. ```go // Regular ZIP file (auto-cleanup) zipPath := testutil.CreateTestZIP(t, files) // Debug-enabled ZIP file (preserved if flag is set) zipPath := testutil.CreateTestZIPWithDebug(t, files, "debug.idml") ``` -------------------------------- ### List Paragraph Styles Source: https://github.com/dimelords/idmllib/blob/main/ARCHITECTURE.md Retrieve a list of all paragraph styles available in the document. ```go // List styles styles := doc.ListParagraphStyles() ``` -------------------------------- ### Integration Test for Full Wizard Flow Source: https://github.com/dimelords/idmllib/blob/main/docs/CLI_TUI_ARCHITECTURE.md Tests the complete interaction flow of the wizard component by simulating a sequence of user messages and verifying the final state. ```go func TestFullFlow(t *testing.T) { w := NewWizard() // Simulate full interaction sequence msgs := []tea.Msg{ tea.KeyMsg{Type: tea.KeyDown}, // Navigate tea.KeyMsg{Type: tea.KeyEnter}, // Select // ... more messages } for _, msg := range msgs { w, _ = w.Update(msg).(* Wizard) } // Verify final state if !w.success { t.Error("Flow should succeed") } } ``` -------------------------------- ### Immutable State Update in Bubbletea Source: https://github.com/dimelords/idmllib/blob/main/docs/CLI_TUI_ARCHITECTURE.md Illustrates the correct way to update state in Bubbletea by returning a new model instance rather than mutating the existing one. This adheres to immutability principles. ```go // ❌ Bad - mutates state func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m.value = "new" // mutation return m, nil } // ✅ Good - returns new state func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { newModel := *m newModel.value = "new" return &newModel, nil } // ✅ Also good - pointer receiver, explicit return func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m.value = "new" return m, nil } ``` -------------------------------- ### Clone IDML Repository Source: https://github.com/dimelords/idmllib/blob/main/ARCHITECTURE.md Clone the idmlbuild repository from GitHub. ```bash # Clone git clone https://github.com/dimelords/idmlbuild cd idmlbuild ``` -------------------------------- ### Add Story to Document Source: https://github.com/dimelords/idmllib/blob/main/ARCHITECTURE.md Add a new story to the document and append text to it. ```go // Add story story := doc.AddStory("My Story") story.AddParagraph("Hello, world!") ``` -------------------------------- ### Write IDML Package Source: https://github.com/dimelords/idmllib/blob/main/ARCHITECTURE.md Writes an IDML package to a specified path, ensuring correct file ordering and compression. Use this for saving modified or newly created IDML packages. ```go func WriteIDML(pkg *Package, path string) error ``` -------------------------------- ### Properties Container Pattern Source: https://github.com/dimelords/idmllib/blob/main/ARCHITECTURE.md Use the Properties struct to consistently handle known and unknown properties within various elements like Document, Layer, and Section. It includes a Label field and a catch-all for other elements. ```Go type Properties struct { XMLName xml.Name `xml:"Properties"` Label *Label OtherElements []RawXMLElement `xml:",any"` } // Used by: Document, Layer, Section, Assignment, ABullet, etc. ``` -------------------------------- ### Core Document Struct Source: https://github.com/dimelords/idmllib/blob/main/ARCHITECTURE.md Represents the designmap.xml manifest file within an IDML package. It includes attributes, explicit child elements, and a catch-all for unknown elements. ```go type Document struct { // 50+ attributes (identity, layout, colors, etc.) XMLName xml.Name Xmlns string DOMVersion string Self string // ... many more ... // Explicit child elements (14 categories, 35+ types) Properties *Properties Languages []Language GraphicResource *ResourceRef // ... all major elements ... // Catch-all for unknown elements OtherElements []RawXMLElement } ``` -------------------------------- ### Automatic Test Cleanup with t.TempDir() Source: https://github.com/dimelords/idmllib/blob/main/README.md Use t.TempDir() within tests for automatic cleanup of temporary directories and their contents. This is the preferred method for managing temporary files during testing. ```go func TestExample(t *testing.T) { // Use t.TempDir() for automatic cleanup tempDir := t.TempDir() outputPath := filepath.Join(tempDir, "output.idml") // Test logic here... // No manual cleanup needed - t.TempDir() handles it } ``` -------------------------------- ### Run tests with debug output preservation Source: https://github.com/dimelords/idmllib/blob/main/docs/TEST_DEBUG.md Use the `-preserve-test-output` flag when running Go tests to keep output files in a `debug_test_output/` directory instead of cleaning them up automatically. This is useful for debugging test failures. ```bash # Run tests with debug output preservation go test -preserve-test-output ./pkg/idml # Run specific test with debug output go test -preserve-test-output -run TestSpecificTest ./pkg/idml # Run all tests with debug output go test -preserve-test-output ./... ``` -------------------------------- ### Component Delegation in Wizards Source: https://github.com/dimelords/idmllib/blob/main/docs/CLI_TUI_ARCHITECTURE.md Shows how a parent component can delegate update logic to a child component. This is useful for managing complex wizards with nested functionalities. ```go type ParentWizard struct { subComponent *ChildComponent } func (p *ParentWizard) Update(msg tea.Msg) (tea.Model, tea.Cmd) { if shouldDelegateToChild { updated, cmd := p.subComponent.Update(msg) p.subComponent = updated.(*ChildComponent) return p, cmd } // handle own updates } ``` -------------------------------- ### Marshal IDML Document Source: https://github.com/dimelords/idmllib/blob/main/ARCHITECTURE.md Generates the designmap.xml file from a Document struct. Handles XML generation and namespace management. ```go func MarshalDocument(doc *Document) ([]byte, error) ``` -------------------------------- ### Save IDML Document Source: https://github.com/dimelords/idmllib/blob/main/ARCHITECTURE.md Save the current document to a specified file path. ```go // Save doc.SaveAs("output.idml") ``` -------------------------------- ### Extract All Text from Document Source: https://github.com/dimelords/idmllib/blob/main/ARCHITECTURE.md Retrieve all text content from the IDML document. ```go // Get all text text := doc.ExtractAllText() ``` -------------------------------- ### Run Linting on Specific Files or Directories Source: https://github.com/dimelords/idmllib/blob/main/LINTING.md Target linting checks to specific parts of the project. This is helpful for focusing on recent changes or particular modules. ```bash golangci-lint run ./pkg/... ``` -------------------------------- ### Elm Architecture Model Interface Source: https://github.com/dimelords/idmllib/blob/main/docs/CLI_TUI_ARCHITECTURE.md Defines the core interface for models in the Bubbletea framework, outlining the Init, Update, and View methods required for state management and rendering. ```go type Model interface { Init() tea.Cmd Update(tea.Msg) (tea.Model, tea.Cmd) View() string } ``` -------------------------------- ### Define New Element Struct Source: https://github.com/dimelords/idmllib/blob/main/ARCHITECTURE.md Define a Go struct for a new XML element, including its attributes and child elements. Use `xml.Name` for the element name and `xml: ```go type NewElement struct { XMLName xml.Name `xml:"NewElement"` Self string `xml:"Self,attr"` Name string `xml:"Name,attr"` // ... attributes ... OtherElements []RawXMLElement `xml:",any"` } ``` -------------------------------- ### Delegating Update to Sub-component Source: https://github.com/dimelords/idmllib/blob/main/docs/CLI_TUI_ARCHITECTURE.md Illustrates how the Update method in a parent component delegates message handling to a sub-component (TextFrameSelector) when the wizard is in a specific state. ```go if m.step == expStepSelectFrame { updatedSelector, cmd := m.frameSelector.Update(msg) m.frameSelector = updatedSelector.(*TextFrameSelector) return m, cmd } ``` -------------------------------- ### Centralized Styles with Lipgloss Source: https://github.com/dimelords/idmllib/blob/main/docs/CLI_TUI_ARCHITECTURE.md Defines various text styles for consistent UI elements in the TUI. These styles are intended for centralized use across the application. ```go var ( TitleStyle // Bold, purple, padded SubtitleStyle // Gray, subtle SelectedStyle // Bold, highlighted background NormalStyle // Default text SuccessStyle // Green, bold ErrorStyle // Red, bold WarningStyle // Orange, bold InfoStyle // Blue HelpStyle // Gray, bottom padding InputStyle // Input field appearance InputLabelStyle // Input label BoxStyle // Bordered container ) ``` -------------------------------- ### Export IDMS Snippet from IDML Source: https://github.com/dimelords/idmllib/blob/main/README.md This Go snippet shows how to read an IDML document, select specific elements (like a text frame), and export them as an IDMS snippet. ```go package main import ( "log" "github.com/dimelords/idmllib/v2/pkg/idml" "github.com/dimelords/idmllib/v2/pkg/idms" ) func main() { // Read source IDML document pkg, err := idml.Read("document.idml") if err != nil { log.Fatal(err) } // Select elements to export sel := idml.NewSelection() textFrame, _ := pkg.SelectTextFrameByID("u1e6") sel.AddTextFrame(textFrame) // Export as IDMS snippet exporter := idms.NewExporter(pkg) snippet, err := exporter.ExportSelection(sel) if err != nil { log.Fatal(err) } // Write the snippet err = snippet.Write("snippet.idms") if err != nil { log.Fatal(err) } } ``` -------------------------------- ### View Test Output Verbosity Source: https://github.com/dimelords/idmllib/blob/main/testdata/golden/README.md Run tests with the verbose flag to see detailed output, which can be helpful when troubleshooting or reviewing changes. ```bash go test ./pkg/idml/... -run TestGolden -v ``` -------------------------------- ### Roundtrip Wizard States Source: https://github.com/dimelords/idmllib/blob/main/docs/CLI_TUI_ARCHITECTURE.md Defines the enumerated states for the Roundtrip Wizard, indicating the progression through input file selection, output file specification, processing, and completion. ```go const ( rtStepInputFile // Get input path rtStepOutputFile // Get output path rtStepProcessing // Execute roundtrip rtStepDone // Show results ) ``` -------------------------------- ### Suppress 'gocyclo' Linter Warning Source: https://github.com/dimelords/idmllib/blob/main/LINTING.md Use a 'nolint:gocyclo' comment to ignore 'gocyclo' (cyclomatic complexity) warnings for functions that are complex but cannot be easily simplified. ```go // nolint:gocyclo func complexFunction() { // ... } ``` -------------------------------- ### Ensure debug files are preserved Source: https://github.com/dimelords/idmllib/blob/main/docs/TEST_DEBUG.md If debug files are not being preserved, verify that the `-preserve-test-output` flag is correctly included in your `go test` command. This flag is essential for enabling the preservation of test artifacts. ```bash go test -preserve-test-output ./pkg/idml ``` -------------------------------- ### Preference Pattern for Text Variables Source: https://github.com/dimelords/idmllib/blob/main/ARCHITECTURE.md The Preference pattern handles TextVariables with varying preference types based on the variable's type. Only one preference field will be populated per variable. ```Go type TextVariable struct { VariableType string // Only one of these will be populated DatePreference *DateVariablePreference FileNamePreference *FileNameVariablePreference PageNumberPreference *PageNumberVariablePreference // ... OtherElements []RawXMLElement `xml:",any"` } ``` -------------------------------- ### Error Handling in Wizard State Source: https://github.com/dimelords/idmllib/blob/main/docs/CLI_TUI_ARCHITECTURE.md Shows a pattern for handling errors within a wizard. Errors are stored in the wizard's state and displayed in the View function using styled error messages. ```go type Wizard struct { error string success bool } func (w *Wizard) performAction() (tea.Model, tea.Cmd) { if err := doSomething(); err != nil { w.error = err.Error() w.step = stepDone return w, nil } w.success = true w.step = stepDone return w, nil } func (w *Wizard) View() string { if w.error != "" { return ErrorStyle.Render("❌ " + w.error) } if w.success { return w.viewSuccess() } // ... normal view } ``` -------------------------------- ### Struct Tags for XML Attributes Source: https://github.com/dimelords/idmllib/blob/main/ARCHITECTURE.md Define struct tags for XML attributes, including optional fields using `omitempty`. ```go // Attributes Self string `xml:"Self,attr"` Name string `xml:"Name,attr,omitempty"` // Optional ``` -------------------------------- ### Add New Element to Document Struct Source: https://github.com/dimelords/idmllib/blob/main/ARCHITECTURE.md Incorporate the new element struct into the main Document struct. Use `xml:"ElementName,omitempty"` to handle optional elements. ```go type Document struct { // ... existing fields ... // Step N: New Elements NewElements []NewElement `xml:"NewElement,omitempty"` OtherElements []RawXMLElement `xml:",any"` } ``` -------------------------------- ### Parse IDML Document Source: https://github.com/dimelords/idmllib/blob/main/ARCHITECTURE.md Parses the designmap.xml file from an IDML package into a Document struct. Handles XML parsing and namespace management. ```go func ParseDocument(data []byte) (*Document, error) ``` -------------------------------- ### Export IDMS Wizard States Source: https://github.com/dimelords/idmllib/blob/main/docs/CLI_TUI_ARCHITECTURE.md Defines the enumerated states for the Export IDMS Wizard, covering input file selection, text frame selection, output file specification, export processing, and completion. ```go const ( expStepInputFile // Get IDML path expStepSelectFrame // TextFrameSelector expStepOutputFile // Get IDMS path expStepExporting // Process export expStepDone // Show results ) ``` -------------------------------- ### Conditional Test Cleanup with Debug Mode Source: https://github.com/dimelords/idmllib/blob/main/README.md Implement conditional cleanup logic based on a debug flag. This snippet shows how to use t.Cleanup() to remove output files only when not preserving them, or to use t.TempDir() otherwise. ```go func TestExampleWithDebug(t *testing.T) { var outputPath string if *preserveTestOutput { outputPath = "debug_output.idml" t.Cleanup(func() { if !t.Failed() { os.Remove(outputPath) } }) } else { tempDir := t.TempDir() outputPath = filepath.Join(tempDir, "output.idml") } // Test logic... ``` -------------------------------- ### Struct Tags for Namespaced XML Elements Source: https://github.com/dimelords/idmllib/blob/main/ARCHITECTURE.md Define struct tags for XML elements within a specific namespace, including optional elements. ```go // Namespaced elements Graphic *ResourceRef `xml:"http://ns.adobe.com/AdobeInDesign/idml/1.0/packaging Graphic,omitempty"` ``` -------------------------------- ### RawXMLElement Pattern for Unknown XML Elements Source: https://github.com/dimelords/idmllib/blob/main/ARCHITECTURE.md Use RawXMLElement to preserve unknown or future XML elements without explicit struct definitions. It captures the element's name, attributes, and inner XML content. ```Go type RawXMLElement struct { XMLName xml.Name Attrs []xml.Attr `xml:",any,attr"` Content []byte `xml:",innerxml"` } type Document struct { // Explicit elements Languages []Language // Catch-all OtherElements []RawXMLElement `xml:",any"` } ``` -------------------------------- ### Struct Tags for XML Child Elements Source: https://github.com/dimelords/idmllib/blob/main/ARCHITECTURE.md Define struct tags for XML child elements, supporting multiple elements and optional single elements. ```go // Child elements Languages []Language `xml:"Language,omitempty"` // Multiple Properties *Properties `xml:"Properties,omitempty"` // Optional single ``` -------------------------------- ### Wrap Errors with Context Source: https://github.com/dimelords/idmllib/blob/main/ARCHITECTURE.md Wrap underlying errors with additional operation context using a custom Error type. ```go // Wrap errors with context if err := doSomething(); err != nil { return nil, &Error{ Op: "operation name", Err: err, } } ``` -------------------------------- ### Research Element Structure Source: https://github.com/dimelords/idmllib/blob/main/ARCHITECTURE.md Use grep to find the structure of an existing element in XML test data. ```bash grep -A 10 "ElementName" testdata/*.xml ``` -------------------------------- ### Suppress 'errcheck' Linter Warning Source: https://github.com/dimelords/idmllib/blob/main/LINTING.md Use a 'nolint:errcheck' comment to bypass the 'errcheck' linter for a specific line where error checking is intentionally skipped. ```go xml.EscapeText(&buf, data) // nolint:errcheck ``` -------------------------------- ### Update Golden File (Intentional Change) Source: https://github.com/dimelords/idmllib/blob/main/testdata/golden/README.md If test output is correct after a change, use this command to update the corresponding golden file. Always review changes before updating. ```bash go test -update ```