ExtractExpressions extracts all ${{ ... }} expressions from the markdown content and creates environment variable mappings for each unique expression.
(markdown string)
| 138 | // ExtractExpressions extracts all ${{ ... }} expressions from the markdown content |
| 139 | // and creates environment variable mappings for each unique expression. |
| 140 | func (e *ExpressionExtractor) ExtractExpressions(markdown string) ([]*ExpressionMapping, error) { |
| 141 | expressionExtractionLog.Printf("Extracting expressions from markdown: content_length=%d", len(markdown)) |
| 142 | |
| 143 | matches := ExpressionPattern.FindAllStringSubmatch(markdown, -1) |
| 144 | expressionExtractionLog.Printf("Found %d expression matches", len(matches)) |
| 145 | |
| 146 | for _, match := range matches { |
| 147 | if len(match) < 2 { |
| 148 | continue |
| 149 | } |
| 150 | e.processMatch(match[0], match[1]) |
| 151 | } |
| 152 | |
| 153 | // Convert map to sorted slice for consistent ordering |
| 154 | var result []*ExpressionMapping |
| 155 | for _, mapping := range e.mappings { |
| 156 | result = append(result, mapping) |
| 157 | } |
| 158 | |
| 159 | // Sort by original expression for deterministic output |
| 160 | slices.SortFunc(result, func(a, b *ExpressionMapping) int { |
| 161 | switch { |
| 162 | case a.Original < b.Original: |
| 163 | return -1 |
| 164 | case a.Original > b.Original: |
| 165 | return 1 |
| 166 | default: |
| 167 | return 0 |
| 168 | } |
| 169 | }) |
| 170 | |
| 171 | expressionExtractionLog.Printf("Extracted %d unique expressions", len(result)) |
| 172 | |
| 173 | return result, nil |
| 174 | } |
| 175 | |
| 176 | // transformActivationOutputs transforms needs.activation.outputs.* expressions to steps.sanitized.outputs.* |
| 177 | // for backward compatibility with existing workflows. |