diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/build.ps1 b/build.ps1 index b1222b2..e547b53 100644 --- a/build.ps1 +++ b/build.ps1 @@ -12,4 +12,6 @@ switch ($Command) { "debug" { odin build $src -out:$out -debug } "test" { odin test .\tests\ -all-packages } "clean" { Remove-Item -Recurse -Force bin -ErrorAction SilentlyContinue } + "golib" { go build -buildmode=c-shared -o libgoldmark.dll parser.go } + "libc" { lib /def:libgoldmark.def /out:libgoldmark.lib /machine:x64 } } diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..f002bde --- /dev/null +++ b/go.mod @@ -0,0 +1,12 @@ +module pheynnx + +go 1.26.5 + +require github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc + +require ( + github.com/alecthomas/chroma/v2 v2.27.0 // indirect + github.com/dlclark/regexp2 v1.7.0 // indirect + github.com/dlclark/regexp2/v2 v2.2.1 // indirect + github.com/yuin/goldmark v1.4.15 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..23c172c --- /dev/null +++ b/go.sum @@ -0,0 +1,27 @@ +github.com/alecthomas/chroma/v2 v2.2.0 h1:Aten8jfQwUqEdadVFFjNyjx7HTexhKP0XuqBG67mRDY= +github.com/alecthomas/chroma/v2 v2.2.0/go.mod h1:vf4zrexSH54oEjJ7EdB65tGNHmH3pGZmVkgTP5RHvAs= +github.com/alecthomas/chroma/v2 v2.27.0 h1:FodwmyOBgJULFYmDqibcp9pvfDLWdtPRh9v/r5BXYZs= +github.com/alecthomas/chroma/v2 v2.27.0/go.mod h1:NjJ3ciIgrqBNeIkWZ4e46nseoLDslxU1LmfCoL+wcY8= +github.com/alecthomas/chroma/v3 v3.0.0-alpha.5 h1:Ins5lDliEp34swfd+nh2eESjBA4MlrHrmi6Uyxsl/9E= +github.com/alecthomas/chroma/v3 v3.0.0-alpha.5/go.mod h1:CjTPYmVdv0LiMgid2gCJeE30AgchDKbdsW7R3xs9mHI= +github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo= +github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/dlclark/regexp2/v2 v2.2.1 h1:mf4KkFUj0gJuarK8P+LgiS+Lit7m9N1yAwEfPbee7R0= +github.com/dlclark/regexp2/v2 v2.2.1/go.mod h1:avUrQvPaLz2DrFNHJF0taWAFFX2C1GMSSoeiqFjcBmU= +github.com/dlclark/regexp2/v2 v2.2.2 h1:MYWvNYw8okuqNhwTYO587EZMiDruVa2vhV6fsGpfya0= +github.com/dlclark/regexp2/v2 v2.2.2/go.mod h1:avUrQvPaLz2DrFNHJF0taWAFFX2C1GMSSoeiqFjcBmU= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/yuin/goldmark v1.4.15 h1:CFa84T0goNn/UIXYS+dmjjVxMyTAvpOmzld40N/nfK0= +github.com/yuin/goldmark v1.4.15/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yuin/goldmark v1.8.5 h1:r6N5afV5qj/5S4UTch8agZHJ8UxNCMwX7WjkkJam2NA= +github.com/yuin/goldmark v1.8.5/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg= +github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc h1:+IAOyRda+RLrxa1WC7umKOZRsGq4QrFFMYApOeHzQwQ= +github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc/go.mod h1:ovIvrum6DQJA4QsJSovrkC4saKHQVs7TvcaeO8AIl5I= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/libgoldmark.def b/libgoldmark.def new file mode 100644 index 0000000..516abbe --- /dev/null +++ b/libgoldmark.def @@ -0,0 +1,4 @@ +; libgoldmark.def +EXPORTS +MarkdownToHTML +FreeString diff --git a/libgoldmark.dll b/libgoldmark.dll new file mode 100644 index 0000000..44fb79f Binary files /dev/null and b/libgoldmark.dll differ diff --git a/libgoldmark.exp b/libgoldmark.exp new file mode 100644 index 0000000..b392d15 Binary files /dev/null and b/libgoldmark.exp differ diff --git a/libgoldmark.h b/libgoldmark.h new file mode 100644 index 0000000..0e8f8bb --- /dev/null +++ b/libgoldmark.h @@ -0,0 +1,94 @@ +/* Code generated by cmd/cgo; DO NOT EDIT. */ + +/* package command-line-arguments */ + + +#line 1 "cgo-builtin-export-prolog" + +#include + +#ifndef GO_CGO_EXPORT_PROLOGUE_H +#define GO_CGO_EXPORT_PROLOGUE_H + +#ifndef GO_CGO_GOSTRING_TYPEDEF +typedef struct { const char *p; ptrdiff_t n; } _GoString_; +extern size_t _GoStringLen(_GoString_ s); +extern const char *_GoStringPtr(_GoString_ s); +#endif + +#endif + +/* Start of preamble from import "C" comments. */ + + +#line 3 "parser.go" + #include + +#line 1 "cgo-generated-wrapper" + + +/* End of preamble from import "C" comments. */ + + +/* Start of boilerplate cgo prologue. */ +#line 1 "cgo-gcc-export-header-prolog" + +#ifndef GO_CGO_PROLOGUE_H +#define GO_CGO_PROLOGUE_H + +typedef signed char GoInt8; +typedef unsigned char GoUint8; +typedef short GoInt16; +typedef unsigned short GoUint16; +typedef int GoInt32; +typedef unsigned int GoUint32; +typedef long long GoInt64; +typedef unsigned long long GoUint64; +typedef GoInt64 GoInt; +typedef GoUint64 GoUint; +typedef size_t GoUintptr; +typedef float GoFloat32; +typedef double GoFloat64; +#ifdef _MSC_VER +#if !defined(__cplusplus) || _MSVC_LANG <= 201402L +#include +typedef _Fcomplex GoComplex64; +typedef _Dcomplex GoComplex128; +#else +#include +typedef std::complex GoComplex64; +typedef std::complex GoComplex128; +#endif +#else +typedef float _Complex GoComplex64; +typedef double _Complex GoComplex128; +#endif + +/* + static assertion to make sure the file is being used on architecture + at least with matching size of GoInt. +*/ +typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1]; + +#ifndef GO_CGO_GOSTRING_TYPEDEF +typedef _GoString_ GoString; +#endif +typedef void *GoMap; +typedef void *GoChan; +typedef struct { void *t; void *v; } GoInterface; +typedef struct { void *data; GoInt len; GoInt cap; } GoSlice; + +#endif + +/* End of boilerplate cgo prologue. */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern char* MarkdownToHTML(char* source); +extern void FreeString(char* s); + +#ifdef __cplusplus +} +#endif diff --git a/libgoldmark.lib b/libgoldmark.lib new file mode 100644 index 0000000..da02a1f Binary files /dev/null and b/libgoldmark.lib differ diff --git a/parser.go b/parser.go new file mode 100644 index 0000000..7b5f147 --- /dev/null +++ b/parser.go @@ -0,0 +1,59 @@ +package main + +// #include +import "C" + +import ( + "bytes" + "fmt" + "unsafe" + + chromahtml "github.com/alecthomas/chroma/v2/formatters/html" + "github.com/yuin/goldmark" + highlighting "github.com/yuin/goldmark-highlighting/v2" + "github.com/yuin/goldmark/util" +) + +var md = goldmark.New( + goldmark.WithExtensions( + highlighting.NewHighlighting( + highlighting.WithStyle("github-dark"), + highlighting.WithWrapperRenderer(func(w util.BufWriter, context highlighting.CodeBlockContext, entering bool) { + lang, _ := context.Language() + + if entering { + if lang == nil { + w.WriteString(`
`)
+						return
+					}
+
+					w.WriteString(fmt.Sprintf(`

%s

`, lang))
+				} else {
+					w.WriteString(`
`) + } + }), + highlighting.WithFormatOptions( + chromahtml.PreventSurroundingPre(true), + ), + ), + ), +) + +//export MarkdownToHTML +func MarkdownToHTML(source *C.char) *C.char { + src := C.GoString(source) + + var buf bytes.Buffer + if err := md.Convert([]byte(src), &buf); err != nil { + return C.CString("") + } + + return C.CString(buf.String()) +} + +//export FreeString +func FreeString(s *C.char) { + C.free(unsafe.Pointer(s)) +} + +func main() {} // required, unused diff --git a/server.odin b/server.odin index aba6a33..3e556de 100644 --- a/server.odin +++ b/server.odin @@ -8,9 +8,17 @@ import "core:path/filepath" import "core:strings" import http "submodules/odin-http" +foreign import goldmark "libgoldmark.lib" + +foreign goldmark { + MarkdownToHTML :: proc(source: cstring) -> cstring --- + FreeString :: proc(s: cstring) --- +} + State :: struct { - num: int, - global_css: string, + num: int, + global_css: string, + import_html: cstring, } state := State { @@ -18,6 +26,18 @@ state := State { } main :: proc() { + + markdown, err1 := os.read_entire_file_from_path("test.markdown", context.temp_allocator) + + src_c := strings.clone_to_cstring(string(markdown)) + result_c := MarkdownToHTML(src_c) + + defer FreeString(result_c) + defer delete(src_c) + + state.import_html = result_c + + context.logger = log.create_console_logger(.Info) data, err2 := os.read_entire_file_from_path("styles/main.css", context.temp_allocator) @@ -56,6 +76,8 @@ main :: proc() { err := http.listen_and_serve(&s, routed, net.Endpoint{address = net.IP4_Loopback, port = 6969}) fmt.assertf(err == nil, "server stopped with error: %v", err) + + free_all(context.temp_allocator) } // ROUTERS diff --git a/styles/main.css b/styles/main.css index 0e2b391..e1a5c72 100644 --- a/styles/main.css +++ b/styles/main.css @@ -1,23 +1 @@ -html { - background-color: black; - color: wheat; - font-family: "Inter", "Helvetica", ui-sans-serif, system-ui, sans-serif, - "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; - -webkit-font-smoothing: antialiased; -} - -@font-face { - font-family: "Inter"; - font-weight: normal; - src: url("/static/fonts/InterVariable.woff2") format("woff2"); - font-display: swap; - font-weight: 100 900; -} - -@font-face { - font-family: "GeistMono"; - font-display: swap; - font-style: normal; - font-weight: normal; - src: url("/static/fonts/GeistMono.ttf"); -} +@font-face{font-family:"Inter";font-weight:normal;src:url("/static/fonts/InterVariable.woff2") format("woff2");font-display:swap;font-weight:100 900}@font-face{font-family:"Geist";font-display:swap;font-style:normal;font-weight:normal;src:url("/static/fonts/Geist.ttf")}@font-face{font-family:"GeistMono";font-display:swap;font-style:normal;font-weight:normal;src:url("/static/fonts/GeistMono.ttf")}.blog-layout{max-width:70rem;margin-left:auto;margin-right:auto;padding:0 4% 0 4%;color:var(--c-gray1)}.post-content-container{width:100%;word-wrap:break-word;font-size:18px}.post-content-container h1{border-left:2px solid #fff;padding-left:15px;color:var()}.post-content-container h2{border-left:2px solid #fff;padding-left:15px;color:var()}.post-content-container h3,.post-content-container h4{border-left:2px solid #fff;padding-left:15px;color:var()}.post-content-container a{text-decoration:none;color:#fff;background-color:#1b1b1f;border-radius:.5rem;font-size:15px;border:1px solid #2d2d35;padding:1px 5px}.post-content-container a:hover{color:var()}.post-content-container p,.post-content-container li{font-size:17px;line-height:1.8;-webkit-font-smoothing:antialiased}.post-content-container p code{text-decoration:none;color:var();background-color:#1b1b1f;border-radius:.5rem;border:1px solid #222227;padding:1px 5px}.code-block{margin:20px 0;display:grid;border-radius:.5rem;border:1px solid #37373d;background-color:#1b1b1f;box-shadow:rgba(0,0,0,.16) 0px 1px 4px}.code-block .code-block-header{height:15px;display:flex;margin:0;justify-content:end}.code-block .language-name{color:#e6e6e6;margin-top:5px;margin-right:10px;font-size:13px}.code-block pre.aero{overflow-y:auto;overflow-x:auto;padding:10px 15px;display:flex;margin-top:0;border-top:none;overflow:auto}.code-block pre.aero::-webkit-scrollbar-track{border-radius:10px;background-color:rgba(0,0,0,0)}.code-block pre.aero::-webkit-scrollbar{height:6px;background-color:rgba(0,0,0,0)}.code-block pre.aero::-webkit-scrollbar-thumb{border-radius:.25rem;background-color:#5b5c5c}.code-block .aero code{font-family:"GeistMono",ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";-webkit-font-smoothing:auto;-moz-osx-font-smoothing:auto;font-size:14px;font-weight:500;line-height:20px;border-radius:.25rem;white-space:pre}:root{--clr-html-bg: #111111;--clr-body: #ffffff;--clr-logo: #db8449;--clr-scrollbar-thumb: #ffffff;--clr-page-title: #db8449;--clr-home-title: #db8449;--clr-sec-border-pri: #db8449;--clr-sec-border-sec: #db8449;--clr-sec-border-ter: #db8449;--clr-listing-border: #ffffff;--clr-listing-border-feat: #ffffff;--clr-post-cat: #ffffff;--clr-post-cat-feat: #ffffff;--clr-post-title: #db8449;--clr-post-title-hover: #ffffff;--clr-post-title-hover-feat: #ffffff;--clr-post-cat-border-feat: rgba(219, 132, 73, 0.35);--clr-post-skill-border-feat: rgba(219, 132, 73, 0.35);--clr-post-date: #ffffff;--clr-post-date-feat: #ffffff;--clr-post-snippet: #ffffff;--clr-post-views: #db8449;--clr-nav-link: #ffffff;--clr-nav-link-hover: #db8449;--clr-nav-link-active: #db8449}:root.red{--clr-logo: #ff5050;--clr-home-title: #ff5050;--clr-page-title: #ff5050;--clr-sec-border-pri: #ff5050;--clr-sec-border-sec: #ff5050;--clr-sec-border-ter: #ff5050;--clr-post-cat-feat: #ff5050;--clr-post-title: #ff5050;--clr-post-cat-border-feat: rgba(255, 80, 80, 0.35);--clr-post-skill-border-feat: rgba(255, 80, 80, 0.35);--clr-post-views: #ff5050;--clr-nav-link-hover: #ff5050;--clr-nav-link-active: #ff5050}:root.orange{--clr-logo: #db8449;--clr-home-title: #db8449;--clr-page-title: #db8449;--clr-sec-border-pri: #db8449;--clr-sec-border-sec: #db8449;--clr-sec-border-ter: #db8449;--clr-post-cat-feat: #db8449;--clr-post-title: #db8449;--clr-post-cat-border-feat: rgba(219, 132, 73, 0.35);--clr-post-skill-border-feat: rgba(219, 132, 73, 0.35);--clr-post-views: #db8449;--clr-nav-link-hover: #db8449;--clr-nav-link-active: #db8449}:root.yellow{--clr-logo: #eaec45;--clr-home-title: #eaec45;--clr-page-title: #eaec45;--clr-sec-border-pri: #eaec45;--clr-sec-border-sec: #eaec45;--clr-sec-border-ter: #eaec45;--clr-post-cat-feat: #eaec45;--clr-post-title: #eaec45;--clr-post-cat-border-feat: rgba(234, 236, 69, 0.35);--clr-post-skill-border-feat: rgba(234, 236, 69, 0.35);--clr-post-views: #eaec45;--clr-nav-link-hover: #eaec45;--clr-nav-link-active: #eaec45}:root.green{--clr-logo: #59df55;--clr-home-title: #59df55;--clr-page-title: #59df55;--clr-sec-border-pri: #59df55;--clr-sec-border-sec: #59df55;--clr-sec-border-ter: #59df55;--clr-post-cat-feat: #59df55;--clr-post-title: #59df55;--clr-post-cat-border-feat: rgba(89, 223, 85, 0.35);--clr-post-skill-border-feat: rgba(89, 223, 85, 0.35);--clr-post-views: #59df55;--clr-nav-link-hover: #59df55;--clr-nav-link-active: #59df55}:root.blue{--clr-logo: #2f91e0;--clr-home-title: #2f91e0;--clr-page-title: #2f91e0;--clr-sec-border-pri: #2f91e0;--clr-sec-border-sec: #2f91e0;--clr-sec-border-ter: #2f91e0;--clr-post-cat-feat: #2f91e0;--clr-post-title: #2f91e0;--clr-post-cat-border-feat: rgba(47, 145, 224, 0.35);--clr-post-skill-border-feat: rgba(47, 145, 224, 0.35);--clr-post-views: #2f91e0;--clr-nav-link-hover: #2f91e0;--clr-nav-link-active: #2f91e0}:root.purple{--clr-logo: #a245ee;--clr-home-title: #a245ee;--clr-page-title: #a245ee;--clr-sec-border-pri: #a245ee;--clr-sec-border-sec: #a245ee;--clr-sec-border-ter: #a245ee;--clr-post-cat-feat: #a245ee;--clr-post-title: #a245ee;--clr-post-cat-border-feat: rgba(162, 69, 238, 0.35);--clr-post-skill-border-feat: rgba(162, 69, 238, 0.35);--clr-post-views: #a245ee;--clr-nav-link-hover: #a245ee;--clr-nav-link-active: #a245ee}:root.pink{--clr-logo: #ff69b4;--clr-home-title: #ff69b4;--clr-page-title: #ff69b4;--clr-sec-border-pri: #ff69b4;--clr-sec-border-sec: #ff69b4;--clr-sec-border-ter: #ff69b4;--clr-post-cat-feat: #ff69b4;--clr-post-title: #ff69b4;--clr-post-cat-border-feat: rgba(255, 105, 180, 0.35);--clr-post-skill-border-feat: rgba(255, 105, 180, 0.35);--clr-post-views: #ff69b4;--clr-nav-link-hover: #ff69b4;--clr-nav-link-active: #ff69b4}*,*:before,*:after{box-sizing:border-box}html{background-color:var(--clr-html-bg);font-family:"Inter","Helvetica",ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";-webkit-font-smoothing:antialiased}body{min-height:100vh;color:var(--clr-body);margin:0;padding:0;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}::-webkit-scrollbar{width:.35rem}::-webkit-scrollbar,::-webkit-scrollbar-track{background:#0d0d0d}::-webkit-scrollbar-thumb{background:var(--clr-scrollbar-thumb)}.dev-bar{padding-top:10px;display:flex;justify-content:center}.dev-container{display:flex;max-width:fit-content;background-color:rgba(150,69,22,.3294117647);padding:3px 20px;font-size:14px;border:1px solid #f7b155;border-radius:.25rem;align-items:center}.dev-container p{line-height:1;font-weight:bold;margin:0;padding:0 20px}header{padding-top:30px;margin-bottom:25px}.header-logo{user-select:none;display:grid;justify-items:center;padding-bottom:15px;align-items:center}.header-logo #symbol{fill:var(--clr-logo);width:50px;height:auto}.nav-container .nav{display:grid}.nav-container .nav .nav-links{user-select:none;display:flex;justify-self:center}.nav-container .nav .nav-logo-container{display:grid}.nav-container .nav .link{text-decoration:none;text-transform:none;color:var(--clr-nav-link);font-size:15px;font-weight:500}.nav-container .nav .link:not(:last-child){margin-right:18px}.nav-container .nav .link:hover{color:var(--clr-nav-link-hover)}.nav-container .nav .link.active{color:var(--clr-nav-link-active)}.main-layout{max-width:48rem;margin-left:auto;margin-right:auto;padding:0 4% 0 4%}.page-title-box{margin-bottom:15px}.page-title-box h3{font-size:22px;margin:0;color:var(--clr-page-title)}.page-title-box+h4{padding:0;margin:0}.home-info-box{margin-bottom:20px}.home-info-box h4{margin:0;font-size:16px;margin-bottom:12px}.home-info-box p{padding:0;padding-left:15px;line-height:1.5;margin:0}.post-list-featured{margin-bottom:20px}.post-list-featured h4{font-size:16px;margin:0;margin-bottom:15px;color:var()}.post-list-non-featured{margin-bottom:20px}.post-list-non-featured h4{font-size:16px;letter-spacing:.03rem;margin:0;margin-bottom:17px;color:var()}.post-list-box{margin-bottom:20px}.post-list{display:grid;list-style-type:none;padding:0;margin:0}.post-list .post-listing{padding-left:15px;line-height:1}.post-list .post-listing:not(:last-child){margin-bottom:30px}.post-list .post-listing.featured .post-listing-categories .post-listing-category{border:1px solid var(--clr-post-cat-border-feat)}.post-list .post-listing.featured .post-listing-skills svg{border:1px solid var(--clr-post-skill-border-feat)}.post-list .post-listing.featured .post-listing-header .post-listing-title:hover{color:var(--clr-post-title-hover-feat)}.post-list .post-listing.featured .post-listing-header .post-listing-date{color:var(--clr-post-date-feat)}.post-list .post-listing .post-listing-header{display:grid}.post-list .post-listing .post-listing-header .post-listing-anchor{text-decoration:none;width:fit-content}.post-list .post-listing .post-listing-header .post-listing-title{color:var(--clr-post-title);font-weight:500;font-size:21px;margin:0;margin-bottom:6px}.post-list .post-listing .post-listing-header .post-listing-title:hover{color:var(--clr-post-title-hover)}.post-list .post-listing .post-listing-header .post-listing-info-box{display:flex;margin-bottom:7px}.post-list .post-listing .post-listing-header .post-listing-date{font-size:13px;color:var(--clr-post-date);margin:0}.post-list .post-listing .post-listing-header .post-listing-views{font-size:13px;width:30px;color:var(--clr-post-views);animation:fadeIn 1s}@keyframes fadeIn{0%{opacity:0}100%{opacity:1}}.post-list .post-listing .post-listing-header .post-listing-views-suffix{font-size:13px}.post-list .post-listing .post-listing-header .post-listing-snippet{padding-left:5px;color:var(--clr-post-snippet);margin:0;margin-bottom:10px;line-height:1.3;font-size:14px}.post-list .post-listing .post-listing-categories{margin-bottom:7px;display:flex;flex-wrap:wrap;gap:7px}.post-list .post-listing .post-listing-categories .post-listing-category{color:var(--clr-post-cat);background-color:#1a1b20;border-radius:.35rem;font-size:12px;border:1px solid #464853;padding:3px 7px}.post-list .post-listing .post-listing-skills{display:flex;flex-wrap:wrap;gap:7px}.post-list .post-listing .post-listing-skills svg{height:20px;width:20px;border-radius:.35rem;border:1px solid #464853} diff --git a/test.markdown b/test.markdown new file mode 100644 index 0000000..7823b91 --- /dev/null +++ b/test.markdown @@ -0,0 +1,129 @@ +--- +title: String Interpolation +published: true +featured: true +author: eac +date: "Oct 25, 2024" +snippet: "String interpolation embeds variables directly in strings for dynamic, readable text. For example, Python's f-strings use {} to include variables or expressions seamlessly, simplifying output formatting." +categories: + - python + - premium + - print "Hello World" + - blizzard + - silver + - attention +skills: + - svelte + - typescript + - javascript + - nim + - rust + - golang + - github-actions + - bash + - apple +--- + +# Header + +## Headers + +### Headerss + +```svelte + + + +``` + +```typescript +const materials = ["Hydrogen", "Helium", "Lithium", "Beryllium"]; + +console.log(materials.map((material) => material.length)); +// Expected output: Array [8, 6, 7, 9] + +(function (a) { + return a + 100; +}); + +const a = async (x) => { + return x++; +}; +``` + +```nim +import macros, strutils + +macro toLookupTable(data: static[string]): untyped = + result = newTree(nnkBracket) + for w in data.split(';'): + result.add newLit(w) + +const + data = "mov;btc;cli;xor" + opcodes = toLookupTable(data) + +for o in opcodes: + echo o +``` + +```java +BufferedWriter out = null; +try { + out = new BufferedWriter(new FileWriter("filename", true)); + out.write("aString"); +} catch (IOException e) { + // error processing code +} finally { + if (out != null) { + out.close(); + } +} +``` + +```scss +$font-stack: Helvetica, sans-serif; +$primary-color: #333; + +body { + font: 100% $font-stack; + color: $primary-color; +} +``` + +```rust +fn main() { + let user = ("Adrian", 38); + println!("User {} is {} years old", user.0, user.1); + + // tuples within tuples + let employee = (("Adrian", 38), "die Mobiliar"); + println!("User {} is {} years old and works for {}", employee.0.1, employee.0.1, employee.1); +} +``` + +```go +func Example() { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + w.Write([]byte("hello world")) + })) + defer ts.Close() + + resp, err := http.Get(ts.URL) + if err != nil { + fmt.Println(err) + } + defer resp.Body.Close() + + fmt.Printf("%s\n", resp.Status) + fmt.Printf("%d\n", resp.StatusCode) +} +``` diff --git a/views.odin b/views.odin index f3afe8e..091ec58 100644 --- a/views.odin +++ b/views.odin @@ -20,6 +20,7 @@ render_index_page :: proc(s: ^State) -> string {

Hello!

`) fmt.sbprintf(&b, `

%v

`, state.num) + fmt.sbprintf(&b, `
%v
`, state.import_html) strings.write_string(&b, `
`) return strings.clone(strings.to_string(b))