project-list: distinguish Quarto PDF vs Quarto Slides in format badge
Build and Deploy Verso / deploy (push) Successful in 9m30s
Build and Deploy Verso / deploy (push) Successful in 9m30s
Add a quartoFlavor field ('revealjs' | 'pdf') to the Project model.
After each successful Quarto compile, CompileController detects the output
type (output.html → revealjs, otherwise pdf) and persists it.
ProjectListController includes it in the projection and serialization so
it reaches the frontend without an extra round-trip.
Badge variants:
- quartoFlavor unset (new/uncompiled) → "Quarto PDF" #447099
- quartoFlavor 'pdf' → "Quarto PDF" #447099 (Quarto blue)
- quartoFlavor 'revealjs' → "Quarto Slides" #7e56c2 (purple)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { pipeline } from 'node:stream/promises'
|
||||
import Metrics from '@overleaf/metrics'
|
||||
import ProjectGetter from '../Project/ProjectGetter.mjs'
|
||||
import { Project } from '../models/Project.mjs'
|
||||
import CompileManager from './CompileManager.mjs'
|
||||
import ClsiManager from './ClsiManager.mjs'
|
||||
import logger from '@overleaf/logger'
|
||||
@@ -300,6 +301,16 @@ const _CompileController = {
|
||||
? getOutputFilesArchiveSpecification(projectId, userId, buildId)
|
||||
: null
|
||||
|
||||
// Persist quarto output flavor so the project-list badge can distinguish
|
||||
// RevealJS presentations from PDF documents without needing a compile.
|
||||
if (status === 'success' && options.compiler === 'quarto') {
|
||||
const isHtml = outputFiles.some(f => f.path === 'output.html')
|
||||
Project.updateOne(
|
||||
{ _id: projectId },
|
||||
{ quartoFlavor: isHtml ? 'revealjs' : 'pdf' }
|
||||
).exec().catch(() => {})
|
||||
}
|
||||
|
||||
res.json({
|
||||
status,
|
||||
outputFiles,
|
||||
|
||||
@@ -681,7 +681,7 @@ async function _getProjects(
|
||||
const results = await Promise.all([
|
||||
ProjectGetter.promises.findAllUsersProjects(
|
||||
userId,
|
||||
'name lastUpdated lastUpdatedBy publicAccesLevel archived trashed owner_ref tokens compiler'
|
||||
'name lastUpdated lastUpdatedBy publicAccesLevel archived trashed owner_ref tokens compiler quartoFlavor'
|
||||
),
|
||||
TagsHandler.promises.getAllTags(userId),
|
||||
])
|
||||
@@ -826,6 +826,7 @@ function _formatProjectInfo(project, accessLevel, source, userId) {
|
||||
archived,
|
||||
trashed,
|
||||
compiler: project.compiler,
|
||||
quartoFlavor: project.quartoFlavor,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -880,6 +881,7 @@ async function _injectProjectUsers(projects) {
|
||||
: users[project.owner_ref.toString()],
|
||||
owner_ref: undefined,
|
||||
compiler: project.compiler,
|
||||
quartoFlavor: project.quartoFlavor,
|
||||
}))
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ export const ProjectSchema = new Schema(
|
||||
version: { type: Number }, // incremented for every change in the project structure (folders and filenames)
|
||||
publicAccesLevel: { type: String, default: 'private' },
|
||||
compiler: { type: String, default: settings.defaultLatexCompiler },
|
||||
quartoFlavor: { type: String, enum: ['revealjs', 'pdf', null] },
|
||||
spellCheckLanguage: { type: String, default: 'en' },
|
||||
deletedByExternalDataSource: { type: Boolean, default: false },
|
||||
description: { type: String, default: '' },
|
||||
|
||||
+10
-4
@@ -4,13 +4,19 @@ import { ProjectCompiler } from '../../../../../../../types/project-settings'
|
||||
// Map the stored compiler engine to the document format the project produces.
|
||||
// CLSI dispatches the real engine from the root file's extension, but the
|
||||
// compiler field is a faithful, cheap proxy for the project's format.
|
||||
function formatLabel(compiler: ProjectCompiler | undefined): {
|
||||
function formatLabel(
|
||||
compiler: ProjectCompiler | undefined,
|
||||
quartoFlavor: 'revealjs' | 'pdf' | undefined
|
||||
): {
|
||||
label: string
|
||||
variant: 'quarto' | 'typst' | 'latex'
|
||||
variant: 'quarto-slides' | 'quarto' | 'typst' | 'latex'
|
||||
} {
|
||||
switch (compiler) {
|
||||
case 'quarto':
|
||||
return { label: 'Quarto', variant: 'quarto' }
|
||||
if (quartoFlavor === 'revealjs') {
|
||||
return { label: 'Quarto Slides', variant: 'quarto-slides' }
|
||||
}
|
||||
return { label: 'Quarto PDF', variant: 'quarto' }
|
||||
case 'typst':
|
||||
return { label: 'Typst', variant: 'typst' }
|
||||
default:
|
||||
@@ -24,7 +30,7 @@ type FormatCellProps = {
|
||||
}
|
||||
|
||||
export default function FormatCell({ project }: FormatCellProps) {
|
||||
const { label, variant } = formatLabel(project.compiler)
|
||||
const { label, variant } = formatLabel(project.compiler, project.quartoFlavor)
|
||||
|
||||
return (
|
||||
<span
|
||||
|
||||
@@ -407,7 +407,11 @@ ul.project-list-filters {
|
||||
white-space: nowrap;
|
||||
|
||||
&.project-format-badge-quarto {
|
||||
background-color: #447099;
|
||||
background-color: #447099; // Quarto blue (PDF output)
|
||||
}
|
||||
|
||||
&.project-format-badge-quarto-slides {
|
||||
background-color: #7e56c2; // purple — presentation feel, blends Quarto + RevealJS
|
||||
}
|
||||
|
||||
&.project-format-badge-typst {
|
||||
|
||||
@@ -53,6 +53,7 @@ export type ProjectApi = {
|
||||
accessLevel: ProjectAccessLevel
|
||||
source: Source
|
||||
compiler?: ProjectCompiler
|
||||
quartoFlavor?: 'revealjs' | 'pdf'
|
||||
}
|
||||
|
||||
export type Project = MergeAndOverride<
|
||||
|
||||
Reference in New Issue
Block a user