Adds DOCX and Markdown export functionality

Introduces a modular exporter pattern supporting DOCX and Markdown formats
by implementing Exporter interfaces and restructuring application logic.

Enhances CI to install UPX for binary compression, excluding recent macOS
binaries due to compatibility issues.

Enables CGO when building binaries for all platforms, addressing potential
cross-platform compatibility concerns.

Bumps version to 0.1.1.
This commit is contained in:
2025-05-25 13:01:58 +02:00
parent 48cad7144f
commit 9de7222ec3
15 changed files with 1096 additions and 600 deletions

55
internal/models/course.go Normal file
View File

@ -0,0 +1,55 @@
// Package models defines the data structures representing Articulate Rise courses.
// These structures closely match the JSON format used by Articulate Rise.
package models
// Course represents the top-level structure of an Articulate Rise course.
// It contains metadata and the actual course content.
type Course struct {
// ShareID is the unique identifier used in public sharing URLs
ShareID string `json:"shareId"`
// Author is the name of the course creator
Author string `json:"author"`
// Course contains the detailed course information and content
Course CourseInfo `json:"course"`
// LabelSet contains customized labels used in the course
LabelSet LabelSet `json:"labelSet"`
}
// CourseInfo contains the main details and content of an Articulate Rise course.
type CourseInfo struct {
// ID is the internal unique identifier for the course
ID string `json:"id"`
// Title is the name of the course
Title string `json:"title"`
// Description is the course summary or introduction text
Description string `json:"description"`
// Color is the theme color of the course
Color string `json:"color"`
// NavigationMode specifies how users navigate through the course
NavigationMode string `json:"navigationMode"`
// Lessons is an ordered array of all lessons in the course
Lessons []Lesson `json:"lessons"`
// CoverImage is the main image displayed for the course
CoverImage *Media `json:"coverImage,omitempty"`
// ExportSettings contains configuration for exporting the course
ExportSettings *ExportSettings `json:"exportSettings,omitempty"`
}
// ExportSettings defines configuration options for exporting a course.
type ExportSettings struct {
// Title specifies the export title which might differ from course title
Title string `json:"title"`
// Format indicates the preferred export format
Format string `json:"format"`
}
// LabelSet contains customized labels used throughout the course.
// This allows course creators to modify standard terminology.
type LabelSet struct {
// ID is the unique identifier for this label set
ID string `json:"id"`
// Name is the descriptive name of the label set
Name string `json:"name"`
// Labels is a mapping of label keys to their customized values
Labels map[string]string `json:"labels"`
}

96
internal/models/lesson.go Normal file
View File

