diff --git a/.gitignore b/.gitignore index 7d6d019..74a08b5 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ .quartz-cache node_modules public +wip/output \ No newline at end of file diff --git a/content/Biokemi/Behöver göra.md b/content/Biokemi/Behöver göra.md index 4f76b89..29da73a 100644 --- a/content/Biokemi/Behöver göra.md +++ b/content/Biokemi/Behöver göra.md @@ -33,6 +33,6 @@ Finns det värde i att svara alla med AI? - [ ] göra klart introduktion till metabolismen - [ ] glykolysen, lägg till vilka steg som är reversibla - [ ] också vilka steg som producerar ATP+NADPH -- [ ] β-oxidation +- [ ] β-oxidation (men har använt emils) - [ ] glykogen - [ ] ETK diff --git a/wip/script.js b/wip/script.js new file mode 100644 index 0000000..24e8b18 --- /dev/null +++ b/wip/script.js @@ -0,0 +1,73 @@ +MathJax.Hub.Config({ + config: ["MMLorHTML.js"], + jax: ["input/TeX", "output/HTML-CSS", "output/NativeMML"], + extensions: ["MathMenu.js", "MathZoom.js"] +}); + +let indexData = null; + +async function loadIndex() { + if (indexData) return indexData; + const res = await fetch("/index.json"); + indexData = await res.json(); + return indexData; +} + +const templates = { + folder: i => `
  • ${i.key}${i.inner}
  • `, + file: i => `
  • ${i.title}
  • ` +}; + +function renderTree(data) { + const items = Object.entries(data).map(([key, note]) => { + if (key === "children") return null; + if (note.children) return { type: "folder", key, inner: renderTree(note.children) }; + if (note.folder && note.filename) { + const title = note.title || note.filename.replace(/\.md$/, ""); + let href = title + ".html"; + if (note.folder !== ".") href = `${note.folder}/${href}`; + href = "/" + href; + return { type: "file", href, title }; + } + return null; + }).filter((i) => i !== null); + + // Sort: folders first (alphabetically), then files (alphabetically) + // Use natural sorting for numbers (1, 2, 10 instead of 1, 10, 2) + items.sort((a, b) => { + if (a.type !== b.type) return a.type === "folder" ? -1 : 1; + const nameA = (a.type === "folder" ? a.key : a.title); + const nameB = (b.type === "folder" ? b.key : b.title); + return nameA.localeCompare(nameB, undefined, { numeric: true, sensitivity: "base" }); + }); + + return ``; +} + +loadIndex().then(data => { + const sidebar = document.querySelector(".sidebar"); + if (sidebar) { + sidebar.innerHTML = renderTree(data); + + // Find and highlight the current page link + const currentPath = window.location.pathname; + const links = sidebar.querySelectorAll("a"); + for (const link of links) { + const linkPath = new URL(link.href, window.location.origin).pathname; + if (linkPath === currentPath) { + link.classList.add("active"); + + // Expand all parent
    elements + let parent = link.parentElement; + while (parent && parent !== sidebar) { + if (parent.tagName === "DETAILS") { + parent.open = true; + } + parent = parent.parentElement; + } + break; + } + } + } +}); + diff --git a/wip/static.py b/wip/static.py index 9883816..d1a3f5a 100644 --- a/wip/static.py +++ b/wip/static.py @@ -1,16 +1,27 @@ +import argparse +import http.server +import json +import os import pathlib import re - +import shutil import jinja2 + from markdown.core import Markdown from markdown.extensions import Extension from markdown.preprocessors import Preprocessor -from obsidian_parser import Vault +from obsidian_parser import Note, Vault +def out_content(self): + content = self.content + if content.startswith("---\n"): + content = content.split("---\n", 2)[2] + return content +Note.our_content = property(out_content) + root_dir = pathlib.Path(__file__).parent vault = Vault(root_dir.parent / "content") -note = vault.get_note("Biokemi/Cellulära processer/Transport över cellmembran/Anteckningar.md") loader = jinja2.FileSystemLoader(root_dir / "templates") env = jinja2.Environment(loader=loader) @@ -23,9 +34,9 @@ class ObsidianImage(Preprocessor): if m: if "|" in m.group(1): img, width = m.group(1).split("|") - new_lines.append("") + new_lines.append(f"") else: - new_lines.append("") + new_lines.append(f"") else: new_lines.append(line) return new_lines @@ -35,35 +46,145 @@ class ObsidianImageExtension(Extension): def extendMarkdown(self, md): md.preprocessors.register(ObsidianImage(md), 'obsidianimage', 175) -m = Markdown( - extensions=[ - "mdx_math", - "nl2br", - ObsidianImageExtension(), - ], - extension_configs={ - "mdx_math": { - "enable_dollar_delimiter": True - } - }, - tab_length=2, -) -env.filters["markdown"] = m.convert +def make_markdown(): + return Markdown( + extensions=[ + "fenced_code", + "mdx_math", + "nl2br", + "tables", + ObsidianImageExtension(), + ], + extension_configs={ + "mdx_math": { + "enable_dollar_delimiter": True + } + }, + tab_length=2, + ) + +def markdown_filter(text): + md = make_markdown() + return md.convert(text) + +env.filters["markdown"] = markdown_filter -output = root_dir / "test.html" template = env.get_template("base.html") +output_dir = root_dir / "output" -def out_content(self): - content = note.content - if content.startswith("---\n"): - content = content.split("---\n", 2)[2] - return content -note.__class__.our_content = property(out_content) -with output.open("w", encoding="utf-8") as f: - data = template.render(note=note, vault=vault) - f.write(data) +def build_tree(vault: Vault): + root = vault.path + tree = {} + for folder, dirnames, filenames in root.walk(): + for dirname in dirnames[:]: + if dirname.startswith(".") or dirname == "attachments": + dirnames.remove(dirname) + cur = tree + for part in folder.relative_to(root).parts: + cur = cur.setdefault(part, {"children": {}})["children"] -import webbrowser -webbrowser.open(output.as_uri()) -print(f"Written to {output}") \ No newline at end of file + for filename in filenames: + # .DS_Store etc + if filename.startswith("."): + continue + item = { + "filename": filename, + "folder": str(folder.relative_to(root)), + } + note = vault.get_note((folder / filename).relative_to(root)) + if note: + item["title"] = note.title + # TODO: for search add tags, modified time, content etc + + cur[filename] = item + return tree + + +def write_note(item, tree_json): + if "children" in item: + for child in item["children"].values(): + write_note(child, tree_json) + else: + path = pathlib.Path(item["folder"]) / item["filename"] + note = vault.get_note(path) + if note: + out_path = output_dir / item["folder"] / (item["title"] + ".html") + out_path.parent.mkdir(parents=True, exist_ok=True) + + # Calculate relative base_path based on folder depth + folder = item["folder"] + if folder == ".": + base_path = "" + else: + depth = len(pathlib.Path(folder).parts) + base_path = "../" * depth + + with out_path.open("w", encoding="utf-8") as f: + data = template.render(note=note, vault=vault, base_path=base_path, index_json=tree_json) + f.write(data) + else: + print(f"Note not found for {path}") + + +def build(): + """Build the static site.""" + print("Building...") + + # 1. Create output dir + shutil.rmtree(output_dir, ignore_errors=True) + output_dir.mkdir(exist_ok=True) + + # 1b. Symlink CSS/JS to output root + (output_dir / "style.css").symlink_to(root_dir / "style.css") + (output_dir / "script.js").symlink_to(root_dir / "script.js") + + # 1c. Symlink attachments directory + attachments_src = root_dir.parent / "content" / "attachments" + attachments_dst = output_dir / "attachments" + attachments_dst.symlink_to(attachments_src) + + # 2. Build tree and write index json + tree = build_tree(vault) + tree_json = json.dumps(tree) + with (output_dir / "index.json").open("w") as f: + f.write(tree_json) + + # 3. Write out each note as html + write_note({"children": tree}, tree_json) + + print(f"Built to {output_dir}") + + +def serve(port): + """Build and serve the site.""" + build() + + os.chdir(output_dir) + print(f"Serving at http://localhost:{port}") + server = http.server.HTTPServer(("", port), http.server.SimpleHTTPRequestHandler) + try: + server.serve_forever() + except KeyboardInterrupt: + print("\nStopped.") + + +def main(): + parser = argparse.ArgumentParser(description="Static site generator for medical notes") + subparsers = parser.add_subparsers(dest="command", required=True) + + subparsers.add_parser("build", help="Build the static site") + + serve_parser = subparsers.add_parser("serve", help="Build and serve the site") + serve_parser.add_argument("-p", "--port", type=int, default=8000, help="Port to serve on") + + args = parser.parse_args() + + if args.command == "build": + build() + elif args.command == "serve": + serve(args.port) + + +if __name__ == "__main__": + main() diff --git a/wip/style.css b/wip/style.css new file mode 100644 index 0000000..68b76ed --- /dev/null +++ b/wip/style.css @@ -0,0 +1,139 @@ +:root { + color-scheme: light dark; + --font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; + --font-mono: ui-monospace, "SF Mono", Menlo, monospace; + --max-width: 70ch; + --line-height: 1.15; + --space: 1.25rem; + --radius: 6px; + --sidebar-width: 250px; +} +body { + margin: 0; + display: flex; + font-family: var(--font-sans-serif); + line-height: var(--line-height); + font-size: 1rem; +} +.sidebar { + width: var(--sidebar-width); + height: 100vh; + position: sticky; + top: 0; + overflow-y: auto; + padding: var(--space); + box-sizing: border-box; +} +.sidebar ul { list-style: none; padding: 0; margin: 0; } +.sidebar details ul { padding-left: 1rem; } +.sidebar li { margin: 0.2rem 0; } +.sidebar a { text-decoration: none; } +.sidebar a.active { font-weight: 600; } +.sidebar details { margin: 0.2rem 0; } +.sidebar summary { cursor: pointer; } +.content { + flex: 1; + max-width: var(--max-width); + padding: calc(var(--space) * 1.2); +} + +@media (prefers-color-scheme: light) { + body { background: #fafafa; color: #222; } + .sidebar { background: #f0f0f0; } + a { color: #0645ad; } + code, pre { background: #f0f0f0; } + hr { border-color: #ddd; } +} +@media (prefers-color-scheme: dark) { + body { background: #111; color: #ddd; } + .sidebar { background: #1a1a1a; } + a { color: #7bbaff; } + code, pre { background: #222; } + hr { border-color: #333; } +} + +p, ul, ol, blockquote, pre, table { + margin: var(--space) 0; +} + +h1, h2, h3, h4, h5, h6 { + line-height: 1.25; + margin: calc(var(--space) * 1.6) 0 var(--space); + font-weight: 600; +} + +h1 { + font-size: 1.8rem; +} + +h2 { + font-size: 1.45rem; +} + +h3 { + font-size: 1.25rem; +} + +h4 { + font-size: 1.1rem; +} + +h5, h6 { + font-size: 1rem; +} + +ul, ol { + padding-inline-start: 1.4rem; + margin-block-start: var(--space); +} + +li { + margin: 0.3rem 0; +} + +code, pre { + font-family: var(--font-mono) monospace; + font-size: 0.9rem; + border-radius: var(--radius); +} + +pre { + padding: 0.75rem 1rem; + overflow-x: auto; +} + +table { + width: 100%; + border-collapse: collapse; + font-size: 0.95rem; +} + +th, td { + padding: 0.5rem 0.75rem; + border: 1px solid currentcolor; +} + +th { + font-weight: 600; +} + +blockquote { + padding: 0.75rem 1rem; + border-inline-start: 4px solid currentcolor; + opacity: 0.9; +} + +img, video { + max-width: 100%; + height: auto; + display: block; + border-radius: var(--radius); + margin: var(--space) 0; +} + +hr { + margin: calc(var(--space) * 2) 0; + border: none; + border-bottom: 1px solid; + opacity: 0.2; +} diff --git a/wip/templates/base.html b/wip/templates/base.html index d1d6065..1ffc3cb 100644 --- a/wip/templates/base.html +++ b/wip/templates/base.html @@ -1,175 +1,14 @@ - + + {{note.title}} - - + + +

    {{note.title}}

    {{note.our_content | markdown}} +
    + \ No newline at end of file diff --git a/wip/test.html b/wip/test.html deleted file mode 100644 index 5754c06..0000000 --- a/wip/test.html +++ /dev/null @@ -1,495 +0,0 @@ - - - - - Anteckningar - - - - -

    Anteckningar

    - -

    Diffusion är något INTE behöver hjälp
    -Passiv vs Aktiv transport
    -Faciliterad diffusion

    -

    plasmamembransystem

    - -
    -

    Diffusion över membran

    -

    Vad är lättast att diffunder?

    - -
    -

    Glukostransportörer faciliterar diffusion
    -
    -Även kallade bärarproteiner

    -

    Passiv transport

    -

    med gradienten - Man behöver inte tillföra energi, använder energin som tillför gradienten

    -

    Transportörer/Bärarproteiner

    - -

    GLUT1-5 har olika affinitet för glukos
    -Varje transportör kan ta ungefär ~1000 molekyler per sekund
    -Högre i blodet och ECM, transport av glukos sker oftast inåt i cellen
    -Hastigheten beror på
    -- antal transportprotein
    -- hur hög koncentration

    -

    - -
    -C1 = till
    -C2 = från

    -

    Q: Behöver vi kunna formeln. Svaret är att vi inte behöver en miniräknare på tentan.

    -

    Diffusion av -

    -

    Fysiologiskt salt ~150mM = isotonisk
    -- Det är så mkt joner vi har i miljön runt om och i våra celler
    -- Har man exakt händer ingenting
    -- Har man mer eller mindre så händer osmos
    -- hypertonisk, högre saltkoncentration
    - - då kommer vatten gå ut ur cellen för att xxx koncentrationsgradienten
    - - Då får vi en cell som krymper
    -- hypotonisk, lägre saltkoncentration
    - - då försöker vattnet att ta sig in
    - - då sväller cellen
    - - när det kommer in för mycket vatten så går den sönder, då säger den lysering
    - - man kan använda saltlösning för att få ut innehållet i en cell
    - - sen centrifugerar man så man får ut sina mitokondrier
    -- osmos = strävar mot utjämning av koncentrationsgradienten

    -
    -

    Diffusion av vatten faciliteras av aquaporiner

    -

    Aquaporiner

    - -

    Jonkanalerna

    - -
    -

    Transporthastigheten genom jonkanaler styrs av skillnader i koncentrations- och elektriska gradienter

    -

    Beroende av andra joner
    - -

    -

    R: gaskonstanten = 8.314 J·mol⁻¹·K⁻¹
    -T: absoluta temperaturen i Kelvin (t.ex. 310 K för 37°C)
    -C₂: koncentration utanför cellen
    -C₁: koncentration innanför cellen
    -Z: jonens laddning (t.ex. Na⁺ = +1, Ca²⁺ = +2, Cl⁻ = –1)
    -F: Faradays konstant (≈ 96 485 C/mol), laddning per mol elektroner
    -ΔV: skillnaden i membranpotential (V₂ – V₁), mäts i volt

    -
    -

    Hur skulle en jonkanal vara uppbyggd?

    - -
    -

    Uppbyggnaden av katjonkanaler är konserverad

    -


    -- central por av helix S5 och S6
    -- S1-4 bildar paddel utanför por

    -

    S4 positivt laddad, känner av ändring i membranpotential
    -padel fälls upp vid aktivering

    -
    -

    --kanalen passar perfekt om dehydratisering sker

    -

    Selektivitetsfilter K+-kanalen
    -Det känner igen storlek, konkurrerar mot Na och Ka.
    - 0.95 Å
    - 1.33 Å

    -

    För att passa den här kanalen som är 3 Å,
    -Dehydratiseras, bort med vatten
    -Binder till röda grupper som är karbonylgrupper
    -Dehydratisering av ger lika många bindingar i filtret som till -
    -1000 gr höre selektivitet för än -

    -

    Kostar energi att föra igenom Na+, då blir det inte effektivt
    -Transport via repulsion i fyra bindingsställning (skjutsa vidare)

    -

    Na⁺ är mindre → har mycket högre laddningstäthet → binder vatten hårdare. Att ta bort vatten kostar därför mer energi för Na⁺ än för K⁺.

    -

    Varför kan K⁺ passera utan kostnad?
    -Selektivitetsfiltret är byggt exakt för K⁺-storlek: karbonylgrupperna sitter så att de ersätter precis de vattenbindningar K⁺ förlorar. Energin blir nästan neutral.

    -
    -

    Jonkanal stängs snabbt efter att ha öppnats

    -

    Bolldomän i cytoplasman med en länk med ett bindningsställe i den aktiverade, öppna kanalen den kan binda in till
    -- I öppen kanal blir bindningen→inaktiverad
    -- States
    - - Closed hänger och slänger
    - - Open precis utanför
    - - Inactivated inne i hållet

    -

    Kanalen stängs efter ms efter aktivering

    -

    Acetylkolinreceptorn är en receptor för ormgift
    -Alkaliner, cuarve, hämar transport av jonkanaler

    -

    kanaler och transportförer har olika mekanismer för att öppna och stänga

    -
    -

    Kanalfogar

    -

    (gap junctions)

    -

    Möliggör snabb transport mellan celler
    -Förbinder cytoplasman
    -Uppbyggda av konnexinringar
    -Fri passage för små hydrofila molekyler/joner < kDa

    -

    Näringsöverföring: lins & ben
    -Synkronisering:
    -- finns mkt i hjärtat så allt drar åt sig samtidigt
    -- livmoder för forlossning, för sammandrarning
    -- stängs av går upp eller -

    -
    -

    Aktiv transport

    -

    mot gradient
    -kräver energitillsförsel

    -

    Det finns jongradienter i däggdjursceller
    -- Na+ lågt i högt utanför
    -- K högt inne, lågt utanför
    -- Cl lågt inne, högt utanför

    -

    Na+–K+ ATPaset, en jonpump

    -

    1/3 av all energi i alla celler används till det här
    -(mer i vissa celler än andra)

    - -
    -

    Kardiotona steoider hämmar Na+-K+ ATPaset

    -

    Används som läkemedel för personer som har hjärtsvikt, leder till starkar kontraktioner av hjärtmuskler
    -Läkemedel heter Digitoxin, Onabain som man kan plocka från växter

    -

    Behöver veta vad det här proteinet gör

    -
    -

    ABC-transportörer ändrar konformation när de binder och hydrolyserar ATP

    -

    ATP-bindande kasett
    -Kräver två ATP per transportcykel
    -Används för att transportera ut socker i eukaryota (i prokaryoter in)
    -1. Substrat binder från cytoplasman
    -2. Konformationsändring - ökad affinitet för ATP
    -3. ATP binder - eversion (vänder)
    -4. Substrat frisläpps ECM
    -5. Defosfylering 2 ATP → 2 ADP, konformationsändring, eversion

    -

    Ställer till besvär inom medicinen, skickar in hydrofoba föreningar. Många läkemedel är hydrofoba. Men sådana här proteiner finns det som inducerar läkemedel, multidrog-resistans, när de fått en så skickar de ut. Men de skickar ut andra läkemedel också

    -

    MDR-multidrogresistens

    - -
    -

    Tre grupper av membrantransportör

    -

    Kan vara både passiva och transporta

    - -
    -

    Glukos kan tas upp mot koncentrationsgradient med sekundär aktiv transport Glukosupptag

    -
    -

    Glukosupptag från tarmarna involverar transportörer av olika typer Begrepp

    -

    I samma cell kan man ha olika typer av transport av samma typ av

    -

    Summary

    -

    transportör med gradient
    -hyperton mer joner, ut vatten
    -hypoton mindre joner, in vatten
    -aquaporiner släpper bara igenom vatten
    -jonkanaler behöver aktiveras 3 st (ligand, potential, mekaniska dragningar)
    -primärt om ATP är med i reaktionen
    -sekundär om ATP hjälpt till att bygga upp gradienten
    -kanalfogar binder ihop små celler, t.ex. näring i benceller
    -Jongradienter Na/Kalium mkt inne/ut på av ATPaset-pump
    -ABC kräver 2 ATP fosfo+defosfo
    -MDR inblandat i pumpar

    - - \ No newline at end of file