Merge branch 'nuke-scss' of git.handmade.network:hmn/hmn into nuke-scss
This commit is contained in:
commit
410c94bb51
|
@ -375,7 +375,7 @@ function editTimelineSnippet(timelineItemEl, stickyProjectId) {
|
|||
let ownerAvatar = timelineItemEl.querySelector(".avatar")?.src;
|
||||
let creationDate = new Date(timelineItemEl.querySelector("time").dateTime);
|
||||
let rawDesc = timelineItemEl.querySelector(".rawdesc").textContent;
|
||||
let attachment = timelineItemEl.querySelector(".timeline-content-box")?.children?.[0];
|
||||
let attachment = timelineItemEl.querySelector(".timeline-media")?.children?.[0];
|
||||
let projectIds = [];
|
||||
let projectEls = timelineItemEl.querySelectorAll(".projects > a");
|
||||
for (let i = 0; i < projectEls.length; ++i) {
|
||||
|
|
|
@ -1,106 +1,24 @@
|
|||
function TabState(tabbed) {
|
||||
this.container = tabbed;
|
||||
this.tabs = tabbed.querySelector(".tab");
|
||||
function initTabs(container, initialTab = null) {
|
||||
const buttons = Array.from(container.querySelectorAll("[data-tab-button]"));
|
||||
const tabs = Array.from(container.querySelectorAll("[data-tab]"));
|
||||
|
||||
this.tabbar = document.createElement("div");
|
||||
this.tabbar.classList.add("tab-bar");
|
||||
this.container.insertBefore(this.tabbar, this.container.firstChild);
|
||||
|
||||
this.current_i = -1;
|
||||
this.tab_buttons = [];
|
||||
}
|
||||
|
||||
function switch_tab_old(state, tab_i) {
|
||||
return function() {
|
||||
if (state.current_i >= 0) {
|
||||
state.tabs[state.current_i].classList.add("hidden");
|
||||
state.tab_buttons[state.current_i].classList.remove("current");
|
||||
}
|
||||
|
||||
state.tabs[tab_i].classList.remove("hidden");
|
||||
state.tab_buttons[tab_i].classList.add("current");
|
||||
|
||||
var hash = "";
|
||||
if (state.tabs[tab_i].hasAttribute("data-url-hash")) {
|
||||
hash = state.tabs[tab_i].getAttribute("data-url-hash");
|
||||
}
|
||||
window.location.hash = hash;
|
||||
|
||||
state.current_i = tab_i;
|
||||
};
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
const tabContainers = document.getElementsByClassName("tabbed");
|
||||
for (const container of tabContainers) {
|
||||
const tabBar = document.createElement("div");
|
||||
tabBar.classList.add("tab-bar");
|
||||
container.insertAdjacentElement('afterbegin', tabBar);
|
||||
|
||||
const tabs = container.querySelectorAll(".tab");
|
||||
for (let i = 0; i < tabs.length; i++) {
|
||||
const tab = tabs[i];
|
||||
tab.classList.toggle('dn', i > 0);
|
||||
|
||||
const slug = tab.getAttribute("data-slug");
|
||||
|
||||
// TODO: Should this element be a link?
|
||||
const tabButton = document.createElement("div");
|
||||
tabButton.classList.add("tab-button");
|
||||
tabButton.classList.toggle("current", i === 0);
|
||||
tabButton.innerText = tab.getAttribute("data-name");
|
||||
tabButton.setAttribute("data-slug", slug);
|
||||
|
||||
tabButton.addEventListener("click", () => {
|
||||
switchTab(container, slug);
|
||||
});
|
||||
|
||||
tabBar.appendChild(tabButton);
|
||||
}
|
||||
|
||||
const initialSlug = window.location.hash;
|
||||
if (initialSlug) {
|
||||
switchTab(container, initialSlug.substring(1));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function switchTab(container, slug) {
|
||||
const tabs = container.querySelectorAll('.tab');
|
||||
|
||||
let didMatch = false;
|
||||
for (const tab of tabs) {
|
||||
const slugMatches = tab.getAttribute("data-slug") === slug;
|
||||
tab.classList.toggle('dn', !slugMatches);
|
||||
|
||||
if (slugMatches) {
|
||||
didMatch = true;
|
||||
}
|
||||
if (!initialTab) {
|
||||
initialTab = tabs[0].getAttribute("data-tab");
|
||||
}
|
||||
|
||||
const tabButtons = document.querySelectorAll(".tab-button");
|
||||
for (const tabButton of tabButtons) {
|
||||
const buttonSlug = tabButton.getAttribute("data-slug");
|
||||
tabButton.classList.toggle('current', slug === buttonSlug);
|
||||
function switchTo(name) {
|
||||
for (const tab of tabs) {
|
||||
tab.hidden = tab.getAttribute("data-tab") !== name;
|
||||
}
|
||||
for (const button of buttons) {
|
||||
button.classList.toggle("tab-button-active", button.getAttribute("data-tab-button") === name);
|
||||
}
|
||||
}
|
||||
switchTo(initialTab);
|
||||
|
||||
if (!didMatch) {
|
||||
// switch to first tab as a fallback
|
||||
tabs[0].classList.remove('dn');
|
||||
tabButtons[0].classList.add('current');
|
||||
for (const button of buttons) {
|
||||
button.addEventListener("click", () => {
|
||||
switchTo(button.getAttribute("data-tab-button"));
|
||||
});
|
||||
}
|
||||
|
||||
window.location.hash = slug;
|
||||
}
|
||||
|
||||
function switchToTabOfElement(container, el) {
|
||||
const tabs = Array.from(container.querySelectorAll('.tab'));
|
||||
let target = el.parentElement;
|
||||
while (target) {
|
||||
if (tabs.includes(target)) {
|
||||
switchTab(container, target.getAttribute("data-slug"));
|
||||
return;
|
||||
}
|
||||
target = target.parentElement;
|
||||
}
|
||||
}
|
||||
|
|
102
public/style.css
102
public/style.css
|
@ -7159,9 +7159,6 @@ code {
|
|||
--color: black;
|
||||
--link-color: #d12991;
|
||||
--red: #c61d24;
|
||||
--dim-color: #333;
|
||||
--dimmer-color: #999;
|
||||
--dimmest-color: #bbb;
|
||||
--theme-color: #b1b1b1;
|
||||
--theme-color-dim: #c0c0c0;
|
||||
--theme-color-dimmer: #dddddd;
|
||||
|
@ -7173,6 +7170,7 @@ code {
|
|||
--card-background: #ebebeb;
|
||||
--card-background-hover: #f1f1f1;
|
||||
--card-background-transparent: #ebebeb00;
|
||||
--timeline-media-background: #b4b4b466;
|
||||
--bg-1: #f8f8f8;
|
||||
--bg-2: #e8e8e8;
|
||||
--bg-3: #d8d8d8;
|
||||
|
@ -7200,9 +7198,6 @@ code {
|
|||
--color: #eee;
|
||||
--link-color: #ff5dc2;
|
||||
--color-error: #ff6666;
|
||||
--dim-color: #bbb;
|
||||
--dimmer-color: #999;
|
||||
--dimmest-color: #777;
|
||||
--theme-color: #666;
|
||||
--theme-color-dim: #444;
|
||||
--theme-color-dimmer: #383838;
|
||||
|
@ -7214,6 +7209,7 @@ code {
|
|||
--card-background: #494949;
|
||||
--card-background-hover: #333;
|
||||
--card-background-transparent: #24242400;
|
||||
--timeline-media-background: #24242466;
|
||||
--bg-1: #1f1f1f;
|
||||
--bg-2: #2f2f2f;
|
||||
--bg-3: #494949;
|
||||
|
@ -7323,27 +7319,6 @@ pre,
|
|||
flex-shrink: 1;
|
||||
}
|
||||
}
|
||||
.b--dim {
|
||||
border-color: var(--dim-color);
|
||||
}
|
||||
.b--dimmer {
|
||||
border-color: var(--dimmer-color);
|
||||
}
|
||||
.b--dimmest {
|
||||
border-color: var(--dimmest-color);
|
||||
}
|
||||
.b--theme {
|
||||
border-color: var(--theme-color);
|
||||
}
|
||||
.b--theme-dim {
|
||||
border-color: var(--theme-color-dim);
|
||||
}
|
||||
.b--theme-dimmer {
|
||||
border-color: var(--theme-color-dimmer);
|
||||
}
|
||||
.b--theme-dimmest {
|
||||
border-color: var(--theme-color-dimmest);
|
||||
}
|
||||
.b--theme-dark {
|
||||
border-color: var(--theme-color-dark);
|
||||
}
|
||||
|
@ -7393,24 +7368,6 @@ pre,
|
|||
.c--inherit:active {
|
||||
color: inherit;
|
||||
}
|
||||
.c--dim {
|
||||
color: var(--dim-color);
|
||||
}
|
||||
.c--theme-dim {
|
||||
color: var(--theme-color-dim);
|
||||
}
|
||||
.c--dimmer {
|
||||
color: var(--dimmer-color);
|
||||
}
|
||||
.c--theme-dimmer {
|
||||
color: var(--theme-color-dimmer);
|
||||
}
|
||||
.c--dimmest {
|
||||
color: var(--dimmest-color);
|
||||
}
|
||||
.c--theme-dimmest {
|
||||
color: var(--theme-color-dimmest);
|
||||
}
|
||||
.f8 {
|
||||
font-size: 0.65rem;
|
||||
}
|
||||
|
@ -7809,7 +7766,7 @@ pre,
|
|||
align-items: center;
|
||||
border-style: dashed;
|
||||
border-width: 0 0 1px;
|
||||
border-color: var(--dimmest-color);
|
||||
border-color: var(--bg-3);
|
||||
}
|
||||
@media screen and (min-width: 35em) {
|
||||
.optionbar {
|
||||
|
@ -7885,7 +7842,7 @@ pre,
|
|||
transition: all 100ms ease-in-out;
|
||||
}
|
||||
.carousel-container .carousel-button:hover {
|
||||
background-color: var(--dimmest-color);
|
||||
background-color: var(--bg-3);
|
||||
}
|
||||
.carousel-container .carousel-button.active {
|
||||
border-color: var(--theme-color);
|
||||
|
@ -7967,10 +7924,10 @@ pre,
|
|||
.post-content th,
|
||||
.post-content td {
|
||||
padding: var(--spacing-extra-small) var(--spacing-small);
|
||||
border: 1px solid var(--dimmest-color);
|
||||
border: 1px solid var(--border-color);
|
||||
}
|
||||
.post-content code {
|
||||
background-color: var(--dim-background);
|
||||
background-color: var(--bg-3);
|
||||
padding: .2em 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
@ -7982,12 +7939,12 @@ pre,
|
|||
}
|
||||
.post-content pre > code,
|
||||
.post-content pre.hmn-code {
|
||||
background-color: var(--dim-background);
|
||||
background-color: var(--bg-3);
|
||||
padding: 0.7em;
|
||||
overflow-x: auto;
|
||||
}
|
||||
.post-content blockquote {
|
||||
border-color: var(--dimmest-color);
|
||||
border-color: var(--bg-3);
|
||||
margin-left: var(--spacing-small);
|
||||
padding-left: var(--spacing-small);
|
||||
margin-right: 0;
|
||||
|
@ -8130,7 +8087,7 @@ pre,
|
|||
height: var(--height);
|
||||
border-width: 0 0 1px 1px;
|
||||
border-style: solid;
|
||||
border-color: var(--dimmest-color);
|
||||
border-color: var(--bg-3);
|
||||
left: -1.5rem;
|
||||
top: calc(1rem - var(--height));
|
||||
border-bottom-left-radius: 0.5rem;
|
||||
|
@ -8471,7 +8428,7 @@ header.old .submenu > a {
|
|||
}
|
||||
}
|
||||
header {
|
||||
background-color: var(--bg-3);
|
||||
background-color: var(--bg-2);
|
||||
border-bottom-style: solid;
|
||||
border-bottom-width: 1px;
|
||||
}
|
||||
|
@ -8501,7 +8458,7 @@ header .header-nav .submenu {
|
|||
position: absolute;
|
||||
z-index: 100;
|
||||
min-width: 8rem;
|
||||
background-color: var(--card-background);
|
||||
background-color: var(--bg-2);
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-top-width: 0;
|
||||
|
@ -8887,11 +8844,20 @@ code .ss,
|
|||
color: #a31515;
|
||||
}
|
||||
|
||||
/* src/rawdata/scss/tabs.css */
|
||||
.tab-button {
|
||||
border-bottom: 2px solid transparent;
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
.tab-button-active {
|
||||
border-color: var(--link-color);
|
||||
}
|
||||
|
||||
/* src/rawdata/scss/timeline.css */
|
||||
.avatar {
|
||||
object-fit: cover;
|
||||
overflow: hidden;
|
||||
background-color: var(--dimmest-color);
|
||||
background-color: var(--bg-3);
|
||||
flex-shrink: 0;
|
||||
border: none;
|
||||
width: var(--avatar-size-normal);
|
||||
|
@ -8909,16 +8875,28 @@ code .ss,
|
|||
--fade-color: var(--card-background);
|
||||
color: var(--main-color);
|
||||
}
|
||||
.timeline-item .timeline-content-box.timeline-item-bg {
|
||||
background-color: var(--timeline-content-background);
|
||||
.timeline-item .timeline-media {
|
||||
background-color: var(--timeline-media-background);
|
||||
max-height: 60vh;
|
||||
}
|
||||
.timeline-item .timeline-content-box > * {
|
||||
.timeline-item .timeline-media.timeline-embed {
|
||||
height: 0;
|
||||
position: relative;
|
||||
padding-bottom: 56.25%;
|
||||
}
|
||||
.timeline-item .timeline-media.timeline-embed > iframe {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 100;
|
||||
}
|
||||
.timeline-item .timeline-media > * {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
max-height: 80vh;
|
||||
}
|
||||
.timeline-item .avatar {
|
||||
width: 2.5rem;
|
||||
}
|
||||
.timeline-modal .container {
|
||||
max-height: 100vh;
|
||||
|
|
|
@ -1,309 +0,0 @@
|
|||
/*
|
||||
Inserts a CSS expression with one or more custom variables.
|
||||
You can provide an arbitrary number of strings in the second
|
||||
argument, separated by spaces. Any strings corresponding to
|
||||
variable names will be replaced by the correct values, while
|
||||
other strings are left untouched.
|
||||
|
||||
Example usage:
|
||||
|
||||
@include usevar(border-color, dimmer-color);
|
||||
@include usevar(background, "linear-gradient(" dim-background-transparent "," dim-background ")");
|
||||
|
||||
For clarity and to avoid syntax issues, you are encouraged to
|
||||
use unquoted strings for variables and quoted strings for
|
||||
everything else.
|
||||
|
||||
For convenience in common cases, if only a single argument
|
||||
is provided and it does not match an existing variable, this
|
||||
will throw an error.
|
||||
*/
|
||||
pre, code, .codeblock {
|
||||
/* Comment */
|
||||
/* Error */
|
||||
/* Keyword */
|
||||
/* Literal */
|
||||
/* Name */
|
||||
/* Operator */
|
||||
/* Punctuation */
|
||||
/* Comment.Multiline */
|
||||
/* Comment.Preproc */
|
||||
/* Comment.Single */
|
||||
/* Comment.Special */
|
||||
/* Generic.Emph */
|
||||
/* Generic.Strong */
|
||||
/* Keyword.Constant */
|
||||
/* Keyword.Declaration */
|
||||
/* Keyword.Namespace */
|
||||
/* Keyword.Pseudo */
|
||||
/* Keyword.Reserved */
|
||||
/* Keyword.Type */
|
||||
/* Literal.Date */
|
||||
/* Literal.Number */
|
||||
/* Literal.String */
|
||||
/* Name.Attribute */
|
||||
/* Name.Builtin */
|
||||
/* Name.Class */
|
||||
/* Name.Constant */
|
||||
/* Name.Decorator */
|
||||
/* Name.Entity */
|
||||
/* Name.Exception */
|
||||
/* Name.Function */
|
||||
/* Name.Label */
|
||||
/* Name.Namespace */
|
||||
/* Name.Other */
|
||||
/* Name.Property */
|
||||
/* Name.Tag */
|
||||
/* Name.Variable */
|
||||
/* Operator.Word */
|
||||
/* Text.Whitespace */
|
||||
/* Literal.Number.Float */
|
||||
/* Literal.Number.Hex */
|
||||
/* Literal.Number.Integer */
|
||||
/* Literal.Number.Oct */
|
||||
/* Literal.String.Backtick */
|
||||
/* Literal.String.Char */
|
||||
/* Literal.String.Doc */
|
||||
/* Literal.String.Double */
|
||||
/* Literal.String.Escape */
|
||||
/* Literal.String.Heredoc */
|
||||
/* Literal.String.Interpol */
|
||||
/* Literal.String.Other */
|
||||
/* Literal.String.Regex */
|
||||
/* Literal.String.Single */
|
||||
/* Literal.String.Symbol */
|
||||
/* Name.Builtin.Pseudo */
|
||||
/* Name.Variable.Class */
|
||||
/* Name.Variable.Global */
|
||||
/* Name.Variable.Instance */
|
||||
/* Literal.Number.Integer.Long */
|
||||
/* Generic Heading & Diff Header */
|
||||
/* Generic.Subheading & Diff Unified/Comment? */
|
||||
/* Generic.Deleted & Diff Deleted */
|
||||
/* Generic.Inserted & Diff Inserted */ }
|
||||
pre .hll, code .hll, .codeblock .hll {
|
||||
background-color: #49483e; }
|
||||
pre .c, code .c, .codeblock .c {
|
||||
color: #75715e; }
|
||||
pre .err, code .err, .codeblock .err {
|
||||
color: #ff0000; }
|
||||
pre .k, code .k, .codeblock .k {
|
||||
color: #66d9ef; }
|
||||
pre .l, code .l, .codeblock .l {
|
||||
color: #ae81ff; }
|
||||
pre .n, code .n, .codeblock .n {
|
||||
color: #f8f8f2; }
|
||||
pre .o, code .o, .codeblock .o {
|
||||
color: #f92672; }
|
||||
pre .p, code .p, .codeblock .p {
|
||||
color: #f8f8f2; }
|
||||
pre .cm, code .cm, .codeblock .cm {
|
||||
color: #75715e; }
|
||||
pre .cp, code .cp, .codeblock .cp {
|
||||
color: #75715e; }
|
||||
pre .c1, code .c1, .codeblock .c1 {
|
||||
color: #75715e; }
|
||||
pre .cs, code .cs, .codeblock .cs {
|
||||
color: #75715e; }
|
||||
pre .ge, code .ge, .codeblock .ge {
|
||||
font-style: italic; }
|
||||
pre .gs, code .gs, .codeblock .gs {
|
||||
font-weight: bold; }
|
||||
pre .kc, code .kc, .codeblock .kc {
|
||||
color: #66d9ef; }
|
||||
pre .kd, code .kd, .codeblock .kd {
|
||||
color: #66d9ef; }
|
||||
pre .kn, code .kn, .codeblock .kn {
|
||||
color: #f92672; }
|
||||
pre .kp, code .kp, .codeblock .kp {
|
||||
color: #66d9ef; }
|
||||
pre .kr, code .kr, .codeblock .kr {
|
||||
color: #66d9ef; }
|
||||
pre .kt, code .kt, .codeblock .kt {
|
||||
color: #66d9ef; }
|
||||
pre .ld, code .ld, .codeblock .ld {
|
||||
color: #e6db74; }
|
||||
pre .m, code .m, .codeblock .m {
|
||||
color: #ae81ff; }
|
||||
pre .s, code .s, .codeblock .s {
|
||||
color: #e6db74; }
|
||||
pre .na, code .na, .codeblock .na {
|
||||
color: #a6e22e; }
|
||||
pre .nb, code .nb, .codeblock .nb {
|
||||
color: #f8f8f2; }
|
||||
pre .nc, code .nc, .codeblock .nc {
|
||||
color: #a6e22e; }
|
||||
pre .no, code .no, .codeblock .no {
|
||||
color: #66d9ef; }
|
||||
pre .nd, code .nd, .codeblock .nd {
|
||||
color: #a6e22e; }
|
||||
pre .ni, code .ni, .codeblock .ni {
|
||||
color: #f8f8f2; }
|
||||
pre .ne, code .ne, .codeblock .ne {
|
||||
color: #a6e22e; }
|
||||
pre .nf, code .nf, .codeblock .nf {
|
||||
color: #a6e22e; }
|
||||
pre .nl, code .nl, .codeblock .nl {
|
||||
color: #f8f8f2; }
|
||||
pre .nn, code .nn, .codeblock .nn {
|
||||
color: #f8f8f2; }
|
||||
pre .nx, code .nx, .codeblock .nx {
|
||||
color: #a6e22e; }
|
||||
pre .py, code .py, .codeblock .py {
|
||||
color: #f8f8f2; }
|
||||
pre .nt, code .nt, .codeblock .nt {
|
||||
color: #f92672; }
|
||||
pre .nv, code .nv, .codeblock .nv {
|
||||
color: #f8f8f2; }
|
||||
pre .ow, code .ow, .codeblock .ow {
|
||||
color: #f92672; }
|
||||
pre .w, code .w, .codeblock .w {
|
||||
color: #f8f8f2; }
|
||||
pre .mf, code .mf, .codeblock .mf {
|
||||
color: #ae81ff; }
|
||||
pre .mh, code .mh, .codeblock .mh {
|
||||
color: #ae81ff; }
|
||||
pre .mi, code .mi, .codeblock .mi {
|
||||
color: #ae81ff; }
|
||||
pre .mo, code .mo, .codeblock .mo {
|
||||
color: #ae81ff; }
|
||||
pre .sb, code .sb, .codeblock .sb {
|
||||
color: #e6db74; }
|
||||
pre .sc, code .sc, .codeblock .sc {
|
||||
color: #e6db74; }
|
||||
pre .sd, code .sd, .codeblock .sd {
|
||||
color: #e6db74; }
|
||||
pre .s2, code .s2, .codeblock .s2 {
|
||||
color: #e6db74; }
|
||||
pre .se, code .se, .codeblock .se {
|
||||
color: #ae81ff; }
|
||||
pre .sh, code .sh, .codeblock .sh {
|
||||
color: #e6db74; }
|
||||
pre .si, code .si, .codeblock .si {
|
||||
color: #e6db74; }
|
||||
pre .sx, code .sx, .codeblock .sx {
|
||||
color: #e6db74; }
|
||||
pre .sr, code .sr, .codeblock .sr {
|
||||
color: #e6db74; }
|
||||
pre .s1, code .s1, .codeblock .s1 {
|
||||
color: #e6db74; }
|
||||
pre .ss, code .ss, .codeblock .ss {
|
||||
color: #e6db74; }
|
||||
pre .bp, code .bp, .codeblock .bp {
|
||||
color: #f8f8f2; }
|
||||
pre .vc, code .vc, .codeblock .vc {
|
||||
color: #f8f8f2; }
|
||||
pre .vg, code .vg, .codeblock .vg {
|
||||
color: #f8f8f2; }
|
||||
pre .vi, code .vi, .codeblock .vi {
|
||||
color: #f8f8f2; }
|
||||
pre .il, code .il, .codeblock .il {
|
||||
color: #ae81ff; }
|
||||
pre .gu, code .gu, .codeblock .gu {
|
||||
color: #75715e; }
|
||||
pre .gd, code .gd, .codeblock .gd {
|
||||
color: #f92672; }
|
||||
pre .gi, code .gi, .codeblock .gi {
|
||||
color: #a6e22e; }
|
||||
|
||||
.light {
|
||||
background-color: #fff;
|
||||
color: #000; }
|
||||
|
||||
:root {
|
||||
--fg-font-color: #eee;
|
||||
--theme-color: #666;
|
||||
--theme-color-dim: #444;
|
||||
--theme-color-dimmer: #383838;
|
||||
--theme-color-dimmest: #333;
|
||||
--theme-color-dark: #666;
|
||||
--theme-color-light: #666;
|
||||
--link-color: #aaa;
|
||||
--link-border-color: #aaa;
|
||||
--hr-color: #aaa;
|
||||
--main-background-color: #202020;
|
||||
--main-color: #eee;
|
||||
--dim-color: #bbb;
|
||||
--dimmer-color: #999;
|
||||
--dimmest-color: #777;
|
||||
--menu-bottom-border-color: #444;
|
||||
--login-popup-background: #181818;
|
||||
--content-background: #202020;
|
||||
--content-background-transparent: rgba(32, 32, 32, 0);
|
||||
--dim-background: #252525;
|
||||
--dim-background-transparent: rgba(37, 37, 37, 0);
|
||||
--text-background: #181818;
|
||||
--spoiler-border: #777;
|
||||
--background-even-background: #242424;
|
||||
--project-card-border-color: #333;
|
||||
--project-user-suggestions-background: #222;
|
||||
--project-user-suggestions-border-color: #444;
|
||||
--notice-text-color: #eee;
|
||||
--notice-unapproved-color: #7a2020;
|
||||
--notice-hidden-color: #494949;
|
||||
--notice-hiatus-color: #876327;
|
||||
--notice-dead-color: #7a2020;
|
||||
--notice-lts-color: #2a681d;
|
||||
--notice-lts-reqd-color: #876327;
|
||||
--notice-success-color: #2a681d;
|
||||
--notice-warn-color: #876327;
|
||||
--notice-failure-color: #7a2020;
|
||||
--optionbar-border-color: #333;
|
||||
--tab-background: #181818;
|
||||
--tab-border-color: #3f3f3f;
|
||||
--tab-button-background: #303030;
|
||||
--tab-button-background-hover: #383838;
|
||||
--tab-button-background-current: #181818;
|
||||
--form-check-background: #252527;
|
||||
--form-check-border-color: #666;
|
||||
--form-check-border-color-hover: #084068;
|
||||
--form-text-background: #181818;
|
||||
--form-text-background-active: #252527;
|
||||
--form-text-border-color: #444;
|
||||
--form-text-border-color-active: #084068;
|
||||
--form-button-color: #999;
|
||||
--form-button-color-active: #4c9ed9;
|
||||
--form-button-background: #383838;
|
||||
--form-button-background-active: #303840;
|
||||
--form-button-border-color: transparent;
|
||||
--form-button-inline-border-color: transparent;
|
||||
--form-error-color: #c61d24;
|
||||
--landing-search-background: #282828;
|
||||
--landing-search-background-hover: #181818;
|
||||
--editor-toolbar-background: #282828;
|
||||
--editor-toolbar-border-color: #333;
|
||||
--editor-toolbar-button-background: #282828;
|
||||
--editor-toolbar-button-background-hover: #333;
|
||||
--editor-toolbar-button-border-color: #333;
|
||||
--post-blockquote-border-color: #555;
|
||||
--forum-even-background: #242424;
|
||||
--forum-thread-read-color: #777;
|
||||
--forum-thread-read-link-color: #999;
|
||||
--forum-post-author-color: #999;
|
||||
--forum-diff-source-background: #181818;
|
||||
--forum-diff-source-border-color: #444;
|
||||
--forum-diff-replace-background: #18283a;
|
||||
--forum-diff-replace-border-color: #223d5b;
|
||||
--forum-diff-delete-background: #3a1818;
|
||||
--forum-diff-delete-border-color: #6b1e1c;
|
||||
--forum-diff-insert-background: #233a18;
|
||||
--forum-diff-insert-border-color: #30591b;
|
||||
--card-background: #282828;
|
||||
--card-background-hover: #333;
|
||||
--timeline-content-background: rgba(255, 255, 255, 0.06);
|
||||
--irc-border-color: #333;
|
||||
--irc-tab-current-shadow: 0px 0px 5px #000 inset;
|
||||
--irc-tab-close-button-color: #bbb;
|
||||
--irc-tab-close-button-background: #444;
|
||||
--irc-nick-border-color: #444;
|
||||
--irc-users-color: #aaa;
|
||||
--irc-users-background: #181818;
|
||||
--irc-users-border-color: transparent;
|
||||
--irc-users-popout-background: #181818;
|
||||
--irc-users-popout-border-color-left: #444;
|
||||
--irc-users-popout-border-color-right: #333;
|
||||
--code-line-number-color: #444;
|
||||
--library-star-btn-background: #252525;
|
||||
--library-star-btn-border-color: #bbb;
|
||||
--library-star-btn-a-border-color: #999;
|
||||
--library-star-btn-a-hover-background: #333; }
|
|
@ -1,327 +0,0 @@
|
|||
/*
|
||||
Inserts a CSS expression with one or more custom variables.
|
||||
You can provide an arbitrary number of strings in the second
|
||||
argument, separated by spaces. Any strings corresponding to
|
||||
variable names will be replaced by the correct values, while
|
||||
other strings are left untouched.
|
||||
|
||||
Example usage:
|
||||
|
||||
@include usevar(border-color, dimmer-color);
|
||||
@include usevar(background, "linear-gradient(" dim-background-transparent "," dim-background ")");
|
||||
|
||||
For clarity and to avoid syntax issues, you are encouraged to
|
||||
use unquoted strings for variables and quoted strings for
|
||||
everything else.
|
||||
|
||||
For convenience in common cases, if only a single argument
|
||||
is provided and it does not match an existing variable, this
|
||||
will throw an error.
|
||||
*/
|
||||
pre, code, .codeblock {
|
||||
/* Comment */
|
||||
/* Error */
|
||||
/* Keyword */
|
||||
/* Operator */
|
||||
/* Comment.Multiline */
|
||||
/* Comment.Preproc */
|
||||
/* Comment.Single */
|
||||
/* Comment.Special */
|
||||
/* Generic.Deleted */
|
||||
/* Generic.Emph */
|
||||
/* Generic.Error */
|
||||
/* Generic.Heading */
|
||||
/* Generic.Inserted */
|
||||
/* Generic.Output */
|
||||
/* Generic.Prompt */
|
||||
/* Generic.Strong */
|
||||
/* Generic.Subheading */
|
||||
/* Generic.Traceback */
|
||||
/* Keyword.Constant */
|
||||
/* Keyword.Declaration */
|
||||
/* Keyword.Namespace */
|
||||
/* Keyword.Pseudo */
|
||||
/* Keyword.Reserved */
|
||||
/* Keyword.Type */
|
||||
/* Literal.Number */
|
||||
/* Literal.String */
|
||||
/* Name.Attribute */
|
||||
/* Name.Builtin */
|
||||
/* Name.Class */
|
||||
/* Name.Constant */
|
||||
/* Name.Decorator */
|
||||
/* Name.Entity */
|
||||
/* Name.Exception */
|
||||
/* Name.Function */
|
||||
/* Name.Label */
|
||||
/* Name.Namespace */
|
||||
/* Name.Tag */
|
||||
/* Name.Variable */
|
||||
/* Operator.Word */
|
||||
/* Text.Whitespace */
|
||||
/* Literal.Number.Float */
|
||||
/* Literal.Number.Hex */
|
||||
/* Literal.Number.Integer */
|
||||
/* Literal.Number.Oct */
|
||||
/* Literal.String.Backtick */
|
||||
/* Literal.String.Char */
|
||||
/* Literal.String.Doc */
|
||||
/* Literal.String.Double */
|
||||
/* Literal.String.Escape */
|
||||
/* Literal.String.Heredoc */
|
||||
/* Literal.String.Interpol */
|
||||
/* Literal.String.Other */
|
||||
/* Literal.String.Regex */
|
||||
/* Literal.String.Single */
|
||||
/* Literal.String.Symbol */
|
||||
/* Name.Builtin.Pseudo */
|
||||
/* Name.Variable.Class */
|
||||
/* Name.Variable.Global */
|
||||
/* Name.Variable.Instance */
|
||||
/* Literal.Number.Integer.Long */ }
|
||||
pre .hll, code .hll, .codeblock .hll {
|
||||
background-color: #ffffcc; }
|
||||
pre .c, code .c, .codeblock .c {
|
||||
color: #60a0b0;
|
||||
font-style: italic; }
|
||||
pre .err, code .err, .codeblock .err {
|
||||
color: #FF0000; }
|
||||
pre .k, code .k, .codeblock .k {
|
||||
color: #007020;
|
||||
font-weight: bold; }
|
||||
pre .o, code .o, .codeblock .o {
|
||||
color: #666666; }
|
||||
pre .cm, code .cm, .codeblock .cm {
|
||||
color: #60a0b0;
|
||||
font-style: italic; }
|
||||
pre .cp, code .cp, .codeblock .cp {
|
||||
color: #007020; }
|
||||
pre .c1, code .c1, .codeblock .c1 {
|
||||
color: #60a0b0;
|
||||
font-style: italic; }
|
||||
pre .cs, code .cs, .codeblock .cs {
|
||||
color: #60a0b0;
|
||||
background-color: #fff0f0; }
|
||||
pre .gd, code .gd, .codeblock .gd {
|
||||
color: #A00000; }
|
||||
pre .ge, code .ge, .codeblock .ge {
|
||||
font-style: italic; }
|
||||
pre .gr, code .gr, .codeblock .gr {
|
||||
color: #FF0000; }
|
||||
pre .gh, code .gh, .codeblock .gh {
|
||||
color: #000080;
|
||||
font-weight: bold; }
|
||||
pre .gi, code .gi, .codeblock .gi {
|
||||
color: #00A000; }
|
||||
pre .go, code .go, .codeblock .go {
|
||||
color: #808080; }
|
||||
pre .gp, code .gp, .codeblock .gp {
|
||||
color: #c65d09;
|
||||
font-weight: bold; }
|
||||
pre .gs, code .gs, .codeblock .gs {
|
||||
font-weight: bold; }
|
||||
pre .gu, code .gu, .codeblock .gu {
|
||||
color: #800080;
|
||||
font-weight: bold; }
|
||||
pre .gt, code .gt, .codeblock .gt {
|
||||
color: #0040D0; }
|
||||
pre .kc, code .kc, .codeblock .kc {
|
||||
color: #007020;
|
||||
font-weight: bold; }
|
||||
pre .kd, code .kd, .codeblock .kd {
|
||||
color: #007020;
|
||||
font-weight: bold; }
|
||||
pre .kn, code .kn, .codeblock .kn {
|
||||
color: #007020;
|
||||
font-weight: bold; }
|
||||
pre .kp, code .kp, .codeblock .kp {
|
||||
color: #007020; }
|
||||
pre .kr, code .kr, .codeblock .kr {
|
||||
color: #007020;
|
||||
font-weight: bold; }
|
||||
pre .kt, code .kt, .codeblock .kt {
|
||||
color: #902000; }
|
||||
pre .m, code .m, .codeblock .m {
|
||||
color: #40a070; }
|
||||
pre .s, code .s, .codeblock .s {
|
||||
color: #4070a0; }
|
||||
pre .na, code .na, .codeblock .na {
|
||||
color: #4070a0; }
|
||||
pre .nb, code .nb, .codeblock .nb {
|
||||
color: #007020; }
|
||||
pre .nc, code .nc, .codeblock .nc {
|
||||
color: #0e84b5;
|
||||
font-weight: bold; }
|
||||
pre .no, code .no, .codeblock .no {
|
||||
color: #60add5; }
|
||||
pre .nd, code .nd, .codeblock .nd {
|
||||
color: #555555;
|
||||
font-weight: bold; }
|
||||
pre .ni, code .ni, .codeblock .ni {
|
||||
color: #d55537;
|
||||
font-weight: bold; }
|
||||
pre .ne, code .ne, .codeblock .ne {
|
||||
color: #007020; }
|
||||
pre .nf, code .nf, .codeblock .nf {
|
||||
color: #06287e; }
|
||||
pre .nl, code .nl, .codeblock .nl {
|
||||
color: #002070;
|
||||
font-weight: bold; }
|
||||
pre .nn, code .nn, .codeblock .nn {
|
||||
color: #0e84b5;
|
||||
font-weight: bold; }
|
||||
pre .nt, code .nt, .codeblock .nt {
|
||||
color: #062873;
|
||||
font-weight: bold; }
|
||||
pre .nv, code .nv, .codeblock .nv {
|
||||
color: #bb60d5; }
|
||||
pre .ow, code .ow, .codeblock .ow {
|
||||
color: #007020;
|
||||
font-weight: bold; }
|
||||
pre .w, code .w, .codeblock .w {
|
||||
color: #bbbbbb; }
|
||||
pre .mf, code .mf, .codeblock .mf {
|
||||
color: #40a070; }
|
||||
pre .mh, code .mh, .codeblock .mh {
|
||||
color: #40a070; }
|
||||
pre .mi, code .mi, .codeblock .mi {
|
||||
color: #40a070; }
|
||||
pre .mo, code .mo, .codeblock .mo {
|
||||
color: #40a070; }
|
||||
pre .sb, code .sb, .codeblock .sb {
|
||||
color: #4070a0; }
|
||||
pre .sc, code .sc, .codeblock .sc {
|
||||
color: #4070a0; }
|
||||
pre .sd, code .sd, .codeblock .sd {
|
||||
color: #4070a0;
|
||||
font-style: italic; }
|
||||
pre .s2, code .s2, .codeblock .s2 {
|
||||
color: #4070a0; }
|
||||
pre .se, code .se, .codeblock .se {
|
||||
color: #4070a0;
|
||||
font-weight: bold; }
|
||||
pre .sh, code .sh, .codeblock .sh {
|
||||
color: #4070a0; }
|
||||
pre .si, code .si, .codeblock .si {
|
||||
color: #70a0d0;
|
||||
font-style: italic; }
|
||||
pre .sx, code .sx, .codeblock .sx {
|
||||
color: #c65d09; }
|
||||
pre .sr, code .sr, .codeblock .sr {
|
||||
color: #235388; }
|
||||
pre .s1, code .s1, .codeblock .s1 {
|
||||
color: #4070a0; }
|
||||
pre .ss, code .ss, .codeblock .ss {
|
||||
color: #517918; }
|
||||
pre .bp, code .bp, .codeblock .bp {
|
||||
color: #007020; }
|
||||
pre .vc, code .vc, .codeblock .vc {
|
||||
color: #bb60d5; }
|
||||
pre .vg, code .vg, .codeblock .vg {
|
||||
color: #bb60d5; }
|
||||
pre .vi, code .vi, .codeblock .vi {
|
||||
color: #bb60d5; }
|
||||
pre .il, code .il, .codeblock .il {
|
||||
color: #40a070; }
|
||||
|
||||
.dark {
|
||||
background-color: #222;
|
||||
color: #bbb; }
|
||||
|
||||
:root {
|
||||
--fg-font-color: black;
|
||||
--theme-color: #666;
|
||||
--theme-color-dim: #aaa;
|
||||
--theme-color-dimmer: #bbb;
|
||||
--theme-color-dimmest: #ccc;
|
||||
--theme-color-dark: #666;
|
||||
--theme-color-light: #666;
|
||||
--link-color: #666;
|
||||
--link-border-color: #666;
|
||||
--hr-color: #444;
|
||||
--main-background-color: #fff;
|
||||
--main-color: black;
|
||||
--dim-color: #333;
|
||||
--dimmer-color: #999;
|
||||
--dimmest-color: #bbb;
|
||||
--menu-bottom-border-color: black;
|
||||
--login-popup-background: #fbfbfb;
|
||||
--content-background: #f8f8f8;
|
||||
--content-background-transparent: rgba(248, 248, 248, 0);
|
||||
--dim-background: #f0f0f0;
|
||||
--dim-background-transparent: rgba(240, 240, 240, 0);
|
||||
--text-background: #f9f9f9;
|
||||
--spoiler-border: #aaa;
|
||||
--background-even-background: #f8f8f8;
|
||||
--project-card-border-color: #aaa;
|
||||
--project-user-suggestions-background: #fff;
|
||||
--project-user-suggestions-border-color: #ddd;
|
||||
--notice-text-color: #fff;
|
||||
--notice-unapproved-color: #b42222;
|
||||
--notice-hidden-color: #b6b6b6;
|
||||
--notice-hiatus-color: #aa7d30;
|
||||
--notice-dead-color: #b42222;
|
||||
--notice-lts-color: #43a52f;
|
||||
--notice-lts-reqd-color: #aa7d30;
|
||||
--notice-success-color: #43a52f;
|
||||
--notice-warn-color: #aa7d30;
|
||||
--notice-failure-color: #b42222;
|
||||
--optionbar-border-color: #ccc;
|
||||
--tab-background: #fff;
|
||||
--tab-border-color: #d8d8d8;
|
||||
--tab-button-background: #dfdfdf;
|
||||
--tab-button-background-hover: #efefef;
|
||||
--tab-button-background-current: #fff;
|
||||
--form-check-background: #fafafc;
|
||||
--form-check-border-color: #999;
|
||||
--form-check-border-color-hover: #4c9ed9;
|
||||
--form-text-background: #fff;
|
||||
--form-text-background-active: #fafafc;
|
||||
--form-text-border-color: #999;
|
||||
--form-text-border-color-active: #4c9ed9;
|
||||
--form-button-color: black;
|
||||
--form-button-color-active: #4c9ed9;
|
||||
--form-button-background: #fff;
|
||||
--form-button-background-active: #f2f2f2;
|
||||
--form-button-border-color: #ccc;
|
||||
--form-button-inline-border-color: #999;
|
||||
--form-error-color: #c61d24;
|
||||
--landing-search-background: #f8f8f8;
|
||||
--landing-search-background-hover: #fefeff;
|
||||
--editor-toolbar-background: #fff;
|
||||
--editor-toolbar-border-color: transparent;
|
||||
--editor-toolbar-button-background: transparent;
|
||||
--editor-toolbar-button-background-hover: #ddd;
|
||||
--editor-toolbar-button-border-color: #ccc;
|
||||
--post-blockquote-border-color: #ddd;
|
||||
--forum-even-background: #f0f0f0;
|
||||
--forum-thread-read-color: #555;
|
||||
--forum-thread-read-link-color: #888;
|
||||
--forum-post-author-color: #333;
|
||||
--forum-diff-source-background: #fff;
|
||||
--forum-diff-source-border-color: #999;
|
||||
--forum-diff-replace-background: #adcef4;
|
||||
--forum-diff-replace-border-color: #4787d1;
|
||||
--forum-diff-delete-background: #e57979;
|
||||
--forum-diff-delete-border-color: #c12626;
|
||||
--forum-diff-insert-background: #96e579;
|
||||
--forum-diff-insert-border-color: #5baa3f;
|
||||
--card-background: #e8e8e8;
|
||||
--card-background-hover: #f0f0f0;
|
||||
--timeline-content-background: rgba(0, 0, 0, 0.2);
|
||||
--irc-border-color: #ddd;
|
||||
--irc-tab-current-shadow: 0px 0px 5px #bbb inset;
|
||||
--irc-tab-close-button-color: #fff;
|
||||
--irc-tab-close-button-background: #aaa;
|
||||
--irc-nick-border-color: #ccc;
|
||||
--irc-users-color: black;
|
||||
--irc-users-background: #fff;
|
||||
--irc-users-border-color: #ccc;
|
||||
--irc-users-popout-background: #fff;
|
||||
--irc-users-popout-border-color-left: #bbb;
|
||||
--irc-users-popout-border-color-right: #ccc;
|
||||
--code-line-number-color: #777;
|
||||
--library-star-btn-background: #fff;
|
||||
--library-star-btn-border-color: #999;
|
||||
--library-star-btn-a-border-color: #aaa;
|
||||
--library-star-btn-a-hover-background: #fafafa; }
|
|
@ -23,6 +23,7 @@ type ProjectsQuery struct {
|
|||
// are generally visible to all users.
|
||||
Lifecycles []models.ProjectLifecycle // If empty, defaults to visible lifecycles. Do not conflate this with permissions; those are checked separately.
|
||||
Types ProjectTypeQuery // bitfield
|
||||
FeaturedOnly bool
|
||||
IncludeHidden bool
|
||||
|
||||
// Ignored when using FetchProject
|
||||
|
@ -133,6 +134,9 @@ func FetchProjects(
|
|||
}
|
||||
qb.Add(`)`)
|
||||
}
|
||||
if q.FeaturedOnly {
|
||||
qb.Add(`AND project.featured`)
|
||||
}
|
||||
if !q.IncludeHidden {
|
||||
qb.Add(`AND NOT project.hidden`)
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@ type SnippetQuery struct {
|
|||
Tags []int
|
||||
DiscordMessageIDs []string
|
||||
|
||||
FeaturedOnly bool
|
||||
|
||||
Limit, Offset int // if empty, no pagination
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
transition: all 100ms ease-in-out;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--dimmest-color);
|
||||
background-color: var(--bg-3);
|
||||
}
|
||||
|
||||
&.active {
|
||||
|
|
|
@ -87,11 +87,11 @@
|
|||
th,
|
||||
td {
|
||||
padding: var(--spacing-extra-small) var(--spacing-small);
|
||||
border: 1px solid var(--dimmest-color);
|
||||
border: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
code {
|
||||
background-color: var(--dim-background);
|
||||
background-color: var(--bg-3);
|
||||
|
||||
padding: .2em 0;
|
||||
white-space: nowrap;
|
||||
|
@ -106,14 +106,14 @@
|
|||
|
||||
pre>code,
|
||||
pre.hmn-code {
|
||||
background-color: var(--dim-background);
|
||||
background-color: var(--bg-3);
|
||||
|
||||
padding: 0.7em;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
border-color: var(--dimmest-color);
|
||||
border-color: var(--bg-3);
|
||||
margin-left: var(--spacing-small);
|
||||
padding-left: var(--spacing-small);
|
||||
margin-right: 0;
|
||||
|
|
|
@ -108,34 +108,6 @@ pre,
|
|||
}
|
||||
}
|
||||
|
||||
.b--dim {
|
||||
border-color: var(--dim-color);
|
||||
}
|
||||
|
||||
.b--dimmer {
|
||||
border-color: var(--dimmer-color);
|
||||
}
|
||||
|
||||
.b--dimmest {
|
||||
border-color: var(--dimmest-color);
|
||||
}
|
||||
|
||||
.b--theme {
|
||||
border-color: var(--theme-color);
|
||||
}
|
||||
|
||||
.b--theme-dim {
|
||||
border-color: var(--theme-color-dim);
|
||||
}
|
||||
|
||||
.b--theme-dimmer {
|
||||
border-color: var(--theme-color-dimmer);
|
||||
}
|
||||
|
||||
.b--theme-dimmest {
|
||||
border-color: var(--theme-color-dimmest);
|
||||
}
|
||||
|
||||
.b--theme-dark {
|
||||
border-color: var(--theme-color-dark);
|
||||
}
|
||||
|
@ -201,30 +173,6 @@ pre,
|
|||
}
|
||||
}
|
||||
|
||||
.c--dim {
|
||||
color: var(--dim-color);
|
||||
}
|
||||
|
||||
.c--theme-dim {
|
||||
color: var(--theme-color-dim);
|
||||
}
|
||||
|
||||
.c--dimmer {
|
||||
color: var(--dimmer-color);
|
||||
}
|
||||
|
||||
.c--theme-dimmer {
|
||||
color: var(--theme-color-dimmer);
|
||||
}
|
||||
|
||||
.c--dimmest {
|
||||
color: var(--dimmest-color);
|
||||
}
|
||||
|
||||
.c--theme-dimmest {
|
||||
color: var(--theme-color-dimmest);
|
||||
}
|
||||
|
||||
.f8 {
|
||||
font-size: 0.65rem;
|
||||
}
|
||||
|
@ -755,7 +703,7 @@ lite variant instead.
|
|||
align-items: center;
|
||||
border-style: dashed;
|
||||
border-width: 0 0 1px;
|
||||
border-color: var(--dimmest-color);
|
||||
border-color: var(--bg-3);
|
||||
|
||||
@media screen and (min-width: 35em) {
|
||||
flex-direction: row;
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
height: var(--height);
|
||||
border-width: 0 0 1px 1px;
|
||||
border-style: solid;
|
||||
border-color: var(--dimmest-color);
|
||||
border-color: var(--bg-3);
|
||||
left: -1.5rem;
|
||||
top: calc(1rem - var(--height));
|
||||
border-bottom-left-radius: 0.5rem;
|
||||
|
|
|
@ -114,7 +114,7 @@ header.old {
|
|||
}
|
||||
|
||||
header {
|
||||
background-color: var(--bg-3);
|
||||
background-color: var(--bg-2);
|
||||
border-bottom-style: solid;
|
||||
border-bottom-width: 1px;
|
||||
|
||||
|
@ -151,7 +151,7 @@ header {
|
|||
position: absolute;
|
||||
z-index: 100;
|
||||
min-width: 8rem;
|
||||
background-color: var(--card-background);
|
||||
background-color: var(--bg-2);
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-top-width: 0;
|
||||
|
|
|
@ -16,4 +16,5 @@
|
|||
@import "projects.css";
|
||||
@import "showcase.css";
|
||||
@import "syntax.css";
|
||||
@import "tabs.css";
|
||||
@import "timeline.css";
|
|
@ -0,0 +1,8 @@
|
|||
.tab-button {
|
||||
border-bottom: 2px solid transparent;
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
|
||||
.tab-button-active {
|
||||
border-color: var(--link-color);
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
.avatar {
|
||||
object-fit: cover;
|
||||
overflow: hidden;
|
||||
background-color: var(--dimmest-color);
|
||||
background-color: var(--bg-3);
|
||||
flex-shrink: 0;
|
||||
border: none;
|
||||
|
||||
|
@ -23,22 +23,34 @@
|
|||
--fade-color: var(--card-background);
|
||||
color: var(--main-color);
|
||||
|
||||
.timeline-content-box {
|
||||
&.timeline-item-bg {
|
||||
background-color: var(--timeline-content-background);
|
||||
.timeline-media {
|
||||
background-color: var(--timeline-media-background);
|
||||
max-height: 60vh;
|
||||
|
||||
&.timeline-embed {
|
||||
/* aspect-ratio aspect-ratio--16x9 */
|
||||
height: 0;
|
||||
position: relative;
|
||||
padding-bottom: 56.25%;
|
||||
|
||||
>iframe {
|
||||
/* aspect-ratio--object */
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 100;
|
||||
}
|
||||
}
|
||||
|
||||
>* {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
max-height: 80vh;
|
||||
}
|
||||
}
|
||||
|
||||
.avatar {
|
||||
/* 40px */
|
||||
width: 2.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.timeline-modal {
|
||||
|
|
|
@ -14,10 +14,6 @@ $breakpoint-large: screen and (min-width: 60em)
|
|||
--link-color: #d12991;
|
||||
--red: #c61d24;
|
||||
|
||||
--dim-color: #333;
|
||||
--dimmer-color: #999;
|
||||
--dimmest-color: #bbb;
|
||||
|
||||
/* Default theme colors in case the project.css is busted */
|
||||
--theme-color: #b1b1b1;
|
||||
--theme-color-dim: #c0c0c0;
|
||||
|
@ -34,6 +30,8 @@ $breakpoint-large: screen and (min-width: 60em)
|
|||
--card-background-hover: #f1f1f1;
|
||||
--card-background-transparent: #ebebeb00;
|
||||
|
||||
--timeline-media-background: #b4b4b466;
|
||||
|
||||
--bg-1: #f8f8f8;
|
||||
--bg-2: #e8e8e8;
|
||||
--bg-3: #d8d8d8;
|
||||
|
@ -71,10 +69,6 @@ $breakpoint-large: screen and (min-width: 60em)
|
|||
--link-color: #ff5dc2;
|
||||
--color-error: #ff6666;
|
||||
|
||||
--dim-color: #bbb;
|
||||
--dimmer-color: #999;
|
||||
--dimmest-color: #777;
|
||||
|
||||
--theme-color: #666;
|
||||
--theme-color-dim: #444;
|
||||
--theme-color-dimmer: #383838;
|
||||
|
@ -91,6 +85,8 @@ $breakpoint-large: screen and (min-width: 60em)
|
|||
--card-background-hover: #333;
|
||||
--card-background-transparent: #24242400;
|
||||
|
||||
--timeline-media-background: #24242466;
|
||||
|
||||
--bg-1: #1f1f1f;
|
||||
--bg-2: #2f2f2f;
|
||||
--bg-3: #494949;
|
||||
|
|
|
@ -389,16 +389,17 @@ func TimelineItemsToJSON(items []TimelineItem) string {
|
|||
builder.WriteString(item.Url)
|
||||
builder.WriteString(`",`)
|
||||
|
||||
// TODO(redesign): This only serializes a single piece of media.
|
||||
var mediaType TimelineItemMediaType
|
||||
var assetUrl string
|
||||
var thumbnailUrl string
|
||||
var width, height int
|
||||
if len(item.EmbedMedia) > 0 {
|
||||
mediaType = item.EmbedMedia[0].Type
|
||||
assetUrl = item.EmbedMedia[0].AssetUrl
|
||||
thumbnailUrl = item.EmbedMedia[0].ThumbnailUrl
|
||||
width = item.EmbedMedia[0].Width
|
||||
height = item.EmbedMedia[0].Height
|
||||
if len(item.Media) > 0 {
|
||||
mediaType = item.Media[0].Type
|
||||
assetUrl = item.Media[0].AssetUrl
|
||||
thumbnailUrl = item.Media[0].ThumbnailUrl
|
||||
width = item.Media[0].Width
|
||||
height = item.Media[0].Height
|
||||
}
|
||||
|
||||
builder.WriteString(`"media_type":`)
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
{{ cleancontrolchars .Description }}
|
||||
]]>
|
||||
</div>
|
||||
{{ range .EmbedMedia }}
|
||||
{{ range .Media }}
|
||||
<div>
|
||||
{{ if eq .Type mediaimage }}
|
||||
<img src="{{ .AssetUrl }}"/>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<div class="breadcrumbs f7 o-80">
|
||||
<div class="breadcrumbs f7">
|
||||
{{ range $i, $breadcrumb := . }}
|
||||
{{ if gt $i 0 }} » {{ end }}
|
||||
<a href="{{ $breadcrumb.Url }}">{{ $breadcrumb.Name }}</a>
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
<div>{{ trim .Description }}</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ range .EmbedMedia }}
|
||||
{{ range .Media }}
|
||||
<div class="flex flex-column {{ if eq .Type mediaembed }}wide-screen{{ end }} justify-stretch iframe-fill">
|
||||
{{ if eq .Type mediaimage }}
|
||||
<img src="{{ .AssetUrl }}">
|
||||
|
|
|
@ -1,43 +1,64 @@
|
|||
<div class="timeline-item flex flex-column pa3" data-id="{{ .ID }}" {{ with .FilterTitle }}data-filter-title="{{ . }}"{{ end }}>
|
||||
{{/* top bar - avatar, info, date */}}
|
||||
|
||||
<div class="flex items-center">
|
||||
{{ if .OwnerAvatarUrl }}
|
||||
<a class="flex flex-shrink-0" href="{{ .OwnerUrl }}">
|
||||
<img class="avatar avatar-user {{ if .SmallInfo }}avatar-small mr2{{ else }}mr3{{ end }}" src="{{ .OwnerAvatarUrl }}" />
|
||||
<img class="avatar avatar-user {{ if .ForumLayout }}mr3{{ else }}mr2{{ end }}" src="{{ .OwnerAvatarUrl }}" />
|
||||
</a>
|
||||
{{ end }}
|
||||
{{ if .ForumLayout }}
|
||||
<div class="overflow-hidden flex-grow-1 flex flex-column g1 justify-center">
|
||||
{{ with .Breadcrumbs }}
|
||||
{{ template "breadcrumbs.html" . }}
|
||||
{{ end }}
|
||||
{{ if .Title }}
|
||||
<div class="f5 lh-title {{ if not .AllowTitleWrap }}nowrap truncate{{ end }}">
|
||||
{{ with .TypeTitle }}<b class="dn di-ns">{{ . }}:</b>{{ end }}
|
||||
<a href="{{ .Url }}">{{ .Title }}</a>
|
||||
</div>
|
||||
{{ end }}
|
||||
<div class="details link--normal">
|
||||
<a class="user" href="{{ .OwnerUrl }}">{{ .OwnerName }}</a>
|
||||
— {{ timehtml (absoluteshortdate .Date) .Date }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="overflow-hidden flex-grow-1 flex flex-column justify-center">
|
||||
{{ if .Breadcrumbs }}
|
||||
{{ template "breadcrumbs.html" .Breadcrumbs }}
|
||||
{{ if .Editable }}
|
||||
<a href="javascript:;" class="edit ml2">✎</a>
|
||||
<div class="dn rawdesc">{{ .RawDescription }}</div>
|
||||
{{ end }}
|
||||
{{ if .Title }}
|
||||
<div class="f5 {{ if not .AllowTitleWrap }}nowrap truncate{{ end }}">
|
||||
{{ with .TypeTitle }}<b class="dn di-ns">{{ . }}:</b>{{ end }}
|
||||
<a href="{{ .Url }}">{{ .Title }}</a>
|
||||
{{ else }}
|
||||
<div class="overflow-hidden flex-grow-1 flex flex-column g1 justify-center link--normal">
|
||||
{{ if .Breadcrumbs }}
|
||||
<div>Use .ForumLayout if you want breadcrumbs :)</div>
|
||||
{{ end }}
|
||||
{{ if .Title }}
|
||||
<div>Use .ForumLayout if you want a title :)</div>
|
||||
{{ end }}
|
||||
<a class="user b" href="{{ .OwnerUrl }}">{{ .OwnerName }}</a>
|
||||
<a class="f6" href="{{ .Url }}">{{ timehtml (absoluteshortdate .Date) .Date }}</a>
|
||||
</div>
|
||||
{{ if eq (len .Projects) 1 }}
|
||||
{{ $p := index .Projects 0 }}
|
||||
<div class="overflow-hidden flex flex-column g1 justify-center link--normal tr">
|
||||
<a class="user b" href="{{ $p.Url }}">{{ $p.Name }}</a>
|
||||
</div>
|
||||
{{ end }}
|
||||
<div class="details">
|
||||
<a class="user" href="{{ .OwnerUrl }}">{{ .OwnerName }}</a>
|
||||
{{ if not .SmallInfo }}
|
||||
— {{ timehtml (relativedate .Date) .Date }}
|
||||
{{ range .Projects }}
|
||||
{{ if .Logo }}
|
||||
<a class="flex flex-shrink-0" href="{{ .Url }}">
|
||||
<img class="avatar ml2" src="{{ .Logo }}">
|
||||
</a>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{ if .SmallInfo }}
|
||||
<a href="{{ .Url }}">{{ timehtml (relativedate .Date) .Date }}</a>
|
||||
{{ end }}
|
||||
{{ if .Editable }}
|
||||
<a href="javascript:;" class="edit ml2">✎</a>
|
||||
<div class="dn rawdesc">{{ .RawDescription }}</div>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
</div>
|
||||
|
||||
{{/* content */}}
|
||||
|
||||
{{ range .EmbedMedia }}
|
||||
<div class="timeline-content-box mt3 {{ if eq .Type mediaembed }}embed{{ end }} overflow-hidden flex {{ if not (eq .Type mediaunknown) }}timeline-item-bg justify-center{{ end }}">
|
||||
{{ range .Media }}
|
||||
<div class="timeline-media mt3 {{ if eq .Type mediaembed }}timeline-embed{{ end }} overflow-hidden flex {{ if not (eq .Type mediaunknown) }}justify-center{{ end }}">
|
||||
{{ if eq .Type mediaimage }}
|
||||
<img src="{{ .AssetUrl }}">
|
||||
{{ else if eq .Type mediavideo }}
|
||||
|
@ -72,14 +93,7 @@
|
|||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
{{ with .Projects }}
|
||||
<div class="mt3 flex g2 projects">
|
||||
{{ range $i, $proj := . }}
|
||||
<a data-projid="{{ $proj.ID }}" href="{{ $proj.Url }}" class="snippet-project flex flex-row items-center bg-theme-dimmer ph2 pv1">
|
||||
<img src="{{ $proj.Logo }}" class="db mr1 br1 h1-5" />
|
||||
<div>{{ $proj.Name }}</div>
|
||||
</a>
|
||||
{{ end }}
|
||||
</div>
|
||||
{{ with .DiscordMessageUrl }}
|
||||
<a class="f7 mt3 i" href="{{ . }}" target="_blank">View original message on Discord</a>
|
||||
{{ end }}
|
||||
</div>
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
{{ define "extrahead" }}
|
||||
<script src="{{ static "js/templates.js" }}"></script>
|
||||
<script src="{{ static "js/tabs.js" }}"></script>
|
||||
{{ end }}
|
||||
|
||||
{{ define "content" }}
|
||||
|
@ -87,31 +88,31 @@
|
|||
<div class="w5 flex flex-column g2 flex-shrink-0">
|
||||
{{ if .User }}
|
||||
<div class="sidebar-card bg--card link--normal">
|
||||
<div onclick="collapse(event)" class="pa2 flex justify-between items-center pointer">
|
||||
<div onclick="collapse(event)" class="pa3 flex justify-between items-center pointer">
|
||||
<span class="f7">Your projects</span>
|
||||
<span class="sidebar-chevron svgicon-lite rot-180">{{ svg "chevron-down" }}</span>
|
||||
</div>
|
||||
<div class="sidebar-card-content">
|
||||
<div class="ph2 flex flex-column g2">
|
||||
<div class="ph3 flex flex-column g2">
|
||||
{{ range .UserProjects }}
|
||||
{{ template "list-project" . }}
|
||||
{{ else }}
|
||||
<div class="f7 pv3 tc c--dim">You have not created any projects.</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
<a class="bt mt2 pa2 flex justify-between" href="{{ .NewProjectUrl }}">
|
||||
<a class="bt mt3 pa3 flex justify-between" href="{{ .NewProjectUrl }}">
|
||||
<div>Create new project</div>
|
||||
<div class="svgicon-lite flex items-center">{{ svg "add" }}</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-card bg--card link--normal">
|
||||
<div onclick="collapse(event)" class="pa2 flex justify-between items-center pointer">
|
||||
<div onclick="collapse(event)" class="pa3 flex justify-between items-center pointer">
|
||||
<span class="f7">Following</span>
|
||||
<span class="sidebar-chevron svgicon-lite rot-180">{{ svg "chevron-down" }}</span>
|
||||
</div>
|
||||
<div class="sidebar-card-content">
|
||||
<div class="ph2 pb2 flex flex-column g2">
|
||||
<div class="ph3 pb3 flex flex-column g2">
|
||||
{{ range .Following }}
|
||||
{{ template "list-follow" . }}
|
||||
{{ else }}
|
||||
|
@ -122,11 +123,11 @@
|
|||
</div>
|
||||
{{ else }}
|
||||
<div class="bg--card link--normal">
|
||||
<div class="pa2 flex flex-column g2">
|
||||
<div class="pa3 flex flex-column g2">
|
||||
<div class="b">Join the Handmade Network</div>
|
||||
<div class="f6 post-content">Share your own Handmade projects with the community.</div>
|
||||
</div>
|
||||
<a class="bt pa2 flex justify-between" href="{{ .LoginPageUrl }}">
|
||||
<a class="bt pa3 flex justify-between" href="{{ .LoginPageUrl }}">
|
||||
<div>Log in</div>
|
||||
<div class="svgicon-lite flex items-center">{{ svg "chevron-right" }}</div>
|
||||
</a>
|
||||
|
@ -139,11 +140,40 @@
|
|||
|
||||
<!-- Feed -->
|
||||
<div class="flex flex-column flex-grow-1 overflow-hidden">
|
||||
<div class="timeline flex flex-column g3">
|
||||
{{ range .RecentItems }}
|
||||
{{ template "timeline_item.html" . }}
|
||||
{{ end }}
|
||||
TODO: READ MORE LINK
|
||||
<div id="landing-tabs">
|
||||
<div class="bb mb2 flex f6">
|
||||
{{ if .User }}
|
||||
<div data-tab-button="following" class="tab-button ph3 pv1 pointer">Following</div>
|
||||
{{ end }}
|
||||
<div data-tab-button="featured" class="tab-button ph3 pv1 pointer">Featured</div>
|
||||
<div data-tab-button="recent" class="tab-button ph3 pv1 pointer">Recent</div>
|
||||
<div data-tab-button="news" class="tab-button ph3 pv1 pointer">News</div>
|
||||
</div>
|
||||
<div>
|
||||
{{ if .User }}
|
||||
<div data-tab="following" class="timeline flex flex-column g3">
|
||||
{{ range .FollowingItems }}
|
||||
{{ template "timeline_item.html" . }}
|
||||
{{ end }}
|
||||
</div>
|
||||
{{ end }}
|
||||
<div data-tab="featured" class="timeline flex flex-column g3">
|
||||
{{ range .FeaturedItems }}
|
||||
{{ template "timeline_item.html" . }}
|
||||
{{ end }}
|
||||
</div>
|
||||
<div data-tab="recent" class="timeline flex flex-column g3">
|
||||
{{ range .RecentItems }}
|
||||
{{ template "timeline_item.html" . }}
|
||||
{{ end }}
|
||||
</div>
|
||||
<div data-tab="news" class="timeline flex flex-column g3">
|
||||
{{ range .NewsItems }}
|
||||
{{ template "timeline_item.html" . }}
|
||||
{{ end }}
|
||||
</div>
|
||||
TODO: READ MORE LINK
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -160,6 +190,8 @@
|
|||
content.hidden = hide;
|
||||
chevron.classList.toggle("rot-180", !hide);
|
||||
}
|
||||
|
||||
initTabs(document.querySelector("#landing-tabs"));
|
||||
</script>
|
||||
|
||||
{{ end }}
|
||||
|
|
|
@ -76,6 +76,9 @@
|
|||
|
||||
<body class="{{ join " " .BodyClasses }}">
|
||||
<div class="bg--main m--center mw-site ph3-m ph4-l">
|
||||
<div class="notice notice-warn mt3 mb2 white ph3 pv2 br2-ns">
|
||||
We are currently in the process of converting the website to the new design. Some pages, like this one, are still broken. We appreciate your patience.
|
||||
</div>
|
||||
{{ template "header.html" . }}
|
||||
{{ template "notices.html" .Notices }}
|
||||
{{ with .Breadcrumbs }}
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
--theme-color-dimmer: {{ $themeDimmer }};
|
||||
--theme-color-dimmest: {{ $themeDimmest }};
|
||||
|
||||
--timeline-content-background: rgba(255, 255, 255, 0.1);
|
||||
--timeline-media-background: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
body {
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
--theme-color-dimmer: {{ $themeDimmer }};
|
||||
--theme-color-dimmest: {{ $themeDimmest }};
|
||||
|
||||
--timeline-content-background: rgba(255, 255, 255, 0.1);
|
||||
--timeline-media-background: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
body {
|
||||
|
|
|
@ -58,7 +58,7 @@
|
|||
--theme-color-dimmer: {{ $themeDimmer }};
|
||||
--theme-color-dimmest: {{ $themeDimmest }};
|
||||
|
||||
--timeline-content-background: rgba(255, 255, 255, 0.1);
|
||||
--timeline-media-background: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
body {
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
{{ define "extrahead" }}
|
||||
{{ template "markdown_previews.html" .TextEditor }}
|
||||
<script src="{{ static "js/tabs.js" }}"></script>
|
||||
<script src="{{ static "js/image_selector.js" }}"></script>
|
||||
<script src="{{ static "js/templates.js" }}"></script>
|
||||
<script src="{{ static "js/base64.js" }}"></script>
|
||||
|
|
|
@ -109,6 +109,30 @@ int main() {
|
|||
<span class="n">GetWindowRect</span><span class="p">(</span> <span class="n">big_window</span><span class="p">,</span> <span class="o">&</span><span class="n">window_rect</span> <span class="p">);</span>
|
||||
<span class="n">window_rect</span><span class="p">.</span><span class="n">top</span> <span class="o">+=</span> <span class="mi">30</span><span class="p">;</span>
|
||||
</pre>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Items</th>
|
||||
<th>Expenditure</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Donuts</th>
|
||||
<td>3,000</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Stationery</th>
|
||||
<td>18,000</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th>Totals</th>
|
||||
<td>21,000</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<h1 class="mt3 mb2">Form styles</h1>
|
||||
|
@ -212,7 +236,7 @@ int main() {
|
|||
|
||||
<h1 class="mt3 mb2">Timeline items</h1>
|
||||
|
||||
<div class="hmn-form pa3 ba b--theme-dim flex flex-column g3">
|
||||
<div class="hmn-form pa3 ba b--theme-dim flex flex-column g3 mw7">
|
||||
{{ range .TestTimelineItems }}
|
||||
{{ template "timeline_item.html" . }}
|
||||
{{ end }}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
{{ template "base-2024.html" . }}
|
||||
|
||||
{{ define "extrahead" }}
|
||||
<script src="{{ static "js/tabs.js" }}"></script>
|
||||
<script src="{{ static "js/image_selector.js" }}"></script>
|
||||
{{ end }}
|
||||
|
||||
|
|
|
@ -338,9 +338,9 @@ type TimelineItem struct {
|
|||
Description template.HTML
|
||||
RawDescription string
|
||||
|
||||
EmbedMedia []TimelineItemMedia
|
||||
Media []TimelineItemMedia
|
||||
|
||||
SmallInfo bool
|
||||
ForumLayout bool
|
||||
AllowTitleWrap bool
|
||||
TruncateDescription bool
|
||||
CanShowcase bool // whether this snippet can be shown in a showcase gallery
|
||||
|
|
|
@ -188,7 +188,6 @@ func AdminApprovalQueue(c *RequestContext) ResponseData {
|
|||
}
|
||||
timelineItem := SnippetToTimelineItem(&s.Snippet, s.Asset, s.DiscordMessage, s.Projects, s.Owner, false)
|
||||
timelineItem.OwnerAvatarUrl = ""
|
||||
timelineItem.SmallInfo = true
|
||||
userData.Timeline = append(userData.Timeline, timelineItem)
|
||||
}
|
||||
|
||||
|
@ -210,7 +209,6 @@ func AdminApprovalQueue(c *RequestContext) ResponseData {
|
|||
}
|
||||
timelineItem := PostToTimelineItem(hmndata.UrlContextForProject(&p.Project), lineageBuilder, &p.Post, &p.Thread, &p.Author)
|
||||
timelineItem.OwnerAvatarUrl = ""
|
||||
timelineItem.SmallInfo = true
|
||||
timelineItem.Description = template.HTML(p.CurrentVersion.TextParsed)
|
||||
userData.Timeline = append(userData.Timeline, timelineItem)
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ func StyleTest(c *RequestContext) ResponseData {
|
|||
TestTimelineItems: []templates.TimelineItem{
|
||||
// Forum post
|
||||
{
|
||||
ForumLayout: true,
|
||||
OwnerName: "Cool User",
|
||||
OwnerAvatarUrl: templates.UserAvatarDefaultUrl("dark"),
|
||||
Date: time.Now().Add(-5 * time.Second),
|
||||
|
@ -28,45 +29,73 @@ func StyleTest(c *RequestContext) ResponseData {
|
|||
Title: "How can I a website?",
|
||||
},
|
||||
// Blog post
|
||||
// Snippet
|
||||
// Snippet with image
|
||||
{
|
||||
SmallInfo: true,
|
||||
OwnerName: "Cool User",
|
||||
OwnerAvatarUrl: templates.UserAvatarDefaultUrl("dark"),
|
||||
Date: time.Date(2022, 3, 20, 13, 32, 54, 0, time.UTC),
|
||||
Url: "test",
|
||||
DiscordMessageUrl: "test",
|
||||
EmbedMedia: []templates.TimelineItemMedia{
|
||||
Media: []templates.TimelineItemMedia{
|
||||
{
|
||||
Type: templates.TimelineItemMediaTypeImage,
|
||||
AssetUrl: "https://assets.media.handmade.network/32ff3e7e-1d9c-4740-a062-1f8bec2e44cf/unknown.png",
|
||||
},
|
||||
},
|
||||
Projects: []templates.Project{
|
||||
{Name: "Cool Project", Logo: "https://assets.media.handmade.network/8c6a3b71-9e91-4bf6-80ef-bc8f3d21b30d/netsim.png"},
|
||||
},
|
||||
},
|
||||
// Snippet with tall image
|
||||
{
|
||||
OwnerName: "Cool User",
|
||||
OwnerAvatarUrl: templates.UserAvatarDefaultUrl("dark"),
|
||||
Date: time.Date(2022, 3, 20, 13, 32, 54, 0, time.UTC),
|
||||
Description: "I got my LaGUI working on Android! 😄",
|
||||
Url: "test",
|
||||
DiscordMessageUrl: "https://discord.com/channels/239737791225790464/404399251276169217/1245228715407966208",
|
||||
Media: []templates.TimelineItemMedia{
|
||||
{
|
||||
Type: templates.TimelineItemMediaTypeImage,
|
||||
AssetUrl: "https://assets.media.handmade.network/ea6f914a-ea00-4cbb-bbd7-586b82fdb484/Screenshot_20240529_120344_com.lagui.simplest.jpg",
|
||||
},
|
||||
},
|
||||
},
|
||||
// Snippet with video
|
||||
{
|
||||
OwnerName: "Cool User",
|
||||
OwnerAvatarUrl: templates.UserAvatarDefaultUrl("dark"),
|
||||
Date: time.Date(2024, 1, 30, 3, 32, 54, 0, time.UTC),
|
||||
Url: "test",
|
||||
Description: "Using my newfound decoding knowledge I started working on a simple video editor. I also tried decoding 16 files at once, which didn't seem to bother my 3080 at all.",
|
||||
DiscordMessageUrl: "https://discord.com/channels/239737791225790464/404399251276169217/1249562779619168266",
|
||||
Media: []templates.TimelineItemMedia{
|
||||
{
|
||||
Type: templates.TimelineItemMediaTypeVideo,
|
||||
AssetUrl: "https://assets.media.handmade.network/b122c7be-dc6d-41fe-a5ed-033fe991927e/show16.mp4",
|
||||
ThumbnailUrl: "https://assets.media.handmade.network/b122c7be-dc6d-41fe-a5ed-033fe991927e/b122c7be-dc6d-41fe-a5ed-033fe991927e_thumb.jpg",
|
||||
},
|
||||
},
|
||||
},
|
||||
// Snippet with embed
|
||||
{
|
||||
SmallInfo: true,
|
||||
OwnerName: "Cool User",
|
||||
OwnerAvatarUrl: templates.UserAvatarDefaultUrl("dark"),
|
||||
Date: time.Date(2021, 4, 3, 1, 44, 54, 0, time.UTC),
|
||||
Url: "test",
|
||||
DiscordMessageUrl: "test",
|
||||
EmbedMedia: []templates.TimelineItemMedia{
|
||||
Media: []templates.TimelineItemMedia{
|
||||
youtubeMediaItem("FN9hZcTB16g"),
|
||||
},
|
||||
Projects: []templates.Project{
|
||||
{Name: "Cool Project", Logo: templates.UserAvatarDefaultUrl("light")},
|
||||
},
|
||||
},
|
||||
// Snippet with two images & multiple projects
|
||||
{
|
||||
SmallInfo: true,
|
||||
OwnerName: "Cool User",
|
||||
OwnerAvatarUrl: templates.UserAvatarDefaultUrl("dark"),
|
||||
Date: time.Now().Add(-2 * 24 * time.Hour),
|
||||
Url: "test",
|
||||
DiscordMessageUrl: "test",
|
||||
EmbedMedia: []templates.TimelineItemMedia{
|
||||
Media: []templates.TimelineItemMedia{
|
||||
{
|
||||
Type: templates.TimelineItemMediaTypeImage,
|
||||
AssetUrl: "https://assets.media.handmade.network/979d8850-f6b6-44b4-984e-93be82eb492b/PBR_WIP_20240620_01.png",
|
||||
|
@ -77,19 +106,18 @@ func StyleTest(c *RequestContext) ResponseData {
|
|||
},
|
||||
},
|
||||
Projects: []templates.Project{
|
||||
{Name: "Cool Project", Logo: templates.UserAvatarDefaultUrl("light")},
|
||||
{Name: "Cool Project", Logo: "https://assets.media.handmade.network/8c6a3b71-9e91-4bf6-80ef-bc8f3d21b30d/netsim.png"},
|
||||
{Name: "Uncool Project"},
|
||||
},
|
||||
},
|
||||
// Snippet with a video and an image
|
||||
{
|
||||
SmallInfo: true,
|
||||
OwnerName: "Cool User",
|
||||
OwnerAvatarUrl: templates.UserAvatarDefaultUrl("dark"),
|
||||
Date: time.Now().Add(-2 * time.Hour),
|
||||
Url: "test",
|
||||
DiscordMessageUrl: "test",
|
||||
EmbedMedia: []templates.TimelineItemMedia{
|
||||
Media: []templates.TimelineItemMedia{
|
||||
{
|
||||
Type: templates.TimelineItemMediaTypeImage,
|
||||
AssetUrl: "https://assets.media.handmade.network/979d8850-f6b6-44b4-984e-93be82eb492b/PBR_WIP_20240620_01.png",
|
||||
|
@ -100,8 +128,7 @@ func StyleTest(c *RequestContext) ResponseData {
|
|||
},
|
||||
},
|
||||
Projects: []templates.Project{
|
||||
{Name: "Cool Project", Logo: templates.UserAvatarDefaultUrl("light")},
|
||||
{Name: "Uncool Project"},
|
||||
{Name: "Project without logo"},
|
||||
},
|
||||
},
|
||||
// Snippet with every type of embed at once
|
||||
|
|
|
@ -271,7 +271,6 @@ func getLJ2024FeedData(c *RequestContext, maxTimelineItems int) (JamFeedDataLJ20
|
|||
timelineItems = make([]templates.TimelineItem, 0, len(snippets))
|
||||
for _, s := range snippets {
|
||||
timelineItem := SnippetToTimelineItem(&s.Snippet, s.Asset, s.DiscordMessage, s.Projects, s.Owner, false)
|
||||
timelineItem.SmallInfo = true
|
||||
timelineItems = append(timelineItems, timelineItem)
|
||||
}
|
||||
}
|
||||
|
@ -451,7 +450,6 @@ func JamFeed2023(c *RequestContext) ResponseData {
|
|||
timelineItems = make([]templates.TimelineItem, 0, len(snippets))
|
||||
for _, s := range snippets {
|
||||
timelineItem := SnippetToTimelineItem(&s.Snippet, s.Asset, s.DiscordMessage, s.Projects, s.Owner, false)
|
||||
timelineItem.SmallInfo = true
|
||||
timelineItems = append(timelineItems, timelineItem)
|
||||
}
|
||||
}
|
||||
|
@ -619,7 +617,6 @@ func JamFeed2023_Visibility(c *RequestContext) ResponseData {
|
|||
timelineItems = make([]templates.TimelineItem, 0, len(snippets))
|
||||
for _, s := range snippets {
|
||||
timelineItem := SnippetToTimelineItem(&s.Snippet, s.Asset, s.DiscordMessage, s.Projects, s.Owner, false)
|
||||
timelineItem.SmallInfo = true
|
||||
timelineItems = append(timelineItems, timelineItem)
|
||||
}
|
||||
}
|
||||
|
@ -832,7 +829,6 @@ func JamFeed2022(c *RequestContext) ResponseData {
|
|||
timelineItems = make([]templates.TimelineItem, 0, len(snippets))
|
||||
for _, s := range snippets {
|
||||
timelineItem := SnippetToTimelineItem(&s.Snippet, s.Asset, s.DiscordMessage, s.Projects, s.Owner, false)
|
||||
timelineItem.SmallInfo = true
|
||||
timelineItems = append(timelineItems, timelineItem)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@ func Index(c *RequestContext) ResponseData {
|
|||
type LandingTemplateData struct {
|
||||
templates.BaseData
|
||||
|
||||
NewsPost *templates.TimelineItem
|
||||
FollowingItems []templates.TimelineItem
|
||||
FeaturedItems []templates.TimelineItem
|
||||
RecentItems []templates.TimelineItem
|
||||
|
@ -56,6 +55,24 @@ func Index(c *RequestContext) ResponseData {
|
|||
}
|
||||
}
|
||||
|
||||
featuredProjects, err := hmndata.FetchProjects(c, c.Conn, c.CurrentUser, hmndata.ProjectsQuery{
|
||||
FeaturedOnly: true,
|
||||
})
|
||||
if err != nil {
|
||||
c.Logger.Warn().Err(err).Msg("failed to fetch featured projects")
|
||||
}
|
||||
var featuredProjectIDs []int
|
||||
for _, p := range featuredProjects {
|
||||
featuredProjectIDs = append(featuredProjectIDs, p.Project.ID)
|
||||
}
|
||||
featuredItems, err = FetchTimeline(c, c.Conn, c.CurrentUser, TimelineQuery{
|
||||
ProjectIDs: featuredProjectIDs,
|
||||
Limit: 100,
|
||||
})
|
||||
if err != nil {
|
||||
c.Logger.Warn().Err(err).Msg("failed to fetch featured feed")
|
||||
}
|
||||
|
||||
recentItems, err = FetchTimeline(c, c.Conn, c.CurrentUser, TimelineQuery{
|
||||
Limit: 100,
|
||||
})
|
||||
|
@ -63,27 +80,24 @@ func Index(c *RequestContext) ResponseData {
|
|||
c.Logger.Warn().Err(err).Msg("failed to fetch recent feed")
|
||||
}
|
||||
|
||||
c.Perf.StartBlock("SQL", "Get news")
|
||||
newsThreads, err := hmndata.FetchThreads(c, c.Conn, c.CurrentUser, hmndata.ThreadsQuery{
|
||||
ProjectIDs: []int{models.HMNProjectID},
|
||||
ThreadTypes: []models.ThreadType{models.ThreadTypeProjectBlogPost},
|
||||
Limit: 1,
|
||||
ProjectIDs: []int{models.HMNProjectID},
|
||||
ThreadTypes: []models.ThreadType{models.ThreadTypeProjectBlogPost},
|
||||
Limit: 100,
|
||||
OrderByCreated: true,
|
||||
})
|
||||
if err != nil {
|
||||
return c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to fetch news post"))
|
||||
return c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to fetch news threads"))
|
||||
}
|
||||
var newsPostItem *templates.TimelineItem
|
||||
if len(newsThreads) > 0 {
|
||||
t := newsThreads[0]
|
||||
item := PostToTimelineItem(hmndata.UrlContextForProject(&t.Project), lineageBuilder, &t.FirstPost, &t.Thread, t.FirstPostAuthor)
|
||||
for _, t := range newsThreads {
|
||||
item := PostToTimelineItem(c.UrlContext, lineageBuilder, &t.FirstPost, &t.Thread, t.FirstPostAuthor)
|
||||
item.Breadcrumbs = nil
|
||||
item.TypeTitle = ""
|
||||
item.AllowTitleWrap = true
|
||||
item.Description = template.HTML(t.FirstPostCurrentVersion.TextParsed)
|
||||
item.AllowTitleWrap = true
|
||||
item.TruncateDescription = true
|
||||
newsPostItem = &item
|
||||
newsItems = append(newsItems, item)
|
||||
}
|
||||
c.Perf.EndBlock()
|
||||
|
||||
var projects []templates.Project
|
||||
if c.CurrentUser != nil {
|
||||
|
@ -117,7 +131,6 @@ func Index(c *RequestContext) ResponseData {
|
|||
err = res.WriteTemplate("landing.html", LandingTemplateData{
|
||||
BaseData: baseData,
|
||||
|
||||
NewsPost: newsPostItem,
|
||||
FollowingItems: followingItems,
|
||||
FeaturedItems: featuredItems,
|
||||
RecentItems: recentItems,
|
||||
|
|
|
@ -58,7 +58,6 @@ func Snippet(c *RequestContext) ResponseData {
|
|||
|
||||
canEdit := (c.CurrentUser != nil && (c.CurrentUser.IsStaff || c.CurrentUser.ID == s.Owner.ID))
|
||||
snippet := SnippetToTimelineItem(&s.Snippet, s.Asset, s.DiscordMessage, s.Projects, s.Owner, canEdit)
|
||||
snippet.SmallInfo = true
|
||||
|
||||
opengraph := []templates.OpenGraphItem{
|
||||
{Property: "og:site_name", Value: "Handmade Network"},
|
||||
|
@ -68,8 +67,8 @@ func Snippet(c *RequestContext) ResponseData {
|
|||
{Property: "og:description", Value: string(snippet.Description)},
|
||||
}
|
||||
|
||||
if len(snippet.EmbedMedia) > 0 {
|
||||
media := snippet.EmbedMedia[0]
|
||||
if len(snippet.Media) > 0 {
|
||||
media := snippet.Media[0]
|
||||
|
||||
switch media.Type {
|
||||
case templates.TimelineItemMediaTypeImage:
|
||||
|
|
|
@ -148,7 +148,6 @@ func FetchTimeline(ctx context.Context, conn db.ConnOrTx, currentUser *models.Us
|
|||
s.Owner,
|
||||
false,
|
||||
)
|
||||
item.SmallInfo = true
|
||||
timelineItems = append(timelineItems, item)
|
||||
}
|
||||
|
||||
|
@ -300,6 +299,8 @@ func PostToTimelineItem(
|
|||
OwnerAvatarUrl: ownerTmpl.AvatarUrl,
|
||||
OwnerName: ownerTmpl.Name,
|
||||
OwnerUrl: ownerTmpl.ProfileUrl,
|
||||
|
||||
ForumLayout: true,
|
||||
}
|
||||
|
||||
if typeTitles, ok := TimelineTypeTitleMap[post.ThreadType]; ok {
|
||||
|
@ -349,7 +350,7 @@ func TwitchStreamToTimelineItem(
|
|||
OwnerName: ownerName,
|
||||
OwnerUrl: ownerUrl,
|
||||
|
||||
SmallInfo: true,
|
||||
ForumLayout: true,
|
||||
}
|
||||
|
||||
return item
|
||||
|
@ -382,26 +383,26 @@ func SnippetToTimelineItem(
|
|||
|
||||
if asset != nil {
|
||||
if strings.HasPrefix(asset.MimeType, "image/") {
|
||||
item.EmbedMedia = append(item.EmbedMedia, imageMediaItem(asset))
|
||||
item.Media = append(item.Media, imageMediaItem(asset))
|
||||
} else if strings.HasPrefix(asset.MimeType, "video/") {
|
||||
item.EmbedMedia = append(item.EmbedMedia, videoMediaItem(asset))
|
||||
item.Media = append(item.Media, videoMediaItem(asset))
|
||||
} else if strings.HasPrefix(asset.MimeType, "audio/") {
|
||||
item.EmbedMedia = append(item.EmbedMedia, audioMediaItem(asset))
|
||||
item.Media = append(item.Media, audioMediaItem(asset))
|
||||
} else {
|
||||
item.EmbedMedia = append(item.EmbedMedia, unknownMediaItem(asset))
|
||||
item.Media = append(item.Media, unknownMediaItem(asset))
|
||||
}
|
||||
}
|
||||
|
||||
if snippet.Url != nil {
|
||||
url := *snippet.Url
|
||||
if videoId := getYoutubeVideoID(url); videoId != "" {
|
||||
item.EmbedMedia = append(item.EmbedMedia, youtubeMediaItem(videoId))
|
||||
item.Media = append(item.Media, youtubeMediaItem(videoId))
|
||||
item.CanShowcase = false
|
||||
}
|
||||
}
|
||||
|
||||
if len(item.EmbedMedia) == 0 ||
|
||||
(len(item.EmbedMedia) > 0 && (item.EmbedMedia[0].Width == 0 || item.EmbedMedia[0].Height == 0)) {
|
||||
if len(item.Media) == 0 ||
|
||||
(len(item.Media) > 0 && (item.Media[0].Width == 0 || item.Media[0].Height == 0)) {
|
||||
item.CanShowcase = false
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
- [x] column
|
||||
- [ ] content
|
||||
- [ ] description
|
||||
- [ ] c--dim and friends
|
||||
- [ ] Re-evaluate form styles
|
||||
- [ ] theme-color-light is used only for buttons
|
||||
- [x] center-layout vs. margin-center
|
||||
|
@ -55,4 +56,4 @@
|
|||
- TikTok?
|
||||
- Trello?
|
||||
- [ ] Handle empty avatar URLs correctly in various places (render as theme-dependent default)
|
||||
- [ ] Resolve TODO(redesign) comments
|
||||
- [ ] Resolve TODO(redesign) comments
|
Reference in New Issue