34 Commits
v1.0.0 ... main

Author SHA1 Message Date
17145628a0 fix orientation of images
All checks were successful
Datadog Software Composition Analysis / Datadog SBOM Generation and Upload (push) Successful in 56s
Datadog Secrets Scanning / Datadog Static Analyzer (push) Successful in 57s
Release / build (push) Successful in 1m46s
Release / publish_head (push) Successful in 1m18s
Datadog Static Analysis / Datadog Static Analyzer (push) Successful in 3m42s
2025-07-06 22:27:33 -04:00
195c353710 Merge branch 'main' of https://git.dws.rip/dubey/foldsite 2025-07-06 22:20:23 -04:00
8c23e9d811 Update main.py
All checks were successful
Datadog Software Composition Analysis / Datadog SBOM Generation and Upload (push) Successful in 50s
Datadog Secrets Scanning / Datadog Static Analyzer (push) Successful in 56s
Release / build (push) Successful in 1m21s
Release / publish_head (push) Successful in 1m17s
Datadog Static Analysis / Datadog Static Analyzer (push) Successful in 3m40s
2025-07-06 22:10:51 -04:00
5a56496538 Update src/rendering/image.py
All checks were successful
Datadog Software Composition Analysis / Datadog SBOM Generation and Upload (push) Successful in 52s
Datadog Secrets Scanning / Datadog Static Analyzer (push) Successful in 1m0s
Release / build (push) Successful in 1m22s
Release / publish_head (push) Successful in 1m17s
Datadog Static Analysis / Datadog Static Analyzer (push) Successful in 3m44s
2025-07-06 21:54:59 -04:00
9c06401557 up to 8 cores
All checks were successful
Datadog Software Composition Analysis / Datadog SBOM Generation and Upload (push) Successful in 50s
Release / build (push) Successful in 2m51s
Datadog Secrets Scanning / Datadog Static Analyzer (push) Successful in 47s
Release / publish_head (push) Successful in 2m29s
Datadog Static Analysis / Datadog Static Analyzer (push) Successful in 3m32s
2025-07-02 15:54:23 -04:00
9b1b84e5be CI Bump
All checks were successful
Datadog Secrets Scanning / Datadog Static Analyzer (push) Successful in 2m23s
Release / build (push) Successful in 2m59s
Datadog Software Composition Analysis / Datadog SBOM Generation and Upload (push) Successful in 3m40s
Datadog Static Analysis / Datadog Static Analyzer (push) Successful in 4m56s
Release / publish_head (push) Successful in 2m40s
2025-07-02 15:33:29 -04:00
23cc4c3876 Small cleanups 2025-04-24 17:58:36 -04:00
9e62a84843 no check for line
All checks were successful
Datadog Software Composition Analysis / Datadog SBOM Generation and Upload (push) Successful in 50s
Datadog Secrets Scanning / Datadog Static Analyzer (push) Successful in 1m5s
Release / build (push) Successful in 2m36s
Release / publish_head (push) Successful in 2m18s
Datadog Static Analysis / Datadog Static Analyzer (push) Successful in 3m17s
2025-04-10 12:08:45 -04:00
dda3be0101 Update README.md
All checks were successful
Datadog Software Composition Analysis / Datadog SBOM Generation and Upload (push) Successful in 43s
Datadog Secrets Scanning / Datadog Static Analyzer (push) Successful in 58s
Release / build (push) Successful in 1m31s
Release / publish_head (push) Successful in 1m27s
Datadog Static Analysis / Datadog Static Analyzer (push) Successful in 3m11s
2025-03-25 05:06:12 -04:00
3fd24c75fc Update README.md
All checks were successful
Datadog Software Composition Analysis / Datadog SBOM Generation and Upload (push) Successful in 44s
Release / build (push) Successful in 1m35s
Datadog Secrets Scanning / Datadog Static Analyzer (push) Successful in 2m1s
Release / publish_head (push) Successful in 1m29s
Datadog Static Analysis / Datadog Static Analyzer (push) Successful in 4m13s
2025-03-25 05:00:11 -04:00
07bb33006e Update main.py
All checks were successful
Datadog Software Composition Analysis / Datadog SBOM Generation and Upload (push) Successful in 14s
Datadog Secrets Scanning / Datadog Static Analyzer (push) Successful in 17s
Release / build (push) Successful in 39s
Release / publish_head (push) Successful in 36s
Datadog Static Analysis / Datadog Static Analyzer (push) Successful in 1m18s
2025-03-21 14:01:34 -04:00
aab53f1e54 Update .gitea/workflows/datadog-static-analysis.yml
All checks were successful
Datadog Software Composition Analysis / Datadog SBOM Generation and Upload (push) Successful in 15s
Datadog Secrets Scanning / Datadog Static Analyzer (push) Successful in 18s
Release / build (push) Successful in 34s
Release / publish_head (push) Successful in 34s
Datadog Static Analysis / Datadog Static Analyzer (push) Successful in 1m10s
2025-03-21 12:56:49 -04:00
0e6ca5859a Update .gitea/workflows/datadog-static-analysis.yml
Some checks failed
Datadog Software Composition Analysis / Datadog SBOM Generation and Upload (push) Successful in 15s
Datadog Secrets Scanning / Datadog Static Analyzer (push) Successful in 15s
Datadog Static Analysis / Datadog Static Analyzer (push) Failing after 1m8s
Release / publish_head (push) Successful in 1m15s
Release / build (push) Successful in 1m33s
2025-03-21 12:53:30 -04:00
7986ad2f88 Update .gitea/workflows/datadog-static-analysis.yml
Some checks failed
Datadog Software Composition Analysis / Datadog SBOM Generation and Upload (push) Successful in 21s
Datadog Secrets Scanning / Datadog Static Analyzer (push) Successful in 23s
Datadog Static Analysis / Datadog Static Analyzer (push) Failing after 1m20s
Release / publish_head (push) Successful in 1m19s
Release / build (push) Successful in 1m41s
2025-03-21 12:46:06 -04:00
7c4c20b3ce Update .gitea/workflows/datadog-static-analysis.yml
Some checks failed
Datadog Software Composition Analysis / Datadog SBOM Generation and Upload (push) Successful in 16s
Datadog Secrets Scanning / Datadog Static Analyzer (push) Successful in 17s
Release / build (push) Successful in 40s
Datadog Static Analysis / Datadog Static Analyzer (push) Failing after 1m8s
Release / publish_head (push) Successful in 33s
2025-03-21 12:41:14 -04:00
b407497713 nvm save me!
Some checks failed
Datadog Secrets Scanning / Datadog Static Analyzer (push) Successful in 15s
Datadog Software Composition Analysis / Datadog SBOM Generation and Upload (push) Successful in 16s
Release / build (push) Successful in 37s
Datadog Static Analysis / Datadog Static Analyzer (push) Failing after 58s
Release / publish_head (push) Successful in 35s
2025-03-21 12:39:16 -04:00
90d20978b1 Update .gitea/workflows/datadog-static-analysis.yml
Some checks failed
Datadog Secrets Scanning / Datadog Static Analyzer (push) Successful in 14s
Datadog Software Composition Analysis / Datadog SBOM Generation and Upload (push) Successful in 15s
Release / build (push) Successful in 37s
Release / publish_head (push) Successful in 35s
Datadog Static Analysis / Datadog Static Analyzer (push) Failing after 1m33s
2025-03-21 12:36:10 -04:00
1a26b0b3fb Update .gitea/workflows/datadog-static-analysis.yml
Some checks failed
Datadog Software Composition Analysis / Datadog SBOM Generation and Upload (push) Successful in 16s
Datadog Secrets Scanning / Datadog Static Analyzer (push) Successful in 15s
Release / build (push) Successful in 38s
Datadog Static Analysis / Datadog Static Analyzer (push) Failing after 43s
Release / publish_head (push) Successful in 38s
2025-03-21 12:20:22 -04:00
71efbfcc83 Update .gitea/workflows/datadog-static-analysis.yml
All checks were successful
Datadog Secrets Scanning / Datadog Static Analyzer (push) Successful in 13s
Datadog Software Composition Analysis / Datadog SBOM Generation and Upload (push) Successful in 15s
Release / build (push) Successful in 39s
Datadog Static Analysis / Datadog Static Analyzer (push) Successful in 47s
Release / publish_head (push) Successful in 39s
2025-03-21 11:08:24 -04:00
27ef2d4ca3 Delete .gitea/workflows/semgrep-ce.yaml
All checks were successful
Datadog Software Composition Analysis / Datadog SBOM Generation and Upload (push) Successful in 14s
Datadog Secrets Scanning / Datadog Static Analyzer (push) Successful in 14s
Release / build (push) Successful in 36s
Datadog Static Analysis / Datadog Static Analyzer (push) Successful in 43s
Release / publish_head (push) Successful in 38s
2025-03-21 11:01:30 -04:00
1aa1964853 Update .gitea/workflows/datadog-static-analysis.yml
Some checks failed
Datadog Static Analysis / Datadog Static Analyzer (push) Waiting to run
Release / build (push) Waiting to run
Release / publish_head (push) Waiting to run
Datadog Software Composition Analysis / Datadog SBOM Generation and Upload (push) Has been cancelled
Datadog Secrets Scanning / Datadog Static Analyzer (push) Has been cancelled
Semgrep CE scan / semgrep-oss/scan (push) Failing after 2s
2025-03-21 11:01:17 -04:00
aae43a0001 Update .gitea/workflows/datadog-static-analysis.yml
Some checks failed
Datadog Secrets Scanning / Datadog Static Analyzer (push) Successful in 13s
Datadog Software Composition Analysis / Datadog SBOM Generation and Upload (push) Successful in 14s
Release / build (push) Successful in 36s
Datadog Static Analysis / Datadog Static Analyzer (push) Successful in 37s
Semgrep CE scan / semgrep-oss/scan (push) Failing after 2s
Release / publish_head (push) Successful in 37s
2025-03-21 10:57:35 -04:00
61392e296c Update .gitea/workflows/datadog-static-analysis.yml
Some checks failed
Datadog Software Composition Analysis / Datadog SBOM Generation and Upload (push) Successful in 14s
Datadog Secrets Scanning / Datadog Static Analyzer (push) Successful in 14s
Datadog Static Analysis / Datadog Static Analyzer (push) Failing after 21s
Release / build (push) Successful in 34s
Semgrep CE scan / semgrep-oss/scan (push) Failing after 8s
Release / publish_head (push) Successful in 35s
2025-03-21 10:32:29 -04:00
997afcdd9e Add Semgrep Scanning
Some checks failed
Datadog Software Composition Analysis / Datadog SBOM Generation and Upload (push) Successful in 15s
Datadog Secrets Scanning / Datadog Static Analyzer (push) Successful in 14s
Datadog Static Analysis / Datadog Static Analyzer (push) Successful in 24s
Release / build (push) Successful in 39s
Semgrep CE scan / semgrep-oss/scan (push) Failing after 21s
Release / publish_head (push) Successful in 39s
2025-03-21 10:23:09 -04:00
5a611dd893 Update config.toml
All checks were successful
Datadog Secrets Scanning / Datadog Static Analyzer (push) Successful in 51s
Datadog Software Composition Analysis / Datadog SBOM Generation and Upload (push) Successful in 1m15s
Datadog Static Analysis / Datadog Static Analyzer (push) Successful in 24s
Release / publish_head (push) Successful in 43s
Release / build (push) Successful in 43s
2025-03-20 22:04:51 -04:00
2adde253c9 start updating docs, other changes to file upload
All checks were successful
Release / build (push) Successful in 34s
Release / publish_head (push) Successful in 33s
Datadog Software Composition Analysis / Datadog SBOM Generation and Upload (push) Successful in 15s
Datadog Secrets Scanning / Datadog Static Analyzer (push) Successful in 10s
Datadog Static Analysis / Datadog Static Analyzer (push) Successful in 20s
Release / publish_head (release) Has been skipped
Release / build (release) Successful in 37s
2025-03-16 21:22:28 -04:00
744693a5f1 Update to resolve GHSA-cpwx-vrp4-4pq7
All checks were successful
Release / build (push) Successful in 37s
Release / publish_head (push) Successful in 34s
Datadog Secrets Scanning / Datadog Static Analyzer (push) Successful in 10s
Datadog Software Composition Analysis / Datadog SBOM Generation and Upload (push) Successful in 15s
Datadog Static Analysis / Datadog Static Analyzer (push) Successful in 20s
Release / publish_head (release) Has been skipped
Release / build (release) Successful in 36s
2025-03-16 13:11:23 -04:00
102c7a2b94 more fixes
All checks were successful
Datadog Software Composition Analysis / Datadog SBOM Generation and Upload (push) Successful in 15s
Datadog Secrets Scanning / Datadog Static Analyzer (push) Successful in 15s
Datadog Static Analysis / Datadog Static Analyzer (push) Successful in 25s
Release / build (push) Successful in 36s
Release / publish_head (push) Successful in 34s
2025-03-15 20:08:29 -04:00
74a010e82a more fixes
All checks were successful
Datadog Secrets Scanning / Datadog Static Analyzer (push) Successful in 15s
Datadog Software Composition Analysis / Datadog SBOM Generation and Upload (push) Successful in 15s
Datadog Static Analysis / Datadog Static Analyzer (push) Successful in 25s
Release / build (push) Successful in 36s
Release / publish_head (push) Successful in 34s
2025-03-15 20:03:58 -04:00
23ce3be362 more fixes
All checks were successful
Datadog Secrets Scanning / Datadog Static Analyzer (push) Successful in 14s
Datadog Software Composition Analysis / Datadog SBOM Generation and Upload (push) Successful in 16s
Datadog Static Analysis / Datadog Static Analyzer (push) Successful in 24s
Release / build (push) Successful in 35s
Release / publish_head (push) Successful in 35s
2025-03-15 20:01:07 -04:00
f12247b0b1 more fixes
All checks were successful
Datadog Software Composition Analysis / Datadog SBOM Generation and Upload (push) Successful in 15s
Datadog Secrets Scanning / Datadog Static Analyzer (push) Successful in 14s
Datadog Static Analysis / Datadog Static Analyzer (push) Successful in 20s
Release / build (push) Successful in 33s
Release / publish_head (push) Successful in 35s
2025-03-15 19:58:45 -04:00
2605f7db37 more fixes
All checks were successful
Datadog Secrets Scanning / Datadog Static Analyzer (push) Successful in 14s
Datadog Software Composition Analysis / Datadog SBOM Generation and Upload (push) Successful in 15s
Datadog Static Analysis / Datadog Static Analyzer (push) Successful in 20s
Release / build (push) Successful in 35s
Release / publish_head (push) Successful in 35s
2025-03-15 19:56:40 -04:00
3898a198bd add testing builds
All checks were successful
Datadog Software Composition Analysis / Datadog SBOM Generation and Upload (push) Successful in 15s
Datadog Secrets Scanning / Datadog Static Analyzer (push) Successful in 15s
Datadog Static Analysis / Datadog Static Analyzer (push) Successful in 24s
Release / build (push) Successful in 37s
Release / publish_head (push) Successful in 37s
2025-03-15 19:49:12 -04:00
d901f00c1f test fix image rotation
All checks were successful
Datadog Secrets Scanning / Datadog Static Analyzer (push) Successful in 15s
Datadog Software Composition Analysis / Datadog SBOM Generation and Upload (push) Successful in 15s
Datadog Static Analysis / Datadog Static Analyzer (push) Successful in 23s
2025-03-15 19:47:44 -04:00
32 changed files with 132 additions and 340 deletions

