@@ -57,6 +57,7 @@ import JSZip from "jszip";
57
57
import {
58
58
boolean ,
59
59
elements ,
60
+ empty ,
60
61
enumeration ,
61
62
float64 ,
62
63
int32 ,
@@ -225,8 +226,20 @@ export interface DocumentType extends EntryCommon {
225
226
lastOpened : string ;
226
227
}
227
228
229
+ /** a template, such as from methods.remarkable.com */
230
+ export interface TemplateType extends EntryCommon {
231
+ /** the key to identify this as a template */
232
+ type : "TemplateType" ;
233
+ /** the timestamp of when the template was added/created */
234
+ createdTime ?: string ;
235
+ /** where this template was installed from */
236
+ source ?: string ;
237
+ /** indicates if this is a newly-installed template */
238
+ new ?: boolean ;
239
+ }
240
+
228
241
/** a remarkable entry for cloud items */
229
- export type Entry = CollectionEntry | DocumentType ;
242
+ export type Entry = CollectionEntry | DocumentType | TemplateType ;
230
243
231
244
/** an simple entry without any extra information */
232
245
export interface SimpleEntry {
@@ -673,8 +686,58 @@ export interface DocumentContent {
673
686
viewBackgroundFilter ?: BackgroundFilter ;
674
687
}
675
688
689
+ /**
690
+ * content metadata, stored with the "content" extension
691
+ *
692
+ * This largely contains description of how to render the document, rather than
693
+ * metadata about it.
694
+ */
695
+ export interface TemplateContent {
696
+ /** the template name */
697
+ name : string ;
698
+ /** the template's author */
699
+ author : string ;
700
+ /** Base64-encoded SVG icon image */
701
+ iconData : string ;
702
+ /** category names this template belongs to (eg: "Planning", "Productivity") */
703
+ categories : string [ ] ;
704
+ /** labels associated with this template (eg: "Project management") */
705
+ labels : string [ ] ;
706
+ /** the orientation of this template */
707
+ orientation : "portrait" | "landscape" ;
708
+ /** semantic version for this template */
709
+ templateVersion : string ;
710
+ /** template configuration format version (currently just `1`) */
711
+ formatVersion : number ;
712
+ /**
713
+ * which screens the template supports:
714
+ *
715
+ * - `rm2`: reMarkable 2
716
+ * - `rmPP`: reMarkable Paper Pro
717
+ */
718
+ supportedScreens : ( "rm2" | "rmPP" ) [ ] ;
719
+ /** constant values used by the commands in `items` */
720
+ constants ?: { [ name : string ] : number } [ ] ;
721
+ /** the template definition, an SVG-like DSL in JSON */
722
+ items : object [ ] ;
723
+ }
724
+
725
+ const templateContent = properties ( {
726
+ name : string ( ) ,
727
+ author : string ( ) ,
728
+ iconData : string ( ) ,
729
+ categories : elements ( string ( ) ) ,
730
+ labels : elements ( string ( ) ) ,
731
+ orientation : enumeration ( "portrait" , "landscape" ) ,
732
+ templateVersion : string ( ) ,
733
+ formatVersion : uint8 ( ) ,
734
+ supportedScreens : elements ( enumeration ( "rm2" , "rmPP" ) ) ,
735
+ constants : elements ( values ( int32 ( ) ) ) ,
736
+ items : elements ( empty ( ) as CompiledSchema < object , unknown > ) ,
737
+ } ) satisfies CompiledSchema < TemplateContent , unknown > ;
738
+
676
739
/** content metadata for any item */
677
- export type Content = CollectionContent | DocumentContent ;
740
+ export type Content = CollectionContent | DocumentContent | TemplateContent ;
678
741
679
742
const documentContent = properties (
680
743
{
@@ -774,7 +837,15 @@ export interface Metadata {
774
837
* DocumentType is a document, an epub, pdf, or notebook, CollectionType is a
775
838
* folder.
776
839
*/
777
- type : "DocumentType" | "CollectionType" ;
840
+ type : "DocumentType" | "CollectionType" | "TemplateType" ;
841
+ /** whether this is this a newly-installed template */
842
+ new ?: boolean ;
843
+ /**
844
+ * the provider from which this item was obtained/installed
845
+ *
846
+ * Example: a template from "com.remarkable.methods".
847
+ */
848
+ source ?: string ;
778
849
/** [speculative] metadata version, always 0 */
779
850
version ?: number ;
780
851
/** the visible name of the item, what it's called on the reMarkable */
@@ -786,7 +857,7 @@ const metadata = properties(
786
857
lastModified : string ( ) ,
787
858
parent : string ( ) ,
788
859
pinned : boolean ( ) ,
789
- type : enumeration ( "DocumentType" , "CollectionType" ) ,
860
+ type : enumeration ( "DocumentType" , "CollectionType" , "TemplateType" ) ,
790
861
visibleName : string ( ) ,
791
862
} ,
792
863
{
@@ -959,7 +1030,7 @@ export interface RawRemarkableApi {
959
1030
* these are hashed differently than files.
960
1031
961
1032
* @param hash - the hash to get entries for
962
- * @returns the entries
1033
+ * @returns the entries
963
1034
*/
964
1035
getEntries ( hash : string ) : Promise < RawEntry [ ] > ;
965
1036
@@ -1563,6 +1634,8 @@ class RawRemarkable implements RawRemarkableApi {
1563
1634
// the full error for the richer content.
1564
1635
if ( collectionContent . guard ( loaded ) ) {
1565
1636
return loaded ;
1637
+ } else if ( templateContent . guard ( loaded ) ) {
1638
+ return loaded ;
1566
1639
} else if ( documentContent . guardAssert ( loaded ) ) {
1567
1640
return loaded ;
1568
1641
} else {
@@ -1824,12 +1897,34 @@ class Remarkable implements RemarkableApi {
1824
1897
throw new Error ( `couldn't find content for hash ${ hash } ` ) ;
1825
1898
}
1826
1899
1827
- const [ { visibleName, lastModified, pinned, parent, lastOpened } , content ] =
1828
- await Promise . all ( [
1829
- this . raw . getMetadata ( metaEnt . hash ) ,
1830
- this . raw . getContent ( contentEnt . hash ) ,
1831
- ] ) ;
1832
- if ( content . fileType === undefined ) {
1900
+ const [
1901
+ {
1902
+ visibleName,
1903
+ lastModified,
1904
+ pinned,
1905
+ parent,
1906
+ lastOpened,
1907
+ new : isNew ,
1908
+ source,
1909
+ } ,
1910
+ content ,
1911
+ ] = await Promise . all ( [
1912
+ this . raw . getMetadata ( metaEnt . hash ) ,
1913
+ this . raw . getContent ( contentEnt . hash ) ,
1914
+ ] ) ;
1915
+ if ( "templateVersion" in content ) {
1916
+ return {
1917
+ id,
1918
+ hash,
1919
+ visibleName,
1920
+ lastModified,
1921
+ new : isNew ,
1922
+ pinned,
1923
+ source,
1924
+ parent,
1925
+ type : "TemplateType" ,
1926
+ } ;
1927
+ } else if ( content . fileType === undefined ) {
1833
1928
return {
1834
1929
id,
1835
1930
hash,
0 commit comments