feat: add project file system with CRUD, upload, inline editing, and video attachment support
- Add new `/projects/{slug}/files` endpoint group for per-project filesystem operations including directory and file CRUD, upload, and inline editing with public read and owner write access
- Extend attachment system to support video formats (webm, ogv, mov, m4v) with proper file icons and MIME types
- Implement configurable allowed file types via `allowed_file_types` site setting, replacing hardcoded `ALLOWED_UPLOAD_TYPES` with dynamic `allowed_extensions()` and `is_extension_allowed()` functions
- Add `delete_all_project_files()` call in `delete_content_item()` to clean up project files when a project is deleted
- Create database indexes on `project_files` table for `(project_uid, path)` and `(project_uid, parent_path)` to optimize file lookups
- Introduce `docs_prose.py` module with `render_prose()` function that renders Markdown content inside `data-render` divs using mistune, enabling dynamic prose rendering in documentation pages
- Enhance docs search with Markdown-aware text stripping (`_demarkdown()`) and improved HTML/script/style sanitization for better search indexing
- Update documentation API samples to reflect new attachment response fields (`is_image`, `is_video`, `mime_type`) and note video format support
- Update README to document the new project files endpoint and clarify AI gateway attribution for guest Devii sessions
2026-06-08 22:51:09 +02:00
|
|
|
# retoor <retoor@molodetz.nl>
|
|
|
|
|
|
|
|
|
|
import html
|
|
|
|
|
import re
|
2026-06-19 10:06:09 +02:00
|
|
|
from functools import lru_cache
|
feat: add project file system with CRUD, upload, inline editing, and video attachment support
- Add new `/projects/{slug}/files` endpoint group for per-project filesystem operations including directory and file CRUD, upload, and inline editing with public read and owner write access
- Extend attachment system to support video formats (webm, ogv, mov, m4v) with proper file icons and MIME types
- Implement configurable allowed file types via `allowed_file_types` site setting, replacing hardcoded `ALLOWED_UPLOAD_TYPES` with dynamic `allowed_extensions()` and `is_extension_allowed()` functions
- Add `delete_all_project_files()` call in `delete_content_item()` to clean up project files when a project is deleted
- Create database indexes on `project_files` table for `(project_uid, path)` and `(project_uid, parent_path)` to optimize file lookups
- Introduce `docs_prose.py` module with `render_prose()` function that renders Markdown content inside `data-render` divs using mistune, enabling dynamic prose rendering in documentation pages
- Enhance docs search with Markdown-aware text stripping (`_demarkdown()`) and improved HTML/script/style sanitization for better search indexing
- Update documentation API samples to reflect new attachment response fields (`is_image`, `is_video`, `mime_type`) and note video format support
- Update README to document the new project files endpoint and clarify AI gateway attribution for guest Devii sessions
2026-06-08 22:51:09 +02:00
|
|
|
|
|
|
|
|
import mistune
|
|
|
|
|
|
|
|
|
|
_markdown = mistune.create_markdown(
|
|
|
|
|
escape=False,
|
|
|
|
|
hard_wrap=True,
|
|
|
|
|
plugins=["table", "strikethrough", "url"],
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
_RENDER_BLOCK = re.compile(
|
|
|
|
|
r'<div class="docs-content" data-render>(.*?)</div>', re.DOTALL
|
|
|
|
|
)
|
|
|
|
|
|
2026-07-06 05:57:47 +02:00
|
|
|
_HEADING = re.compile(r"<h([23])>(.*?)</h\1>", re.DOTALL)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def heading_slug(text: str) -> str:
|
|
|
|
|
plain = html.unescape(re.sub(r"<[^>]+>", "", text)).strip().lower()
|
|
|
|
|
slug = re.sub(r"[^a-z0-9]+", "-", plain).strip("-")
|
|
|
|
|
return slug or "section"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _anchor_headings(rendered: str) -> str:
|
|
|
|
|
seen: dict[str, int] = {}
|
|
|
|
|
|
|
|
|
|
def _inject(match: re.Match) -> str:
|
|
|
|
|
level, inner = match.group(1), match.group(2)
|
|
|
|
|
slug = heading_slug(inner)
|
|
|
|
|
count = seen.get(slug, 0)
|
|
|
|
|
seen[slug] = count + 1
|
|
|
|
|
if count:
|
|
|
|
|
slug = f"{slug}-{count}"
|
|
|
|
|
return (
|
|
|
|
|
f'<h{level} id="{slug}">{inner}'
|
|
|
|
|
f'<a class="docs-heading-anchor" href="#{slug}" aria-label="Link to this section">#</a>'
|
|
|
|
|
f"</h{level}>"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
return _HEADING.sub(_inject, rendered)
|
|
|
|
|
|
feat: add project file system with CRUD, upload, inline editing, and video attachment support
- Add new `/projects/{slug}/files` endpoint group for per-project filesystem operations including directory and file CRUD, upload, and inline editing with public read and owner write access
- Extend attachment system to support video formats (webm, ogv, mov, m4v) with proper file icons and MIME types
- Implement configurable allowed file types via `allowed_file_types` site setting, replacing hardcoded `ALLOWED_UPLOAD_TYPES` with dynamic `allowed_extensions()` and `is_extension_allowed()` functions
- Add `delete_all_project_files()` call in `delete_content_item()` to clean up project files when a project is deleted
- Create database indexes on `project_files` table for `(project_uid, path)` and `(project_uid, parent_path)` to optimize file lookups
- Introduce `docs_prose.py` module with `render_prose()` function that renders Markdown content inside `data-render` divs using mistune, enabling dynamic prose rendering in documentation pages
- Enhance docs search with Markdown-aware text stripping (`_demarkdown()`) and improved HTML/script/style sanitization for better search indexing
- Update documentation API samples to reflect new attachment response fields (`is_image`, `is_video`, `mime_type`) and note video format support
- Update README to document the new project files endpoint and clarify AI gateway attribution for guest Devii sessions
2026-06-08 22:51:09 +02:00
|
|
|
|
2026-06-19 10:06:09 +02:00
|
|
|
@lru_cache(maxsize=512)
|
|
|
|
|
def _render_markdown(source: str) -> str:
|
2026-07-06 05:57:47 +02:00
|
|
|
return _anchor_headings(_markdown(source))
|
2026-06-19 10:06:09 +02:00
|
|
|
|
|
|
|
|
|
feat: add project file system with CRUD, upload, inline editing, and video attachment support
- Add new `/projects/{slug}/files` endpoint group for per-project filesystem operations including directory and file CRUD, upload, and inline editing with public read and owner write access
- Extend attachment system to support video formats (webm, ogv, mov, m4v) with proper file icons and MIME types
- Implement configurable allowed file types via `allowed_file_types` site setting, replacing hardcoded `ALLOWED_UPLOAD_TYPES` with dynamic `allowed_extensions()` and `is_extension_allowed()` functions
- Add `delete_all_project_files()` call in `delete_content_item()` to clean up project files when a project is deleted
- Create database indexes on `project_files` table for `(project_uid, path)` and `(project_uid, parent_path)` to optimize file lookups
- Introduce `docs_prose.py` module with `render_prose()` function that renders Markdown content inside `data-render` divs using mistune, enabling dynamic prose rendering in documentation pages
- Enhance docs search with Markdown-aware text stripping (`_demarkdown()`) and improved HTML/script/style sanitization for better search indexing
- Update documentation API samples to reflect new attachment response fields (`is_image`, `is_video`, `mime_type`) and note video format support
- Update README to document the new project files endpoint and clarify AI gateway attribution for guest Devii sessions
2026-06-08 22:51:09 +02:00
|
|
|
def _convert(match: re.Match) -> str:
|
|
|
|
|
source = html.unescape(match.group(1)).strip()
|
2026-06-19 10:06:09 +02:00
|
|
|
return f'<div class="docs-content">{_render_markdown(source)}</div>'
|
feat: add project file system with CRUD, upload, inline editing, and video attachment support
- Add new `/projects/{slug}/files` endpoint group for per-project filesystem operations including directory and file CRUD, upload, and inline editing with public read and owner write access
- Extend attachment system to support video formats (webm, ogv, mov, m4v) with proper file icons and MIME types
- Implement configurable allowed file types via `allowed_file_types` site setting, replacing hardcoded `ALLOWED_UPLOAD_TYPES` with dynamic `allowed_extensions()` and `is_extension_allowed()` functions
- Add `delete_all_project_files()` call in `delete_content_item()` to clean up project files when a project is deleted
- Create database indexes on `project_files` table for `(project_uid, path)` and `(project_uid, parent_path)` to optimize file lookups
- Introduce `docs_prose.py` module with `render_prose()` function that renders Markdown content inside `data-render` divs using mistune, enabling dynamic prose rendering in documentation pages
- Enhance docs search with Markdown-aware text stripping (`_demarkdown()`) and improved HTML/script/style sanitization for better search indexing
- Update documentation API samples to reflect new attachment response fields (`is_image`, `is_video`, `mime_type`) and note video format support
- Update README to document the new project files endpoint and clarify AI gateway attribution for guest Devii sessions
2026-06-08 22:51:09 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def render_prose(slug: str, context: dict) -> str:
|
|
|
|
|
from devplacepy.templating import templates
|
|
|
|
|
|
|
|
|
|
rendered = templates.env.get_template(f"docs/{slug}.html").render(**context)
|
|
|
|
|
return _RENDER_BLOCK.sub(_convert, rendered, count=1)
|