View File

@ -7,15 +7,15 @@ jobs:
runs-on: ubuntu-latest
name: Datadog Static Analyzer
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Check code for comitted secrets
id: datadog-static-analysis
uses: DataDog/datadog-static-analyzer-github-action@v1
with:
dd_api_key: ${{ secrets.DD_API_KEY }}
dd_app_key: ${{ secrets.DD_APP_KEY }}
dd_site: datadoghq.com
secrets_enabled: true
static_analysis_enabled: false
cpu_count: 2
- name: Checkout
uses: actions/checkout@v3
- name: Check code for comitted secrets
id: datadog-static-analysis
uses: DataDog/datadog-static-analyzer-github-action@v1
with:
dd_api_key: ${{ secrets.DD_API_KEY }}
dd_app_key: ${{ secrets.DD_APP_KEY }}
dd_site: datadoghq.com
secrets_enabled: true
static_analysis_enabled: false
cpu_count: 8

View File

@ -16,4 +16,26 @@ jobs:
dd_api_key: ${{ secrets.DD_API_KEY }}
dd_app_key: ${{ secrets.DD_APP_KEY }}
dd_site: datadoghq.com
cpu_count: 2
cpu_count: 2
- name: Run Semgrep
run: |
python3 -m pip install --break-system-package semgrep
semgrep scan --sarif -o /tmp/semgrep.sarif
cat /tmp/semgrep.sarif
# Download and install nvm:
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.2/install.sh | bash
# in lieu of restarting the shell
\. "$HOME/.nvm/nvm.sh"
# Download and install Node.js:
nvm install 22
# Verify the Node.js version:
node -v # Should print "v22.14.0".
nvm current # Should print "v22.14.0".
# Verify npm version:
npm -v # Should print "10.9.2".
npm install -g @datadog/datadog-ci
datadog-ci sarif upload /tmp/semgrep.sarif
env:
DD_API_KEY: ${{ secrets.DD_API_KEY }}
DD_APP_KEY: ${{ secrets.DD_APP_KEY }}
DD_SITE: datadoghq.com

