Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ However, you can also compile the utility manually if Go is [installed](#install

Navigate to the project root and run:
```bash
go build main.go
go build -trimpath main.go
```

There may be issues when running `go build` outside of the directory containing `main.go`,
Expand All @@ -130,4 +130,15 @@ even if the path is specified correctly.
This command creates an executable named `embed-code` (or `embed-code.exe` on Windows).
For further information, please refer to the [docs](https://pkg.go.dev/cmd/go#hdr-Compile_packages_and_dependencies).

Without the `-trimpath` flag, Go includes absolute file paths in stack traces
based on the system where the binary was built.

Run following command to build binaries for macOS, Windows and Ubuntu:
```bash
mkdir -p bin && \
GOOS=darwin GOARCH=amd64 go build -trimpath -o bin/embed-code-macos main.go && \
GOOS=windows GOARCH=amd64 go build -trimpath -o bin/embed-code-windows.exe main.go && \
GOOS=linux GOARCH=amd64 go build -trimpath -o bin/embed-code-linux main.go
```

[embed-code-jekyll]: https://github.com/SpineEventEngine/embed-code
Binary file added bin/embed-code-linux
Binary file not shown.
Binary file modified bin/embed-code-macos
Binary file not shown.
Binary file removed bin/embed-code-ubuntu
Binary file not shown.
Binary file removed bin/embed-code-win.exe
Binary file not shown.
Binary file added bin/embed-code-windows.exe
Binary file not shown.
44 changes: 30 additions & 14 deletions cli/cli.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2024, TeamDev. All rights reserved.
// Copyright 2026, TeamDev. All rights reserved.
//
// Redistribution and use in source and/or binary forms, with or without
// modification, must retain the above copyright notice and the following
Expand Down Expand Up @@ -72,6 +72,8 @@ type Config struct {
BaseCodePath string `yaml:"code-path"`
BaseDocsPath string `yaml:"docs-path"`
EmbedMappings []EmbedMapping `yaml:"embed-mappings"`
Info bool `yaml:"info"`
Stacktrace bool `yaml:"stacktrace"`
ConfigPath string
Mode string
}
Expand All @@ -82,6 +84,16 @@ type EmbedMapping struct {
DocsPath string `yaml:"docs-path"`
}

// EmbedCodeSamplesResult is result of the EmbedCodeSamples method.
//
// WriteFragmentFilesResult the result of code fragmentation.
//
// EmbedAllResult the result of embedding code fragments in the documentation.
type EmbedCodeSamplesResult struct {
fragmentation.WriteFragmentFilesResult
embedding.EmbedAllResult
}

const (
ModeCheck = "check"
ModeEmbed = "embed"
Expand All @@ -93,32 +105,28 @@ const (
//
// config — a configuration for checking code samples.
func CheckCodeSamples(config configuration.Configuration) {
err := fragmentation.WriteFragmentFiles(config)
if err != nil {
panic(err)
}
fragmentation.WriteFragmentFiles(config)
embedding.CheckUpToDate(config)
}

// EmbedCodeSamples embeds code fragments in documentation files.
//
// config — a configuration for embedding.
func EmbedCodeSamples(config configuration.Configuration) {
err := fragmentation.WriteFragmentFiles(config)
if err != nil {
panic(err)
func EmbedCodeSamples(config configuration.Configuration) EmbedCodeSamplesResult {
fragmentationResult := fragmentation.WriteFragmentFiles(config)
embeddingResult := embedding.EmbedAll(config)
embedding.CheckUpToDate(config)
return EmbedCodeSamplesResult{
fragmentationResult,
embeddingResult,
}
embedding.EmbedAll(config)
}

// AnalyzeCodeSamples analyzes code fragments in documentation files.
//
// config — a configuration for embedding.
func AnalyzeCodeSamples(config configuration.Configuration) {
err := fragmentation.WriteFragmentFiles(config)
if err != nil {
panic(err)
}
fragmentation.WriteFragmentFiles(config)
analyzing.AnalyzeAll(config)
fragmentation.CleanFragmentFiles(config)
}
Expand All @@ -142,6 +150,10 @@ func ReadArgs() Config {
configPath := flag.String("config-path", "", "a path to a yaml configuration file")
mode := flag.String("mode", "",
"a mode of embed-code execution, which can be 'check' or 'embed'")
info := flag.Bool("info", false,
"an info-level logging setter that enables info logs when set to 'true'")
stacktrace := flag.Bool("stacktrace", false,
"a stack trace setter that enables stack traces in error logs when set to 'true'")

flag.Parse()

Expand All @@ -155,6 +167,8 @@ func ReadArgs() Config {
Separator: *separator,
ConfigPath: *configPath,
Mode: *mode,
Info: *info,
Stacktrace: *stacktrace,
}
}

Expand Down Expand Up @@ -186,6 +200,8 @@ func FillArgsFromConfigFile(args Config) (Config, error) {
if isNotEmpty(configFields.Separator) {
args.Separator = configFields.Separator
}
args.Info = configFields.Info
args.Stacktrace = configFields.Stacktrace

return args, nil
}
Expand Down
38 changes: 0 additions & 38 deletions embedding/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ package embedding

import (
"fmt"

"embed-code/embed-code-go/embedding/parsing"
)

// UnexpectedDiffError describes an error which occurs if outdated files are found during
Expand All @@ -33,39 +31,3 @@ type UnexpectedDiffError struct {
func (e *UnexpectedDiffError) Error() string {
return fmt.Sprintf("unexpected diff: %v", e.changedFiles)
}

// UnexpectedProcessingError describes an error which occurs if something goes wrong
// during embedding.
type UnexpectedProcessingError struct {
Context parsing.Context
initialError error
}

func (e *UnexpectedProcessingError) Error() string {
errorString := fmt.Sprintf("embedding error for file `%s`: %s.",
e.Context.MarkdownFilePath, e.initialError)

if len(e.Context.EmbeddingsNotFound) > 0 {
embeddingsNotFoundStr := "\nMissing embeddings: \n"
for _, emb := range e.Context.EmbeddingsNotFound {
embeddingsNotFoundStr += fmt.Sprintf(
"%s — %s\n",
emb.CodeFile,
emb.Fragment)
}
errorString += embeddingsNotFoundStr
}

if len(e.Context.UnacceptedEmbeddings) > 0 {
unacceptedEmbeddingStr := "\nUnaccepted embeddings: \n"
for _, emb := range e.Context.UnacceptedEmbeddings {
unacceptedEmbeddingStr += fmt.Sprintf(
"%s — %s\n",
emb.CodeFile,
emb.Fragment)
}
errorString += unacceptedEmbeddingStr
}

return errorString
}
3 changes: 1 addition & 2 deletions embedding/parsing/code_fence_end.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
package parsing

import (
"fmt"
"strings"

"embed-code/embed-code-go/configuration"
Expand Down Expand Up @@ -73,7 +72,7 @@ func (c CodeFenceEndState) Accept(context *Context, _ configuration.Configuratio
func renderSample(context *Context) error {
content, err := context.EmbeddingInstruction.Content()
if err != nil {
return fmt.Errorf("unable to read the code fence end: %s", err.Error())
return err
}
for _, line := range content {
indentation := strings.Repeat(" ", context.CodeFenceIndentation)
Expand Down
41 changes: 23 additions & 18 deletions embedding/parsing/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,25 +54,30 @@ type Context struct {
// fileContainsEmbedding - a flag indicating whether the file contains an embedding instruction.
fileContainsEmbedding bool
// embeddings - a list of embedding instructions found in the markdown file.
embeddings []parsingContext
embeddings []ParsingContext
}

// parsingContext contains the information about the position in the source and the
// EmbeddingsCount returns number of found embeddings.
func (c *Context) EmbeddingsCount() int {
return len(c.embeddings)
}

// ParsingContext contains the information about the position in the source and the
// resulting Markdown files.
//
// embeddingInstruction - an Instruction, containing all the needed embedding information.
//
// sourceStartIndex - an index of the StartState line in the original markdown file.
// SourceStartIndex - an index of the StartState line in the original markdown file.
//
// sourceEndIndex - an index of the end line in the original markdown file.
// SourceEndIndex - an index of the end line in the original markdown file.
//
// resultStartIndex - an index of the StartState line in the result markdown file.
//
// resultEndIndex - an index of the end line in the result markdown file.
type parsingContext struct {
type ParsingContext struct {
embeddingInstruction Instruction
sourceStartIndex int
sourceEndIndex int
SourceStartIndex int
SourceEndIndex int
resultStartIndex int
resultEndIndex int
}
Expand Down Expand Up @@ -141,7 +146,7 @@ func (c *Context) IsContainsEmbedding() bool {
// ResolveEmbeddingNotFound writes the source content of the markdown file if embedding
// is not found.
func (c *Context) ResolveEmbeddingNotFound() {
currentEmbedding := *c.currentEmbedding()
currentEmbedding := *c.CurrentEmbedding()
source := c.readEmbeddingSource(currentEmbedding)
c.Result = append(c.Result, source...)
c.EmbeddingsNotFound = append(c.EmbeddingsNotFound, currentEmbedding.embeddingInstruction)
Expand All @@ -151,7 +156,7 @@ func (c *Context) ResolveEmbeddingNotFound() {
//
// Also appends it to the list of such embeddings for logging.
func (c *Context) ResolveUnacceptedEmbedding() {
currentEmbeddingInstruction := c.currentEmbedding().embeddingInstruction
currentEmbeddingInstruction := c.CurrentEmbedding().embeddingInstruction
c.UnacceptedEmbeddings = append(c.UnacceptedEmbeddings, currentEmbeddingInstruction)
c.embeddings = c.embeddings[:c.currentEmbeddingIndex()]
c.SetEmbedding(nil)
Expand All @@ -163,11 +168,11 @@ func (c *Context) SetEmbedding(embedding *Instruction) {
resultIndex := len(c.Result)

if embedding == nil {
c.currentEmbedding().sourceEndIndex = sourceIndex
c.currentEmbedding().resultEndIndex = resultIndex
c.CurrentEmbedding().SourceEndIndex = sourceIndex
c.CurrentEmbedding().resultEndIndex = resultIndex
} else {
c.fileContainsEmbedding = true
context := parsingContext{
context := ParsingContext{
embeddingInstruction: *embedding,
}

Expand All @@ -180,8 +185,8 @@ func (c *Context) SetEmbedding(embedding *Instruction) {
// include instructions in the embedding.
func (c *Context) SetCodeStart() {
if c.fileContainsEmbedding {
lastEmbedding := c.currentEmbedding()
lastEmbedding.sourceStartIndex = c.lineIndex
lastEmbedding := c.CurrentEmbedding()
lastEmbedding.SourceStartIndex = c.lineIndex
lastEmbedding.resultStartIndex = len(c.Result)
}
}
Expand All @@ -197,19 +202,19 @@ func (c *Context) String() string {
c.EmbeddingInstruction, c.MarkdownFilePath, c.lineIndex)
}

func (c *Context) currentEmbedding() *parsingContext {
func (c *Context) CurrentEmbedding() *ParsingContext {
return &c.embeddings[c.currentEmbeddingIndex()]
}

func (c *Context) currentEmbeddingIndex() int {
return len(c.embeddings) - 1
}

func (c *Context) readEmbeddingSource(context parsingContext) []string {
return c.source[context.sourceStartIndex:context.sourceEndIndex]
func (c *Context) readEmbeddingSource(context ParsingContext) []string {
return c.source[context.SourceStartIndex:context.SourceEndIndex]
}

func (c *Context) readEmbeddingResult(context parsingContext) []string {
func (c *Context) readEmbeddingResult(context ParsingContext) []string {
return c.Result[context.resultStartIndex:context.resultEndIndex]
}

Expand Down
Loading