@ -0,0 +1,96 @@
// Package models defines the data structures representing Articulate Rise courses.
// These structures closely match the JSON format used by Articulate Rise.
package models
// Lesson represents a single lesson or section within an Articulate Rise course.
// Lessons are the main organizational units and contain various content items.
type Lesson struct {
// ID is the unique identifier for the lesson
ID string `json:"id"`
// Title is the name of the lesson
Title string `json:"title"`
// Description is the introductory text for the lesson
Description string `json:"description"`
// Type indicates whether this is a regular lesson or a section header
Type string `json:"type"`
// Icon is the identifier for the icon displayed with this lesson
Icon string `json:"icon"`
// Items is an ordered array of content items within the lesson
Items []Item `json:"items"`
// Position stores the ordering information for the lesson
Position interface{} `json:"position"`
// Ready indicates whether the lesson is marked as complete
Ready bool `json:"ready"`
// CreatedAt is the timestamp when the lesson was created
CreatedAt string `json:"createdAt"`
// UpdatedAt is the timestamp when the lesson was last modified
UpdatedAt string `json:"updatedAt"`
}
// Item represents a content block within a lesson.
// Items can be of various types such as text, multimedia, knowledge checks, etc.
type Item struct {
// ID is the unique identifier for the item
ID string `json:"id"`
// Type indicates the kind of content (text, image, knowledge check, etc.)
Type string `json:"type"`
// Family groups similar item types together
Family string `json:"family"`
// Variant specifies a sub-type within the main type
Variant string `json:"variant"`
// Items contains the actual content elements (sub-items) of this item
Items []SubItem `json:"items"`
// Settings contains configuration options specific to this item type
Settings interface{} `json:"settings"`
// Data contains additional structured data for the item
Data interface{} `json:"data"`
// Media contains any associated media for the item
Media *Media `json:"media,omitempty"`
}
// SubItem represents a specific content element within an Item.
// SubItems are the most granular content units like paragraphs, headings, or answers.
type SubItem struct {
// ID is the unique identifier for the sub-item
ID string `json:"id"`
// Type indicates the specific kind of sub-item
Type string `json:"type,omitempty"`
// Title is the name or label of the sub-item
Title string `json:"title,omitempty"`
// Heading is a heading text for this sub-item
Heading string `json:"heading,omitempty"`
// Paragraph contains regular text content
Paragraph string `json:"paragraph,omitempty"`
// Caption is text associated with media elements
Caption string `json:"caption,omitempty"`
// Media contains any associated images or videos
Media *Media `json:"media,omitempty"`
// Answers contains possible answers for question-type sub-items
Answers []Answer `json:"answers,omitempty"`
// Feedback is the response shown after user interaction
Feedback string `json:"feedback,omitempty"`
// Front contains content for the front side of a card-type sub-item
Front *CardSide `json:"front,omitempty"`
// Back contains content for the back side of a card-type sub-item
Back *CardSide `json:"back,omitempty"`
}
// Answer represents a possible response in a knowledge check or quiz item.
type Answer struct {
// ID is the unique identifier for the answer
ID string `json:"id"`
// Title is the text of the answer option
Title string `json:"title"`
// Correct indicates whether this is the right answer
Correct bool `json:"correct"`
// MatchTitle is used in matching-type questions to pair answers
MatchTitle string `json:"matchTitle,omitempty"`
}
// CardSide represents one side of a flipcard-type content element.
type CardSide struct {
// Media is the image or video associated with this side of the card
Media *Media `json:"media,omitempty"`
// Description is the text content for this side of the card
Description string `json:"description,omitempty"`
}

50
internal/models/media.go Normal file
View File

@ -0,0 +1,50 @@
// Package models defines the data structures representing Articulate Rise courses.
// These structures closely match the JSON format used by Articulate Rise.
package models
// Media represents a media element that can be either an image or a video.
// Only one of the fields (Image or Video) will be populated at a time.
type Media struct {
// Image contains metadata for an image element
Image *ImageMedia `json:"image,omitempty"`
// Video contains metadata for a video element
Video *VideoMedia `json:"video,omitempty"`
}
// ImageMedia contains the metadata and properties of an image.
type ImageMedia struct {
// Key is the unique identifier for the image in the Articulate system
Key string `json:"key"`
// Type indicates the image format (jpg, png, etc.)
Type string `json:"type"`
// Width is the pixel width of the image
Width int `json:"width,omitempty"`
// Height is the pixel height of the image
Height int `json:"height,omitempty"`
// CrushedKey is the identifier for a compressed version of the image
CrushedKey string `json:"crushedKey,omitempty"`
// OriginalUrl is the URL to the full-resolution image
OriginalUrl string `json:"originalUrl"`
// UseCrushedKey indicates whether to use the compressed version
UseCrushedKey bool `json:"useCrushedKey,omitempty"`
}
// VideoMedia contains the metadata and properties of a video.
type VideoMedia struct {
// Key is the unique identifier for the video in the Articulate system
Key string `json:"key"`
// URL is the direct link to the video content
URL string `json:"url"`
// Type indicates the video format (mp4, webm, etc.)
Type string `json:"type"`
// Poster is the URL to the static thumbnail image for the video
Poster string `json:"poster,omitempty"`
// Duration is the length of the video in seconds
Duration int `json:"duration,omitempty"`
// InputKey is the original identifier for uploaded videos
InputKey string `json:"inputKey,omitempty"`
// Thumbnail is the URL to a smaller preview image
Thumbnail string `json:"thumbnail,omitempty"`
// OriginalUrl is the URL to the source video file
OriginalUrl string `json:"originalUrl"`
}