View File

@ -3,6 +3,9 @@ name: Release
on:
release:
types: [published]
push:
branches:
- main
jobs:
build:
@ -41,4 +44,29 @@ jobs:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
labels: ${{ steps.meta.outputs.labels }}
publish_head:
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Login to Gitea Container Registry
uses: docker/login-action@v2
with:
registry: git.dws.rip
username: ${{ github.actor }}
password: ${{ secrets.GLOBAL_KEY }}
- name: Build and push "head" image
uses: docker/build-push-action@v4
with:
context: .
push: true
tags: git.dws.rip/${{ github.repository }}:head

View File

@ -167,6 +167,7 @@ COPY . .
CMD ["python", "main.py"]
```
## Docker Compose Example
Below is an example `docker-compose.yml` file to deploy Foldsite using Docker Compose:
@ -182,4 +183,4 @@ services:
- .:/app
environment:
- CONFIG_PATH=config.toml
```
```

16
config.toml Normal file
View File

@ -0,0 +1,16 @@
[paths]
content_dir = "/home/dubey/projects/foldsitedocs/content"
templates_dir = "/home/dubey/projects/foldsitedocs/templates"
styles_dir = "/home/dubey/projects/foldsitedocs/styles"
[server]
listen_address = "0.0.0.0"
listen_port = 8080
enable_admin_browser = false
admin_password = "password"
max_threads = 4
debug = false
access_log = true

View File

@ -1,3 +0,0 @@
# Added Tools for the Template
Foldsite provides additional tools for templates, such as functions to get sibling content files, text document previews, and folder contents.

View File

@ -1,19 +0,0 @@
# Configuration
The configuration file is written in TOML format and contains various settings for the application. Below is an example configuration file (`config.toml`):
```toml
[paths]
content_dir = "example/content"
templates_dir = "templates"
styles_dir = "styles"
[server]
listen_address = "127.0.0.1"
listen_port = 8080
debug = false
access_log = true
max_threads = 4
admin_browser = false
admin_password = "your_admin_password"
```

View File

@ -1,12 +0,0 @@
# Deployment
To deploy Foldsite, you can use Docker. Below is an example Dockerfile:
```dockerfile
FROM python:3.13.2-bookworm
WORKDIR /app
COPY requirements.txt requirements.txt
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "main.py"]
```

View File

@ -1,16 +0,0 @@
# Docker Compose Example
Below is an example `docker-compose.yml` file to deploy Foldsite using Docker Compose:
```yaml
version: '3.8'
services:
foldsite:
build: .
ports:
- "8080:8080"
volumes:
- .:/app
environment:
- CONFIG_PATH=config.toml
```

View File

@ -1,39 +0,0 @@
# Example Usages for Tools and Types
### Example Usage of `get_sibling_content_files`
```html
<ul>
{% for file in get_sibling_content_files('path/to/directory') %}
<li>{{ file[0] }} - {{ file[1] }}</li>
{% endfor %}
</ul>
```
### Example Usage of `get_text_document_preview`
```html
<div>
{{ get_text_document_preview('path/to/document.md') }}
</div>
```
### Example Usage of `get_sibling_content_folders`
```html
<ul>
{% for folder in get_sibling_content_folders('path/to/directory') %}
<li>{{ folder[0] }} - {{ folder[1] }}</li>
{% endfor %}
</ul>
```
### Example Usage of `get_folder_contents`
```html
<ul>
{% for item in get_folder_contents('path/to/directory') %}
<li>{{ item.name }} - {{ item.path }}</li>
{% endfor %}
</ul>
```

View File

@ -1,23 +0,0 @@
# How a Template is Written
Templates are written in HTML and use Jinja2 syntax for dynamic content. Below is an example template (`base.html`):
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ title }}</title>
<link rel="stylesheet" href="{{ url_for('static', filename='base.css') }}">
{% for style in styles %}
<link rel="stylesheet" href="{{ style }}">
{% endfor %}
</head>
<body>
<div class="content">
{{ content }}
</div>
</body>
</html>
```

