Finished blogs
This commit is contained in:
parent
42c4281276
commit
af69ba98ba
|
@ -14,6 +14,7 @@
|
||||||
"@types/react-dom": "^17.0.0",
|
"@types/react-dom": "^17.0.0",
|
||||||
"@types/react-router-dom": "^5.3.3",
|
"@types/react-router-dom": "^5.3.3",
|
||||||
"@types/react-slick": "^0.23.4",
|
"@types/react-slick": "^0.23.4",
|
||||||
|
"@types/react-syntax-highlighter": "^13.5.2",
|
||||||
"@types/react-tabs": "^2.3.2",
|
"@types/react-tabs": "^2.3.2",
|
||||||
"@types/react-typing-animation": "^1.6.2",
|
"@types/react-typing-animation": "^1.6.2",
|
||||||
"bootstrap": "^4.6.0",
|
"bootstrap": "^4.6.0",
|
||||||
|
@ -23,12 +24,15 @@
|
||||||
"react-animate-on-scroll": "^2.1.5",
|
"react-animate-on-scroll": "^2.1.5",
|
||||||
"react-bootstrap": "^1.6.1",
|
"react-bootstrap": "^1.6.1",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
|
"react-markdown": "^8.0.3",
|
||||||
"react-router-dom": "^6.3.0",
|
"react-router-dom": "^6.3.0",
|
||||||
"react-scripts": "4.0.3",
|
"react-scripts": "4.0.3",
|
||||||
"react-slick": "^0.28.1",
|
"react-slick": "^0.28.1",
|
||||||
"react-snapshot": "^1.3.0",
|
"react-snapshot": "^1.3.0",
|
||||||
|
"react-syntax-highlighter": "^15.5.0",
|
||||||
"react-tabs": "^3.2.2",
|
"react-tabs": "^3.2.2",
|
||||||
"react-typing-animation": "^1.6.2",
|
"react-typing-animation": "^1.6.2",
|
||||||
|
"remarkable": "^2.0.1",
|
||||||
"typescript": "^4.1.2",
|
"typescript": "^4.1.2",
|
||||||
"web-vitals": "^1.0.1"
|
"web-vitals": "^1.0.1"
|
||||||
},
|
},
|
||||||
|
|
BIN
public/blog-images/example-blog-content.png
Normal file
BIN
public/blog-images/example-blog-content.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 MiB |
BIN
public/blog-images/example-blog-list.png
Normal file
BIN
public/blog-images/example-blog-list.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 622 KiB |
|
@ -2,12 +2,14 @@ import React from 'react';
|
||||||
import { Routes, Route } from 'react-router-dom';
|
import { Routes, Route } from 'react-router-dom';
|
||||||
import Home from './pages/Home';
|
import Home from './pages/Home';
|
||||||
import Blog from "./pages/Blog";
|
import Blog from "./pages/Blog";
|
||||||
|
import SingleBlog from "./pages/SingleBlog";
|
||||||
|
|
||||||
const Main = () => {
|
const Main = () => {
|
||||||
return (
|
return (
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route element={<Home/>} path='/'/>
|
<Route element={<Home/>} path='/'/>
|
||||||
<Route element={<Blog/>} path='/blog'/>
|
<Route element={<Blog/>} path='/blogs'/>
|
||||||
|
<Route element={<SingleBlog/>} path='/blog'/>
|
||||||
</Routes>
|
</Routes>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
36
src/components/blog-card/BlogCard.css
Normal file
36
src/components/blog-card/BlogCard.css
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
|
||||||
|
@media only screen and (max-width: 768px) {
|
||||||
|
.blog-card {
|
||||||
|
margin-top: 100px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.blog-card {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.blog-card-img {
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
padding: 20px;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border-top-left-radius: 10px;
|
||||||
|
border-top-right-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.blog-card-info {
|
||||||
|
padding-bottom: 5px;
|
||||||
|
padding-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.blog-card-int {
|
||||||
|
border-radius: 10px;
|
||||||
|
background-color: #1a1a1e;
|
||||||
|
transition: 1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.blog-card-int:hover {
|
||||||
|
transform: translateY(-5px);
|
||||||
|
transition: .5s;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
19
src/components/blog-card/BlogCard.tsx
Normal file
19
src/components/blog-card/BlogCard.tsx
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
import ScrollAnimation from "react-animate-on-scroll";
|
||||||
|
import React from "react";
|
||||||
|
import Job from "../../types/Job";
|
||||||
|
import "./BlogCard.css";
|
||||||
|
import Blog from "../../types/Blog";
|
||||||
|
|
||||||
|
export default function BlogCard(props: {style?: any, className?: string, blog: Blog, num: number}){
|
||||||
|
return (
|
||||||
|
<ScrollAnimation className={"blog-card "+(props.className || "")} style={props.style} animateIn="fade-up" duration={2} animateOnce={true} offset={50} delay={200}>
|
||||||
|
<div onClick={()=>{window.location.href="/blog?id="+props.num}} className={"blog-card-int"}>
|
||||||
|
{/*<img className={"blog-card-img"} src={props.blog.image}/>*/}
|
||||||
|
<div className={"blog-card-info"}>
|
||||||
|
<h3>{props.blog.title}</h3>
|
||||||
|
<p>{props.blog.date.toLocaleDateString()}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ScrollAnimation>
|
||||||
|
);
|
||||||
|
}
|
24
src/components/blogs/Blogs.css
Normal file
24
src/components/blogs/Blogs.css
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
.react-tabs__tab--selected {
|
||||||
|
transition: 1s;
|
||||||
|
border-top: 1px #00AA00 solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-btn {
|
||||||
|
background-color: #121212;
|
||||||
|
transition: 1s;
|
||||||
|
|
||||||
|
|
||||||
|
border-bottom: 1px #FFFFFF solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-beg {
|
||||||
|
border-bottom-left-radius: 10px;
|
||||||
|
border-top-left-radius: 10px;
|
||||||
|
border-left: 1px #FFFFFF solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-end {
|
||||||
|
border-bottom-right-radius: 10px;
|
||||||
|
border-top-right-radius: 10px;
|
||||||
|
border-right: 1px #FFFFFF solid;
|
||||||
|
}
|
22
src/components/blogs/Blogs.tsx
Normal file
22
src/components/blogs/Blogs.tsx
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
import React, {useState} from "react";
|
||||||
|
import "./Blogs.css";
|
||||||
|
import BlogCard from "../blog-card/BlogCard";
|
||||||
|
import {AllBlogs} from "../../static/data/Blogs";
|
||||||
|
|
||||||
|
export default function Blogs() {
|
||||||
|
|
||||||
|
let blogId = 0;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={"child"}>
|
||||||
|
<div className={"row"} style={{alignContent: "center", padding: 50}}>
|
||||||
|
{AllBlogs.reverse().map((blog, i) => {
|
||||||
|
blogId++;
|
||||||
|
if(!blog.private) {
|
||||||
|
return <BlogCard num={AllBlogs.length - blogId} className={"col-md-4"} blog={blog}/>
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
|
@ -23,6 +23,10 @@ export default function SocialBar(props: {style: any}) {
|
||||||
<div className={"col-md-2 col-4 fade-up-3 fade-up-md-3"} style={{display: "flex", justifyContent: "center"}}>
|
<div className={"col-md-2 col-4 fade-up-3 fade-up-md-3"} style={{display: "flex", justifyContent: "center"}}>
|
||||||
<svg onClick={ () => window.location.href="mailto:nickorlow@nickorlow.com"} className={"mail-icon icon"} viewBox="0 0 100 100" width="100px" height="100px"><g id="surface12014155"><path d="M 28 8 C 16.976562 8 8 16.976562 8 28 L 8 72 C 8 83.023438 16.976562 92 28 92 L 72 92 C 83.023438 92 92 83.023438 92 72 L 92 28 C 92 16.976562 83.023438 8 72 8 Z M 26 32 L 74 32 C 74.359375 32 74.699219 32.039062 75.019531 32.140625 L 55.359375 51.78125 C 52.398438 54.742188 47.582031 54.742188 44.621094 51.78125 L 24.980469 32.140625 C 25.300781 32.039062 25.640625 32 26 32 Z M 22.140625 34.980469 L 37.179688 50 L 22.140625 65.019531 C 22.039062 64.699219 22 64.359375 22 64 L 22 36 C 22 35.640625 22.039062 35.300781 22.140625 34.980469 Z M 77.859375 34.980469 C 77.960938 35.300781 78 35.640625 78 36 L 78 64 C 78 64.359375 77.960938 64.699219 77.859375 65.019531 L 62.800781 50 Z M 40 52.820312 L 41.78125 54.621094 C 44.042969 56.882812 47.019531 58 49.980469 58 C 52.960938 58 55.917969 56.882812 58.179688 54.621094 L 59.980469 52.820312 L 75.019531 67.859375 C 74.699219 67.960938 74.359375 68 74 68 L 26 68 C 25.640625 68 25.300781 67.960938 24.980469 67.859375 Z M 40 52.820312 "/></g></svg>
|
<svg onClick={ () => window.location.href="mailto:nickorlow@nickorlow.com"} className={"mail-icon icon"} viewBox="0 0 100 100" width="100px" height="100px"><g id="surface12014155"><path d="M 28 8 C 16.976562 8 8 16.976562 8 28 L 8 72 C 8 83.023438 16.976562 92 28 92 L 72 92 C 83.023438 92 92 83.023438 92 72 L 92 28 C 92 16.976562 83.023438 8 72 8 Z M 26 32 L 74 32 C 74.359375 32 74.699219 32.039062 75.019531 32.140625 L 55.359375 51.78125 C 52.398438 54.742188 47.582031 54.742188 44.621094 51.78125 L 24.980469 32.140625 C 25.300781 32.039062 25.640625 32 26 32 Z M 22.140625 34.980469 L 37.179688 50 L 22.140625 65.019531 C 22.039062 64.699219 22 64.359375 22 64 L 22 36 C 22 35.640625 22.039062 35.300781 22.140625 34.980469 Z M 77.859375 34.980469 C 77.960938 35.300781 78 35.640625 78 36 L 78 64 C 78 64.359375 77.960938 64.699219 77.859375 65.019531 L 62.800781 50 Z M 40 52.820312 L 41.78125 54.621094 C 44.042969 56.882812 47.019531 58 49.980469 58 C 52.960938 58 55.917969 56.882812 58.179688 54.621094 L 59.980469 52.820312 L 75.019531 67.859375 C 74.699219 67.960938 74.359375 68 74 68 L 26 68 C 25.640625 68 25.300781 67.960938 24.980469 67.859375 Z M 40 52.820312 "/></g></svg>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className={"col-md-12 col-12 fade-up-3 fade-up-md-2"} style={{display: "flex", justifyContent: "center"}}>
|
||||||
|
<a href={"/blogs"}>Read My Blog</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
1
src/declaration.d.ts
vendored
Normal file
1
src/declaration.d.ts
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
declare module '*.md'
|
|
@ -1,11 +1,14 @@
|
||||||
import React, {useState} from 'react';
|
import React, {useState} from 'react';
|
||||||
import './Home.css';
|
import './Home.css';
|
||||||
|
import Blogs from "../components/blogs/Blogs";
|
||||||
|
|
||||||
function Blog() {
|
function Blog() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="Blog">
|
<div className="Blog" style={{padding: 20}}>
|
||||||
<h1>Blog</h1>
|
<h1>Blog</h1>
|
||||||
|
<a href={"/"}>Return Home</a>
|
||||||
|
<Blogs/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
img[alt=cavcash-newsroom] {
|
||||||
|
width: 49.5%
|
||||||
|
}
|
||||||
|
|
||||||
.App {
|
.App {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
background-color: black;
|
background-color: black;
|
||||||
|
|
62
src/pages/SingleBlog.tsx
Normal file
62
src/pages/SingleBlog.tsx
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
import React, {useEffect, useState} from 'react';
|
||||||
|
import './Home.css';
|
||||||
|
import ReactMarkdown from 'react-markdown'
|
||||||
|
import {AllBlogs} from "../static/data/Blogs";
|
||||||
|
import {Prism as SyntaxHighlighter} from 'react-syntax-highlighter'
|
||||||
|
import {a11yDark as theme} from "react-syntax-highlighter/dist/esm/styles/prism";
|
||||||
|
|
||||||
|
function SingleBlog() {
|
||||||
|
|
||||||
|
const [blog, setBlog] = useState('');
|
||||||
|
const [blogId, setBlogId] = useState(0);
|
||||||
|
|
||||||
|
useEffect(()=> {
|
||||||
|
const queryString = window.location.search;
|
||||||
|
const urlParams = new URLSearchParams(queryString);
|
||||||
|
setBlogId(parseInt(urlParams.get('id') || ''));
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
fetch(AllBlogs[blogId].mdfile)
|
||||||
|
.then(response => {
|
||||||
|
return response.text()
|
||||||
|
})
|
||||||
|
.then(text => {
|
||||||
|
setBlog(text)
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="Blog" style={{padding: 20}}>
|
||||||
|
<h1>{AllBlogs[blogId].title}</h1>
|
||||||
|
<p>{AllBlogs[blogId].date.toLocaleDateString()}</p>
|
||||||
|
<p><a href={"/"}>Return Home</a> | <a href={"/blogs"}>All Blogs</a></p>
|
||||||
|
<div style={{width: "100%", display: 'flex', justifyContent: 'center'}}>
|
||||||
|
<div style={{textAlign: "left", margin: 20, maxWidth: "80vw"}}>
|
||||||
|
<ReactMarkdown
|
||||||
|
components={{
|
||||||
|
code({node, inline, className, children, ...props}) {
|
||||||
|
const match = /language-(\w+)/.exec(className || '')
|
||||||
|
return !inline && match ? (
|
||||||
|
<SyntaxHighlighter
|
||||||
|
children={String(children).replace(/\n$/, '')}
|
||||||
|
style={theme}
|
||||||
|
language={match[1]}
|
||||||
|
PreTag="div"
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<code className={className} {...props}>
|
||||||
|
{children}
|
||||||
|
</code>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{blog}
|
||||||
|
</ReactMarkdown>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SingleBlog;
|
32
src/static/data/Blogs.ts
Normal file
32
src/static/data/Blogs.ts
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
import VrboImage from "../images/vrbo-logo-min.png";
|
||||||
|
import Blog from "../../types/Blog";
|
||||||
|
import CSMD from "./blogs/c-sharp-c-assignment.md";
|
||||||
|
import TAB from "./blogs/there-is-a-blog.md";
|
||||||
|
|
||||||
|
const CSharpBlog: Blog = {
|
||||||
|
title: "Doing C assignments in C#",
|
||||||
|
date: new Date(2022, 2, 18, 14, 15, 0),
|
||||||
|
image: VrboImage,
|
||||||
|
mdfile: CSMD,
|
||||||
|
private: false
|
||||||
|
}
|
||||||
|
|
||||||
|
const TestBlog: Blog = {
|
||||||
|
title: "There's a Blog!",
|
||||||
|
date: new Date(),
|
||||||
|
image: VrboImage,
|
||||||
|
mdfile: TAB,
|
||||||
|
private: false
|
||||||
|
}
|
||||||
|
|
||||||
|
const PrivateBlog: Blog = {
|
||||||
|
title: "This blog can only be accessed via the direct URI",
|
||||||
|
date: new Date(),
|
||||||
|
image: VrboImage,
|
||||||
|
mdfile: TAB,
|
||||||
|
private: true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export const AllBlogs: Blog[] = [CSharpBlog, PrivateBlog, TestBlog];
|
||||||
|
|
|
@ -4,7 +4,7 @@ const RunningHobby: InfoCardProps = {
|
||||||
title: "Running",
|
title: "Running",
|
||||||
description: "I started running cross country in 7th grade after wanting to beat my friend in the mile. I kept running all the way through to my senior year of high school. I made varsity my sophomore year. Today, I just run with friends casually along with other physical activity like lifting, biking, and kayaking.",
|
description: "I started running cross country in 7th grade after wanting to beat my friend in the mile. I kept running all the way through to my senior year of high school. I made varsity my sophomore year. Today, I just run with friends casually along with other physical activity like lifting, biking, and kayaking.",
|
||||||
listTitle: "Personal Records",
|
listTitle: "Personal Records",
|
||||||
list:["1600 - 4:34", "3200 - 10:11", "5K XC - 16:42"],
|
list:["1600 - 4:34", "3200 - 10:11", "5K XC - 16:43"],
|
||||||
link: "https://tx.milesplit.com/athletes/7325388-nicholas-orlowsky/stats",
|
link: "https://tx.milesplit.com/athletes/7325388-nicholas-orlowsky/stats",
|
||||||
linkTitle: "Milesplit Profile",
|
linkTitle: "Milesplit Profile",
|
||||||
listClassName: "col-12"
|
listClassName: "col-12"
|
||||||
|
@ -14,7 +14,7 @@ const Lifting: InfoCardProps = {
|
||||||
title: "Lifting",
|
title: "Lifting",
|
||||||
description: "Once I was done with cross country, I was so used to working out everyday, I just couldn't stop. I started lifting as a break from my 6 years and 10,000 miles of running and really really liked it.",
|
description: "Once I was done with cross country, I was so used to working out everyday, I just couldn't stop. I started lifting as a break from my 6 years and 10,000 miles of running and really really liked it.",
|
||||||
listTitle: "Personal Records",
|
listTitle: "Personal Records",
|
||||||
list:["Bench - 235lbs", "Squat - 345lbs", "Deadlift - 345lbs (I think)"],
|
list:["Bench - 255lbs (Done at the Home Depot's HQ in Atlanta, GA)", "Squat - 345lbs", "Deadlift - 345lbs"],
|
||||||
listClassName: "col-12"
|
listClassName: "col-12"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
# Doing C assignments in C#
|
|
||||||
|
|
||||||
Thanks to Arpan Dhatt for doing most of the work on this (his blog here: [https://arpan.one/posts/messing-with-gradescope/](https://arpan.one/posts/messing-with-gradescope/))
|
Thanks to Arpan Dhatt for doing most of the work on this (his blog here: [https://arpan.one/posts/messing-with-gradescope/](https://arpan.one/posts/messing-with-gradescope/))
|
||||||
|
|
||||||
|
@ -11,25 +10,18 @@ This makes running assignments in a docker container where the runtime is not al
|
||||||
|
|
||||||
The better solution is to use .NET's (experimental) AOT compilation feature (formerly called CoreRT). C# has had a number of attempts at an AOT compiler such as :
|
The better solution is to use .NET's (experimental) AOT compilation feature (formerly called CoreRT). C# has had a number of attempts at an AOT compiler such as :
|
||||||
|
|
||||||
- List
|
- [AOT](https://www.mono-project.com/docs/advanced/aot/) by Mono
|
||||||
- LLD2CPP built by Unity
|
- LLD2CPP built by Unity
|
||||||
|
- [Ready2Run](https://docs.microsoft.com/en-us/dotnet/core/deploying/ready-to-run) by Microsoft
|
||||||
|
|
||||||
We'll be using the official AOT compilation built by Microsoft. In order to use it, all you have to do is add the following to your `nuget.config`:
|
We'll be using the official Ready2Run AOT compilation built by Microsoft. In order to use it, all you have to do is add the following to your `nuget.config`:
|
||||||
```xaml
|
```xml
|
||||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
|
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
|
||||||
```
|
```
|
||||||
and then install the package: `Microsoft.DotNet.ILCompiler`. After doing that if you run the command: `dotnet publish -r [Runtime] -c [Config]` and after waiting a considerable amount of time, you'll have a full-fledged C# application compiled directly to your target runtime's bytecode!
|
and then install the package: `Microsoft.DotNet.ILCompiler`. After doing that if you run the command: `dotnet publish -r [Runtime] -c [Config]` and after waiting a considerable amount of time, you'll have a full-fledged C# application compiled directly to your target runtime's bytecode!
|
||||||
|
|
||||||
Compiling my simple Hello, Wold test to linux-x64 (`dotnet publish -r linux-x64 -c Release`) and adding it to my project files should let me run it using the same method Arpan used in his blog.
|
Compiling my simple Hello, Wold test to linux-x64 (`dotnet publish -r linux-x64 -c Release`) and adding it to my project files should let me run it using the same method Arpan used in his blog.
|
||||||
|
|
||||||
But running that command gives this beautiful error:
|
|
||||||
`Cross-OS native compilation is not supported. https://github.com/dotnet/corert/issues/5458 [.../CSharpAOTCompilation/CSharpAOTCompilation/CSharpAOTCompilation.csproj]`
|
|
||||||
|
|
||||||
This (unfortunately) means that I need to either find a Linux machine to run this on or spin up a docker container to compile it for me. Luckily, I'm pretty good with docker and was able to spin this Dockerfile up relatively quickly that allows for this compilation:
|
|
||||||
```dockerfile
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
After doing that, we can follow the instructions followed by Arpan and viola! C# runs on Gradescope!
|
After doing that, we can follow the instructions followed by Arpan and viola! C# runs on Gradescope!
|
||||||
|
|
||||||
I don't recommend this but it was fun to do and I needed stuff to write in a blog.
|
I don't recommend this but it was fun to do and I needed stuff to write in a blog.
|
||||||
|
@ -39,7 +31,7 @@ I don't recommend this but it was fun to do and I needed stuff to write in a blo
|
||||||
C# actually has many lower level features people don't expect it to have. Some of these include pointers and direct memory management. Pointers can be enabled by encasing your code in an unsafe code block.
|
C# actually has many lower level features people don't expect it to have. Some of these include pointers and direct memory management. Pointers can be enabled by encasing your code in an unsafe code block.
|
||||||
|
|
||||||
Example (Written by [Microsoft](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/unsafe-code))
|
Example (Written by [Microsoft](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/unsafe-code))
|
||||||
```c#
|
```csharp
|
||||||
|
|
||||||
// Normal pointer to an object.
|
// Normal pointer to an object.
|
||||||
int[] a = new int[5] { 10, 20, 30, 40, 50 };
|
int[] a = new int[5] { 10, 20, 30, 40, 50 };
|
||||||
|
@ -68,4 +60,4 @@ unsafe
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
In .NET 6, the `NativeMemory` class was introduced which you can read about here: [](). It allows for malloc-like memory allocation and freeing which can be important for performance (and is also generally just better than letting a garbage garbage collector do your
|
In .NET 6, the `NativeMemory` class was introduced which you can read about [here](https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.nativememory.alloc?view=net-6.0). It allows for malloc-like memory allocation and freeing which can be important for high-performance workloads.
|
||||||
|
|
80
src/static/data/blogs/there-is-a-blog.md
Normal file
80
src/static/data/blogs/there-is-a-blog.md
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
My Website now has a blog! I've always wanted to write a blog and I've been keeping a collection of writings in Google Docs that I'll eventually move over here.
|
||||||
|
|
||||||
|
In this blog, I'm going to discuss how I built this blog and the differences it has with the other blogs I've built. As a point of comparison to this blog, I'm going
|
||||||
|
to be using the [CavCash Newsroom](https://cavcash.com/newsroom) which I also built.
|
||||||
|
|
||||||
|
## How I built this blog
|
||||||
|
|
||||||
|
This blog has no real backend. Blogs are written in Markdown files that are hosted with this website, which itself is a React webapp. I then have a file that adds metadata
|
||||||
|
to the blogs such as a title and a date. The metadata file looks like this:
|
||||||
|
```typescript
|
||||||
|
import BlogImage from "../images/blog-img-min.png";
|
||||||
|
import Blog from "../../types/Blog";
|
||||||
|
import CSMD from "./blogs/c-sharp-c-assignment.md";
|
||||||
|
import TAB from "./blogs/there-is-a-blog.md";
|
||||||
|
|
||||||
|
const CSharpBlog: Blog = {
|
||||||
|
title: "Doing C assignments in C#",
|
||||||
|
date: new Date(2022, 2, 18, 14, 15, 0),
|
||||||
|
image: BlogImage,
|
||||||
|
mdfile: CSMD,
|
||||||
|
private: false
|
||||||
|
}
|
||||||
|
|
||||||
|
const TestBlog: Blog = {
|
||||||
|
title: "There's a Blog!",
|
||||||
|
date: new Date(2022, 7, 6, 12, 0, 0),
|
||||||
|
image: BlogImage,
|
||||||
|
mdfile: TAB,
|
||||||
|
private: false
|
||||||
|
}
|
||||||
|
|
||||||
|
const PrivateBlog: Blog = {
|
||||||
|
title: "This blog can only be accessed via the direct URI",
|
||||||
|
date: new Date(2022, 7, 6, 12, 0, 0),
|
||||||
|
image: BlogImage,
|
||||||
|
mdfile: TAB,
|
||||||
|
private: true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export const AllBlogs: Blog[] = [CSharpBlog, PrivateBlog, TestBlog];
|
||||||
|
```
|
||||||
|
This metadata then gets converted into a list and whenever you view a blog, it fetches the associated markdown file and parses it to show you here.
|
||||||
|
|
||||||
|
I decided to add an option to hide some blogs from the 'All blogs' page (Notice how you don't see [This Blog](http://localhost:3000/blog?id=1) there?)
|
||||||
|
It's intended to be used so I can host things like Privacy Policies and Terms of Services for apps I write without cluttering up my blog.
|
||||||
|
|
||||||
|
You may have noticed that there's an unused Image option. This option would provide a thumbnail, but I decided to remove them for now in favor of a cleaner look.
|
||||||
|
|
||||||
|
## How I built the CavCash Newsroom
|
||||||
|
|
||||||
|
The CavCash Newsroom does have a backend. The backend is a part of the larger CavCashAPI which also manages the rest of the backend code for CavCash.
|
||||||
|
It simply stores blog details in a MongoDB collection and returns them to the React frontend. It also supports 'private' blogs, however, it filters
|
||||||
|
out the private blogs in the backend which makes it harder to find a private blog. An entry for a CavCash Newsroom entry looks like this:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"_id" : ObjectId("60ecc0b23eae899e4e46616f"),
|
||||||
|
"BlogID" : NumberInt(3),
|
||||||
|
"Title" : "CavCash acquires Apple Inc",
|
||||||
|
"Author" : "nickorlow",
|
||||||
|
"CreatedDate" : ISODate("2021-07-12T22:22:41.000+0000"),
|
||||||
|
"HideBlog": false,
|
||||||
|
"Content" : "*AUSTIN, TX* - CavCash Inc has finalized a deal to buy Apple Inc (NASDAQ: AAPL) for 3.3 trillion dollars. This marks the 3rd 'FAANG' company CavCash has acquired, with the others being Google and Amazon. CavCash CEO Nicholas Orlowsky has been quoted as saying: \"We are pleased to welcome Apple to the CavCash family.\"\n\nApple CEO Tim Cook was enthused about the deal, expressing excitement for Apple's integration into the overall CavCash ecosystem. Tim will remain CEO of Apple for at least the next two years. \n\nSome have expressed antitrust concerns about CavCash becoming a monopoly.\"\n",
|
||||||
|
"CoverImage" : "data:image/jpeg;base64,/9j/4AAQS...GMvWWXtB1/9k="
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This blog looks like the following:
|
||||||
|
|
||||||
|
![cavcash-newsroom](/blog-images/example-blog-list.png)
|
||||||
|
![cavcash-newsroom](/blog-images/example-blog-content.png)
|
||||||
|
|
||||||
|
_Screenshot of CavCash Newsroom_
|
||||||
|
|
||||||
|
## Comparison of CavCash Newsroom and this Blog
|
||||||
|
|
||||||
|
CavCash Newsroom needed to be able to be published to without pushing new code to the frontend. We also already had an API written for other things that I could just add
|
||||||
|
blog functionality to, so I chose to write it with a C# backend and a React frontend. The CavCash Newsroom also has some features not present in this blog such as author information and cover images. These features were left out because I am the only author on this blog, and I decided that cover images wouldn't be necessary.
|
||||||
|
|
||||||
|
This blog does not have a backend api associated with it and using a blog API seemed like more trouble than building the feature myself. In order to ship blogs quickly and not create unnecessary complexities in my codebase, I decided to just have markdown files that were included in the frontend as my blogs. As I write more blogs this may prove to be a poor idea for performance but that's a bridge I can cross when I get there (Maybe build my own [NWS](https://nws.nickorlow.com) Blogging service?).
|
7
src/types/Blog.ts
Normal file
7
src/types/Blog.ts
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
export default interface Blog {
|
||||||
|
title: string,
|
||||||
|
date: Date
|
||||||
|
image: string,
|
||||||
|
mdfile: string,
|
||||||
|
private: boolean
|
||||||
|
}
|
Loading…
Reference in a new issue