# HTML vs Markdown files

**URL:** <https://discourse.gohugo.io/t/html-vs-markdown-files/40469>\
**Category:** support\
**Created:** [September 10, 2022, 11:18pm UTC](https://discourse.gohugo.io/t/html-vs-markdown-files/40469 "2022-09-10T23:18:47Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![burtcrismore](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/burtcrismore/32/16954_2.png) [@burtcrismore](https://discourse.gohugo.io/u/burtcrismore)\
**Post date:** [September 10, 2022, 11:18pm UTC](https://discourse.gohugo.io/t/html-vs-markdown-files/40469/1 "2022-09-10T23:18:47Z")

</div>

Based on what I’ve read in the documentation there is no way to apply semantic meaning to an MD file. For example, if I wanted to place a `<section>` tag it is not possible to do inline knowing that we cannot wrap MD in HTML tags.

I love the simplicity of MD, but I’m finding I need to do a little more than what is provided in MD. Should I use HTML files in my content folder instead of MD knowing that I need more?

Does anyone else us HTML over MD for flexibility? Are there any drawbacks to using HTML knowing that I can still use shortcodes in HTML?

---

<div class="post-metadata">

**Author:** ![bwintx](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/bwintx/32/10450_2.png) [@bwintx](https://discourse.gohugo.io/u/bwintx)\
**Post date:** [September 11, 2022, 3:17am UTC](https://discourse.gohugo.io/t/html-vs-markdown-files/40469/2 "2022-09-11T03:17:53Z")

</div>

You can wrap an HTML element tag, like `<section>`, around Markdown if you separate each tag from the Markdown with an empty line:

```auto
<section>

**Here** is my [Markdown](https://daringfireball.net/projects/markdown).

</section>

```

Not sure whether this meets your requirements, however.

---

<div class="post-metadata">

**Author:** ![burtcrismore](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/burtcrismore/32/16954_2.png) [@burtcrismore](https://discourse.gohugo.io/u/burtcrismore)\
**Post date:** [September 11, 2022, 5:35am UTC](https://discourse.gohugo.io/t/html-vs-markdown-files/40469/3 "2022-09-11T05:35:45Z")

</div>

@bwintx that definitely helps with the semantic tag issue in the markdown. So simple it’s silly. I tried adding the tags but without the extra space at first. I didn’t realize you needed that space. Thank you!

Any thoughts on using an HTML file over Markdown? I can see where I might have some issues when I want to format pages differently or add a new pattern (i.e. extra columns for a row of cards), and it seems that HTML would be easier than trying to come up with a shortcode solution. Would you try to use shortcodes for everything, mix HTML into your MD file, or just us an HTML file?

---

<div class="post-metadata">

**Author:** ![bwintx](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/bwintx/32/10450_2.png) [@bwintx](https://discourse.gohugo.io/u/bwintx)\
**Post date:** [September 11, 2022, 11:30am UTC](https://discourse.gohugo.io/t/html-vs-markdown-files/40469/4 "2022-09-11T11:30:42Z")

</div>

Glad to help!

It definitely sounds like a case for more layouts (perhaps partials, as in the columns-rendering you mentioned) and/or shortcodes, assuming you’re comfortable keeping the content in Markdown format.

However, you certainly can put as much as you wish in HTML, if you find that simpler. For example, my home page, posts lists, and sitemap are completely HTML (with some templating, of course), while the other content is Markdown rendered within layouts.

It’s all a matter of what’s more convenient from a standpoint of content management.

---

<div class="post-metadata">

**Author:** ![jsonbecker](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/jsonbecker/32/2305_2.png) [@jsonbecker](https://discourse.gohugo.io/u/jsonbecker)\
**Post date:** [September 11, 2022, 3:39pm UTC](https://discourse.gohugo.io/t/html-vs-markdown-files/40469/5 "2022-09-11T15:39:53Z")

</div>

Does this work with `div`s? I feel like I’ve tried this with `div` before and the interior markdown is not rendered.

---

<div class="post-metadata">

**Author:** ![bwintx](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/bwintx/32/10450_2.png) [@bwintx](https://discourse.gohugo.io/u/bwintx)\
**Post date:** [September 11, 2022, 3:42pm UTC](https://discourse.gohugo.io/t/html-vs-markdown-files/40469/6 "2022-09-11T15:42:39Z")

</div>

Just now tried it locally and, yes, as long as you keep the extra line spaces, it works. Don’t know whether earlier versions had a problem but it works with Hugo 0.102.3.

---

<div class="post-metadata">

**Author:** ![jsonbecker](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/jsonbecker/32/2305_2.png) [@jsonbecker](https://discourse.gohugo.io/u/jsonbecker)\
**Post date:** [September 11, 2022, 6:00pm UTC](https://discourse.gohugo.io/t/html-vs-markdown-files/40469/7 "2022-09-11T18:00:47Z")

</div>

Wow that did the trick! Thanks. Pretty sure I can close this issue now [Incompatibility with Either Galleries or a Photo Page · Issue #3 · jsonbecker/plugin-glightbox · GitHub](https://github.com/jsonbecker/plugin-glightbox/issues/3).

---

<div class="post-metadata">

**Author:** ![burtcrismore](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/burtcrismore/32/16954_2.png) [@burtcrismore](https://discourse.gohugo.io/u/burtcrismore)\
**Post date:** [September 11, 2022, 8:56pm UTC](https://discourse.gohugo.io/t/html-vs-markdown-files/40469/8 "2022-09-11T20:56:41Z")

</div>

@bwintx Thank again for you help. You’ve answered a lot of my questions during my Hugo journey, some on your website, and I really appreciate.

Any security concerns with using HTML in MD? I had to change the renderer to unsafe. Is that ok considering the final output is all HTML?

---

<div class="post-metadata">

**Author:** ![bwintx](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/bwintx/32/10450_2.png) [@bwintx](https://discourse.gohugo.io/u/bwintx)\
**Post date:** [September 11, 2022, 9:01pm UTC](https://discourse.gohugo.io/t/html-vs-markdown-files/40469/9 "2022-09-11T21:01:06Z")

</div>

@burtcrismore Well, that’s the setting I use, and for that reason. I should note that I have a fairly tight Content Security Policy on my site, so am hoping that compensates adequately. You might want to think about a CSP, too, in case you haven’t already done so.

Again, glad if I can be of any help, and thank you for the kind words.

---

<div class="post-metadata">

**Author:** ![cshoredaniel](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/cshoredaniel/32/19684_2.png) [@cshoredaniel](https://discourse.gohugo.io/u/cshoredaniel)\
**Post date:** [September 11, 2022, 10:08pm UTC](https://discourse.gohugo.io/t/html-vs-markdown-files/40469/10 "2022-09-11T22:08:09Z")

</div>

> [@burtcrismore](#):
>
> Any security concerns with using HTML in MD? I had to change the renderer to unsafe. Is that ok considering the final output is all HTML?

The unsafe has more to do with when you have content editors other than yourself. In that case a content editor could insert malicious HTML / JavaScript (via attributes) into your site.

---

<div class="post-metadata">

**Author:** ![burtcrismore](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/burtcrismore/32/16954_2.png) [@burtcrismore](https://discourse.gohugo.io/u/burtcrismore)\
**Post date:** [September 11, 2022, 11:06pm UTC](https://discourse.gohugo.io/t/html-vs-markdown-files/40469/11 "2022-09-11T23:06:06Z")

</div>

@cshoredaniel that’s good to know. Thank you.

@bwintx thanks for the heads up on CSP. I’ll have to read up on that.

I’ve also seen some people us a “raw html” shortcode which seems like a good option.

---

<div class="post-metadata">

**Author:** ![devsr-gt](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/devsr-gt/32/15058_2.png) [@devsr-gt](https://discourse.gohugo.io/u/devsr-gt)\
**Post date:** [September 11, 2022, 11:24pm UTC](https://discourse.gohugo.io/t/html-vs-markdown-files/40469/12 "2022-09-11T23:24:29Z")

</div>

This worked for me but I did not have any javascript in my site. You need to put this in your header using a function or worker.

Think Lambda function, Cloudflare worker, GCP has them… all the major hosting players have them.

addEventListener(‘fetch’, event =\> {  
event.respondWith(handleRequest(event.request))  
})

async function handleRequest(request) {

let originalResponse = await fetch(request)

// pass in the original response so we can modify some of it.  
let response = new Response(originalResponse.body,originalResponse);

response.headers.set(‘X-Frame-Options’, ‘SAMEORIGIN’);  
response.headers.set(‘Strict-Transport-Security’, ‘max-age=31536000; includeSubdomains; preload’);  
response.headers.set(‘Referrer-Policy’,‘same-origin’);  
response.headers.set(‘Content-Security-Policy’, ‘default-src 'self'’);  
response.headers.set(‘Feature-Policy’,‘camera 'none'; geolocation 'none'’);  
response.headers.set(‘X-Content-Type-Options’,‘nosniff’);  
response.headers.set(‘X-XSS-Protection’,‘1; mode=block’);  
response.headers.set(‘Permissions-Policy’, ‘camera=(), geolocation=(), microphone=()’);  
return response  
}

I used this in a cloudflare worker.

Start here and generate one [Report URI: Generate your Content Security Policy](https://report-uri.com/home/generate) and implement.

---

<div class="post-metadata">

**Author:** ![bwintx](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/bwintx/32/10450_2.png) [@bwintx](https://discourse.gohugo.io/u/bwintx)\
**Post date:** [September 11, 2022, 11:37pm UTC](https://discourse.gohugo.io/t/html-vs-markdown-files/40469/13 "2022-09-11T23:37:59Z")

</div>

Agreed. I use a CFW not only for my CSP (including insertion of nonces in scripts and styles) but also caching static assets. Very helpful.

---

<div class="post-metadata">

**Author:** ![devsr-gt](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/devsr-gt/32/15058_2.png) [@devsr-gt](https://discourse.gohugo.io/u/devsr-gt)\
**Post date:** [September 11, 2022, 11:44pm UTC](https://discourse.gohugo.io/t/html-vs-markdown-files/40469/14 "2022-09-11T23:44:40Z")

</div>

I was trying to use nonce to inline my css. I had an issue with unsafe inline. Can this be achieved with an MD5 hash or a hash created by blockchain?

---

<div class="post-metadata">

**Author:** ![bwintx](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/bwintx/32/10450_2.png) [@bwintx](https://discourse.gohugo.io/u/bwintx)\
**Post date:** [September 11, 2022, 11:51pm UTC](https://discourse.gohugo.io/t/html-vs-markdown-files/40469/15 "2022-09-11T23:51:33Z")

</div>

Here’s a repo with an older version of my CFW. (Much of it shamelessly borrowed 🙂)

> **[GitHub - brycewray/cache-nonce-mix: Cloudflare Worker for caching and CSP nonces](https://github.com/brycewray/cache-nonce-mix)**
>
> Cloudflare Worker for caching and CSP nonces. Contribute to brycewray/cache-nonce-mix development by creating an account on GitHub.

(Sorry for the switcheroo; earlier link was to a private repo.)

You can see how the `replace` statements can be used to add nonces. For example, in a newer version of this code, I have:

```auto
    .replace(
      'rel="stylesheet"',
      `rel="stylesheet" nonce="${nonce}"`
    )

```

---

<div class="post-metadata">

**Author:** ![devsr-gt](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/devsr-gt/32/15058_2.png) [@devsr-gt](https://discourse.gohugo.io/u/devsr-gt)\
**Post date:** [September 11, 2022, 11:52pm UTC](https://discourse.gohugo.io/t/html-vs-markdown-files/40469/16 "2022-09-11T23:52:31Z")

</div>

Shoulders of giants. Die before you quit.

---

<div class="post-metadata">

**Author:** ![nternetinspired](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/nternetinspired/32/19706_2.png) [@nternetinspired](https://discourse.gohugo.io/u/nternetinspired)\
**Post date:** [September 12, 2022, 1:13pm UTC](https://discourse.gohugo.io/t/html-vs-markdown-files/40469/17 "2022-09-12T13:13:53Z")

</div>

All my html is in my layouts and partials, content is in Markdown with html thrown in when Markdown falls short, flow content like `<abbr title="Hyper Text Markup Language">` or `<q cite="Some guy">`, for example.

I can’t imagine a situation where I’d ever want to put sectioning content like `<section>` inside an `<article>`. My list layouts are `<sections>` containing a load of `<article>`s and my single layouts are `<articles>`, layout and content are entirely separate. If I want to format a particular section differently, I’ll use a different layout.

---

<div class="post-metadata">

**Author:** ![bwintx](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/bwintx/32/10450_2.png) [@bwintx](https://discourse.gohugo.io/u/bwintx)\
**Post date:** [September 12, 2022, 4:20pm UTC](https://discourse.gohugo.io/t/html-vs-markdown-files/40469/18 "2022-09-12T16:20:23Z")

</div>

This is the ideal and most semantically correct way to go, yes. However, I think the earlier questions were whether Hugo supports inserting HTML in Markdown when, for some reason (perhaps due to time constraints during a rushed project), that should become unavoidable — as opposed to doing so as a matter of habit.

---

<div class="post-metadata">

**Author:** ![devsr-gt](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/devsr-gt/32/15058_2.png) [@devsr-gt](https://discourse.gohugo.io/u/devsr-gt)\
**Post date:** [September 12, 2022, 10:43pm UTC](https://discourse.gohugo.io/t/html-vs-markdown-files/40469/19 "2022-09-12T22:43:46Z")

</div>

I tried this one out today. Let me know if you see any errors.

addEventListener(‘fetch’, event =\> {  
event.respondWith(handleRequest(event.request))  
})

function dec2hex(dec) {  
return (“0” + dec.toString(16)).substr(-2)  
}

function generateNonce() {  
const arr = new Uint8Array(12)  
crypto.getRandomValues(arr)  
const values = Array.from(arr, dec2hex)  
return [  
btoa(values.slice(0, 5).join(“”)).substr(0, 14),  
btoa(values.slice(5).join(“”)),  
].join(“/”)  
}

/\*\*

- Respond to the request
- @param {Request} request  
\*/

async function handleRequest(request) {  
const nonce = generateNonce()  
let response = await fetch(request)

let imageResponse = await fetch(request)  
let type = imageResponse.headers.get(“Content-Type”) || “”  
if (!type.startsWith(“text/”)) {  
// Not text. Don’t modify.  
let newHeaders = new Headers(imageResponse.headers)  
newHeaders.set(“Cache-Control”, “public, max-age=2678400, immutable”)  
newHeaders.set(“CDN-Cache-Control”, “public, max-age=2678400, immutable”)  
newHeaders.set(“x-BW-test”, “Non-text item - headers edited!”)  
// newHeaders.set(“Permissions-Policy”, “interest-cohort=()”)  
newHeaders.set(“Strict-Transport-Security”, “max-age=63072000; includeSubDomains; preload”)  
newHeaders.set(“X-Frame-Options”, “SAMEORIGIN”)  
newHeaders.set(“X-Content-Type-Options”, “nosniff”)  
newHeaders.set(“Referrer-Policy”, “no-referrer, strict-origin-when-cross-origin”)  
newHeaders.set(“Content-Security-Policy”, “default-src ‘strict-dynamic’ [https://perfectlighthousescores.com](https://perfectlighthousescores.com)”)  
newHeaders.set(“Permissions-Policy”, “geolocation=(), microphone=(), battery=(), accelerometer=(), camera=(), gyroscope=(), magnetometer=(), payment=(), usb=(), interest-cohort=()”)  
newHeaders.set(“cf-nonce-generator”, “HIT”)  
newHeaders.set(“Expect-CT”, “enforce max-age=30 report-uri=[Report URI: Welcome to report-uri.com](https://perfectlighthousescores.report-uri.com/r/d/ct/enforce)”)  
newHeaders.set(“Cross-Origin-Embedder-Policy”, “require-corp; report-to=default”)  
newHeaders.set(“Cross-origin-opener-policy-report-only”, “same-origin; report-to=default”)  
newHeaders.set(“cross-origin-resource-policy”, “same-origin”)  
newHeaders.set(“Cross-Origin-Opener-Policy”, “same-origin”)  
return new Response(imageResponse.body, {  
status: imageResponse.status,  
statusText: imageResponse.statusText,  
headers: newHeaders  
})  
}

const html = (await response.text())  
.replace(/DhcnhD3khTMePgXw/gi, nonce)  
.replace(  
‘src="[https://ajax.cloudflare.com](https://ajax.cloudflare.com)’,  
`nonce="${nonce}" src="https://ajax.cloudflare.com`  
)  
.replace(  
‘src="[https://static.cloudflareinsights.com](https://static.cloudflareinsights.com)’,  
`nonce="${nonce}" src="https://static.cloudflareinsights.com`  
)  
.replace(  
‘cloudflare-static/email-decode.min.js"’,  
`cloudflare-static/email-decode.min.js" nonce="${nonce}"`  
)

let ttl = undefined  
let cache = caches.default  
let url = new URL(request.url)  
let shouldCache = false  
let jsStuff = false  
let svgStuff = false

const filesRegex = /(._.(ac3|avi|bmp|br|bz2|css|cue|dat|doc|docx|dts|eot|exe|flv|gif|gz|ico|img|iso|jpeg|jpg|js|json|map|mkv|mp3|mp4|mpeg|mpg|ogg|pdf|png|ppt|pptx|qt|rar|rm|svg|swf|tar|tgz|ttf|txt|wav|webp|webm|webmanifest|woff|woff2|xls|xlsx|xml|zip))$/  
const jsRegex = /(._.(js))$/  
const svgRegex = /(.\*.(svg))$/

if (url.pathname.match(filesRegex)) {  
shouldCache = true  
ttl = 31536000  
}  
if (url.pathname.match(jsRegex)) {  
jsStuff = true  
}  
if (url.pathname.match(svgRegex)) {  
svgStuff = true  
}

let newHeaders = new Headers(response.headers)  
newHeaders.set(“Cache-Control”, “public, max-age=0”)  
// newHeaders.set(“Permissions-Policy”, “interest-cohort=()”)  
newHeaders.set(“Strict-Transport-Security”, “max-age=63072000; includeSubDomains; preload”)  
newHeaders.set(“X-Frame-Options”, “SAMEORIGIN”)  
newHeaders.set(“X-Content-Type-Options”, “nosniff”)  
newHeaders.set(“Referrer-Policy”, “no-referrer, strict-origin-when-cross-origin”)  
newHeaders.set(“Content-Security-Policy”, “default-src ‘strict-dynamic’ [https://perfectlighthousescores.com](https://perfectlighthousescores.com)”)  
newHeaders.set(“Permissions-Policy”, “geolocation=(), microphone=(), accelerometer=(), battery=(), camera=(), gyroscope=(), magnetometer=(), payment=(), usb=(), interest-cohort=()”)  
newHeaders.set(“Expect-CT”, “enforce max-age=30 report-uri=[Report URI: Welcome to report-uri.com](https://perfectlighthousescores.report-uri.com/r/d/ct/enforce)”)  
newHeaders.set(“Cross-Origin-Embedder-Policy”, “require-corp; report-to=default”)  
newHeaders.set(“Cross-origin-opener-policy-report-only”, “same-origin; report-to=default”)  
newHeaders.set(“cross-origin-resource-policy”, “same-origin”)  
newHeaders.set(“Cross-Origin-Opener-Policy”, “same-origin”)  
if (ttl) {  
newHeaders.set(“Cache-Control”, “public, max-age=” + ttl + “, immutable”)  
newHeaders.set(“CDN-Cache-Control”, “public, max-age=” + ttl + “, immutable”)  
} else {  
newHeaders.set(“Content-Security-Policy-Report-Only”, `report-uri https://perfectlighthousescores.report-uri.com/r/d/csp/enforce; default-src 'strict-dynamic' https://perfectlighthousescores.com; connect-src 'self' https://perfectlighthousescores.com https://cloudflareinsights.com; base-uri 'self' https://perfectlighthousescores.com; frame-src 'self' https://perfectlighthousescores.com; frame-ancestors 'self' https://perfectlighthousescores.com; form-action 'self'; style-src 'self' https://perfectlighthousescores.com; style-src-attr 'self' https://perfectlighthousescores.com; img-src 'self' https://perfectlighthousescores.com; font-src 'self' https://perfectlighthousescores.com; script-src 'nonce-${nonce}' 'strict-dynamic' https: 'self'; script-src-elem 'self' https://perfectlighthousescores.com 'nonce-${nonce}'`)  
newHeaders.set(“Report-To”, “{‘group’:‘default’,‘max\_age’:31536000,‘endpoints’:[{‘url’:‘[Report URI: Welcome to report-uri.com](https://perfectlighthousescores.report-uri.com/a/d/g'%7D%5D,'include_subdomains)’:true}”)  
newHeaders.set(“X-XSS-Protection”, “1”)  
}  
newHeaders.set(“cf-nonce-generator”, “HIT”)  
if (jsStuff) {  
newHeaders.set(“Content-Type”, “application/javascript; charset=utf-8”)  
}  
if (svgStuff) {  
newHeaders.set(“Content-Type”, “image/svg+xml; charset=utf-8”)  
}

return new Response(html, {  
status: response.status,  
statusText: response.statusText,  
headers: newHeaders  
})  
}

---

<div class="post-metadata">

**Author:** ![bwintx](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/bwintx/32/10450_2.png) [@bwintx](https://discourse.gohugo.io/u/bwintx)\
**Post date:** [September 12, 2022, 10:45pm UTC](https://discourse.gohugo.io/t/html-vs-markdown-files/40469/20 "2022-09-12T22:45:12Z")

</div>

I’m no expert on these. If you’re running into a specific error, I might have an idea based on my own glitches over time but, other than that, 🤷

[Next page](https://discourse.gohugo.io/t/html-vs-markdown-files/40469.md?page=2)