View File

@ -1,20 +0,0 @@
# Foldsite Documentation
Welcome to the Foldsite documentation. This site will guide you through the setup, configuration, and usage of Foldsite.
## Table of Contents
1. [Introduction](introduction.md)
2. [Configuration](configuration.md)
3. [Template Setup](template-setup.md)
4. [Site Setup](site-setup.md)
5. [Style Setup](style-setup.md)
6. [Template and Style Search](template-style-search.md)
7. [How a Template is Written](how-template-written.md)
8. [Jinja Primer](jinja-primer.md)
9. [Added Tools for the Template](added-tools.md)
10. [Tool Input and Return Types](tool-input-return-types.md)
11. [Example Usages for Tools and Types](example-usages.md)
12. [Deployment](deployment.md)
13. [Docker Compose Example](docker-compose-example.md)
14. [Folder Layout](folder-layout.md)

View File

@ -1,5 +0,0 @@
# Introduction
Foldsite is a dynamic site generator built with Python and Flask. It allows you to create and manage a website using Markdown content, HTML templates, and CSS styles.
This documentation will guide you through the setup, configuration, and usage of Foldsite.

View File

@ -1,8 +0,0 @@
# Jinja Primer
Jinja2 is a templating engine for Python. It allows you to include dynamic content in your HTML templates. Below are some basic Jinja2 syntax examples:
- Variables: `{{ variable }}`
- Loops: `{% for item in list %} ... {% endfor %}`
- Conditionals: `{% if condition %} ... {% endif %}`
- Includes: `{% include 'template.html' %}`

