inject sakura css into cached html
This commit is contained in:
@@ -12,8 +12,6 @@ import { FormField } from "~/components/form-field"
|
||||
import { LoadingSpinner } from "~/components/loading-spinner"
|
||||
import { useMnemonics } from "~/hooks/use-mnemonics"
|
||||
import { useLogOut } from "~/auth"
|
||||
import sakuraCssSrc from "~/reader-styles/sakura.css?url"
|
||||
import sakuraDarkCssSrc from "~/reader-styles/sakura-dark.css?url"
|
||||
|
||||
const LAYOUT_MODE = {
|
||||
popup: "popup",
|
||||
@@ -153,8 +151,8 @@ function Main({ children }: React.PropsWithChildren) {
|
||||
return (
|
||||
<main
|
||||
className={clsx(
|
||||
"grid flex justify-center relative w-full",
|
||||
isPreviewOpened && layoutMode === LAYOUT_MODE.sideBySide ? "grid-cols-3" : "grid-cols-1",
|
||||
"relative w-full",
|
||||
isPreviewOpened && layoutMode === LAYOUT_MODE.sideBySide ? "grid grid-cols-3" : "flex justify-center",
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
@@ -166,7 +164,12 @@ function BookmarkListPane() {
|
||||
const isBookmarkPreviewOpened = useBookmarkPageStore((state) => state.isBookmarkPreviewOpened)
|
||||
|
||||
return (
|
||||
<div className={clsx("flex flex-col py-16", { "md:flex-row lg:py-32 justify-center ": !isBookmarkPreviewOpened })}>
|
||||
<div
|
||||
className={clsx(
|
||||
"flex flex-col py-16",
|
||||
isBookmarkPreviewOpened ? "w-full" : "container max-w-3xl md:flex-row lg:py-32",
|
||||
)}
|
||||
>
|
||||
<header className="mb-4 md:mb-0 md:mr-16 text-start">
|
||||
<h1 className={clsx("font-bold text-start", { "mb-4": isBookmarkPreviewOpened })}>
|
||||
<span
|
||||
@@ -179,7 +182,9 @@ function BookmarkListPane() {
|
||||
YOUR BOOKMARKS
|
||||
</h1>
|
||||
</header>
|
||||
<BookmarkListSection />
|
||||
<div className="flex-1">
|
||||
<BookmarkListSection />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -393,7 +398,7 @@ function BookmarkListSection() {
|
||||
switch (status) {
|
||||
case "pending":
|
||||
return (
|
||||
<p className="container max-w-2xl">
|
||||
<p>
|
||||
Loading
|
||||
<LoadingSpinner />
|
||||
</p>
|
||||
@@ -468,7 +473,7 @@ function BookmarkList({ bookmarks }: { bookmarks: LinkBookmark[] }) {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-col container max-w-2xl -mt-2">
|
||||
<div className="flex flex-col -mt-2">
|
||||
{bookmarks.length === 0 ? (
|
||||
<p className="mt-2">You have not saved any bookmark!</p>
|
||||
) : (
|
||||
@@ -495,15 +500,15 @@ function BookmarkPreview() {
|
||||
},
|
||||
)}
|
||||
>
|
||||
<BookmarkPreviewFrame />
|
||||
<BookmarkPreviewContent />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function BookmarkPreviewFrame() {
|
||||
function BookmarkPreviewContent() {
|
||||
const selectedBookmarkId = useBookmarkPageStore((state) => state.selectedBookmarkId)
|
||||
const actionBarHeight = useBookmarkPageStore((state) => state.actionBarHeight)
|
||||
const { data, status } = useAuthenticatedQuery(["bookmarks", selectedBookmarkId], () =>
|
||||
const { data, status } = useAuthenticatedQuery(["bookmarks", `${selectedBookmarkId}.html`], () =>
|
||||
fetchApi(`/bookmark/${selectedBookmarkId}`, {
|
||||
headers: {
|
||||
Accept: "text/html",
|
||||
@@ -511,23 +516,6 @@ function BookmarkPreviewFrame() {
|
||||
}).then((res) => res.text()),
|
||||
)
|
||||
|
||||
function injectCss(event: React.SyntheticEvent<HTMLIFrameElement, Element>) {
|
||||
const lightCssLink = document.createElement("link")
|
||||
lightCssLink.rel = "stylesheet"
|
||||
lightCssLink.href = sakuraCssSrc
|
||||
lightCssLink.media = "screen"
|
||||
|
||||
const darkCssLink = document.createElement("link")
|
||||
darkCssLink.rel = "stylesheet"
|
||||
darkCssLink.href = sakuraDarkCssSrc
|
||||
darkCssLink.media = "screen and (prefers-color-scheme: dark)"
|
||||
|
||||
if (event.currentTarget.contentDocument) {
|
||||
event.currentTarget.contentDocument.head.appendChild(lightCssLink)
|
||||
event.currentTarget.contentDocument.head.appendChild(darkCssLink)
|
||||
}
|
||||
}
|
||||
|
||||
switch (status) {
|
||||
case "pending":
|
||||
return (
|
||||
@@ -537,7 +525,13 @@ function BookmarkPreviewFrame() {
|
||||
)
|
||||
case "success":
|
||||
return (
|
||||
<iframe className="w-full h-full" style={{ paddingBottom: actionBarHeight }} srcDoc={data} onLoad={injectCss} />
|
||||
<iframe
|
||||
key="preview-iframe"
|
||||
title="asd"
|
||||
className={clsx("w-full h-full")}
|
||||
style={{ paddingBottom: actionBarHeight }}
|
||||
srcDoc={data}
|
||||
/>
|
||||
)
|
||||
|
||||
default:
|
||||
|
36
packages/web/src/hooks/use-color-scheme.ts
Normal file
36
packages/web/src/hooks/use-color-scheme.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { useEffect, useState } from "react"
|
||||
|
||||
enum ColorScheme {
|
||||
Light = "Light",
|
||||
Dark = "Dark",
|
||||
}
|
||||
|
||||
const initialColorScheme = window.matchMedia?.("(prefers-color-scheme: dark)").matches
|
||||
? ColorScheme.Dark
|
||||
: ColorScheme.Light
|
||||
|
||||
function useColorScheme() {
|
||||
const [colorScheme, setColorScheme] = useState(initialColorScheme)
|
||||
|
||||
useEffect(() => {
|
||||
if (!window.matchMedia) {
|
||||
return
|
||||
}
|
||||
|
||||
function onMediaChange(this: MediaQueryList) {
|
||||
setColorScheme(this.matches ? ColorScheme.Dark : ColorScheme.Light)
|
||||
}
|
||||
|
||||
const l = window.matchMedia("(prefers-color-scheme: dark)")
|
||||
onMediaChange.call(l)
|
||||
l.addEventListener("change", onMediaChange)
|
||||
|
||||
return () => {
|
||||
l.removeEventListener("change", onMediaChange)
|
||||
}
|
||||
}, [])
|
||||
|
||||
return colorScheme
|
||||
}
|
||||
|
||||
export { ColorScheme, useColorScheme }
|
@@ -1,4 +1,5 @@
|
||||
@import "tailwindcss";
|
||||
@plugin "@tailwindcss/typography";
|
||||
|
||||
:root {
|
||||
font-family: monospace;
|
||||
|
@@ -1,268 +0,0 @@
|
||||
/* $color-text: #dedce5; */
|
||||
/* Sakura.css v1.5.0
|
||||
* ================
|
||||
* Minimal css theme.
|
||||
* Project: https://github.com/oxalorg/sakura/
|
||||
*/
|
||||
/* Body */
|
||||
html {
|
||||
font-size: 62.5%;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
||||
"Helvetica Neue", Arial, "Noto Sans", sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
font-size: 1.8rem;
|
||||
line-height: 1.618;
|
||||
max-width: 38em;
|
||||
margin: auto;
|
||||
color: #c9c9c9;
|
||||
background-color: #222222;
|
||||
padding: 13px;
|
||||
}
|
||||
|
||||
@media (max-width: 684px) {
|
||||
body {
|
||||
font-size: 1.53rem;
|
||||
}
|
||||
}
|
||||
@media (max-width: 382px) {
|
||||
body {
|
||||
font-size: 1.35rem;
|
||||
}
|
||||
}
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
line-height: 1.1;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
||||
"Helvetica Neue", Arial, "Noto Sans", sans-serif;
|
||||
font-weight: 700;
|
||||
margin-top: 3rem;
|
||||
margin-bottom: 1.5rem;
|
||||
overflow-wrap: break-word;
|
||||
word-wrap: break-word;
|
||||
-ms-word-break: break-all;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2.35em;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.75em;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 1.25em;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0px;
|
||||
margin-bottom: 2.5rem;
|
||||
}
|
||||
|
||||
small,
|
||||
sub,
|
||||
sup {
|
||||
font-size: 75%;
|
||||
}
|
||||
|
||||
hr {
|
||||
border-color: #ffffff;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: #ffffff;
|
||||
}
|
||||
a:visited {
|
||||
color: #e6e6e6;
|
||||
}
|
||||
a:hover {
|
||||
color: #c9c9c9;
|
||||
border-bottom: 2px solid #c9c9c9;
|
||||
}
|
||||
|
||||
ul {
|
||||
padding-left: 1.4em;
|
||||
margin-top: 0px;
|
||||
margin-bottom: 2.5rem;
|
||||
}
|
||||
|
||||
li {
|
||||
margin-bottom: 0.4em;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin-left: 0px;
|
||||
margin-right: 0px;
|
||||
padding-left: 1em;
|
||||
padding-top: 0.8em;
|
||||
padding-bottom: 0.8em;
|
||||
padding-right: 0.8em;
|
||||
border-left: 5px solid #ffffff;
|
||||
margin-bottom: 2.5rem;
|
||||
background-color: #4a4a4a;
|
||||
}
|
||||
|
||||
blockquote p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
img,
|
||||
video {
|
||||
height: auto;
|
||||
max-width: 100%;
|
||||
margin-top: 0px;
|
||||
margin-bottom: 2.5rem;
|
||||
}
|
||||
|
||||
/* Pre and Code */
|
||||
pre {
|
||||
background-color: #4a4a4a;
|
||||
display: block;
|
||||
padding: 1em;
|
||||
overflow-x: auto;
|
||||
margin-top: 0px;
|
||||
margin-bottom: 2.5rem;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-size: 0.9em;
|
||||
padding: 0 0.5em;
|
||||
background-color: #4a4a4a;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
pre > code {
|
||||
padding: 0;
|
||||
background-color: transparent;
|
||||
white-space: pre;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
/* Tables */
|
||||
table {
|
||||
text-align: justify;
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
td,
|
||||
th {
|
||||
padding: 0.5em;
|
||||
border-bottom: 1px solid #4a4a4a;
|
||||
}
|
||||
|
||||
/* Buttons, forms and input */
|
||||
input,
|
||||
textarea {
|
||||
border: 1px solid #c9c9c9;
|
||||
}
|
||||
input:focus,
|
||||
textarea:focus {
|
||||
border: 1px solid #ffffff;
|
||||
}
|
||||
|
||||
textarea {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.button,
|
||||
button,
|
||||
input[type="submit"],
|
||||
input[type="reset"],
|
||||
input[type="button"],
|
||||
input[type="file"]::file-selector-button {
|
||||
display: inline-block;
|
||||
padding: 5px 10px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
background-color: #ffffff;
|
||||
color: #222222;
|
||||
border-radius: 1px;
|
||||
border: 1px solid #ffffff;
|
||||
cursor: pointer;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.button[disabled],
|
||||
button[disabled],
|
||||
input[type="submit"][disabled],
|
||||
input[type="reset"][disabled],
|
||||
input[type="button"][disabled],
|
||||
input[type="file"]::file-selector-button[disabled] {
|
||||
cursor: default;
|
||||
opacity: 0.5;
|
||||
}
|
||||
.button:hover,
|
||||
button:hover,
|
||||
input[type="submit"]:hover,
|
||||
input[type="reset"]:hover,
|
||||
input[type="button"]:hover,
|
||||
input[type="file"]::file-selector-button:hover {
|
||||
background-color: #c9c9c9;
|
||||
color: #222222;
|
||||
outline: 0;
|
||||
}
|
||||
.button:focus-visible,
|
||||
button:focus-visible,
|
||||
input[type="submit"]:focus-visible,
|
||||
input[type="reset"]:focus-visible,
|
||||
input[type="button"]:focus-visible,
|
||||
input[type="file"]::file-selector-button:focus-visible {
|
||||
outline-style: solid;
|
||||
outline-width: 2px;
|
||||
}
|
||||
|
||||
textarea,
|
||||
select,
|
||||
input {
|
||||
color: #c9c9c9;
|
||||
padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */
|
||||
margin-bottom: 10px;
|
||||
background-color: #4a4a4a;
|
||||
border: 1px solid #4a4a4a;
|
||||
border-radius: 4px;
|
||||
box-shadow: none;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
textarea:focus,
|
||||
select:focus,
|
||||
input:focus {
|
||||
border: 1px solid #ffffff;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
input[type="checkbox"]:focus {
|
||||
outline: 1px dotted #ffffff;
|
||||
}
|
||||
|
||||
label,
|
||||
legend,
|
||||
fieldset {
|
||||
display: block;
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: 600;
|
||||
}
|
@@ -1,269 +0,0 @@
|
||||
/* Sakura.css v1.5.0
|
||||
* ================
|
||||
* Minimal css theme.
|
||||
* Project: https://github.com/oxalorg/sakura/
|
||||
*/
|
||||
/* Body */
|
||||
html {
|
||||
font-size: 62.5%;
|
||||
font-family:
|
||||
-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue",
|
||||
Arial, "Noto Sans", sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
font-size: 1.8rem;
|
||||
line-height: 1.618;
|
||||
max-width: 38em;
|
||||
margin: auto;
|
||||
color: #4a4a4a;
|
||||
background-color: #f9f9f9;
|
||||
padding: 13px;
|
||||
}
|
||||
|
||||
@media (max-width: 684px) {
|
||||
body {
|
||||
font-size: 1.53rem;
|
||||
}
|
||||
}
|
||||
@media (max-width: 382px) {
|
||||
body {
|
||||
font-size: 1.35rem;
|
||||
}
|
||||
}
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
line-height: 1.1;
|
||||
font-family:
|
||||
-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue",
|
||||
Arial, "Noto Sans", sans-serif;
|
||||
font-weight: 700;
|
||||
margin-top: 3rem;
|
||||
margin-bottom: 1.5rem;
|
||||
overflow-wrap: break-word;
|
||||
word-wrap: break-word;
|
||||
-ms-word-break: break-all;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2.35em;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.75em;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 1.25em;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0px;
|
||||
margin-bottom: 2.5rem;
|
||||
}
|
||||
|
||||
small,
|
||||
sub,
|
||||
sup {
|
||||
font-size: 75%;
|
||||
}
|
||||
|
||||
hr {
|
||||
border-color: #1d7484;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: #1d7484;
|
||||
}
|
||||
a:visited {
|
||||
color: #144f5a;
|
||||
}
|
||||
a:hover {
|
||||
color: #982c61;
|
||||
border-bottom: 2px solid #4a4a4a;
|
||||
}
|
||||
|
||||
ul {
|
||||
padding-left: 1.4em;
|
||||
margin-top: 0px;
|
||||
margin-bottom: 2.5rem;
|
||||
}
|
||||
|
||||
li {
|
||||
margin-bottom: 0.4em;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin-left: 0px;
|
||||
margin-right: 0px;
|
||||
padding-left: 1em;
|
||||
padding-top: 0.8em;
|
||||
padding-bottom: 0.8em;
|
||||
padding-right: 0.8em;
|
||||
border-left: 5px solid #1d7484;
|
||||
margin-bottom: 2.5rem;
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
|
||||
blockquote p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
img,
|
||||
video {
|
||||
height: auto;
|
||||
max-width: 100%;
|
||||
margin-top: 0px;
|
||||
margin-bottom: 2.5rem;
|
||||
}
|
||||
|
||||
/* Pre and Code */
|
||||
pre {
|
||||
background-color: #f1f1f1;
|
||||
display: block;
|
||||
padding: 1em;
|
||||
overflow-x: auto;
|
||||
margin-top: 0px;
|
||||
margin-bottom: 2.5rem;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-size: 0.9em;
|
||||
padding: 0 0.5em;
|
||||
background-color: #f1f1f1;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
pre > code {
|
||||
padding: 0;
|
||||
background-color: transparent;
|
||||
white-space: pre;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
/* Tables */
|
||||
table {
|
||||
text-align: justify;
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
td,
|
||||
th {
|
||||
padding: 0.5em;
|
||||
border-bottom: 1px solid #f1f1f1;
|
||||
}
|
||||
|
||||
/* Buttons, forms and input */
|
||||
input,
|
||||
textarea {
|
||||
border: 1px solid #4a4a4a;
|
||||
}
|
||||
input:focus,
|
||||
textarea:focus {
|
||||
border: 1px solid #1d7484;
|
||||
}
|
||||
|
||||
textarea {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.button,
|
||||
button,
|
||||
input[type="submit"],
|
||||
input[type="reset"],
|
||||
input[type="button"],
|
||||
input[type="file"]::file-selector-button {
|
||||
display: inline-block;
|
||||
padding: 5px 10px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
background-color: #1d7484;
|
||||
color: #f9f9f9;
|
||||
border-radius: 1px;
|
||||
border: 1px solid #1d7484;
|
||||
cursor: pointer;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.button[disabled],
|
||||
button[disabled],
|
||||
input[type="submit"][disabled],
|
||||
input[type="reset"][disabled],
|
||||
input[type="button"][disabled],
|
||||
input[type="file"]::file-selector-button[disabled] {
|
||||
cursor: default;
|
||||
opacity: 0.5;
|
||||
}
|
||||
.button:hover,
|
||||
button:hover,
|
||||
input[type="submit"]:hover,
|
||||
input[type="reset"]:hover,
|
||||
input[type="button"]:hover,
|
||||
input[type="file"]::file-selector-button:hover {
|
||||
background-color: #982c61;
|
||||
color: #f9f9f9;
|
||||
outline: 0;
|
||||
}
|
||||
.button:focus-visible,
|
||||
button:focus-visible,
|
||||
input[type="submit"]:focus-visible,
|
||||
input[type="reset"]:focus-visible,
|
||||
input[type="button"]:focus-visible,
|
||||
input[type="file"]::file-selector-button:focus-visible {
|
||||
outline-style: solid;
|
||||
outline-width: 2px;
|
||||
}
|
||||
|
||||
textarea,
|
||||
select,
|
||||
input {
|
||||
color: #4a4a4a;
|
||||
padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */
|
||||
margin-bottom: 10px;
|
||||
background-color: #f1f1f1;
|
||||
border: 1px solid #f1f1f1;
|
||||
border-radius: 4px;
|
||||
box-shadow: none;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
textarea:focus,
|
||||
select:focus,
|
||||
input:focus {
|
||||
border: 1px solid #1d7484;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
input[type="checkbox"]:focus {
|
||||
outline: 1px dotted #1d7484;
|
||||
}
|
||||
|
||||
label,
|
||||
legend,
|
||||
fieldset {
|
||||
display: block;
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: 600;
|
||||
}
|
Reference in New Issue
Block a user