statiqdev / Statiq.Framework

A flexible and extensible static content generation framework for .NET.
https://statiq.dev/framework
MIT License
417 stars 74 forks source link

Razor 'using' statements are put at top of file by default in Visual Studio, breaking YAML Parsing #196

Open gortok opened 3 years ago

gortok commented 3 years ago

If you have a code block in Visual Studio .cshtml that needs to include a using directive, like @using Statiq.Razor, Visual Studio puts the using directive at the top of the file; and in Statiq, this is sometimes reserved for Frontmatter(?)

Example:

Source : "This is a source"
---
//..rest of cshtml here.

after using statement is added:

@using Statiq.Razor
Source: "This is a source"
---
//..rest of cshtmlhere

I understand a sidecar file may be added to resolve this issue; unclear if the existing error message should be updated when a @using statement is encountered for it to specially parse that as an error the user needs to fix; or otherwise fix it in the parsing stage so there isn't a tooling mismatch between Visual Studio and Statiq.

Here's the error stack that is generated when this happens:

[INFO] <- Inputs/Input » Finished Inputs Input phase execution (53 output document(s), 64 ms)
[INFO] -> Inputs/Process » Starting Inputs Process phase execution... (53 input document(s), 8 module(s))
[ERRO] Inputs/Process » ExecuteIf » ExtractFrontMatter » ParseYaml » [C:/Users/George/src/lwidn-newsletter/LwidnGenerator/input/newsletters.cshtml => newsletters.cshtml] (Line: 1, Col: 1, Idx: 0) - (Line: 1, Col: 2, Idx: 1): While scanning for the next token, found character that cannot start any token.
[INFO] ========== Execution Summary ==========

Number of output documents per pipeline and phase:

 | Pipeline          | Input      | Process  | PostProcess | Output | Total Time |
 |-------------------------------------------------------------------------------|
 | DirectoryMetadata | 0 (61 ms)  | 0 (1 ms) |             |        | 62 ms      |
 | Inputs            | 53 (64 ms) |          |             |        | 64 ms      |

Pipeline phase timeline:

 | Pipeline          | Timeline (64 total ms not including overhead)                                        |
 |----------------------------------------------------------------------------------------------------------|
 | DirectoryMetadata | I----------------------------------------------------------------------------------- |
 | Inputs            | I----------------------------------------------------------------------------------- |

[INFO] ========== Completed ==========
[INFO] 0 total files output (written or already existed)
[INFO] 0 actual files written
[INFO] 0 files already existed
[INFO] Finished in 360 ms:
[INFO] - Before Engine Execution Clean in 38 ms
[INFO] - Before Engine Execution Events in 96 ms
[INFO] - Analyzer Before Engine Execution Events in 1 ms
[INFO] - Engine Execution in 224 ms
[CRIT] One or more errors occurred
[INFO] To get more detailed logging output run with the "-l Debug" flag
daveaglick commented 3 years ago

fix it in the parsing stage so there isn't a tooling mismatch between Visual Studio and Statiq

I like this approach since it saves the developer from their tools. We can check if the document being parsed for front matter is Razor and skip/move any @ lines down below the dashes (it wouldn't work for block statements, but we'd at least get the usings).

I don't love that it's not "pure" though, so I'll probably have it emit a warning as well so the developer knows what happened and can correct it later.

daveaglick commented 3 years ago

Gave this a little more thought and I’m going to move the issue to Statiq Framework and resolve it mostly in the ExtractFrontMatter module. Specifically, I think there are two general cases we can handle in that module:

For each, the media type of the underlying file where front matter is being extracted may or may not be important. For example, we may want commented lines to be ignored regardless of media type, but @using should only fall through for Razor files.

Then once the ExtractFrontMatter module supports both these cases in general, I can implement specific content to either ignore or fall through in Statiq Web (like @using for Razor files). It would be nice if the user could also specify additional front matter ignore or fall through rules as well.