View File

@ -1,3 +0,0 @@
# Site Setup
The site content is stored in the `content` directory. Each Markdown file represents a page on your site. The directory structure of the `content` directory determines the URL structure of your site.

View File

@ -1,3 +0,0 @@
# Style Setup
Styles are CSS files that define the appearance of your web pages. They are stored in the `styles` directory. You can create specific styles for different types of content and categories.

View File

@ -1,3 +0,0 @@
# Template Setup
Templates are HTML files that define the structure of your web pages. They are stored in the `templates` directory. Each template can include other templates and use Jinja2 syntax for dynamic content.

View File

@ -1,3 +0,0 @@
# Template and Style Search
Templates and styles are searched in a specific order to apply the most specific styles first, followed by more general styles, and finally the base style.

View File

@ -1,13 +0,0 @@
# Tool Input and Return Types
### `get_sibling_content_files(path: str) -> list`
Returns a list of sibling content files in the specified directory.
### `get_text_document_preview(path: str) -> str`
Generates a preview of the text document located at the given path.
### `get_sibling_content_folders(path: str) -> list`
Returns a list of sibling content folders within a specified directory.
### `get_folder_contents(path: str) -> list`
Retrieves the contents of a folder and returns a list of `TemplateFile` objects.

View File

@ -1,24 +0,0 @@
article {
max-width: 800px;
margin: 0 auto;
}
article h1, article h2, article h3, article h4, article h5, article h6 {
margin-top: 1.5rem;
}
article p {
margin: 1rem 0;
}
article pre {
background: #f4f4f4;
padding: 1rem;
overflow-x: auto;
}
article code {
background: #f4f4f4;
padding: 0.2rem 0.4rem;
border-radius: 3px;
}

