mirror of
https://github.com/kjanat/articulate-parser.git
synced 2026-01-16 09:42:09 +01:00
Compare commits
3 Commits
33673d661b
...
remove-ci-
| Author | SHA1 | Date | |
|---|---|---|---|
| a1a49a75b7 | |||
| 8d606706e2 | |||
| e7de5d044a |
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
@ -1,5 +1,5 @@
|
||||
# These owners will be the default owners for everything in
|
||||
# the repo. Unless a later match takes precedence, they will
|
||||
# the repo. Unless a later match takes precedence, they will
|
||||
# be requested for review when someone opens a pull request.
|
||||
* @kjanat
|
||||
|
||||
|
||||
20
.github/CODE_OF_CONDUCT.md
vendored
20
.github/CODE_OF_CONDUCT.md
vendored
@ -17,23 +17,23 @@ diverse, inclusive, and healthy community.
|
||||
Examples of behavior that contributes to a positive environment for our
|
||||
community include:
|
||||
|
||||
- Demonstrating empathy and kindness toward other people
|
||||
- Being respectful of differing opinions, viewpoints, and experiences
|
||||
- Giving and gracefully accepting constructive feedback
|
||||
- Accepting responsibility and apologizing to those affected by our mistakes,
|
||||
- Demonstrating empathy and kindness toward other people
|
||||
- Being respectful of differing opinions, viewpoints, and experiences
|
||||
- Giving and gracefully accepting constructive feedback
|
||||
- Accepting responsibility and apologizing to those affected by our mistakes,
|
||||
and learning from the experience
|
||||
- Focusing on what is best not just for us as individuals, but for the
|
||||
- Focusing on what is best not just for us as individuals, but for the
|
||||
overall community
|
||||
|
||||
Examples of unacceptable behavior include:
|
||||
|
||||
- The use of sexualized language or imagery, and sexual attention or
|
||||
- The use of sexualized language or imagery, and sexual attention or
|
||||
advances of any kind
|
||||
- Trolling, insulting or derogatory comments, and personal or political attacks
|
||||
- Public or private harassment
|
||||
- Publishing others' private information, such as a physical or email
|
||||
- Trolling, insulting or derogatory comments, and personal or political attacks
|
||||
- Public or private harassment
|
||||
- Publishing others' private information, such as a physical or email
|
||||
address, without their explicit permission
|
||||
- Other conduct which could reasonably be considered inappropriate in a
|
||||
- Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Enforcement Responsibilities
|
||||
|
||||
108
.github/CONTRIBUTING.md
vendored
108
.github/CONTRIBUTING.md
vendored
@ -12,38 +12,38 @@ This project and everyone participating in it is governed by our Code of Conduct
|
||||
|
||||
Before creating bug reports, please check existing issues as you might find that the issue has already been reported. When creating a bug report, include as many details as possible:
|
||||
|
||||
- Use the bug report template
|
||||
- Include sample Articulate Rise content that reproduces the issue
|
||||
- Provide your environment details (OS, Go version, etc.)
|
||||
- Include error messages and stack traces
|
||||
- Use the bug report template
|
||||
- Include sample Articulate Rise content that reproduces the issue
|
||||
- Provide your environment details (OS, Go version, etc.)
|
||||
- Include error messages and stack traces
|
||||
|
||||
### Suggesting Enhancements
|
||||
|
||||
Enhancement suggestions are welcome! Please use the feature request template and include:
|
||||
|
||||
- A clear description of the enhancement
|
||||
- Your use case and why this would be valuable
|
||||
- Any implementation ideas you might have
|
||||
- A clear description of the enhancement
|
||||
- Your use case and why this would be valuable
|
||||
- Any implementation ideas you might have
|
||||
|
||||
### Pull Requests
|
||||
|
||||
1. **Fork the repository** and create your branch from `master`
|
||||
2. **Make your changes** following our coding standards
|
||||
3. **Add tests** for any new functionality
|
||||
4. **Ensure all tests pass** by running `go test ./...`
|
||||
5. **Run `go fmt`** to format your code
|
||||
6. **Run `go vet`** to check for common issues
|
||||
7. **Update documentation** if needed
|
||||
8. **Create a pull request** with a clear title and description
|
||||
1. **Fork the repository** and create your branch from `master`
|
||||
2. **Make your changes** following our coding standards
|
||||
3. **Add tests** for any new functionality
|
||||
4. **Ensure all tests pass** by running `go test ./...`
|
||||
5. **Run `go fmt`** to format your code
|
||||
6. **Run `go vet`** to check for common issues
|
||||
7. **Update documentation** if needed
|
||||
8. **Create a pull request** with a clear title and description
|
||||
|
||||
## Development Setup
|
||||
|
||||
1. **Prerequisites:**
|
||||
1. **Prerequisites:**
|
||||
|
||||
- Go 1.21 or later
|
||||
- Git
|
||||
- Go 1.21 or later
|
||||
- Git
|
||||
|
||||
2. **Clone and setup:**
|
||||
2. **Clone and setup:**
|
||||
|
||||
```bash
|
||||
git clone https://github.com/your-username/articulate-parser.git
|
||||
@ -51,13 +51,13 @@ Enhancement suggestions are welcome! Please use the feature request template and
|
||||
go mod download
|
||||
```
|
||||
|
||||
3. **Run tests:**
|
||||
3. **Run tests:**
|
||||
|
||||
```bash
|
||||
go test -v ./...
|
||||
```
|
||||
|
||||
4. **Build:**
|
||||
4. **Build:**
|
||||
|
||||
```bash
|
||||
go build main.go
|
||||
@ -67,18 +67,18 @@ Enhancement suggestions are welcome! Please use the feature request template and
|
||||
|
||||
### Go Style Guide
|
||||
|
||||
- Follow the [Go Code Review Comments](https://github.com/golang/go/wiki/CodeReviewComments)
|
||||
- Use `gofmt` to format your code
|
||||
- Use meaningful variable and function names
|
||||
- Add comments for exported functions and types
|
||||
- Keep functions focused and small
|
||||
- Follow the [Go Code Review Comments](https://github.com/golang/go/wiki/CodeReviewComments)
|
||||
- Use `gofmt` to format your code
|
||||
- Use meaningful variable and function names
|
||||
- Add comments for exported functions and types
|
||||
- Keep functions focused and small
|
||||
|
||||
### Testing
|
||||
|
||||
- Write tests for new functionality
|
||||
- Use table-driven tests where appropriate
|
||||
- Aim for good test coverage
|
||||
- Test error cases and edge conditions
|
||||
- Write tests for new functionality
|
||||
- Use table-driven tests where appropriate
|
||||
- Aim for good test coverage
|
||||
- Test error cases and edge conditions
|
||||
|
||||
### Commit Messages
|
||||
|
||||
@ -112,19 +112,19 @@ articulate-parser/
|
||||
|
||||
### New Content Types
|
||||
|
||||
1. Add the content type definition to `types/`
|
||||
2. Implement parsing logic in `parser/`
|
||||
3. Add export handling in `exporters/`
|
||||
4. Write comprehensive tests
|
||||
5. Update documentation
|
||||
1. Add the content type definition to `types/`
|
||||
2. Implement parsing logic in `parser/`
|
||||
3. Add export handling in `exporters/`
|
||||
4. Write comprehensive tests
|
||||
5. Update documentation
|
||||
|
||||
### New Export Formats
|
||||
|
||||
1. Create a new exporter in `exporters/`
|
||||
2. Implement the `Exporter` interface
|
||||
3. Add CLI support in `main.go`
|
||||
4. Add tests with sample output
|
||||
5. Update README with usage examples
|
||||
1. Create a new exporter in `exporters/`
|
||||
2. Implement the `Exporter` interface
|
||||
3. Add CLI support in `main.go`
|
||||
4. Add tests with sample output
|
||||
5. Update README with usage examples
|
||||
|
||||
## Testing
|
||||
|
||||
@ -146,31 +146,31 @@ go test -run TestSpecificFunction ./...
|
||||
|
||||
### Test Data
|
||||
|
||||
- Add sample Articulate Rise JSON files to `tests/data/`
|
||||
- Include both simple and complex content examples
|
||||
- Test edge cases and error conditions
|
||||
- Add sample Articulate Rise JSON files to `tests/data/`
|
||||
- Include both simple and complex content examples
|
||||
- Test edge cases and error conditions
|
||||
|
||||
## Documentation
|
||||
|
||||
- Update the README for user-facing changes
|
||||
- Add inline code comments for complex logic
|
||||
- Update examples when adding new features
|
||||
- Keep the feature list current
|
||||
- Update the README for user-facing changes
|
||||
- Add inline code comments for complex logic
|
||||
- Update examples when adding new features
|
||||
- Keep the feature list current
|
||||
|
||||
## Release Process
|
||||
|
||||
Releases are handled by maintainers:
|
||||
|
||||
1. Version bumping follows semantic versioning
|
||||
2. Releases are created from the `master` branch
|
||||
3. GitHub Actions automatically builds and publishes releases
|
||||
4. Release notes are auto-generated from commits
|
||||
1. Version bumping follows semantic versioning
|
||||
2. Releases are created from the `master` branch
|
||||
3. GitHub Actions automatically builds and publishes releases
|
||||
4. Release notes are auto-generated from commits
|
||||
|
||||
## Questions?
|
||||
|
||||
- Open a discussion for general questions
|
||||
- Use the question issue template for specific help
|
||||
- Check existing issues and documentation first
|
||||
- Open a discussion for general questions
|
||||
- Use the question issue template for specific help
|
||||
- Check existing issues and documentation first
|
||||
|
||||
## Recognition
|
||||
|
||||
|
||||
32
.github/PULL_REQUEST_TEMPLATE.md
vendored
32
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -10,26 +10,26 @@ Fixes #
|
||||
## Type of Change
|
||||
|
||||
<!-- Mark the appropriate option with an "x" -->
|
||||
- [ ] Bug fix (non-breaking change which fixes an issue)
|
||||
- [ ] New feature (non-breaking change which adds functionality)
|
||||
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
|
||||
- [ ] Documentation update
|
||||
- [ ] Performance improvement
|
||||
- [ ] Code refactoring (no functional changes)
|
||||
- [ ] Test updates
|
||||
- [ ] Bug fix (non-breaking change which fixes an issue)
|
||||
- [ ] New feature (non-breaking change which adds functionality)
|
||||
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
|
||||
- [ ] Documentation update
|
||||
- [ ] Performance improvement
|
||||
- [ ] Code refactoring (no functional changes)
|
||||
- [ ] Test updates
|
||||
|
||||
## Checklist
|
||||
|
||||
<!-- Mark the items you've completed with an "x" -->
|
||||
- [ ] My code follows the style guidelines of this project
|
||||
- [ ] I have performed a self-review of my code
|
||||
- [ ] I have added comments to complex logic
|
||||
- [ ] I have updated the documentation
|
||||
- [ ] I have added tests that prove my fix is effective or that my feature works
|
||||
- [ ] New and existing unit tests pass locally with my changes
|
||||
- [ ] I have checked for potential breaking changes
|
||||
- [ ] No new warnings are generated
|
||||
- [ ] The commit message follows our guidelines
|
||||
- [ ] My code follows the style guidelines of this project
|
||||
- [ ] I have performed a self-review of my code
|
||||
- [ ] I have added comments to complex logic
|
||||
- [ ] I have updated the documentation
|
||||
- [ ] I have added tests that prove my fix is effective or that my feature works
|
||||
- [ ] New and existing unit tests pass locally with my changes
|
||||
- [ ] I have checked for potential breaking changes
|
||||
- [ ] No new warnings are generated
|
||||
- [ ] The commit message follows our guidelines
|
||||
|
||||
## Screenshots (if appropriate)
|
||||
|
||||
|
||||
32
.github/SECURITY.md
vendored
32
.github/SECURITY.md
vendored
@ -13,32 +13,32 @@ Currently, the following versions of Articulate Rise Parser are supported with s
|
||||
|
||||
We take the security of Articulate Rise Parser seriously. If you believe you have found a security vulnerability, please follow these steps:
|
||||
|
||||
1. **Do not disclose the vulnerability publicly** - Please do not create a public GitHub issue for security vulnerabilities.
|
||||
2. **Email the details to [security+articulate-parser@kjanat.com]** - Include as much information as possible about the vulnerability.
|
||||
3. **Wait for a response** - We will acknowledge your email within 48 hours and provide an estimated timeline for a fix.
|
||||
4. **Work with us** - We may ask for additional information to help us understand and address the issue.
|
||||
1. **Do not disclose the vulnerability publicly** - Please do not create a public GitHub issue for security vulnerabilities.
|
||||
2. **Email the details to [security+articulate-parser@kjanat.com]** - Include as much information as possible about the vulnerability.
|
||||
3. **Wait for a response** - We will acknowledge your email within 48 hours and provide an estimated timeline for a fix.
|
||||
4. **Work with us** - We may ask for additional information to help us understand and address the issue.
|
||||
|
||||
## What to Include in a Report
|
||||
|
||||
When reporting a vulnerability, please include:
|
||||
|
||||
- A clear description of the issue
|
||||
- Steps to reproduce the vulnerability
|
||||
- The potential impact of the vulnerability
|
||||
- Any possible mitigations you've identified
|
||||
- A clear description of the issue
|
||||
- Steps to reproduce the vulnerability
|
||||
- The potential impact of the vulnerability
|
||||
- Any possible mitigations you've identified
|
||||
|
||||
## What to Expect
|
||||
|
||||
- We will acknowledge receipt of your vulnerability report within 48 hours.
|
||||
- We will provide regular updates about our progress.
|
||||
- We will notify you when the vulnerability is fixed.
|
||||
- With your permission, we will include your name in the acknowledgments.
|
||||
- We will acknowledge receipt of your vulnerability report within 48 hours.
|
||||
- We will provide regular updates about our progress.
|
||||
- We will notify you when the vulnerability is fixed.
|
||||
- With your permission, we will include your name in the acknowledgments.
|
||||
|
||||
## Security Measures
|
||||
|
||||
This project follows these security practices:
|
||||
|
||||
- Regular dependency updates via Dependabot
|
||||
- CodeQL security scanning
|
||||
- Automated testing for each pull request
|
||||
- Code review requirements for all changes
|
||||
- Regular dependency updates via Dependabot
|
||||
- CodeQL security scanning
|
||||
- Automated testing for each pull request
|
||||
- Code review requirements for all changes
|
||||
|
||||
8
.github/workflows/autofix.yml
vendored
8
.github/workflows/autofix.yml
vendored
@ -2,7 +2,7 @@ name: autofix.ci
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches: ["master"]
|
||||
branches: [ "master" ]
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
@ -11,18 +11,18 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Install Task
|
||||
uses: go-task/setup-task@v1
|
||||
|
||||
- uses: actions/setup-go@v6
|
||||
with: { go-version-file: "go.mod" }
|
||||
with: { go-version-file: 'go.mod' }
|
||||
|
||||
- name: Setup go deps
|
||||
run: |
|
||||
# Install golangci-lint
|
||||
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/HEAD/install.sh | sh -s -- -b $(go env GOPATH)/bin
|
||||
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/HEAD/install.sh | sh -s -- -b "$(go env GOPATH)/bin"
|
||||
|
||||
# Install go-task dependencies
|
||||
go install golang.org/x/tools/cmd/goimports@latest
|
||||
|
||||
216
.github/workflows/ci.yml
vendored
216
.github/workflows/ci.yml
vendored
@ -2,7 +2,7 @@ name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["master", "develop"]
|
||||
branches: ['master', 'develop']
|
||||
pull_request:
|
||||
|
||||
env:
|
||||
@ -21,12 +21,12 @@ jobs:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: stable
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v9
|
||||
uses: golangci/golangci-lint-action@v8
|
||||
with: { version: latest }
|
||||
|
||||
test:
|
||||
@ -42,7 +42,7 @@ jobs:
|
||||
- 1.25.x
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Set up Go ${{ matrix.go }}
|
||||
uses: actions/setup-go@v6
|
||||
@ -64,14 +64,18 @@ jobs:
|
||||
|
||||
- name: Run tests with enhanced reporting
|
||||
id: test
|
||||
env:
|
||||
CGO_ENABLED: 1
|
||||
run: |
|
||||
cat >> $GITHUB_STEP_SUMMARY << EOF
|
||||
{
|
||||
cat << EOF
|
||||
## 🔧 Test Environment
|
||||
- **Go Version:** ${{ matrix.go }}
|
||||
- **OS:** ubuntu-latest
|
||||
- **Timestamp:** $(date -u)
|
||||
|
||||
EOF
|
||||
} >> "$GITHUB_STEP_SUMMARY"
|
||||
|
||||
echo "Running tests with coverage..."
|
||||
task test:coverage 2>&1 | tee test-output.log
|
||||
@ -79,21 +83,22 @@ jobs:
|
||||
# Extract test results for summary
|
||||
TEST_STATUS=$?
|
||||
TOTAL_TESTS=$(grep -c "=== RUN" test-output.log || echo "0")
|
||||
PASSED_TESTS=$(grep -c "--- PASS:" test-output.log || echo "0")
|
||||
FAILED_TESTS=$(grep -c "--- FAIL:" test-output.log || echo "0")
|
||||
SKIPPED_TESTS=$(grep -c "--- SKIP:" test-output.log || echo "0")
|
||||
PASSED_TESTS=$(grep -c -- "--- PASS:" test-output.log || echo "0")
|
||||
FAILED_TESTS=$(grep -c -- "--- FAIL:" test-output.log || echo "0")
|
||||
SKIPPED_TESTS=$(grep -c -- "--- SKIP:" test-output.log || echo "0")
|
||||
|
||||
# Generate test summary
|
||||
cat >> $GITHUB_STEP_SUMMARY << EOF
|
||||
{
|
||||
cat << EOF
|
||||
## 🧪 Test Results (Go ${{ matrix.go }})
|
||||
|
||||
| Metric | Value |
|
||||
| ----------- | ----------------------------------------------------------- |
|
||||
| Total Tests | $TOTAL_TESTS |
|
||||
| Passed | $PASSED_TESTS |
|
||||
| Failed | $FAILED_TESTS |
|
||||
| Skipped | $SKIPPED_TESTS |
|
||||
| Status | $([ $TEST_STATUS -eq 0 ] && echo "PASSED" || echo "FAILED") |
|
||||
| Metric | Value |
|
||||
| ----------- | ------------------------------------------------------------- |
|
||||
| Total Tests | $TOTAL_TESTS |
|
||||
| Passed | $PASSED_TESTS |
|
||||
| Failed | $FAILED_TESTS |
|
||||
| Skipped | $SKIPPED_TESTS |
|
||||
| Status | $([ "$TEST_STATUS" -eq 0 ] && echo "PASSED" || echo "FAILED") |
|
||||
|
||||
### 📦 Package Test Results
|
||||
|
||||
@ -105,38 +110,39 @@ jobs:
|
||||
grep "^ok\|^FAIL" test-output.log | while read -r line; do
|
||||
if [[ $line == ok* ]]; then
|
||||
pkg=$(echo "$line" | awk '{print $2}')
|
||||
echo "| $pkg | ✅ PASS |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| $pkg | ✅ PASS |"
|
||||
elif [[ $line == FAIL* ]]; then
|
||||
pkg=$(echo "$line" | awk '{print $2}')
|
||||
echo "| $pkg | ❌ FAIL |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| $pkg | ❌ FAIL |"
|
||||
fi
|
||||
done
|
||||
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo ""
|
||||
|
||||
# Add detailed results if tests failed
|
||||
if [ $TEST_STATUS -ne 0 ]; then
|
||||
cat >> $GITHUB_STEP_SUMMARY << 'EOF'
|
||||
if [ "$TEST_STATUS" -ne 0 ]; then
|
||||
cat << 'EOF'
|
||||
### ❌ Failed Tests Details
|
||||
```
|
||||
EOF
|
||||
grep -A 10 "--- FAIL:" test-output.log | head -100 >> $GITHUB_STEP_SUMMARY
|
||||
cat >> $GITHUB_STEP_SUMMARY << 'EOF'
|
||||
grep -A 10 -- "--- FAIL:" test-output.log | head -100
|
||||
cat << 'EOF'
|
||||
```
|
||||
|
||||
EOF
|
||||
fi
|
||||
} >> "$GITHUB_STEP_SUMMARY"
|
||||
|
||||
# Set outputs for other steps
|
||||
cat >> $GITHUB_OUTPUT << EOF
|
||||
test-status=$TEST_STATUS
|
||||
total-tests=$TOTAL_TESTS
|
||||
passed-tests=$PASSED_TESTS
|
||||
failed-tests=$FAILED_TESTS
|
||||
EOF
|
||||
{
|
||||
echo "test-status=$TEST_STATUS"
|
||||
echo "total-tests=$TOTAL_TESTS"
|
||||
echo "passed-tests=$PASSED_TESTS"
|
||||
echo "failed-tests=$FAILED_TESTS"
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
|
||||
# Exit with the original test status
|
||||
exit $TEST_STATUS
|
||||
exit "$TEST_STATUS"
|
||||
|
||||
- name: Generate coverage report
|
||||
if: always()
|
||||
@ -144,7 +150,8 @@ jobs:
|
||||
if [ -f coverage/coverage.out ]; then
|
||||
COVERAGE=$(go tool cover -func=coverage/coverage.out | grep total | awk '{print $3}')
|
||||
|
||||
cat >> $GITHUB_STEP_SUMMARY << EOF
|
||||
{
|
||||
cat << EOF
|
||||
## 📊 Code Coverage (Go ${{ matrix.go }})
|
||||
|
||||
**Total Coverage: $COVERAGE**
|
||||
@ -156,45 +163,46 @@ jobs:
|
||||
| ------- | -------- |
|
||||
EOF
|
||||
|
||||
# Create temporary file for package coverage aggregation
|
||||
temp_coverage=$(mktemp)
|
||||
# Create temporary file for package coverage aggregation
|
||||
temp_coverage=$(mktemp)
|
||||
|
||||
# Extract package-level coverage data
|
||||
go tool cover -func=coverage/coverage.out | grep -v total | while read -r line; do
|
||||
if [[ $line == *".go:"* ]]; then
|
||||
# Extract package path from file path (everything before the filename)
|
||||
filepath=$(echo "$line" | awk '{print $1}')
|
||||
pkg_path=$(dirname "$filepath" | sed 's|github.com/kjanat/articulate-parser/||; s|^\./||')
|
||||
coverage=$(echo "$line" | awk '{print $3}' | sed 's/%//')
|
||||
# Extract package-level coverage data
|
||||
go tool cover -func=coverage/coverage.out | grep -v total | while read -r line; do
|
||||
if [[ $line == *".go:"* ]]; then
|
||||
# Extract package path from file path (everything before the filename)
|
||||
filepath=$(echo "$line" | awk '{print $1}')
|
||||
pkg_path=$(dirname "$filepath" | sed 's|github.com/kjanat/articulate-parser/||; s|^\./||')
|
||||
coverage=$(echo "$line" | awk '{print $3}' | sed 's/%//')
|
||||
|
||||
# Use root package if no subdirectory
|
||||
[[ "$pkg_path" == "." || "$pkg_path" == "" ]] && pkg_path="root"
|
||||
# Use root package if no subdirectory
|
||||
[[ "$pkg_path" == "." || "$pkg_path" == "" ]] && pkg_path="root"
|
||||
|
||||
echo "$pkg_path $coverage" >> "$temp_coverage"
|
||||
fi
|
||||
done
|
||||
echo "$pkg_path $coverage" >> "$temp_coverage"
|
||||
fi
|
||||
done
|
||||
|
||||
# Aggregate coverage by package (average)
|
||||
awk '{
|
||||
packages[$1] += $2
|
||||
counts[$1]++
|
||||
}
|
||||
END {
|
||||
for (pkg in packages) {
|
||||
avg = packages[pkg] / counts[pkg]
|
||||
printf "| %s | %.1f%% |\n", pkg, avg
|
||||
# Aggregate coverage by package (average)
|
||||
awk '{
|
||||
packages[$1] += $2
|
||||
counts[$1]++
|
||||
}
|
||||
}' "$temp_coverage" | sort >> $GITHUB_STEP_SUMMARY
|
||||
END {
|
||||
for (pkg in packages) {
|
||||
avg = packages[pkg] / counts[pkg]
|
||||
printf "| %s | %.1f%% |\n", pkg, avg
|
||||
}
|
||||
}' "$temp_coverage" | sort
|
||||
|
||||
rm -f "$temp_coverage"
|
||||
rm -f "$temp_coverage"
|
||||
|
||||
cat >> $GITHUB_STEP_SUMMARY << 'EOF'
|
||||
cat << 'EOF'
|
||||
|
||||
</details>
|
||||
|
||||
EOF
|
||||
} >> "$GITHUB_STEP_SUMMARY"
|
||||
else
|
||||
cat >> $GITHUB_STEP_SUMMARY << 'EOF'
|
||||
cat >> "$GITHUB_STEP_SUMMARY" << 'EOF'
|
||||
## ⚠️ Coverage Report
|
||||
No coverage file generated
|
||||
|
||||
@ -203,7 +211,7 @@ jobs:
|
||||
|
||||
- name: Upload test artifacts
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v6
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: test-results-go-${{ matrix.go }}
|
||||
path: |
|
||||
@ -214,51 +222,53 @@ jobs:
|
||||
- name: Run linters
|
||||
run: |
|
||||
# Initialize summary
|
||||
cat >> $GITHUB_STEP_SUMMARY << EOF
|
||||
{
|
||||
cat << EOF
|
||||
## 🔍 Static Analysis (Go ${{ matrix.go }})
|
||||
|
||||
EOF
|
||||
|
||||
# Run go vet
|
||||
VET_OUTPUT=$(task lint:vet 2>&1 || echo "")
|
||||
VET_STATUS=$?
|
||||
# Run go vet
|
||||
VET_OUTPUT=$(task lint:vet 2>&1 || echo "")
|
||||
VET_STATUS=$?
|
||||
|
||||
if [ $VET_STATUS -eq 0 ]; then
|
||||
echo "✅ **go vet:** No issues found" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
cat >> $GITHUB_STEP_SUMMARY << 'EOF'
|
||||
if [ "$VET_STATUS" -eq 0 ]; then
|
||||
echo "✅ **go vet:** No issues found"
|
||||
else
|
||||
cat << 'EOF'
|
||||
❌ **go vet:** Issues found
|
||||
|
||||
```
|
||||
EOF
|
||||
echo "$VET_OUTPUT" >> $GITHUB_STEP_SUMMARY
|
||||
echo '```' >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "$VET_OUTPUT"
|
||||
echo '```'
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Run go fmt check
|
||||
FMT_OUTPUT=$(task lint:fmt 2>&1 || echo "")
|
||||
FMT_STATUS=$?
|
||||
# Run go fmt check
|
||||
FMT_OUTPUT=$(task lint:fmt 2>&1 || echo "")
|
||||
FMT_STATUS=$?
|
||||
|
||||
if [ $FMT_STATUS -eq 0 ]; then
|
||||
echo "✅ **go fmt:** All files properly formatted" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
cat >> $GITHUB_STEP_SUMMARY << 'EOF'
|
||||
if [ "$FMT_STATUS" -eq 0 ]; then
|
||||
echo "✅ **go fmt:** All files properly formatted"
|
||||
else
|
||||
cat << 'EOF'
|
||||
❌ **go fmt:** Files need formatting
|
||||
|
||||
```
|
||||
EOF
|
||||
echo "$FMT_OUTPUT" >> $GITHUB_STEP_SUMMARY
|
||||
echo '```' >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
echo "$FMT_OUTPUT"
|
||||
echo '```'
|
||||
fi
|
||||
} >> "$GITHUB_STEP_SUMMARY"
|
||||
|
||||
# Exit with error if any linter failed
|
||||
[ $VET_STATUS -eq 0 ] && [ $FMT_STATUS -eq 0 ] || exit 1
|
||||
[ "$VET_STATUS" -eq 0 ] && [ "$FMT_STATUS" -eq 0 ] || exit 1
|
||||
|
||||
- name: Job Summary
|
||||
if: always()
|
||||
run: |
|
||||
cat >> $GITHUB_STEP_SUMMARY << 'EOF'
|
||||
cat >> "$GITHUB_STEP_SUMMARY" << 'EOF'
|
||||
## 📋 Job Summary (Go ${{ matrix.go }})
|
||||
|
||||
| Step | Status |
|
||||
@ -294,7 +304,7 @@ jobs:
|
||||
contents: read
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v6
|
||||
@ -313,24 +323,26 @@ jobs:
|
||||
|
||||
- name: Test Docker image using Task
|
||||
run: |
|
||||
cat >> $GITHUB_STEP_SUMMARY << 'EOF'
|
||||
{
|
||||
cat << 'EOF'
|
||||
## 🧪 Docker Image Tests
|
||||
|
||||
EOF
|
||||
|
||||
# Run Task docker test
|
||||
task docker:test
|
||||
# Run Task docker test
|
||||
task docker:test
|
||||
|
||||
echo "**Testing help command:**" >> $GITHUB_STEP_SUMMARY
|
||||
echo '```terminaloutput' >> $GITHUB_STEP_SUMMARY
|
||||
docker run --rm articulate-parser:latest --help >> $GITHUB_STEP_SUMMARY
|
||||
echo '```' >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Testing help command:**"
|
||||
echo '```terminaloutput'
|
||||
docker run --rm articulate-parser:latest --help
|
||||
echo '```'
|
||||
echo ""
|
||||
|
||||
# Test image size
|
||||
IMAGE_SIZE=$(docker image inspect articulate-parser:latest --format='{{.Size}}' | numfmt --to=iec-i --suffix=B)
|
||||
echo "**Image size:** $IMAGE_SIZE" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
# Test image size
|
||||
IMAGE_SIZE=$(docker image inspect articulate-parser:latest --format='{{.Size}}' | numfmt --to=iec-i --suffix=B)
|
||||
echo "**Image size:** $IMAGE_SIZE"
|
||||
echo ""
|
||||
} >> "$GITHUB_STEP_SUMMARY"
|
||||
|
||||
dependency-review:
|
||||
name: Dependency Review
|
||||
@ -339,10 +351,10 @@ jobs:
|
||||
contents: read
|
||||
if: github.event_name == 'pull_request'
|
||||
steps:
|
||||
- name: "Checkout Repository"
|
||||
uses: actions/checkout@v6
|
||||
- name: 'Checkout Repository'
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: "Dependency Review"
|
||||
- name: 'Dependency Review'
|
||||
uses: actions/dependency-review-action@v4
|
||||
with:
|
||||
fail-on-severity: moderate
|
||||
@ -354,14 +366,14 @@ jobs:
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
needs: [test, docker-test, dependency-review]
|
||||
needs: [test]
|
||||
if: |
|
||||
github.event_name == 'push' && (github.ref == 'refs/heads/master' ||
|
||||
github.ref == 'refs/heads/develop' ||
|
||||
startsWith(github.ref, 'refs/heads/feature/docker'))
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
@ -433,7 +445,7 @@ jobs:
|
||||
|
||||
- name: Generate Docker summary
|
||||
run: |
|
||||
cat >> $GITHUB_STEP_SUMMARY << 'EOF'
|
||||
cat >> "$GITHUB_STEP_SUMMARY" << 'EOF'
|
||||
## 🐳 Docker Build Summary
|
||||
|
||||
**Image:** `ghcr.io/${{ github.repository }}`
|
||||
|
||||
208
.github/workflows/codeql.yml
vendored
208
.github/workflows/codeql.yml
vendored
@ -1,104 +1,104 @@
|
||||
# For most projects, this workflow file will not need changing; you simply need
|
||||
# to commit it to your repository.
|
||||
#
|
||||
# You may wish to alter this file to override the set of languages analyzed,
|
||||
# or to provide custom queries or build logic.
|
||||
#
|
||||
# ******** NOTE ********
|
||||
# We have attempted to detect the languages in your repository. Please check
|
||||
# the `language` matrix defined below to confirm you have the correct set of
|
||||
# supported CodeQL languages.
|
||||
#
|
||||
name: "CodeQL"
|
||||
|
||||
# This workflow is configured to be called by other workflows for more controlled execution
|
||||
# This allows integration with the main CI pipeline and avoids redundant runs
|
||||
# To enable automatic execution, uncomment the triggers below:
|
||||
on:
|
||||
workflow_call:
|
||||
schedule:
|
||||
- cron: '44 16 * * 6'
|
||||
# push:
|
||||
# branches: [ "master" ]
|
||||
# pull_request:
|
||||
# branches: [ "master" ]
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze (${{ matrix.language }})
|
||||
# Runner size impacts CodeQL analysis time. To learn more, please see:
|
||||
# - https://gh.io/recommended-hardware-resources-for-running-codeql
|
||||
# - https://gh.io/supported-runners-and-hardware-resources
|
||||
# - https://gh.io/using-larger-runners (GitHub.com only)
|
||||
# Consider using larger runners or machines with greater resources for possible analysis time improvements.
|
||||
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
|
||||
permissions:
|
||||
# required for all workflows
|
||||
security-events: write
|
||||
|
||||
# required to fetch internal or private CodeQL packs
|
||||
packages: read
|
||||
|
||||
# only required for workflows in private repositories
|
||||
actions: read
|
||||
contents: read
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- language: actions
|
||||
build-mode: none
|
||||
- language: go
|
||||
build-mode: autobuild
|
||||
# CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift'
|
||||
# Use `c-cpp` to analyze code written in C, C++ or both
|
||||
# Use 'java-kotlin' to analyze code written in Java, Kotlin or both
|
||||
# Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
|
||||
# To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
|
||||
# see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
|
||||
# If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
|
||||
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
# Add any setup steps before running the `github/codeql-action/init` action.
|
||||
# This includes steps like installing compilers or runtimes (`actions/setup-node`
|
||||
# or others). This is typically only required for manual builds.
|
||||
# - name: Setup runtime (example)
|
||||
# uses: actions/setup-example@v1
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v4
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
build-mode: ${{ matrix.build-mode }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
|
||||
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||
# queries: security-extended,security-and-quality
|
||||
|
||||
# If the analyze step fails for one of the languages you are analyzing with
|
||||
# "We were unable to automatically build your code", modify the matrix above
|
||||
# to set the build mode to "manual" for that language. Then modify this step
|
||||
# to build your code.
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||
- if: matrix.build-mode == 'manual'
|
||||
shell: bash
|
||||
run: |
|
||||
echo 'If you are using a "manual" build mode for one or more of the' \
|
||||
'languages you are analyzing, replace this with the commands to build' \
|
||||
'your code, for example:'
|
||||
echo ' make bootstrap'
|
||||
echo ' make release'
|
||||
exit 1
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v4
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
# For most projects, this workflow file will not need changing; you simply need
|
||||
# to commit it to your repository.
|
||||
#
|
||||
# You may wish to alter this file to override the set of languages analyzed,
|
||||
# or to provide custom queries or build logic.
|
||||
#
|
||||
# ******** NOTE ********
|
||||
# We have attempted to detect the languages in your repository. Please check
|
||||
# the `language` matrix defined below to confirm you have the correct set of
|
||||
# supported CodeQL languages.
|
||||
#
|
||||
name: "CodeQL"
|
||||
|
||||
# This workflow is configured to be called by other workflows for more controlled execution
|
||||
# This allows integration with the main CI pipeline and avoids redundant runs
|
||||
# To enable automatic execution, uncomment the triggers below:
|
||||
on:
|
||||
workflow_call:
|
||||
schedule:
|
||||
- cron: '44 16 * * 6'
|
||||
# push:
|
||||
# branches: [ "master" ]
|
||||
# pull_request:
|
||||
# branches: [ "master" ]
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze (${{ matrix.language }})
|
||||
# Runner size impacts CodeQL analysis time. To learn more, please see:
|
||||
# - https://gh.io/recommended-hardware-resources-for-running-codeql
|
||||
# - https://gh.io/supported-runners-and-hardware-resources
|
||||
# - https://gh.io/using-larger-runners (GitHub.com only)
|
||||
# Consider using larger runners or machines with greater resources for possible analysis time improvements.
|
||||
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
|
||||
permissions:
|
||||
# required for all workflows
|
||||
security-events: write
|
||||
|
||||
# required to fetch internal or private CodeQL packs
|
||||
packages: read
|
||||
|
||||
# only required for workflows in private repositories
|
||||
actions: read
|
||||
contents: read
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- language: actions
|
||||
build-mode: none
|
||||
- language: go
|
||||
build-mode: autobuild
|
||||
# CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift'
|
||||
# Use `c-cpp` to analyze code written in C, C++ or both
|
||||
# Use 'java-kotlin' to analyze code written in Java, Kotlin or both
|
||||
# Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
|
||||
# To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
|
||||
# see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
|
||||
# If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
|
||||
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
|
||||
# Add any setup steps before running the `github/codeql-action/init` action.
|
||||
# This includes steps like installing compilers or runtimes (`actions/setup-node`
|
||||
# or others). This is typically only required for manual builds.
|
||||
# - name: Setup runtime (example)
|
||||
# uses: actions/setup-example@v1
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v4
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
build-mode: ${{ matrix.build-mode }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
|
||||
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||
# queries: security-extended,security-and-quality
|
||||
|
||||
# If the analyze step fails for one of the languages you are analyzing with
|
||||
# "We were unable to automatically build your code", modify the matrix above
|
||||
# to set the build mode to "manual" for that language. Then modify this step
|
||||
# to build your code.
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||
- if: matrix.build-mode == 'manual'
|
||||
shell: bash
|
||||
run: |
|
||||
echo 'If you are using a "manual" build mode for one or more of the' \
|
||||
'languages you are analyzing, replace this with the commands to build' \
|
||||
'your code, for example:'
|
||||
echo ' make bootstrap'
|
||||
echo ' make release'
|
||||
exit 1
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v4
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
|
||||
2
.github/workflows/dependency-review.yml
vendored
2
.github/workflows/dependency-review.yml
vendored
@ -17,7 +17,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: 'Checkout Repository'
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: 'Dependency Review'
|
||||
uses: actions/dependency-review-action@v4
|
||||
|
||||
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
@ -20,7 +20,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
@ -88,7 +88,7 @@ jobs:
|
||||
packages: write
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
|
||||
158
.gitignore
vendored
158
.gitignore
vendored
@ -1,79 +1,79 @@
|
||||
# Created by https://www.toptal.com/developers/gitignore/api/go
|
||||
# Edit at https://www.toptal.com/developers/gitignore?templates=go
|
||||
|
||||
### Go ###
|
||||
# If you prefer the allow list template instead of the deny list, see community template:
|
||||
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
|
||||
#
|
||||
# Binaries for programs and plugins
|
||||
*.exe
|
||||
*.exe~
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
|
||||
# Test binary, built with `go test -c`
|
||||
*.test
|
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
|
||||
# Dependency directories (remove the comment below to include it)
|
||||
# vendor/
|
||||
|
||||
# Go workspace file
|
||||
go.work
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/go
|
||||
|
||||
# Shit
|
||||
.github/TODO
|
||||
|
||||
# Local test files
|
||||
output/
|
||||
outputs/
|
||||
articulate-sample.json
|
||||
test-output.*
|
||||
go-os-arch-matrix.csv
|
||||
test_godocx.go
|
||||
test_input.json
|
||||
|
||||
# Build artifacts
|
||||
build/
|
||||
|
||||
# Old workflows
|
||||
.github/workflows/ci-old.yml
|
||||
.github/workflows/ci-enhanced.yml
|
||||
|
||||
# Test coverage files
|
||||
coverage.out
|
||||
coverage.txt
|
||||
coverage.html
|
||||
coverage.*
|
||||
coverage
|
||||
*.cover
|
||||
*.coverprofile
|
||||
main_coverage
|
||||
|
||||
# Other common exclusions
|
||||
*.exe
|
||||
*.exe~
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
*.test
|
||||
*.out
|
||||
/tmp/
|
||||
.github/copilot-instructions.md
|
||||
|
||||
# Editors
|
||||
.vscode/
|
||||
.idea/
|
||||
|
||||
.task/
|
||||
|
||||
**/*.local.*
|
||||
|
||||
.claude/
|
||||
|
||||
NUL
|
||||
# Created by https://www.toptal.com/developers/gitignore/api/go
|
||||
# Edit at https://www.toptal.com/developers/gitignore?templates=go
|
||||
|
||||
### Go ###
|
||||
# If you prefer the allow list template instead of the deny list, see community template:
|
||||
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
|
||||
#
|
||||
# Binaries for programs and plugins
|
||||
*.exe
|
||||
*.exe~
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
|
||||
# Test binary, built with `go test -c`
|
||||
*.test
|
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
|
||||
# Dependency directories (remove the comment below to include it)
|
||||
# vendor/
|
||||
|
||||
# Go workspace file
|
||||
go.work
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/go
|
||||
|
||||
# Shit
|
||||
.github/TODO
|
||||
|
||||
# Local test files
|
||||
output/
|
||||
outputs/
|
||||
articulate-sample.json
|
||||
test-output.*
|
||||
go-os-arch-matrix.csv
|
||||
test_godocx.go
|
||||
test_input.json
|
||||
|
||||
# Build artifacts
|
||||
build/
|
||||
|
||||
# Old workflows
|
||||
.github/workflows/ci-old.yml
|
||||
.github/workflows/ci-enhanced.yml
|
||||
|
||||
# Test coverage files
|
||||
coverage.out
|
||||
coverage.txt
|
||||
coverage.html
|
||||
coverage.*
|
||||
coverage
|
||||
*.cover
|
||||
*.coverprofile
|
||||
main_coverage
|
||||
|
||||
# Other common exclusions
|
||||
*.exe
|
||||
*.exe~
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
*.test
|
||||
*.out
|
||||
/tmp/
|
||||
.github/copilot-instructions.md
|
||||
|
||||
# Editors
|
||||
.vscode/
|
||||
.idea/
|
||||
|
||||
.task/
|
||||
|
||||
**/*.local.*
|
||||
|
||||
.claude/
|
||||
|
||||
NUL
|
||||
|
||||
75
.pre-commit-config.yaml
Normal file
75
.pre-commit-config.yaml
Normal file
@ -0,0 +1,75 @@
|
||||
# See https://pre-commit.com for more information
|
||||
# See https://pre-commit.com/hooks.html for more hooks
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v6.0.0
|
||||
hooks:
|
||||
# File quality
|
||||
- id: trailing-whitespace
|
||||
exclude: '^\.github/ISSUE_TEMPLATE/.*\.yml$'
|
||||
- id: end-of-file-fixer
|
||||
- id: mixed-line-ending
|
||||
args: ['--fix=lf']
|
||||
|
||||
# File validation
|
||||
- id: check-yaml
|
||||
- id: check-json
|
||||
- id: check-toml
|
||||
|
||||
# Security
|
||||
- id: detect-private-key
|
||||
|
||||
# Git safety
|
||||
- id: check-merge-conflict
|
||||
- id: check-case-conflict
|
||||
- id: no-commit-to-branch
|
||||
args: ['--branch=master', '--branch=main']
|
||||
|
||||
# File structure
|
||||
- id: check-added-large-files
|
||||
- id: check-symlinks
|
||||
- id: check-executables-have-shebangs
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: actionlint
|
||||
name: Lint GitHub Actions workflow files
|
||||
description: Runs actionlint to lint GitHub Actions workflow files
|
||||
language: golang
|
||||
types: ["yaml"]
|
||||
files: ^\.github/workflows/
|
||||
entry: actionlint
|
||||
minimum_pre_commit_version: 3.0.0
|
||||
- repo: https://github.com/golangci/golangci-lint
|
||||
rev: v2.6.1
|
||||
hooks:
|
||||
- id: golangci-lint
|
||||
name: golangci-lint
|
||||
description: Fast linters runner for Go. Note that only modified files are linted, so linters like 'unused' that need to scan all files won't work as expected.
|
||||
entry: golangci-lint run --new-from-rev HEAD --fix
|
||||
types: [go]
|
||||
language: golang
|
||||
require_serial: true
|
||||
pass_filenames: false
|
||||
# - id: golangci-lint-full
|
||||
# name: golangci-lint-full
|
||||
# description: Fast linters runner for Go. Runs on all files in the module. Use this hook if you use pre-commit in CI.
|
||||
# entry: golangci-lint run --fix
|
||||
# types: [go]
|
||||
# language: golang
|
||||
# require_serial: true
|
||||
# pass_filenames: false
|
||||
- id: golangci-lint-fmt
|
||||
name: golangci-lint-fmt
|
||||
description: Fast linters runner for Go. Formats all files in the repo.
|
||||
entry: golangci-lint fmt
|
||||
types: [go]
|
||||
language: golang
|
||||
require_serial: true
|
||||
pass_filenames: false
|
||||
- id: golangci-lint-config-verify
|
||||
name: golangci-lint-config-verify
|
||||
description: Verifies the configuration file
|
||||
entry: golangci-lint config verify
|
||||
files: '\.golangci\.(?:yml|yaml|toml|json)'
|
||||
language: golang
|
||||
pass_filenames: false
|
||||
497
AGENTS.md
497
AGENTS.md
@ -1,82 +1,36 @@
|
||||
# Agent Guidelines for articulate-parser
|
||||
|
||||
A Go CLI tool that parses Articulate Rise courses from URLs or local JSON files and exports them to Markdown, HTML, or DOCX formats.
|
||||
|
||||
## Build/Test Commands
|
||||
|
||||
### Primary Commands (using Taskfile)
|
||||
|
||||
```bash
|
||||
task build # Build binary to bin/articulate-parser
|
||||
task test # Run all tests with race detection
|
||||
task lint # Run all linters (vet, fmt, staticcheck, golangci-lint)
|
||||
task fmt # Format all Go files
|
||||
task ci # Full CI pipeline: deps, lint, test with coverage, build
|
||||
task qa # Quick QA: fmt + lint + test
|
||||
```
|
||||
|
||||
### Direct Go Commands
|
||||
|
||||
```bash
|
||||
# Build
|
||||
go build -o bin/articulate-parser main.go
|
||||
|
||||
# Run all tests
|
||||
go test -race -timeout 5m ./...
|
||||
|
||||
# Run single test by name
|
||||
go test -v -race -run ^TestMarkdownExporter_Export$ ./internal/exporters
|
||||
|
||||
# Run tests in specific package
|
||||
go test -v -race ./internal/services
|
||||
|
||||
# Run tests matching pattern
|
||||
go test -v -race -run "TestParser" ./...
|
||||
|
||||
# Test with coverage
|
||||
go test -race -coverprofile=coverage/coverage.out -covermode=atomic ./...
|
||||
go tool cover -html=coverage/coverage.out -o coverage/coverage.html
|
||||
|
||||
# Benchmarks
|
||||
go test -bench=. -benchmem ./...
|
||||
go test -bench=BenchmarkMarkdownExporter ./internal/exporters
|
||||
```
|
||||
|
||||
### Security & Auditing
|
||||
|
||||
```bash
|
||||
task security:check # Run gosec security scanner
|
||||
task security:audit # Run govulncheck for vulnerabilities
|
||||
```
|
||||
- **Build**: `task build` or `go build -o bin/articulate-parser main.go`
|
||||
- **Run tests**: `task test` or `go test -race -timeout 5m ./...`
|
||||
- **Run single test**: `go test -v -race -run ^TestName$ ./path/to/package`
|
||||
- **Test with coverage**:
|
||||
- `task test:coverage` or
|
||||
- `go test -race -coverprofile=coverage/coverage.out -covermode=atomic ./...`
|
||||
- **Lint**: `task lint` (runs vet, fmt check, staticcheck, golangci-lint)
|
||||
- **Format**: `task fmt` or `gofmt -s -w .`
|
||||
- **CI checks**: `task ci` (deps, lint, test with coverage, build)
|
||||
|
||||
## Code Style Guidelines
|
||||
|
||||
### Imports
|
||||
|
||||
- Use `goimports` with local prefix: `github.com/kjanat/articulate-parser`
|
||||
- Order: stdlib, blank line, external packages, blank line, internal packages
|
||||
|
||||
```go
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/fumiama/go-docx"
|
||||
|
||||
"github.com/kjanat/articulate-parser/internal/interfaces"
|
||||
)
|
||||
```
|
||||
- Order: stdlib, external, internal packages
|
||||
- Group related imports together
|
||||
|
||||
### Formatting
|
||||
|
||||
- Use `gofmt -s` (simplify) and `gofumpt` with extra rules
|
||||
- Function length: max 100 lines, 50 statements
|
||||
- Cyclomatic complexity: max 15; Cognitive complexity: max 20
|
||||
- Cyclomatic complexity: max 15
|
||||
- Cognitive complexity: max 20
|
||||
|
||||
### Types & Naming
|
||||
|
||||
- Use interface-based design (see `internal/interfaces/`)
|
||||
- Exported types/functions require godoc comments ending with period
|
||||
- Export types/functions with clear godoc comments ending with period
|
||||
- Use descriptive names: `ArticulateParser`, `MarkdownExporter`
|
||||
- Receiver names: short (1-2 chars), consistent per type
|
||||
|
||||
@ -87,20 +41,6 @@ import (
|
||||
- Check all error returns (enforced by `errcheck`)
|
||||
- Document error handling rationale in defer blocks when ignoring close errors
|
||||
|
||||
```go
|
||||
// Good: Error wrapping with context
|
||||
if err := json.Unmarshal(body, &course); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal JSON: %w", err)
|
||||
}
|
||||
|
||||
// Good: Documented defer with error handling
|
||||
defer func() {
|
||||
if err := resp.Body.Close(); err != nil {
|
||||
p.Logger.Warn("failed to close response body", "error", err)
|
||||
}
|
||||
}()
|
||||
```
|
||||
|
||||
### Comments
|
||||
|
||||
- All exported types/functions require godoc comments
|
||||
@ -109,70 +49,379 @@ defer func() {
|
||||
|
||||
### Security
|
||||
|
||||
- Use `#nosec` with justification for deliberate security exceptions
|
||||
- G304: File paths from CLI args; G306: Export file permissions
|
||||
|
||||
```go
|
||||
// #nosec G304 - File path provided by user via CLI argument
|
||||
data, err := os.ReadFile(filePath)
|
||||
```
|
||||
- Use `#nosec` with justification for deliberate security exceptions (G304 for CLI file paths, G306 for export file permissions)
|
||||
- Run `gosec` and `govulncheck` for security audits
|
||||
|
||||
### Testing
|
||||
|
||||
- Enable race detection: `-race` flag always
|
||||
- Enable race detection: `-race` flag
|
||||
- Use table-driven tests where applicable
|
||||
- Mark test helpers with `t.Helper()`
|
||||
- Use `t.TempDir()` for temporary files
|
||||
- Benchmarks in `*_bench_test.go`, examples in `*_example_test.go`
|
||||
- Test naming: `Test<Type>_<Method>` or `Test<Function>`
|
||||
|
||||
```go
|
||||
func TestMarkdownExporter_ProcessItemToMarkdown_AllTypes(t *testing.T) {
|
||||
tests := []struct {
|
||||
name, itemType, expectedText string
|
||||
}{
|
||||
{"text item", "text", ""},
|
||||
{"divider item", "divider", "---"},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
// test implementation
|
||||
})
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Minimal external dependencies (go-docx, golang.org/x/net, golang.org/x/text)
|
||||
- Minimal external dependencies (currently: go-docx, golang.org/x/net, golang.org/x/text)
|
||||
- Run `task deps:tidy` after adding/removing dependencies
|
||||
- CGO disabled by default (`CGO_ENABLED=0`)
|
||||
|
||||
## Project Structure
|
||||
---
|
||||
|
||||
```
|
||||
articulate-parser/
|
||||
internal/
|
||||
config/ # Configuration loading
|
||||
exporters/ # Export implementations (markdown, html, docx)
|
||||
interfaces/ # Core interfaces (Exporter, CourseParser, Logger)
|
||||
models/ # Data models (Course, Lesson, Item, Media)
|
||||
services/ # Core services (parser, html cleaner, app, logger)
|
||||
version/ # Version information
|
||||
main.go # Application entry point
|
||||
```
|
||||
## Go 1.24 & 1.25 New Features Reference
|
||||
|
||||
## Common Patterns
|
||||
This project uses Go 1.24+. Below is a comprehensive summary of new features and changes in Go 1.24 and 1.25 that may be relevant for development and maintenance.
|
||||
|
||||
### Creating a new exporter
|
||||
### Go 1.24 Major Changes (Released February 2025)
|
||||
|
||||
1. Implement `interfaces.Exporter` interface
|
||||
2. Add factory method to `internal/exporters/factory.go`
|
||||
3. Register format in `NewFactory()`
|
||||
4. Add tests following existing patterns
|
||||
#### Language Features
|
||||
|
||||
### Adding configuration options
|
||||
**Generic Type Aliases**
|
||||
|
||||
1. Add field to `Config` struct in `internal/config/config.go`
|
||||
2. Load from environment variable with sensible default
|
||||
3. Document in config struct comments
|
||||
- Type aliases can now be parameterized with type parameters
|
||||
- Example: `type List[T any] = []T`
|
||||
- Can be disabled via `GOEXPERIMENT=noaliastypeparams` (removed in 1.25)
|
||||
|
||||
#### Tooling Enhancements
|
||||
|
||||
**Module Tool Dependencies**
|
||||
|
||||
- New `tool` directive in go.mod tracks executable dependencies
|
||||
- Use `go get -tool <package>` to add tool dependencies
|
||||
- Use `go install tool` and `go get tool` to manage them
|
||||
- Eliminates need for blank imports in `tools.go` files
|
||||
|
||||
**Build Output Formatting**
|
||||
|
||||
- Both `go build` and `go test` support `-json` flag for structured JSON output
|
||||
- New action types distinguish build output from test results
|
||||
|
||||
**Authentication**
|
||||
|
||||
- New `GOAUTH` environment variable provides flexible authentication for private modules
|
||||
|
||||
**Automatic Version Tracking**
|
||||
|
||||
- `go build` automatically sets main module version in binaries based on VCS tags
|
||||
- Adds `+dirty` suffix for uncommitted changes
|
||||
|
||||
**Cgo Performance Improvements**
|
||||
|
||||
- New `#cgo noescape` annotation: Prevents escape analysis overhead for C function calls
|
||||
- New `#cgo nocallback` annotation: Indicates C function won't call back to Go
|
||||
|
||||
**Toolchain Tracing**
|
||||
|
||||
- `GODEBUG=toolchaintrace=1` enables tracing of toolchain selection
|
||||
|
||||
#### Runtime & Performance
|
||||
|
||||
**Performance Improvements**
|
||||
|
||||
- **2-3% CPU overhead reduction** across benchmark suites
|
||||
- New Swiss Tables-based map implementation (faster lookups)
|
||||
- Disable via `GOEXPERIMENT=noswissmap`
|
||||
- More efficient small object allocation
|
||||
- Redesigned runtime-internal mutexes
|
||||
- Disable via `GOEXPERIMENT=nospinbitmutex`
|
||||
|
||||
#### Compiler & Linker
|
||||
|
||||
**Method Receiver Restrictions**
|
||||
|
||||
- Methods on cgo-generated types now prevented (both directly and through aliases)
|
||||
|
||||
**Build IDs**
|
||||
|
||||
- Linkers generate GNU build IDs (ELF) and UUIDs (macOS) by default
|
||||
- Disable via `-B none` flag
|
||||
|
||||
#### Standard Library Additions
|
||||
|
||||
**File System Safety - `os.Root`**
|
||||
|
||||
- New `os.Root` type enables directory-limited operations
|
||||
- Prevents path escape and symlink breakouts
|
||||
- Essential for sandboxed file operations
|
||||
|
||||
**Cryptography Expansion**
|
||||
|
||||
- `crypto/mlkem`: ML-KEM-768/1024 post-quantum key exchange (FIPS 203)
|
||||
- `crypto/hkdf`: HMAC-based Extract-and-Expand KDF (RFC 5869)
|
||||
- `crypto/pbkdf2`: Password-based key derivation (RFC 8018)
|
||||
- `crypto/sha3`: SHA-3 and SHAKE functions (FIPS 202)
|
||||
|
||||
**FIPS 140-3 Support**
|
||||
|
||||
- New `GOFIPS140` environment variable enables FIPS mode
|
||||
- New `fips140` GODEBUG setting for cryptographic module compliance
|
||||
|
||||
**Weak References - `weak` Package**
|
||||
|
||||
- New `weak` package provides low-level weak pointers
|
||||
- Enables memory-efficient structures like weak maps and caches
|
||||
- Useful for preventing memory leaks in cache implementations
|
||||
|
||||
**Testing Improvements**
|
||||
|
||||
- `testing.B.Loop()`: Cleaner syntax replacing manual `b.N` iteration
|
||||
- Prevents compiler from optimizing away benchmarked code
|
||||
- New `testing/synctest` package (experimental) for testing concurrent code with fake clocks
|
||||
|
||||
**Iterator Support**
|
||||
|
||||
- Multiple packages now offer iterator-returning variants:
|
||||
- `bytes`: Iterator-based functions
|
||||
- `strings`: Iterator-based functions
|
||||
- `go/types`: Iterator support
|
||||
|
||||
#### Security Enhancements
|
||||
|
||||
**TLS Post-Quantum Cryptography**
|
||||
|
||||
- `X25519MLKEM768` hybrid key exchange enabled by default in TLS
|
||||
- Provides quantum-resistant security
|
||||
|
||||
**Encrypted Client Hello (ECH)**
|
||||
|
||||
- TLS servers can enable ECH via `Config.EncryptedClientHelloKeys`
|
||||
- Protects client identity during TLS handshake
|
||||
|
||||
**RSA Key Validation**
|
||||
|
||||
- Keys smaller than 1024 bits now rejected by default
|
||||
- Use `GODEBUG=rsa1024min=0` to revert (testing only)
|
||||
|
||||
**Constant-Time Execution**
|
||||
|
||||
- New `crypto/subtle.WithDataIndependentTiming()` enables architecture-specific timing guarantees
|
||||
- Helps prevent timing attacks
|
||||
|
||||
#### Deprecations & Removals
|
||||
|
||||
- `runtime.GOROOT()`: Deprecated; use system path instead
|
||||
- `crypto/cipher` OFB/CFB modes: Deprecated (unauthenticated encryption)
|
||||
- `x509sha1` GODEBUG: Removed; SHA-1 certificates no longer verified
|
||||
- Experimental `X25519Kyber768Draft00`: Removed
|
||||
|
||||
#### Platform Changes
|
||||
|
||||
- **Linux**: Now requires kernel 3.2+ (enforced)
|
||||
- **macOS**: Go 1.24 is final release supporting Big Sur
|
||||
- **Windows/ARM 32-bit**: Marked broken
|
||||
- **WebAssembly**:
|
||||
- New `go:wasmexport` directive
|
||||
- Reactor/library builds supported via `-buildmode=c-shared`
|
||||
|
||||
#### Bootstrap Requirements
|
||||
|
||||
- Go 1.24 requires Go 1.22.6+ for bootstrapping
|
||||
- Go 1.26 will require Go 1.24+
|
||||
|
||||
---
|
||||
|
||||
### Go 1.25 Major Changes (Released August 2025)
|
||||
|
||||
#### Language Changes
|
||||
|
||||
- No breaking language changes
|
||||
- "Core types" concept removed from specification (replaced with clearer prose)
|
||||
|
||||
#### Tooling Improvements
|
||||
|
||||
**Go Command Enhancements**
|
||||
|
||||
- `go build -asan`: Now defaults to leak detection at program exit
|
||||
- New `go.mod ignore` directive: Specify directories for go command to ignore
|
||||
- `go doc -http`: Starts documentation server and opens in browser
|
||||
- `go version -m -json`: Prints JSON-encoded BuildInfo structures
|
||||
- Module path resolution now supports subdirectories using `<meta>` syntax
|
||||
- New `work` package pattern matches all packages in work/workspace modules
|
||||
- Removed automatic toolchain line additions when updating `go` version
|
||||
|
||||
**Vet Analyzers**
|
||||
|
||||
- **"waitgroup"**: Detects misplaced `sync.WaitGroup.Add` calls
|
||||
- **"hostport"**: Warns against using `fmt.Sprintf` for constructing addresses
|
||||
- Recommends `net.JoinHostPort` instead
|
||||
|
||||
#### Runtime Enhancements
|
||||
|
||||
**Container-Aware GOMAXPROCS**
|
||||
|
||||
- Linux now respects cgroup CPU bandwidth limits
|
||||
- All OSes periodically update GOMAXPROCS if CPU availability changes
|
||||
- Disable via environment variables or GODEBUG settings
|
||||
- Critical for containerized applications
|
||||
|
||||
**New Garbage Collector - "Green Tea GC"**
|
||||
|
||||
- Experimental `GOEXPERIMENT=greenteagc` enables new GC
|
||||
- **10-40% reduction in garbage collection overhead**
|
||||
- Significant for GC-sensitive applications
|
||||
|
||||
**Trace Flight Recorder**
|
||||
|
||||
- New `runtime/trace.FlightRecorder` API
|
||||
- Captures execution traces in in-memory ring buffer
|
||||
- Essential for debugging rare events and production issues
|
||||
|
||||
**Other Runtime Changes**
|
||||
|
||||
- Simplified unhandled panic output
|
||||
- VMA names on Linux identify memory purpose (debugging aid)
|
||||
- New `SetDefaultGOMAXPROCS` function resets GOMAXPROCS to defaults
|
||||
|
||||
#### Compiler Fixes & Improvements
|
||||
|
||||
**Critical Nil Pointer Bug Fix**
|
||||
|
||||
- Fixed Go 1.21 regression where nil pointer checks were incorrectly delayed
|
||||
- ⚠️ **May cause previously passing code to now panic** (correct behavior)
|
||||
- Review code for assumptions about delayed nil checks
|
||||
|
||||
**DWARF5 Support**
|
||||
|
||||
- Debug information now uses DWARF version 5
|
||||
- Reduces binary size and linking time
|
||||
- Better debugging experience
|
||||
|
||||
**Faster Slices**
|
||||
|
||||
- Expanded stack allocation for slice backing stores
|
||||
- Improved slice performance
|
||||
|
||||
#### Linker
|
||||
|
||||
- New `-funcalign=N` option specifies function entry alignment
|
||||
|
||||
#### Standard Library Highlights
|
||||
|
||||
**New Packages**
|
||||
|
||||
1. **`testing/synctest`** (Promoted from Experimental)
|
||||
- Concurrent code testing with virtualized time
|
||||
- Control time progression in tests
|
||||
- Essential for testing time-dependent concurrent code
|
||||
|
||||
2. **`encoding/json/v2`** (Experimental)
|
||||
- **Substantially better decoding performance**
|
||||
- Improved API design
|
||||
- Backward compatible with v1
|
||||
|
||||
**Major Package Updates**
|
||||
|
||||
| Package | Key Changes |
|
||||
|---------|------------|
|
||||
| `crypto` | New `MessageSigner` interface and `SignMessage` function |
|
||||
| `crypto/ecdsa` | New raw key parsing/serialization functions |
|
||||
| `crypto/rsa` | **Key generation now 3x faster** |
|
||||
| `crypto/sha1` | **Hashing 2x faster on amd64 with SHA-NI** |
|
||||
| `crypto/tls` | New `CurveID` field; SHA-1 algorithms disallowed in TLS 1.2 |
|
||||
| `net` | Windows now supports file-to-connection conversion; IPv6 multicast improvements |
|
||||
| `net/http` | **New `CrossOriginProtection` middleware for CSRF defense** |
|
||||
| `os` | Windows async I/O support; `Root` type expanded with 12 new methods |
|
||||
| `sync` | **New `WaitGroup.Go` method for convenient goroutine creation** |
|
||||
| `testing` | New `Attr`, `Output` methods; `AllocsPerRun` panics with parallel tests |
|
||||
| `unique` | More eager and parallel reclamation of interned values |
|
||||
|
||||
#### Performance Notes
|
||||
|
||||
**Performance Improvements**
|
||||
|
||||
- ECDSA and Ed25519 signing **4x faster** in FIPS 140-3 mode
|
||||
- SHA3 hashing **2x faster** on Apple M processors
|
||||
- AMD64 fused multiply-add instructions in v3+ mode
|
||||
- ⚠️ **Changes floating-point results** (within IEEE 754 spec)
|
||||
|
||||
**Performance Regressions**
|
||||
|
||||
- SHA-1, SHA-256, SHA-512 slower without AVX2
|
||||
- Most servers post-2015 support AVX2
|
||||
|
||||
#### Platform Changes
|
||||
|
||||
- **macOS**: Requires version 12 Monterey or later
|
||||
- **Windows**: 32-bit windows/arm port marked for removal in Go 1.26
|
||||
- **Loong64**: Race detector now supported
|
||||
- **RISC-V**:
|
||||
- Plugin build mode support
|
||||
- New `GORISCV64=rva23u64` environment variable value
|
||||
|
||||
#### Deprecations
|
||||
|
||||
- `go/ast` functions: `FilterPackage`, `PackageExports`, `MergePackageFiles`
|
||||
- `go/parser.ParseDir` function
|
||||
- Old `testing/synctest` API (when `GOEXPERIMENT=synctest` set)
|
||||
|
||||
---
|
||||
|
||||
### Actionable Recommendations for This Project
|
||||
|
||||
#### Immediate Opportunities
|
||||
|
||||
1. **Replace `sync.WaitGroup` patterns with `WaitGroup.Go()`** (Go 1.25)
|
||||
|
||||
```go
|
||||
// Old pattern
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
// work
|
||||
}()
|
||||
|
||||
// New pattern (Go 1.25)
|
||||
wg.Go(func() {
|
||||
// work
|
||||
})
|
||||
```
|
||||
|
||||
2. **Use `testing.B.Loop()` in benchmarks** (Go 1.24)
|
||||
|
||||
```go
|
||||
// Old pattern
|
||||
for i := 0; i < b.N; i++ {
|
||||
// benchmark code
|
||||
}
|
||||
|
||||
// New pattern (Go 1.24)
|
||||
for b.Loop() {
|
||||
// benchmark code
|
||||
}
|
||||
```
|
||||
|
||||
3. **Consider `os.Root` for file operations** (Go 1.24)
|
||||
- Prevents path traversal vulnerabilities
|
||||
- Safer for user-provided file paths
|
||||
|
||||
4. **Enable Green Tea GC for testing** (Go 1.25)
|
||||
- Test with `GOEXPERIMENT=greenteagc`
|
||||
- May reduce GC overhead by 10-40%
|
||||
|
||||
5. **Leverage container-aware GOMAXPROCS** (Go 1.25)
|
||||
- No changes needed; automatic in containers
|
||||
- Improves resource utilization
|
||||
|
||||
6. **Review floating-point operations** (Go 1.25)
|
||||
- AMD64 v3+ uses FMA instructions
|
||||
- May change floating-point results (within spec)
|
||||
|
||||
7. **Watch nil pointer checks** (Go 1.25)
|
||||
- Compiler bug fix may expose latent nil pointer bugs
|
||||
- Review crash reports carefully
|
||||
|
||||
#### Future Considerations
|
||||
|
||||
1. **Evaluate `encoding/json/v2`** when stable
|
||||
- Better performance for JSON operations
|
||||
- Currently experimental in Go 1.25
|
||||
|
||||
2. **Adopt tool directives** in go.mod
|
||||
- Cleaner dependency management for build tools
|
||||
- Remove `tools.go` if present
|
||||
|
||||
3. **Enable FIPS mode if required**
|
||||
- Use `GOFIPS140=1` for compliance
|
||||
- Performance improvements in Go 1.25 (4x faster signing)
|
||||
|
||||
4. **Use `runtime/trace.FlightRecorder`** for production debugging
|
||||
- Capture traces of rare events
|
||||
- Minimal overhead when not triggered
|
||||
|
||||
22
DOCKER.md
22
DOCKER.md
@ -49,17 +49,17 @@ docker run --rm ghcr.io/kjanat/articulate-parser:latest --version
|
||||
|
||||
## Available Tags
|
||||
|
||||
- `latest` - Latest stable release
|
||||
- `v1.x.x` - Specific version tags
|
||||
- `main` - Latest development build
|
||||
- `latest` - Latest stable release
|
||||
- `v1.x.x` - Specific version tags
|
||||
- `main` - Latest development build
|
||||
|
||||
## Image Details
|
||||
|
||||
- **Base Image**: `scratch` (minimal attack surface)
|
||||
- **Architecture**: Multi-arch support (amd64, arm64)
|
||||
- **Size**: < 10MB (optimized binary)
|
||||
- **Security**: Runs as non-root user
|
||||
- **Features**: SBOM and provenance attestation included
|
||||
- **Base Image**: `scratch` (minimal attack surface)
|
||||
- **Architecture**: Multi-arch support (amd64, arm64)
|
||||
- **Size**: < 10MB (optimized binary)
|
||||
- **Security**: Runs as non-root user
|
||||
- **Features**: SBOM and provenance attestation included
|
||||
|
||||
## Development
|
||||
|
||||
@ -77,6 +77,6 @@ docker-compose up --build
|
||||
|
||||
## Repository
|
||||
|
||||
- **Source**: [github.com/kjanat/articulate-parser](https://github.com/kjanat/articulate-parser)
|
||||
- **Issues**: [Report bugs or request features](https://github.com/kjanat/articulate-parser/issues)
|
||||
- **License**: See repository for license details
|
||||
- **Source**: [github.com/kjanat/articulate-parser](https://github.com/kjanat/articulate-parser)
|
||||
- **Issues**: [Report bugs or request features](https://github.com/kjanat/articulate-parser/issues)
|
||||
- **License**: See repository for license details
|
||||
|
||||
@ -27,7 +27,7 @@ ARG BUILD_TIME
|
||||
ARG GIT_COMMIT
|
||||
# Docker buildx automatically provides these for multi-platform builds
|
||||
ARG BUILDPLATFORM
|
||||
ARG TARGETPLATFORM
|
||||
ARG TARGETPLATFORM
|
||||
ARG TARGETOS
|
||||
ARG TARGETARCH
|
||||
ARG TARGETVARIANT
|
||||
|
||||
@ -30,7 +30,7 @@ ARG BUILD_TIME
|
||||
ARG GIT_COMMIT
|
||||
# Docker buildx automatically provides these for multi-platform builds
|
||||
ARG BUILDPLATFORM
|
||||
ARG TARGETPLATFORM
|
||||
ARG TARGETPLATFORM
|
||||
ARG TARGETOS
|
||||
ARG TARGETARCH
|
||||
ARG TARGETVARIANT
|
||||
|
||||
186
README.md
186
README.md
@ -20,36 +20,36 @@ A Go-based parser that converts Articulate Rise e-learning content to various fo
|
||||
flowchart TD
|
||||
%% User Input
|
||||
CLI[Command Line Interface<br/>main.go] --> APP{App Service<br/>services/app.go}
|
||||
|
||||
|
||||
%% Core Application Logic
|
||||
APP --> |"ProcessCourseFromURI"| PARSER[Course Parser<br/>services/parser.go]
|
||||
APP --> |"ProcessCourseFromFile"| PARSER
|
||||
APP --> |"exportCourse"| FACTORY[Exporter Factory<br/>exporters/factory.go]
|
||||
|
||||
|
||||
%% Data Sources
|
||||
PARSER --> |"FetchCourse"| API[Articulate Rise API<br/>rise.articulate.com]
|
||||
PARSER --> |"LoadCourseFromFile"| FILE[Local JSON File<br/>*.json]
|
||||
|
||||
|
||||
%% Data Models
|
||||
API --> MODELS[Data Models<br/>models/course.go]
|
||||
FILE --> MODELS
|
||||
MODELS --> |Course, Lesson, Item| APP
|
||||
|
||||
|
||||
%% Export Factory Pattern
|
||||
FACTORY --> |"CreateExporter"| MARKDOWN[Markdown Exporter<br/>exporters/markdown.go]
|
||||
FACTORY --> |"CreateExporter"| HTML[HTML Exporter<br/>exporters/html.go]
|
||||
FACTORY --> |"CreateExporter"| DOCX[DOCX Exporter<br/>exporters/docx.go]
|
||||
|
||||
|
||||
%% HTML Cleaning Service
|
||||
CLEANER[HTML Cleaner<br/>services/html_cleaner.go] --> MARKDOWN
|
||||
CLEANER --> HTML
|
||||
CLEANER --> DOCX
|
||||
|
||||
|
||||
%% Output Files
|
||||
MARKDOWN --> |"Export"| MD_OUT[Markdown Files<br/>*.md]
|
||||
HTML --> |"Export"| HTML_OUT[HTML Files<br/>*.html]
|
||||
DOCX --> |"Export"| DOCX_OUT[Word Documents<br/>*.docx]
|
||||
|
||||
|
||||
%% Interfaces (Contracts)
|
||||
IPARSER[CourseParser Interface<br/>interfaces/parser.go] -.-> PARSER
|
||||
IEXPORTER[Exporter Interface<br/>interfaces/exporter.go] -.-> MARKDOWN
|
||||
@ -64,7 +64,7 @@ flowchart TD
|
||||
classDef output fill:#fce7f3,stroke:#be185d,stroke-width:2px,color:#be185d
|
||||
classDef interface fill:#ecfdf5,stroke:#16a34a,stroke-width:1px,stroke-dasharray: 5 5,color:#16a34a
|
||||
classDef service fill:#cffafe,stroke:#0891b2,stroke-width:2px,color:#0891b2
|
||||
|
||||
|
||||
class CLI userInput
|
||||
class APP,FACTORY coreLogic
|
||||
class API,FILE,MODELS dataSource
|
||||
@ -78,32 +78,32 @@ flowchart TD
|
||||
|
||||
The system follows **Clean Architecture** principles with clear separation of concerns:
|
||||
|
||||
- **🎯 Entry Point**: Command-line interface handles user input and coordinates operations
|
||||
- **🏗️ Application Layer**: Core business logic with dependency injection
|
||||
- **📋 Interface Layer**: Contracts defining behavior without implementation details
|
||||
- **🔧 Service Layer**: Concrete implementations of parsing and utility services
|
||||
- **📤 Export Layer**: Factory pattern for format-specific exporters
|
||||
- **📊 Data Layer**: Domain models representing course structure
|
||||
- **🎯 Entry Point**: Command-line interface handles user input and coordinates operations
|
||||
- **🏗️ Application Layer**: Core business logic with dependency injection
|
||||
- **📋 Interface Layer**: Contracts defining behavior without implementation details
|
||||
- **🔧 Service Layer**: Concrete implementations of parsing and utility services
|
||||
- **📤 Export Layer**: Factory pattern for format-specific exporters
|
||||
- **📊 Data Layer**: Domain models representing course structure
|
||||
|
||||
## Features
|
||||
|
||||
- Parse Articulate Rise JSON data from URLs or local files
|
||||
- Export to Markdown (.md) format
|
||||
- Export to HTML (.html) format with professional styling
|
||||
- Export to Word Document (.docx) format
|
||||
- Support for various content types:
|
||||
- Text content with headings and paragraphs
|
||||
- Lists and bullet points
|
||||
- Multimedia content (videos and images)
|
||||
- Knowledge checks and quizzes
|
||||
- Interactive content (flashcards)
|
||||
- Course structure and metadata
|
||||
- Parse Articulate Rise JSON data from URLs or local files
|
||||
- Export to Markdown (.md) format
|
||||
- Export to HTML (.html) format with professional styling
|
||||
- Export to Word Document (.docx) format
|
||||
- Support for various content types:
|
||||
- Text content with headings and paragraphs
|
||||
- Lists and bullet points
|
||||
- Multimedia content (videos and images)
|
||||
- Knowledge checks and quizzes
|
||||
- Interactive content (flashcards)
|
||||
- Course structure and metadata
|
||||
|
||||
## Installation
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Go, I don't know the version, but I have [][gomod] configured right now, and it works, see the [CI][Build] workflow where it is tested.
|
||||
- Go, I don't know the version, but I have [][gomod] configured right now, and it works, see the [CI][Build] workflow where it is tested.
|
||||
|
||||
### Install from source
|
||||
|
||||
@ -124,7 +124,7 @@ go install github.com/kjanat/articulate-parser@latest
|
||||
|
||||
The parser uses the following external library:
|
||||
|
||||
- `github.com/fumiama/go-docx` - For creating Word documents (MIT license)
|
||||
- `github.com/fumiama/go-docx` - For creating Word documents (MIT license)
|
||||
|
||||
## Testing
|
||||
|
||||
@ -164,25 +164,25 @@ go run main.go <input_uri_or_file> <output_format> [output_path]
|
||||
|
||||
#### Examples
|
||||
|
||||
1. **Parse from URL and export to Markdown:**
|
||||
1. **Parse from URL and export to Markdown:**
|
||||
|
||||
```bash
|
||||
go run main.go "https://rise.articulate.com/share/N_APNg40Vr2CSH2xNz-ZLATM5kNviDIO#/" md
|
||||
```
|
||||
|
||||
2. **Parse from local file and export to Word:**
|
||||
2. **Parse from local file and export to Word:**
|
||||
|
||||
```bash
|
||||
go run main.go "articulate-sample.json" docx "my-course.docx"
|
||||
```
|
||||
|
||||
3. **Parse from local file and export to HTML:**
|
||||
3. **Parse from local file and export to HTML:**
|
||||
|
||||
```bash
|
||||
go run main.go "articulate-sample.json" html "output.html"
|
||||
```
|
||||
|
||||
4. **Parse from local file and export to Markdown:**
|
||||
4. **Parse from local file and export to Markdown:**
|
||||
|
||||
```bash
|
||||
go run main.go "articulate-sample.json" md "output.md"
|
||||
@ -332,88 +332,88 @@ The Docker image supports the following build-time arguments:
|
||||
|
||||
The project maintains high code quality standards:
|
||||
|
||||
- Cyclomatic complexity ≤ 15 (checked with [gocyclo](https://github.com/fzipp/gocyclo))
|
||||
- Race condition detection enabled
|
||||
- Comprehensive test coverage
|
||||
- Code formatting with `gofmt`
|
||||
- Static analysis with `go vet`
|
||||
- Cyclomatic complexity ≤ 15 (checked with [gocyclo](https://github.com/fzipp/gocyclo))
|
||||
- Race condition detection enabled
|
||||
- Comprehensive test coverage
|
||||
- Code formatting with `gofmt`
|
||||
- Static analysis with `go vet`
|
||||
|
||||
### Contributing
|
||||
|
||||
1. Fork the repository
|
||||
2. Create a feature branch
|
||||
3. Make your changes
|
||||
4. Run tests: `go test ./...`
|
||||
5. Submit a pull request
|
||||
1. Fork the repository
|
||||
2. Create a feature branch
|
||||
3. Make your changes
|
||||
4. Run tests: `go test ./...`
|
||||
5. Submit a pull request
|
||||
|
||||
## Output Formats
|
||||
|
||||
### Markdown (`.md`)
|
||||
|
||||
- Hierarchical structure with proper heading levels
|
||||
- Clean text content with HTML tags removed
|
||||
- Lists and bullet points preserved
|
||||
- Quiz questions with correct answers marked
|
||||
- Media references included
|
||||
- Course metadata at the top
|
||||
- Hierarchical structure with proper heading levels
|
||||
- Clean text content with HTML tags removed
|
||||
- Lists and bullet points preserved
|
||||
- Quiz questions with correct answers marked
|
||||
- Media references included
|
||||
- Course metadata at the top
|
||||
|
||||
### HTML (`.html`)
|
||||
|
||||
- Professional styling with embedded CSS
|
||||
- Interactive and visually appealing layout
|
||||
- Proper HTML structure with semantic elements
|
||||
- Responsive design for different screen sizes
|
||||
- All content types beautifully formatted
|
||||
- Maintains course hierarchy and organization
|
||||
- Professional styling with embedded CSS
|
||||
- Interactive and visually appealing layout
|
||||
- Proper HTML structure with semantic elements
|
||||
- Responsive design for different screen sizes
|
||||
- All content types beautifully formatted
|
||||
- Maintains course hierarchy and organization
|
||||
|
||||
### Word Document (`.docx`)
|
||||
|
||||
- Professional document formatting
|
||||
- Bold headings and proper typography
|
||||
- Bulleted lists
|
||||
- Quiz questions with answers
|
||||
- Media content references
|
||||
- Maintains course structure
|
||||
- Professional document formatting
|
||||
- Bold headings and proper typography
|
||||
- Bulleted lists
|
||||
- Quiz questions with answers
|
||||
- Media content references
|
||||
- Maintains course structure
|
||||
|
||||
## Supported Content Types
|
||||
|
||||
The parser handles the following Articulate Rise content types:
|
||||
|
||||
- **Text blocks**: Headings and paragraphs
|
||||
- **Lists**: Bullet points and numbered lists
|
||||
- **Multimedia**: Videos and images (references only)
|
||||
- **Knowledge Checks**: Multiple choice, multiple response, fill-in-the-blank, matching
|
||||
- **Interactive Content**: Flashcards and interactive scenarios
|
||||
- **Dividers**: Section breaks
|
||||
- **Sections**: Course organization
|
||||
- **Text blocks**: Headings and paragraphs
|
||||
- **Lists**: Bullet points and numbered lists
|
||||
- **Multimedia**: Videos and images (references only)
|
||||
- **Knowledge Checks**: Multiple choice, multiple response, fill-in-the-blank, matching
|
||||
- **Interactive Content**: Flashcards and interactive scenarios
|
||||
- **Dividers**: Section breaks
|
||||
- **Sections**: Course organization
|
||||
|
||||
## Data Structure
|
||||
|
||||
The parser works with the standard Articulate Rise JSON format which includes:
|
||||
|
||||
- Course metadata (title, description, settings)
|
||||
- Lesson structure
|
||||
- Content items with various types
|
||||
- Media references
|
||||
- Quiz/assessment data
|
||||
- Styling and layout information
|
||||
- Course metadata (title, description, settings)
|
||||
- Lesson structure
|
||||
- Content items with various types
|
||||
- Media references
|
||||
- Quiz/assessment data
|
||||
- Styling and layout information
|
||||
|
||||
## URL Pattern Recognition
|
||||
|
||||
The parser automatically extracts share IDs from Articulate Rise URLs:
|
||||
|
||||
- Input: `https://rise.articulate.com/share/N_APNg40Vr2CSH2xNz-ZLATM5kNviDIO#/`
|
||||
- API URL: `https://rise.articulate.com/api/rise-runtime/boot/share/N_APNg40Vr2CSH2xNz-ZLATM5kNviDIO`
|
||||
- Input: `https://rise.articulate.com/share/N_APNg40Vr2CSH2xNz-ZLATM5kNviDIO#/`
|
||||
- API URL: `https://rise.articulate.com/api/rise-runtime/boot/share/N_APNg40Vr2CSH2xNz-ZLATM5kNviDIO`
|
||||
|
||||
## Error Handling
|
||||
|
||||
The parser includes error handling for:
|
||||
|
||||
- Invalid URLs or share IDs
|
||||
- Network connection issues
|
||||
- Malformed JSON data
|
||||
- File I/O errors
|
||||
- Unsupported content types
|
||||
- Invalid URLs or share IDs
|
||||
- Network connection issues
|
||||
- Malformed JSON data
|
||||
- File I/O errors
|
||||
- Unsupported content types
|
||||
|
||||
<!-- ## Code coverage
|
||||
|
||||
@ -425,28 +425,28 @@ The parser includes error handling for:
|
||||
|
||||
## Limitations
|
||||
|
||||
- Media files (videos, images) are referenced but not downloaded
|
||||
- Complex interactive elements may be simplified in export
|
||||
- Styling and visual formatting is not preserved
|
||||
- Assessment logic and interactivity is lost in static exports
|
||||
- Media files (videos, images) are referenced but not downloaded
|
||||
- Complex interactive elements may be simplified in export
|
||||
- Styling and visual formatting is not preserved
|
||||
- Assessment logic and interactivity is lost in static exports
|
||||
|
||||
## Performance
|
||||
|
||||
- Lightweight with minimal dependencies
|
||||
- Fast JSON parsing and export
|
||||
- Memory efficient processing
|
||||
- No external license requirements
|
||||
- Lightweight with minimal dependencies
|
||||
- Fast JSON parsing and export
|
||||
- Memory efficient processing
|
||||
- No external license requirements
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
Potential improvements could include:
|
||||
|
||||
- [ ] PDF export support
|
||||
- [ ] Media file downloading
|
||||
- [x] ~~HTML export with preserved styling~~
|
||||
- [ ] SCORM package support
|
||||
- [ ] Batch processing capabilities
|
||||
- [ ] Custom template support
|
||||
- [ ] PDF export support
|
||||
- [ ] Media file downloading
|
||||
- [x] ~~HTML export with preserved styling~~
|
||||
- [ ] SCORM package support
|
||||
- [ ] Batch processing capabilities
|
||||
- [ ] Custom template support
|
||||
|
||||
## License
|
||||
|
||||
|
||||
76
Taskfile.yml
76
Taskfile.yml
@ -1,7 +1,7 @@
|
||||
# yaml-language-server: $schema=https://taskfile.dev/schema.json
|
||||
# Articulate Parser - Task Automation
|
||||
# https://taskfile.dev
|
||||
version: "3"
|
||||
version: '3'
|
||||
|
||||
# Global output settings
|
||||
output: prefixed
|
||||
@ -47,11 +47,11 @@ vars:
|
||||
|
||||
# Environment variables
|
||||
env:
|
||||
CGO_ENABLED: "{{.CGO_ENABLED}}"
|
||||
CGO_ENABLED: '{{.CGO_ENABLED}}'
|
||||
GO111MODULE: on
|
||||
|
||||
# Load .env files if present
|
||||
dotenv: [".env", ".env.local"]
|
||||
dotenv: ['.env', '.env.local']
|
||||
|
||||
# Task definitions
|
||||
tasks:
|
||||
@ -69,12 +69,12 @@ tasks:
|
||||
interactive: true
|
||||
watch: true
|
||||
sources:
|
||||
- "**/*.go"
|
||||
- '**/*.go'
|
||||
- go.mod
|
||||
- go.sum
|
||||
cmds:
|
||||
- task: build
|
||||
- "{{.OUTPUT_DIR}}/{{.APP_NAME}}{{.EXE_EXT}} --help"
|
||||
- '{{.OUTPUT_DIR}}/{{.APP_NAME}}{{.EXE_EXT}} --help'
|
||||
|
||||
# Build tasks
|
||||
build:
|
||||
@ -82,14 +82,14 @@ tasks:
|
||||
aliases: [b]
|
||||
deps: [clean-bin]
|
||||
sources:
|
||||
- "**/*.go"
|
||||
- '**/*.go'
|
||||
- go.mod
|
||||
- go.sum
|
||||
generates:
|
||||
- "{{.OUTPUT_DIR}}/{{.APP_NAME}}{{.EXE_EXT}}"
|
||||
- '{{.OUTPUT_DIR}}/{{.APP_NAME}}{{.EXE_EXT}}'
|
||||
cmds:
|
||||
- task: mkdir
|
||||
vars: { DIR: "{{.OUTPUT_DIR}}" }
|
||||
vars: { DIR: '{{.OUTPUT_DIR}}' }
|
||||
- go build {{.GO_FLAGS}} -ldflags="{{.LDFLAGS}}" -o {{.OUTPUT_DIR}}/{{.APP_NAME}}{{.EXE_EXT}} {{.MAIN_FILE}}
|
||||
method: checksum
|
||||
|
||||
@ -99,25 +99,25 @@ tasks:
|
||||
deps: [clean-bin]
|
||||
cmds:
|
||||
- task: mkdir
|
||||
vars: { DIR: "{{.OUTPUT_DIR}}" }
|
||||
vars: { DIR: '{{.OUTPUT_DIR}}' }
|
||||
- for:
|
||||
matrix:
|
||||
GOOS: [linux, darwin, windows]
|
||||
GOARCH: [amd64, arm64]
|
||||
task: build:platform
|
||||
vars:
|
||||
TARGET_GOOS: "{{.ITEM.GOOS}}"
|
||||
TARGET_GOARCH: "{{.ITEM.GOARCH}}"
|
||||
TARGET_GOOS: '{{.ITEM.GOOS}}'
|
||||
TARGET_GOARCH: '{{.ITEM.GOARCH}}'
|
||||
- echo "Built binaries for all platforms in {{.OUTPUT_DIR}}/"
|
||||
|
||||
build:platform:
|
||||
internal: true
|
||||
vars:
|
||||
TARGET_EXT: '{{if eq .TARGET_GOOS "windows"}}.exe{{end}}'
|
||||
OUTPUT_FILE: "{{.OUTPUT_DIR}}/{{.APP_NAME}}-{{.TARGET_GOOS}}-{{.TARGET_GOARCH}}{{.TARGET_EXT}}"
|
||||
OUTPUT_FILE: '{{.OUTPUT_DIR}}/{{.APP_NAME}}-{{.TARGET_GOOS}}-{{.TARGET_GOARCH}}{{.TARGET_EXT}}'
|
||||
env:
|
||||
GOOS: "{{.TARGET_GOOS}}"
|
||||
GOARCH: "{{.TARGET_GOARCH}}"
|
||||
GOOS: '{{.TARGET_GOOS}}'
|
||||
GOARCH: '{{.TARGET_GOARCH}}'
|
||||
cmds:
|
||||
- echo "Building {{.OUTPUT_FILE}}..."
|
||||
- go build {{.GO_FLAGS}} -ldflags="{{.LDFLAGS}}" -o "{{.OUTPUT_FILE}}" {{.MAIN_FILE}}
|
||||
@ -134,8 +134,6 @@ tasks:
|
||||
test:
|
||||
desc: Run all tests
|
||||
aliases: [t]
|
||||
env:
|
||||
CGO_ENABLED: 1
|
||||
cmds:
|
||||
- go test {{.GO_FLAGS}} -race -timeout {{.TEST_TIMEOUT}} ./...
|
||||
|
||||
@ -143,11 +141,9 @@ tasks:
|
||||
desc: Run tests with coverage report
|
||||
aliases: [cover, cov]
|
||||
deps: [clean-coverage]
|
||||
env:
|
||||
CGO_ENABLED: 1
|
||||
cmds:
|
||||
- task: mkdir
|
||||
vars: { DIR: "{{.COVERAGE_DIR}}" }
|
||||
vars: { DIR: '{{.COVERAGE_DIR}}' }
|
||||
- go test {{.GO_FLAGS}} -race -coverprofile={{.COVERAGE_DIR}}/coverage.out -covermode=atomic -timeout {{.TEST_TIMEOUT}} ./...
|
||||
- go tool cover -html={{.COVERAGE_DIR}}/coverage.out -o {{.COVERAGE_DIR}}/coverage.html
|
||||
- go tool cover -func={{.COVERAGE_DIR}}/coverage.out
|
||||
@ -156,8 +152,6 @@ tasks:
|
||||
test:verbose:
|
||||
desc: Run tests with verbose output
|
||||
aliases: [tv]
|
||||
env:
|
||||
CGO_ENABLED: 1
|
||||
cmds:
|
||||
- go test -v -race -timeout {{.TEST_TIMEOUT}} ./...
|
||||
|
||||
@ -166,7 +160,7 @@ tasks:
|
||||
aliases: [tw]
|
||||
watch: true
|
||||
sources:
|
||||
- "**/*.go"
|
||||
- '**/*.go'
|
||||
cmds:
|
||||
- task: test
|
||||
|
||||
@ -178,8 +172,6 @@ tasks:
|
||||
|
||||
test:integration:
|
||||
desc: Run integration tests
|
||||
env:
|
||||
CGO_ENABLED: 1
|
||||
status:
|
||||
- '{{if eq OS "windows"}}if not exist "main_test.go" exit 1{{else}}test ! -f "main_test.go"{{end}}'
|
||||
cmds:
|
||||
@ -324,13 +316,13 @@ tasks:
|
||||
docker:run:
|
||||
desc: Run Docker container
|
||||
aliases: [dr]
|
||||
deps: [docker:build]
|
||||
deps: ['docker:build']
|
||||
cmds:
|
||||
- docker run --rm {{.APP_NAME}}:{{.VERSION}} --help
|
||||
|
||||
docker:test:
|
||||
desc: Test Docker image
|
||||
deps: [docker:build]
|
||||
deps: ['docker:build']
|
||||
cmds:
|
||||
- docker run --rm {{.APP_NAME}}:{{.VERSION}} --version
|
||||
- echo "Docker image tested successfully"
|
||||
@ -360,14 +352,14 @@ tasks:
|
||||
internal: true
|
||||
cmds:
|
||||
- task: rmdir
|
||||
vars: { DIR: "{{.OUTPUT_DIR}}" }
|
||||
vars: { DIR: '{{.OUTPUT_DIR}}' }
|
||||
|
||||
clean-coverage:
|
||||
desc: Remove coverage files
|
||||
internal: true
|
||||
cmds:
|
||||
- task: rmdir
|
||||
vars: { DIR: "{{.COVERAGE_DIR}}" }
|
||||
vars: { DIR: '{{.COVERAGE_DIR}}' }
|
||||
|
||||
clean-cache:
|
||||
desc: Clean Go build and test cache
|
||||
@ -418,10 +410,10 @@ tasks:
|
||||
requires:
|
||||
vars: [VERSION]
|
||||
preconditions:
|
||||
- sh: "git diff --exit-code"
|
||||
msg: "Working directory is not clean"
|
||||
- sh: "git diff --cached --exit-code"
|
||||
msg: "Staging area is not clean"
|
||||
- sh: 'git diff --exit-code'
|
||||
msg: 'Working directory is not clean'
|
||||
- sh: 'git diff --cached --exit-code'
|
||||
msg: 'Staging area is not clean'
|
||||
cmds:
|
||||
- git tag -a v{{.VERSION}} -m "Release v{{.VERSION}}"
|
||||
- echo "Tagged v{{.VERSION}}"
|
||||
@ -442,7 +434,7 @@ tasks:
|
||||
|
||||
docs:coverage:
|
||||
desc: Open coverage report in browser
|
||||
deps: [test:coverage]
|
||||
deps: ['test:coverage']
|
||||
cmds:
|
||||
- '{{if eq OS "darwin"}}open {{.COVERAGE_DIR}}/coverage.html{{else if eq OS "windows"}}start {{.COVERAGE_DIR}}/coverage.html{{else}}xdg-open {{.COVERAGE_DIR}}/coverage.html 2>/dev/null || echo "Please open {{.COVERAGE_DIR}}/coverage.html in your browser"{{end}}'
|
||||
|
||||
@ -506,11 +498,11 @@ tasks:
|
||||
- '{{if eq OS "windows"}}if not exist "articulate-sample.json" exit 1{{else}}test ! -f "articulate-sample.json"{{end}}'
|
||||
deps: [build]
|
||||
cmds:
|
||||
- "{{.OUTPUT_DIR}}/{{.APP_NAME}}{{.EXE_EXT}} articulate-sample.json md output-demo.md"
|
||||
- '{{.OUTPUT_DIR}}/{{.APP_NAME}}{{.EXE_EXT}} articulate-sample.json md output-demo.md'
|
||||
- echo "Demo Markdown created{{:}} output-demo.md"
|
||||
- defer:
|
||||
task: rmfile
|
||||
vars: { FILE: "output-demo.md" }
|
||||
vars: { FILE: 'output-demo.md' }
|
||||
|
||||
demo:html:
|
||||
desc: Demo - Convert sample to HTML
|
||||
@ -518,11 +510,11 @@ tasks:
|
||||
- '{{if eq OS "windows"}}if not exist "articulate-sample.json" exit 1{{else}}test ! -f "articulate-sample.json"{{end}}'
|
||||
deps: [build]
|
||||
cmds:
|
||||
- "{{.OUTPUT_DIR}}/{{.APP_NAME}}{{.EXE_EXT}} articulate-sample.json html output-demo.html"
|
||||
- '{{.OUTPUT_DIR}}/{{.APP_NAME}}{{.EXE_EXT}} articulate-sample.json html output-demo.html'
|
||||
- echo "Demo HTML created{{:}} output-demo.html"
|
||||
- defer:
|
||||
task: rmfile
|
||||
vars: { FILE: "output-demo.html" }
|
||||
vars: { FILE: 'output-demo.html' }
|
||||
|
||||
demo:docx:
|
||||
desc: Demo - Convert sample to DOCX
|
||||
@ -530,11 +522,11 @@ tasks:
|
||||
- '{{if eq OS "windows"}}if not exist "articulate-sample.json" exit 1{{else}}test ! -f "articulate-sample.json"{{end}}'
|
||||
deps: [build]
|
||||
cmds:
|
||||
- "{{.OUTPUT_DIR}}/{{.APP_NAME}}{{.EXE_EXT}} articulate-sample.json docx output-demo.docx"
|
||||
- '{{.OUTPUT_DIR}}/{{.APP_NAME}}{{.EXE_EXT}} articulate-sample.json docx output-demo.docx'
|
||||
- echo "Demo DOCX created{{:}} output-demo.docx"
|
||||
- defer:
|
||||
task: rmfile
|
||||
vars: { FILE: "output-demo.docx" }
|
||||
vars: { FILE: 'output-demo.docx' }
|
||||
|
||||
# Performance profiling
|
||||
profile:cpu:
|
||||
@ -544,7 +536,7 @@ tasks:
|
||||
- go tool pprof -http=:8080 cpu.prof
|
||||
- defer:
|
||||
task: rmfile
|
||||
vars: { FILE: "cpu.prof" }
|
||||
vars: { FILE: 'cpu.prof' }
|
||||
|
||||
profile:mem:
|
||||
desc: Run memory profiling
|
||||
@ -553,14 +545,14 @@ tasks:
|
||||
- go tool pprof -http=:8080 mem.prof
|
||||
- defer:
|
||||
task: rmfile
|
||||
vars: { FILE: "mem.prof" }
|
||||
vars: { FILE: 'mem.prof' }
|
||||
|
||||
# Git hooks
|
||||
hooks:install:
|
||||
desc: Install git hooks
|
||||
cmds:
|
||||
- task: mkdir
|
||||
vars: { DIR: ".git/hooks" }
|
||||
vars: { DIR: '.git/hooks' }
|
||||
- '{{if eq OS "windows"}}echo "#!/bin/sh" > .git/hooks/pre-commit && echo "task lint:fmt" >> .git/hooks/pre-commit{{else}}cat > .git/hooks/pre-commit << ''EOF''{{printf "\n"}}#!/bin/sh{{printf "\n"}}task lint:fmt{{printf "\n"}}EOF{{printf "\n"}}chmod +x .git/hooks/pre-commit{{end}}'
|
||||
- echo "Git hooks installed"
|
||||
|
||||
|
||||
8
go.mod
8
go.mod
@ -2,15 +2,13 @@ module github.com/kjanat/articulate-parser
|
||||
|
||||
go 1.24.0
|
||||
|
||||
toolchain go1.25.5
|
||||
|
||||
require (
|
||||
github.com/fumiama/go-docx v0.0.0-20250506085032-0c30fd09304b
|
||||
golang.org/x/net v0.48.0
|
||||
golang.org/x/text v0.32.0
|
||||
golang.org/x/net v0.46.0
|
||||
golang.org/x/text v0.30.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/fumiama/imgsz v0.0.4 // indirect
|
||||
golang.org/x/image v0.34.0 // indirect
|
||||
golang.org/x/image v0.32.0 // indirect
|
||||
)
|
||||
|
||||
12
go.sum
12
go.sum
@ -2,9 +2,9 @@ github.com/fumiama/go-docx v0.0.0-20250506085032-0c30fd09304b h1:/mxSugRc4SgN7Xg
|
||||
github.com/fumiama/go-docx v0.0.0-20250506085032-0c30fd09304b/go.mod h1:ssRF0IaB1hCcKIObp3FkZOsjTcAHpgii70JelNb4H8M=
|
||||
github.com/fumiama/imgsz v0.0.4 h1:Lsasu2hdSSFS+vnD+nvR1UkiRMK7hcpyYCC0FzgSMFI=
|
||||
github.com/fumiama/imgsz v0.0.4/go.mod h1:bISOQVTlw9sRytPwe8ir7tAaEmyz9hSNj9n8mXMBG0E=
|
||||
golang.org/x/image v0.34.0 h1:33gCkyw9hmwbZJeZkct8XyR11yH889EQt/QH4VmXMn8=
|
||||
golang.org/x/image v0.34.0/go.mod h1:2RNFBZRB+vnwwFil8GkMdRvrJOFd1AzdZI6vOY+eJVU=
|
||||
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
|
||||
golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
|
||||
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
|
||||
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
|
||||
golang.org/x/image v0.32.0 h1:6lZQWq75h7L5IWNk0r+SCpUJ6tUVd3v4ZHnbRKLkUDQ=
|
||||
golang.org/x/image v0.32.0/go.mod h1:/R37rrQmKXtO6tYXAjtDLwQgFLHmhW+V6ayXlxzP2Pc=
|
||||
golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4=
|
||||
golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210=
|
||||
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
|
||||
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
|
||||
|
||||
@ -15,7 +15,7 @@ import (
|
||||
//go:embed html_styles.css
|
||||
var defaultCSS string
|
||||
|
||||
//go:embed html_template.html
|
||||
//go:embed html_template.gohtml
|
||||
var htmlTemplate string
|
||||
|
||||
// HTMLExporter implements the Exporter interface for HTML format.
|
||||
|
||||
Binary file not shown.
@ -4,9 +4,8 @@ Course description
|
||||
|
||||
## Course Information
|
||||
|
||||
- **Course ID**:
|
||||
- **Course ID**:
|
||||
- **Share ID**: example-id
|
||||
- **Navigation Mode**:
|
||||
- **Navigation Mode**:
|
||||
|
||||
---
|
||||
|
||||
|
||||
@ -137,7 +137,7 @@ try {
|
||||
# Show targets and exit if requested
|
||||
if ($ShowTargets) {
|
||||
Write-Host 'Available build targets:' -ForegroundColor Cyan
|
||||
|
||||
|
||||
# Get available platforms and architectures from Go toolchain
|
||||
try {
|
||||
$GoTargets = @(go tool dist list 2>$null)
|
||||
@ -148,7 +148,7 @@ try {
|
||||
Write-Host '⚠️ Could not retrieve targets from Go. Using default targets.' -ForegroundColor Yellow
|
||||
$PlatformList = $Platforms.Split(',') | ForEach-Object { $_.Trim() }
|
||||
$ArchList = $Architectures.Split(',') | ForEach-Object { $_.Trim() }
|
||||
|
||||
|
||||
foreach ($platform in $PlatformList) {
|
||||
foreach ($arch in $ArchList) {
|
||||
$BinaryName = "articulate-parser-$platform-$arch"
|
||||
@ -163,12 +163,12 @@ try {
|
||||
$SelectedTargets = @()
|
||||
$PlatformList = $Platforms.Split(',') | ForEach-Object { $_.Trim() }
|
||||
$ArchList = $Architectures.Split(',') | ForEach-Object { $_.Trim() }
|
||||
|
||||
|
||||
foreach ($target in $GoTargets) {
|
||||
$parts = $target.Split('/')
|
||||
$platform = $parts[0]
|
||||
$arch = $parts[1]
|
||||
|
||||
|
||||
if ($PlatformList -contains $platform -and $ArchList -contains $arch) {
|
||||
$SelectedTargets += @{
|
||||
Platform = $platform
|
||||
@ -177,14 +177,14 @@ try {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Display filtered targets
|
||||
foreach ($target in $SelectedTargets) {
|
||||
$BinaryName = "articulate-parser-$($target.Platform)-$($target.Arch)"
|
||||
if ($target.Platform -eq 'windows') { $BinaryName += '.exe' }
|
||||
Write-Host " $($target.Original) -> $BinaryName" -ForegroundColor Gray
|
||||
}
|
||||
|
||||
|
||||
# Show all available targets if verbose
|
||||
if ($VerboseOutput) {
|
||||
Write-Host "`nAll Go targets available on this system:" -ForegroundColor Cyan
|
||||
@ -404,13 +404,13 @@ try {
|
||||
}
|
||||
$BuildArgs += '-o'
|
||||
$BuildArgs += $Target.Path
|
||||
|
||||
|
||||
# If using custom entry point that's not main.go
|
||||
# we need to use the file explicitly to avoid duplicate declarations
|
||||
$EntryPointPath = Join-Path $ProjectRoot $EntryPoint
|
||||
$EntryPointFile = Split-Path $EntryPointPath -Leaf
|
||||
$IsCustomEntryPoint = ($EntryPointFile -ne 'main.go')
|
||||
|
||||
|
||||
if ($IsCustomEntryPoint) {
|
||||
# When using custom entry point, compile only that file
|
||||
$BuildArgs += $EntryPointPath
|
||||
@ -419,7 +419,7 @@ try {
|
||||
$PackagePath = Split-Path $EntryPointPath -Parent
|
||||
$BuildArgs += $PackagePath
|
||||
}
|
||||
|
||||
|
||||
# For verbose output, show the command that will be executed
|
||||
if ($VerboseOutput) {
|
||||
Write-Host "Command: go $($BuildArgs -join ' ')" -ForegroundColor DarkCyan
|
||||
|
||||
@ -73,7 +73,7 @@ EXAMPLES:
|
||||
DEFAULT TARGETS:
|
||||
Operating Systems: darwin, freebsd, linux, windows
|
||||
Architectures: amd64, arm64
|
||||
|
||||
|
||||
This creates 8 binaries total (4 OS × 2 ARCH)
|
||||
|
||||
GO BUILD FLAGS:
|
||||
|
||||
Reference in New Issue
Block a user