diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 994c4503f..4e12bfdd4 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -13,7 +13,7 @@ Include only the fields that help the reviewer: ## Loom video - - ## Scope check - [ ] Ran `$scope-check` against the ENG ticket and final diff. diff --git a/apps/roam/src/utils/__tests__/conceptConversion.test.ts b/apps/roam/src/utils/__tests__/conceptConversion.test.ts index ff694334d..ffc21e432 100644 --- a/apps/roam/src/utils/__tests__/conceptConversion.test.ts +++ b/apps/roam/src/utils/__tests__/conceptConversion.test.ts @@ -92,7 +92,10 @@ describe("discourseNodeSchemaToLocalConcept source slot", () => { nodeType({ text: "Claim", type: "clm", format: "[[CLM]] - {content}" }), ); expect(concept.local_reference_content).toBeUndefined(); - expect(concept.literal_content).toEqual({ label: "Claim" }); + expect(concept.literal_content).toEqual({ + label: "Claim", + format: "[[CLM]] - {content}", + }); }); it("keeps the label and template it already carried", () => { @@ -102,6 +105,7 @@ describe("discourseNodeSchemaToLocalConcept source slot", () => { ); expect(concept.literal_content).toEqual({ label: "Evidence", + format: "[[EVD]] - {content} - {Source}", template: "* Question:\n", roles: ["sourceDocument"], }); diff --git a/apps/roam/src/utils/__tests__/publishNodesToGroups.test.ts b/apps/roam/src/utils/__tests__/publishNodesToGroups.test.ts index 46dae6534..9930fcaa9 100644 --- a/apps/roam/src/utils/__tests__/publishNodesToGroups.test.ts +++ b/apps/roam/src/utils/__tests__/publishNodesToGroups.test.ts @@ -38,6 +38,7 @@ vi.mock("~/utils/roamToCrossAppConverters", () => ({ label: s.text, authorId: "author-1", createdAt: new Date("2026-01-01T00:00:00.000Z"), + format: s.format, }), reifiedRelationToCrossApp: vi.fn(), relationTripleSchemaToCrossApp: vi.fn(), @@ -172,6 +173,7 @@ describe("publishNodesToGroups", () => { source_local_id: SCHEMA_UID, is_schema: true, name: "Claim", + literal_content: { format: "[[CLM]] - {content}" }, }); expect(data[1]).toMatchObject({ source_local_id: "node-1", diff --git a/apps/roam/src/utils/__tests__/roamToCrossAppConverters.test.ts b/apps/roam/src/utils/__tests__/roamToCrossAppConverters.test.ts index 25382d060..53d1ac915 100644 --- a/apps/roam/src/utils/__tests__/roamToCrossAppConverters.test.ts +++ b/apps/roam/src/utils/__tests__/roamToCrossAppConverters.test.ts @@ -147,6 +147,13 @@ describe("nodeSchemaToCrossApp timestamps", () => { }); }); +describe("nodeSchemaToCrossApp format", () => { + it("carries the node type format", () => { + const schema = convertSchemaPull(schemaPull); + expect(schema?.format).toBe("[[EVD]] - {content} - {Source}"); + }); +}); + describe("nodeSchemaToCrossApp source slot", () => { it("adds a sourceDocument slot definition pointing at the Source node type", () => { mockedGetDiscourseNodes.mockReturnValue([ diff --git a/apps/roam/src/utils/conceptConversion.ts b/apps/roam/src/utils/conceptConversion.ts index bc851509d..a26587f6e 100644 --- a/apps/roam/src/utils/conceptConversion.ts +++ b/apps/roam/src/utils/conceptConversion.ts @@ -85,7 +85,10 @@ export const discourseNodeSchemaToLocalConcept = ( ): LocalConceptDataInput => { const titleParts = node.text.split("/"); const label = titleParts[titleParts.length - 1] ?? node.text; - const literalContent: Record = { label }; + const literalContent: Record = { + label, + format: node.format, + }; if (node.template !== undefined) literalContent.template = templateToText(node.template); const hasSourceSlot = schemaHasSourceSlot(node); diff --git a/apps/roam/src/utils/roamToCrossAppConverters.ts b/apps/roam/src/utils/roamToCrossAppConverters.ts index c9090e37e..9d27977de 100644 --- a/apps/roam/src/utils/roamToCrossAppConverters.ts +++ b/apps/roam/src/utils/roamToCrossAppConverters.ts @@ -220,6 +220,7 @@ export const nodeSchemaToCrossApp = ( authorId: userUid, createdAt: new Date(createdTime), modifiedAt: new Date(Math.max(pageEditTime, createdTime)), + format: s.format, ...(hasSourceSlot ? { slotDefinitions: { [SOURCE_SLOT]: sourceSlotSchemaId() } } : {}), diff --git a/apps/website/content/roam/guides/using-the-canvas.mdx b/apps/website/content/roam/guides/using-the-canvas.mdx index 7346b8535..4c3df7485 100644 --- a/apps/website/content/roam/guides/using-the-canvas.mdx +++ b/apps/website/content/roam/guides/using-the-canvas.mdx @@ -79,10 +79,8 @@ To create a relation, click the discourse graph symbol in the lower toolbar and /> _Using the relation menu_ - You can also create a relation on your canvas by clicking on the origin node until the grey drag handles appear and dragging the relation arrow to the target node. You will be prompted to select from one of the available relation types for those nodes. - dragging relationstemplate_content` | | | `templateTitle` | `literal_content->template` | | +| `format` | `literal_content->format` | | | - | `is_schema` | true | | - | `schema_id` | null | | - | `arity` | 0 | diff --git a/packages/database/src/crossAppContracts.ts b/packages/database/src/crossAppContracts.ts index fe97fd6c2..9ec039273 100644 --- a/packages/database/src/crossAppContracts.ts +++ b/packages/database/src/crossAppContracts.ts @@ -25,6 +25,7 @@ export type CrossAppNodeSchema = CrossAppSchemaBase & { label: string; template?: string; templateTitle?: string; + format?: string; slotDefinitions?: Record; }; diff --git a/packages/database/src/lib/__tests__/crossAppConverters.test.ts b/packages/database/src/lib/__tests__/crossAppConverters.test.ts index 55a88d69a..994fd5be0 100644 --- a/packages/database/src/lib/__tests__/crossAppConverters.test.ts +++ b/packages/database/src/lib/__tests__/crossAppConverters.test.ts @@ -23,6 +23,35 @@ const baseNode: CrossAppNode = { }; describe("crossAppNodeSchemaToDbConcept", () => { + it("maps format to literal_content.format", () => { + const concept = crossAppNodeSchemaToDbConcept({ + ...baseSchema, + format: "[[CLM]] - {content}", + }); + expect(concept.literal_content).toEqual({ + format: "[[CLM]] - {content}", + }); + }); + + it("keeps the template keys alongside format", () => { + const concept = crossAppNodeSchemaToDbConcept({ + ...baseSchema, + format: "[[CLM]] - {content}", + template: "* Evidence\n", + templateTitle: "Claim template", + }); + expect(concept.literal_content).toEqual({ + format: "[[CLM]] - {content}", + template: "Claim template", + template_content: "* Evidence\n", + }); + }); + + it("omits literal_content when no keys are set", () => { + const concept = crossAppNodeSchemaToDbConcept(baseSchema); + expect(concept.literal_content).toBeUndefined(); + }); + it("stores slot definitions as roles plus local reference content", () => { const result = crossAppNodeSchemaToDbConcept({ ...baseSchema, diff --git a/packages/database/src/lib/crossAppConverters.ts b/packages/database/src/lib/crossAppConverters.ts index 135cc7e27..59e935c00 100644 --- a/packages/database/src/lib/crossAppConverters.ts +++ b/packages/database/src/lib/crossAppConverters.ts @@ -97,6 +97,7 @@ export const crossAppNodeSchemaToDbConcept = ( const literalInfo = filterUndefined({ template: node.templateTitle, template_content: node.template, + format: node.format, roles: slots.length > 0 ? slots : undefined, }); const referenceContent = slots.length ? node.slotDefinitions : undefined;