View File

@ -1,50 +0,0 @@
body {
font-family: Arial, sans-serif;
line-height: 1.6;
margin: 0;
padding: 0;
}
header {
background: #333;
color: #fff;
padding: 1rem 0;
text-align: center;
}
header h1 {
margin: 0;
}
nav ul {
list-style: none;
padding: 0;
}
nav ul li {
display: inline;
margin-right: 1rem;
}
nav ul li a {
color: #fff;
text-decoration: none;
}
nav ul li a:hover {
text-decoration: underline;
}
main {
padding: 2rem;
}
footer {
background: #333;
color: #fff;
text-align: center;
padding: 1rem 0;
position: fixed;
bottom: 0;
width: 100%;
}

View File

@ -1,4 +0,0 @@
<article>
{{ content|safe }}
</article>

View File

@ -1,42 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ title }}</title>
<link rel="stylesheet" href="{{ url_for('static', filename='base.css') }}">
{% for style in styles %}
<link rel="stylesheet" href="{{ style }}">
{% endfor %}
</head>
<body>
<header>
<h1>Foldsite Documentation</h1>
<nav>
<ul>
<li><a href="{{ url_for('default_route', path='index.md') }}">Home</a></li>
<li><a href="{{ url_for('default_route', path='introduction.md') }}">Introduction</a></li>
<li><a href="{{ url_for('default_route', path='configuration.md') }}">Configuration</a></li>
<li><a href="{{ url_for('default_route', path='template-setup.md') }}">Template Setup</a></li>
<li><a href="{{ url_for('default_route', path='site-setup.md') }}">Site Setup</a></li>
<li><a href="{{ url_for('default_route', path='style-setup.md') }}">Style Setup</a></li>
<li><a href="{{ url_for('default_route', path='template-style-search.md') }}">Template and Style Search</a></li>
<li><a href="{{ url_for('default_route', path='how-template-written.md') }}">How a Template is Written</a></li>
<li><a href="{{ url_for('default_route', path='jinja-primer.md') }}">Jinja Primer</a></li>
<li><a href="{{ url_for('default_route', path='added-tools.md') }}">Added Tools</a></li>
<li><a href="{{ url_for('default_route', path='tool-input-return-types.md') }}">Tool Input and Return Types</a></li>
<li><a href="{{ url_for('default_route', path='example-usages.md') }}">Example Usages</a></li>
<li><a href="{{ url_for('default_route', path='deployment.md') }}">Deployment</a></li>
<li><a href="{{ url_for('default_route', path='docker-compose-example.md') }}">Docker Compose Example</a></li>
<li><a href="{{ url_for('default_route', path='folder-layout.md') }}">Folder Layout</a></li>
</ul>
</nav>
</header>
<main>
{{ content|safe }}
</main>
<footer>
<p>&copy; 2023 Foldsite</p>
</footer>
</body>
</html>

View File

@ -6,11 +6,6 @@ from src.rendering.helpers import TemplateHelpers
from src.server.file_manager import create_filemanager_blueprint
AWS_SECRET_ACCESS_KEY = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
PASSWORD = "YiaysZ4g8QX1R8R"
AWS_ACCESS_KEY_ID = "AIDAJQABLZS4A3QDU576"
def main():
parser = create_parser()
args = parser.parse_args()

View File

@ -8,6 +8,7 @@ dependencies = [
"bs4>=0.0.2",
"flask>=3.1.0",
"gunicorn>=23.0.0",
"jinja2>=3.1.6",
"mistune>=3.1.1",
"pillow>=10.4.0",
"python-frontmatter>=1.1.0",

View File

@ -16,8 +16,10 @@ gunicorn==23.0.0
# via foldsite (pyproject.toml)
itsdangerous==2.2.0
# via flask
jinja2==3.1.5
# via flask
jinja2==3.1.6
# via
# foldsite (pyproject.toml)
# flask
markdown-it-py==3.0.0
# via rich
markupsafe==3.0.2

View File

@ -30,6 +30,7 @@ def generate_thumbnail(image_path, resize_percent, min_width, max_width):
try:
exif = img.info['exif']
orientation = img._getexif().get(0x0112, 1) # 0x0112 is the EXIF orientation tag
print(f"EXIF orientation: {orientation}, {image_path}")
if orientation == 3:
img = img.rotate(180, expand=True)
elif orientation == 6:
@ -38,7 +39,7 @@ def generate_thumbnail(image_path, resize_percent, min_width, max_width):
img = img.rotate(90, expand=True)
except (AttributeError, KeyError, IndexError):
# cases: image don't have getexif
exif = None
exif = b""
# Save the thumbnail to a BytesIO object
thumbnail_io = BytesIO()

View File

@ -69,6 +69,7 @@ def render_error_page(
error_message: str,
error_description: str,
template_path: Path = Path("./"),
currentPath: str = "",
):
inp = DEFAULT_ERROR_TEMPLATE
if (template_path / "__error.html").exists():
@ -84,6 +85,7 @@ def render_error_page(
(template_path / "base.html").read_text(),
content=content,
styles=["/base.css", "/__error.css"],
currentPath=currentPath,
),
error_code,
)
@ -125,6 +127,7 @@ def render_page(
error_message="Not Found",
error_description="The requested resource was not found on this server.",
template_path=template_path,
currentPath=str(path.relative_to(base_path)),
)
target_path = path
target_file = path
@ -200,6 +203,7 @@ def render_page(
"Not Found",
"The requested resource was not found on this server.",
template_path,
currentPath=str(relative_path),
)
content = ""

View File

@ -1,9 +1,11 @@
from pathlib import Path
from src.config.config import Configuration
from src.rendering.renderer import render_page, render_error_page
from flask import send_file, request
from src.rendering.image import generate_thumbnail
import os
from pathlib import Path
from flask import request, send_file
from src.config.config import Configuration
from src.rendering.image import generate_thumbnail
from src.rendering.renderer import render_error_page, render_page
class RouteManager:
@ -32,7 +34,6 @@ class RouteManager:
for part in secure_path_parts:
if part == "." or part == "..":
print("Illegal path nice try")
return None
# Reconstruct the secure path
@ -45,13 +46,15 @@ class RouteManager:
for part in secure_path.parts:
if part.startswith("___"):
print("hidden file")
raise Exception("Illegal path")
return secure_path
def _ensure_route(self, path: str):
file_path: Path = self.config.content_dir / (path if path else "index.md")
file_path: Path = self.config.content_dir / path
if not path or file_path.is_dir():
file_path = file_path / "index.md"
if file_path < self.config.content_dir:
raise Exception("Illegal path")
@ -70,7 +73,9 @@ class RouteManager:
"The requested resource was not found on this server.",
self.config.templates_dir,
)
file_path: Path = self.config.content_dir / (path if path else "index.md")
file_path: Path = self.config.content_dir / path
if not path or file_path.is_dir():
file_path = file_path / "index.md"
return render_page(
file_path,
base_path=self.config.content_dir,
@ -120,8 +125,10 @@ class RouteManager:
return (
thumbnail_bytes,
200,
{"Content-Type": f"image/{img_format.lower()}",
"cache-control": "public, max-age=31536000"},
{
"Content-Type": f"image/{img_format.lower()}",
"cache-control": "public, max-age=31536000",
},
)
return send_file(file_path)
else:

View File

@ -40,6 +40,7 @@ def create_filemanager_blueprint(base_dir, url_prefix='/files', auth_password=No
return redirect(next_url)
else:
flash("Incorrect password")
#no-dd-sa
return render_template_string('''
<!doctype html>
<html>
@ -149,10 +150,10 @@ def create_filemanager_blueprint(base_dir, url_prefix='/files', auth_password=No
</ul>
<button onclick="bulkCut()">Bulk Cut Selected</button>
<hr>
<h2>Upload File</h2>
<h2>Upload File(s)</h2>
<form action="{{ url_for('filemanager.upload') }}" method="post" enctype="multipart/form-data">
<input type="hidden" name="path" value="{{ rel_path }}">
<input type="file" name="file">
<input type="file" name="file" multiple>
<input type="submit" value="Upload">
</form>
<hr>
@ -276,11 +277,13 @@ def create_filemanager_blueprint(base_dir, url_prefix='/files', auth_password=No
return "Invalid path", 400
if not os.path.isdir(abs_path):
return "Not a directory", 400
file = request.files.get('file')
if file:
filename = secure_filename(file.filename)
file.save(os.path.join(abs_path, filename))
flash("Uploaded successfully")
files = request.files.getlist('file')
if files:
for file in files:
if file and file.filename:
filename = secure_filename(file.filename)
file.save(os.path.join(abs_path, filename))
flash("Uploaded files successfully")
return redirect(url_for('filemanager.index', path=rel_path))
@filemanager.route('/rename', methods=['POST'])

20
uv.lock generated
View File

@ -81,6 +81,7 @@ dependencies = [
{ name = "bs4" },
{ name = "flask" },
{ name = "gunicorn" },
{ name = "jinja2" },
{ name = "mistune" },
{ name = "pillow" },
{ name = "python-frontmatter" },
@ -94,6 +95,7 @@ requires-dist = [
{ name = "bs4", specifier = ">=0.0.2" },
{ name = "flask", specifier = ">=3.1.0" },
{ name = "gunicorn", specifier = ">=23.0.0" },
{ name = "jinja2", specifier = ">=3.1.6" },
{ name = "mistune", specifier = ">=3.1.1" },
{ name = "pillow", specifier = ">=10.4.0" },
{ name = "python-frontmatter", specifier = ">=1.1.0" },
@ -125,14 +127,14 @@ wheels = [
[[package]]
name = "jinja2"
version = "3.1.5"
version = "3.1.6"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "markupsafe" },
]
sdist = { url = "https://files.pythonhosted.org/packages/af/92/b3130cbbf5591acf9ade8708c365f3238046ac7cb8ccba6e81abccb0ccff/jinja2-3.1.5.tar.gz", hash = "sha256:8fefff8dc3034e27bb80d67c671eb8a9bc424c0ef4c0826edbff304cceff43bb", size = 244674 }
sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/bd/0f/2ba5fbcd631e3e88689309dbe978c5769e883e4b84ebfe7da30b43275c5a/jinja2-3.1.5-py3-none-any.whl", hash = "sha256:aba0f4dc9ed8013c424088f68a5c226f7d6097ed89b246d7749c2ec4175c6adb", size = 134596 },
{ url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899 },
]
[[package]]
@ -186,11 +188,11 @@ wheels = [
[[package]]
name = "mistune"
version = "3.1.1"
version = "3.1.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/c6/1d/6b2b634e43bacc3239006e61800676aa6c41ac1836b2c57497ed27a7310b/mistune-3.1.1.tar.gz", hash = "sha256:e0740d635f515119f7d1feb6f9b192ee60f0cc649f80a8f944f905706a21654c", size = 94645 }
sdist = { url = "https://files.pythonhosted.org/packages/80/f7/f6d06304c61c2a73213c0a4815280f70d985429cda26272f490e42119c1a/mistune-3.1.2.tar.gz", hash = "sha256:733bf018ba007e8b5f2d3a9eb624034f6ee26c4ea769a98ec533ee111d504dff", size = 94613 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/c6/02/c66bdfdadbb021adb642ca4e8a5ed32ada0b4a3e4b39c5d076d19543452f/mistune-3.1.1-py3-none-any.whl", hash = "sha256:02106ac2aa4f66e769debbfa028509a275069dcffce0dfa578edd7b991ee700a", size = 53696 },
{ url = "https://files.pythonhosted.org/packages/12/92/30b4e54c4d7c48c06db61595cffbbf4f19588ea177896f9b78f0fbe021fd/mistune-3.1.2-py3-none-any.whl", hash = "sha256:4b47731332315cdca99e0ded46fc0004001c1299ff773dfb48fbe1fd226de319", size = 53696 },
]
[[package]]
@ -305,7 +307,7 @@ wheels = [
[[package]]
name = "typer"
version = "0.15.1"
version = "0.15.2"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "click" },
@ -313,9 +315,9 @@ dependencies = [
{ name = "shellingham" },
{ name = "typing-extensions" },
]
sdist = { url = "https://files.pythonhosted.org/packages/cb/ce/dca7b219718afd37a0068f4f2530a727c2b74a8b6e8e0c0080a4c0de4fcd/typer-0.15.1.tar.gz", hash = "sha256:a0588c0a7fa68a1978a069818657778f86abe6ff5ea6abf472f940a08bfe4f0a", size = 99789 }
sdist = { url = "https://files.pythonhosted.org/packages/8b/6f/3991f0f1c7fcb2df31aef28e0594d8d54b05393a0e4e34c65e475c2a5d41/typer-0.15.2.tar.gz", hash = "sha256:ab2fab47533a813c49fe1f16b1a370fd5819099c00b119e0633df65f22144ba5", size = 100711 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/d0/cc/0a838ba5ca64dc832aa43f727bd586309846b0ffb2ce52422543e6075e8a/typer-0.15.1-py3-none-any.whl", hash = "sha256:7994fb7b8155b64d3402518560648446072864beefd44aa2dc36972a5972e847", size = 44908 },
{ url = "https://files.pythonhosted.org/packages/7f/fc/5b29fea8cee020515ca82cc68e3b8e1e34bb19a3535ad854cac9257b414c/typer-0.15.2-py3-none-any.whl", hash = "sha256:46a499c6107d645a9c13f7ee46c5d5096cae6f5fc57dd11eccbbb9ae3e44ddfc", size = 45061 },
]
[[package]]