@blockslides/extension-slide 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +18 -1
- package/dist/index.d.ts +18 -1
- package/dist/index.js +69 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +69 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +1 -0
- package/src/slide.ts +91 -0
package/dist/index.d.mts
CHANGED
|
@@ -12,6 +12,23 @@ interface SlideOptions {
|
|
|
12
12
|
* @default true
|
|
13
13
|
*/
|
|
14
14
|
injectCSS: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Render mode for sizing
|
|
17
|
+
* - fixed: width/height set from size registry (mm/in/px)
|
|
18
|
+
* - dynamic: width:100% with preserved aspect ratio
|
|
19
|
+
* @default 'fixed'
|
|
20
|
+
*/
|
|
21
|
+
renderMode: "fixed" | "dynamic";
|
|
22
|
+
/**
|
|
23
|
+
* Default size applied when attrs.size is absent
|
|
24
|
+
* @default '16x9'
|
|
25
|
+
*/
|
|
26
|
+
defaultSize: "16x9" | "4x3" | "a4-portrait" | "a4-landscape" | "letter-portrait" | "letter-landscape" | "linkedin-banner";
|
|
27
|
+
/**
|
|
28
|
+
* Inject @media print/@page CSS for paper sizes
|
|
29
|
+
* @default true
|
|
30
|
+
*/
|
|
31
|
+
injectPrintCSS: boolean;
|
|
15
32
|
/**
|
|
16
33
|
* Content Security Policy nonce
|
|
17
34
|
*/
|
|
@@ -19,4 +36,4 @@ interface SlideOptions {
|
|
|
19
36
|
}
|
|
20
37
|
declare const Slide: Node<SlideOptions, any>;
|
|
21
38
|
|
|
22
|
-
export { Slide };
|
|
39
|
+
export { Slide, type SlideOptions };
|
package/dist/index.d.ts
CHANGED
|
@@ -12,6 +12,23 @@ interface SlideOptions {
|
|
|
12
12
|
* @default true
|
|
13
13
|
*/
|
|
14
14
|
injectCSS: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Render mode for sizing
|
|
17
|
+
* - fixed: width/height set from size registry (mm/in/px)
|
|
18
|
+
* - dynamic: width:100% with preserved aspect ratio
|
|
19
|
+
* @default 'fixed'
|
|
20
|
+
*/
|
|
21
|
+
renderMode: "fixed" | "dynamic";
|
|
22
|
+
/**
|
|
23
|
+
* Default size applied when attrs.size is absent
|
|
24
|
+
* @default '16x9'
|
|
25
|
+
*/
|
|
26
|
+
defaultSize: "16x9" | "4x3" | "a4-portrait" | "a4-landscape" | "letter-portrait" | "letter-landscape" | "linkedin-banner";
|
|
27
|
+
/**
|
|
28
|
+
* Inject @media print/@page CSS for paper sizes
|
|
29
|
+
* @default true
|
|
30
|
+
*/
|
|
31
|
+
injectPrintCSS: boolean;
|
|
15
32
|
/**
|
|
16
33
|
* Content Security Policy nonce
|
|
17
34
|
*/
|
|
@@ -19,4 +36,4 @@ interface SlideOptions {
|
|
|
19
36
|
}
|
|
20
37
|
declare const Slide: Node<SlideOptions, any>;
|
|
21
38
|
|
|
22
|
-
export { Slide };
|
|
39
|
+
export { Slide, type SlideOptions };
|
package/dist/index.js
CHANGED
|
@@ -40,6 +40,42 @@ var slideStyles = `
|
|
|
40
40
|
margin-bottom: var(--slide-margin-bottom);
|
|
41
41
|
}
|
|
42
42
|
`;
|
|
43
|
+
var fixedSizeStyles = `
|
|
44
|
+
.slide[data-size="16x9"] { width: 1920px; height: 1080px; }
|
|
45
|
+
.slide[data-size="4x3"] { width: 1600px; height: 1200px; }
|
|
46
|
+
.slide[data-size="a4-portrait"] { width: 210mm; height: 297mm; }
|
|
47
|
+
.slide[data-size="a4-landscape"] { width: 297mm; height: 210mm; }
|
|
48
|
+
.slide[data-size="letter-portrait"] { width: 8.5in; height: 11in; }
|
|
49
|
+
.slide[data-size="letter-landscape"] { width: 11in; height: 8.5in; }
|
|
50
|
+
.slide[data-size="linkedin-banner"] { width: 1584px; height: 396px; }
|
|
51
|
+
`.trim();
|
|
52
|
+
var dynamicSizeStyles = `
|
|
53
|
+
.slide[data-size="16x9"] { width: 100%; height: auto; aspect-ratio: 16 / 9; }
|
|
54
|
+
.slide[data-size="4x3"] { width: 100%; height: auto; aspect-ratio: 4 / 3; }
|
|
55
|
+
.slide[data-size="a4-portrait"] { width: 100%; height: auto; aspect-ratio: 210 / 297; }
|
|
56
|
+
.slide[data-size="a4-landscape"] { width: 100%; height: auto; aspect-ratio: 297 / 210; }
|
|
57
|
+
.slide[data-size="letter-portrait"] { width: 100%; height: auto; aspect-ratio: 8.5 / 11; }
|
|
58
|
+
.slide[data-size="letter-landscape"] { width: 100%; height: auto; aspect-ratio: 11 / 8.5; }
|
|
59
|
+
.slide[data-size="linkedin-banner"] { width: 100%; height: auto; aspect-ratio: 1584 / 396; }
|
|
60
|
+
`.trim();
|
|
61
|
+
var printSizeStyles = `
|
|
62
|
+
@media print {
|
|
63
|
+
.slide[data-size="a4-portrait"] { width: 210mm; height: 297mm; }
|
|
64
|
+
@page { size: A4 portrait; margin: 0; }
|
|
65
|
+
}
|
|
66
|
+
@media print {
|
|
67
|
+
.slide[data-size="a4-landscape"] { width: 297mm; height: 210mm; }
|
|
68
|
+
@page { size: A4 landscape; margin: 0; }
|
|
69
|
+
}
|
|
70
|
+
@media print {
|
|
71
|
+
.slide[data-size="letter-portrait"] { width: 8.5in; height: 11in; }
|
|
72
|
+
@page { size: Letter portrait; margin: 0; }
|
|
73
|
+
}
|
|
74
|
+
@media print {
|
|
75
|
+
.slide[data-size="letter-landscape"] { width: 11in; height: 8.5in; }
|
|
76
|
+
@page { size: Letter landscape; margin: 0; }
|
|
77
|
+
}
|
|
78
|
+
`.trim();
|
|
43
79
|
var SlidePluginKey = new import_state.PluginKey("slide");
|
|
44
80
|
var Slide = import_core.Node.create({
|
|
45
81
|
name: "slide",
|
|
@@ -51,9 +87,32 @@ var Slide = import_core.Node.create({
|
|
|
51
87
|
return {
|
|
52
88
|
HTMLAttributes: {},
|
|
53
89
|
injectCSS: true,
|
|
90
|
+
renderMode: "fixed",
|
|
91
|
+
defaultSize: "16x9",
|
|
92
|
+
injectPrintCSS: true,
|
|
54
93
|
injectNonce: void 0
|
|
55
94
|
};
|
|
56
95
|
},
|
|
96
|
+
addAttributes() {
|
|
97
|
+
return {
|
|
98
|
+
size: {
|
|
99
|
+
default: this.options.defaultSize,
|
|
100
|
+
parseHTML: (element) => element.getAttribute("data-size") || this.options.defaultSize,
|
|
101
|
+
renderHTML: (attributes) => {
|
|
102
|
+
if (!attributes.size) {
|
|
103
|
+
return { "data-size": this.options.defaultSize };
|
|
104
|
+
}
|
|
105
|
+
return { "data-size": attributes.size };
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
className: {
|
|
109
|
+
default: ""
|
|
110
|
+
},
|
|
111
|
+
id: {
|
|
112
|
+
default: null
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
},
|
|
57
116
|
parseHTML() {
|
|
58
117
|
return [{ tag: "div.slide" }];
|
|
59
118
|
},
|
|
@@ -75,6 +134,16 @@ var Slide = import_core.Node.create({
|
|
|
75
134
|
init: () => {
|
|
76
135
|
if (this.options.injectCSS && typeof document !== "undefined") {
|
|
77
136
|
(0, import_core.createStyleTag)(slideStyles, this.options.injectNonce, "slide");
|
|
137
|
+
const sizingCss = this.options.renderMode === "dynamic" ? dynamicSizeStyles : fixedSizeStyles;
|
|
138
|
+
if (sizingCss) {
|
|
139
|
+
(0, import_core.createStyleTag)(sizingCss, this.options.injectNonce, "slide-sizes");
|
|
140
|
+
}
|
|
141
|
+
if (this.options.injectPrintCSS) {
|
|
142
|
+
const printCss = printSizeStyles;
|
|
143
|
+
if (printCss) {
|
|
144
|
+
(0, import_core.createStyleTag)(printCss, this.options.injectNonce, "slide-print");
|
|
145
|
+
}
|
|
146
|
+
}
|
|
78
147
|
}
|
|
79
148
|
return {};
|
|
80
149
|
},
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/slide.ts"],"sourcesContent":["export { Slide } from \"./slide\";\n","import { Node, mergeAttributes, createStyleTag } from \"@blockslides/core\";\nimport { Plugin, PluginKey } from \"@blockslides/pm/state\";\n\nconst slideStyles = `\n.slide {\n height: var(--slide-height, 100%);\n min-height: var(--slide-min-height, 250px);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n background-color: var(--slide-bg);\n border-radius: var(--slide-border-radius);\n box-shadow: var(--slide-shadow);\n margin-bottom: var(--slide-margin-bottom);\n}\n`;\n\nexport interface SlideOptions {\n /**\n * The HTML attributes for a slide node.\n * @default {}\n * @example { class: 'foo' }\n */\n HTMLAttributes: Record<string, any>;\n /**\n * Whether to inject CSS styles\n * @default true\n */\n injectCSS: boolean;\n /**\n * Content Security Policy nonce\n */\n injectNonce?: string;\n}\n\nconst SlidePluginKey = new PluginKey(\"slide\");\n\nexport const Slide = Node.create<SlideOptions>({\n name: \"slide\",\n isolating: true,\n content: \"row+\",\n\n group: \"slide\",\n\n defining: true,\n\n addOptions() {\n return {\n HTMLAttributes: {},\n injectCSS: true,\n injectNonce: undefined,\n };\n },\n\n parseHTML() {\n return [{ tag: \"div.slide\" }];\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\n \"div\",\n mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, {\n class: \"slide\",\n \"data-node-type\": \"slide\",\n }),\n 0,\n ];\n },\n\n addProseMirrorPlugins() {\n return [\n new Plugin({\n key: SlidePluginKey,\n state: {\n init: () => {\n if (this.options.injectCSS && typeof document !== \"undefined\") {\n createStyleTag(slideStyles, this.options.injectNonce, \"slide\");\n }\n return {};\n },\n apply: (_tr, pluginState: Record<string, never>) => pluginState,\n },\n }),\n ];\n },\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,kBAAsD;AACtD,mBAAkC;AAElC,IAAM,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/slide.ts"],"sourcesContent":["export { Slide } from \"./slide\";\nexport type { SlideOptions } from \"./slide\";\n","import { Node, mergeAttributes, createStyleTag } from \"@blockslides/core\";\nimport { Plugin, PluginKey } from \"@blockslides/pm/state\";\n\nconst slideStyles = `\n.slide {\n height: var(--slide-height, 100%);\n min-height: var(--slide-min-height, 250px);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n background-color: var(--slide-bg);\n border-radius: var(--slide-border-radius);\n box-shadow: var(--slide-shadow);\n margin-bottom: var(--slide-margin-bottom);\n}\n`;\n\nconst fixedSizeStyles = `\n.slide[data-size=\"16x9\"] { width: 1920px; height: 1080px; }\n.slide[data-size=\"4x3\"] { width: 1600px; height: 1200px; }\n.slide[data-size=\"a4-portrait\"] { width: 210mm; height: 297mm; }\n.slide[data-size=\"a4-landscape\"] { width: 297mm; height: 210mm; }\n.slide[data-size=\"letter-portrait\"] { width: 8.5in; height: 11in; }\n.slide[data-size=\"letter-landscape\"] { width: 11in; height: 8.5in; }\n.slide[data-size=\"linkedin-banner\"] { width: 1584px; height: 396px; }\n`.trim();\n\nconst dynamicSizeStyles = `\n.slide[data-size=\"16x9\"] { width: 100%; height: auto; aspect-ratio: 16 / 9; }\n.slide[data-size=\"4x3\"] { width: 100%; height: auto; aspect-ratio: 4 / 3; }\n.slide[data-size=\"a4-portrait\"] { width: 100%; height: auto; aspect-ratio: 210 / 297; }\n.slide[data-size=\"a4-landscape\"] { width: 100%; height: auto; aspect-ratio: 297 / 210; }\n.slide[data-size=\"letter-portrait\"] { width: 100%; height: auto; aspect-ratio: 8.5 / 11; }\n.slide[data-size=\"letter-landscape\"] { width: 100%; height: auto; aspect-ratio: 11 / 8.5; }\n.slide[data-size=\"linkedin-banner\"] { width: 100%; height: auto; aspect-ratio: 1584 / 396; }\n`.trim();\n\nconst printSizeStyles = `\n@media print {\n .slide[data-size=\"a4-portrait\"] { width: 210mm; height: 297mm; }\n @page { size: A4 portrait; margin: 0; }\n}\n@media print {\n .slide[data-size=\"a4-landscape\"] { width: 297mm; height: 210mm; }\n @page { size: A4 landscape; margin: 0; }\n}\n@media print {\n .slide[data-size=\"letter-portrait\"] { width: 8.5in; height: 11in; }\n @page { size: Letter portrait; margin: 0; }\n}\n@media print {\n .slide[data-size=\"letter-landscape\"] { width: 11in; height: 8.5in; }\n @page { size: Letter landscape; margin: 0; }\n}\n`.trim();\n\nexport interface SlideOptions {\n /**\n * The HTML attributes for a slide node.\n * @default {}\n * @example { class: 'foo' }\n */\n HTMLAttributes: Record<string, any>;\n /**\n * Whether to inject CSS styles\n * @default true\n */\n injectCSS: boolean;\n /**\n * Render mode for sizing\n * - fixed: width/height set from size registry (mm/in/px)\n * - dynamic: width:100% with preserved aspect ratio\n * @default 'fixed'\n */\n renderMode: \"fixed\" | \"dynamic\";\n /**\n * Default size applied when attrs.size is absent\n * @default '16x9'\n */\n defaultSize: \"16x9\" | \"4x3\" | \"a4-portrait\" | \"a4-landscape\" | \"letter-portrait\" | \"letter-landscape\" | \"linkedin-banner\";\n /**\n * Inject @media print/@page CSS for paper sizes\n * @default true\n */\n injectPrintCSS: boolean;\n /**\n * Content Security Policy nonce\n */\n injectNonce?: string;\n}\n\nconst SlidePluginKey = new PluginKey(\"slide\");\n\nexport const Slide = Node.create<SlideOptions>({\n name: \"slide\",\n isolating: true,\n content: \"row+\",\n\n group: \"slide\",\n\n defining: true,\n\n addOptions() {\n return {\n HTMLAttributes: {},\n injectCSS: true,\n renderMode: \"fixed\",\n defaultSize: \"16x9\",\n injectPrintCSS: true,\n injectNonce: undefined,\n };\n },\n\n addAttributes() {\n return {\n size: {\n default: this.options.defaultSize,\n parseHTML: (element) => element.getAttribute(\"data-size\") || this.options.defaultSize,\n renderHTML: (attributes) => {\n if (!attributes.size) {\n return { \"data-size\": this.options.defaultSize };\n }\n return { \"data-size\": attributes.size };\n },\n },\n className: {\n default: \"\",\n },\n id: {\n default: null,\n },\n };\n },\n\n parseHTML() {\n return [{ tag: \"div.slide\" }];\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\n \"div\",\n mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, {\n class: \"slide\",\n \"data-node-type\": \"slide\",\n }),\n 0,\n ];\n },\n\n addProseMirrorPlugins() {\n return [\n new Plugin({\n key: SlidePluginKey,\n state: {\n init: () => {\n if (this.options.injectCSS && typeof document !== \"undefined\") {\n createStyleTag(slideStyles, this.options.injectNonce, \"slide\");\n const sizingCss =\n this.options.renderMode === \"dynamic\" ? dynamicSizeStyles : fixedSizeStyles;\n if (sizingCss) {\n createStyleTag(sizingCss, this.options.injectNonce, \"slide-sizes\");\n }\n if (this.options.injectPrintCSS) {\n const printCss = printSizeStyles;\n if (printCss) {\n createStyleTag(printCss, this.options.injectNonce, \"slide-print\");\n }\n }\n }\n return {};\n },\n apply: (_tr, pluginState: Record<string, never>) => pluginState,\n },\n }),\n ];\n },\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,kBAAsD;AACtD,mBAAkC;AAElC,IAAM,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAcpB,IAAM,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQtB,KAAK;AAEP,IAAM,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQxB,KAAK;AAEP,IAAM,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBtB,KAAK;AAqCP,IAAM,iBAAiB,IAAI,uBAAU,OAAO;AAErC,IAAM,QAAQ,iBAAK,OAAqB;AAAA,EAC7C,MAAM;AAAA,EACN,WAAW;AAAA,EACX,SAAS;AAAA,EAET,OAAO;AAAA,EAEP,UAAU;AAAA,EAEV,aAAa;AACX,WAAO;AAAA,MACL,gBAAgB,CAAC;AAAA,MACjB,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,aAAa;AAAA,MACb,gBAAgB;AAAA,MAChB,aAAa;AAAA,IACf;AAAA,EACF;AAAA,EAEA,gBAAgB;AACd,WAAO;AAAA,MACL,MAAM;AAAA,QACJ,SAAS,KAAK,QAAQ;AAAA,QACtB,WAAW,CAAC,YAAY,QAAQ,aAAa,WAAW,KAAK,KAAK,QAAQ;AAAA,QAC1E,YAAY,CAAC,eAAe;AAC1B,cAAI,CAAC,WAAW,MAAM;AACpB,mBAAO,EAAE,aAAa,KAAK,QAAQ,YAAY;AAAA,UACjD;AACA,iBAAO,EAAE,aAAa,WAAW,KAAK;AAAA,QACxC;AAAA,MACF;AAAA,MACA,WAAW;AAAA,QACT,SAAS;AAAA,MACX;AAAA,MACA,IAAI;AAAA,QACF,SAAS;AAAA,MACX;AAAA,IACF;AAAA,EACF;AAAA,EAEA,YAAY;AACV,WAAO,CAAC,EAAE,KAAK,YAAY,CAAC;AAAA,EAC9B;AAAA,EAEA,WAAW,EAAE,eAAe,GAAG;AAC7B,WAAO;AAAA,MACL;AAAA,UACA,6BAAgB,KAAK,QAAQ,gBAAgB,gBAAgB;AAAA,QAC3D,OAAO;AAAA,QACP,kBAAkB;AAAA,MACpB,CAAC;AAAA,MACD;AAAA,IACF;AAAA,EACF;AAAA,EAEA,wBAAwB;AACtB,WAAO;AAAA,MACL,IAAI,oBAAO;AAAA,QACT,KAAK;AAAA,QACL,OAAO;AAAA,UACL,MAAM,MAAM;AACV,gBAAI,KAAK,QAAQ,aAAa,OAAO,aAAa,aAAa;AAC7D,8CAAe,aAAa,KAAK,QAAQ,aAAa,OAAO;AAC7D,oBAAM,YACJ,KAAK,QAAQ,eAAe,YAAY,oBAAoB;AAC9D,kBAAI,WAAW;AACb,gDAAe,WAAW,KAAK,QAAQ,aAAa,aAAa;AAAA,cACnE;AACA,kBAAI,KAAK,QAAQ,gBAAgB;AAC/B,sBAAM,WAAW;AACjB,oBAAI,UAAU;AACZ,kDAAe,UAAU,KAAK,QAAQ,aAAa,aAAa;AAAA,gBAClE;AAAA,cACF;AAAA,YACF;AACA,mBAAO,CAAC;AAAA,UACV;AAAA,UACA,OAAO,CAAC,KAAK,gBAAuC;AAAA,QACtD;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACF,CAAC;","names":[]}
|
package/dist/index.mjs
CHANGED
|
@@ -14,6 +14,42 @@ var slideStyles = `
|
|
|
14
14
|
margin-bottom: var(--slide-margin-bottom);
|
|
15
15
|
}
|
|
16
16
|
`;
|
|
17
|
+
var fixedSizeStyles = `
|
|
18
|
+
.slide[data-size="16x9"] { width: 1920px; height: 1080px; }
|
|
19
|
+
.slide[data-size="4x3"] { width: 1600px; height: 1200px; }
|
|
20
|
+
.slide[data-size="a4-portrait"] { width: 210mm; height: 297mm; }
|
|
21
|
+
.slide[data-size="a4-landscape"] { width: 297mm; height: 210mm; }
|
|
22
|
+
.slide[data-size="letter-portrait"] { width: 8.5in; height: 11in; }
|
|
23
|
+
.slide[data-size="letter-landscape"] { width: 11in; height: 8.5in; }
|
|
24
|
+
.slide[data-size="linkedin-banner"] { width: 1584px; height: 396px; }
|
|
25
|
+
`.trim();
|
|
26
|
+
var dynamicSizeStyles = `
|
|
27
|
+
.slide[data-size="16x9"] { width: 100%; height: auto; aspect-ratio: 16 / 9; }
|
|
28
|
+
.slide[data-size="4x3"] { width: 100%; height: auto; aspect-ratio: 4 / 3; }
|
|
29
|
+
.slide[data-size="a4-portrait"] { width: 100%; height: auto; aspect-ratio: 210 / 297; }
|
|
30
|
+
.slide[data-size="a4-landscape"] { width: 100%; height: auto; aspect-ratio: 297 / 210; }
|
|
31
|
+
.slide[data-size="letter-portrait"] { width: 100%; height: auto; aspect-ratio: 8.5 / 11; }
|
|
32
|
+
.slide[data-size="letter-landscape"] { width: 100%; height: auto; aspect-ratio: 11 / 8.5; }
|
|
33
|
+
.slide[data-size="linkedin-banner"] { width: 100%; height: auto; aspect-ratio: 1584 / 396; }
|
|
34
|
+
`.trim();
|
|
35
|
+
var printSizeStyles = `
|
|
36
|
+
@media print {
|
|
37
|
+
.slide[data-size="a4-portrait"] { width: 210mm; height: 297mm; }
|
|
38
|
+
@page { size: A4 portrait; margin: 0; }
|
|
39
|
+
}
|
|
40
|
+
@media print {
|
|
41
|
+
.slide[data-size="a4-landscape"] { width: 297mm; height: 210mm; }
|
|
42
|
+
@page { size: A4 landscape; margin: 0; }
|
|
43
|
+
}
|
|
44
|
+
@media print {
|
|
45
|
+
.slide[data-size="letter-portrait"] { width: 8.5in; height: 11in; }
|
|
46
|
+
@page { size: Letter portrait; margin: 0; }
|
|
47
|
+
}
|
|
48
|
+
@media print {
|
|
49
|
+
.slide[data-size="letter-landscape"] { width: 11in; height: 8.5in; }
|
|
50
|
+
@page { size: Letter landscape; margin: 0; }
|
|
51
|
+
}
|
|
52
|
+
`.trim();
|
|
17
53
|
var SlidePluginKey = new PluginKey("slide");
|
|
18
54
|
var Slide = Node.create({
|
|
19
55
|
name: "slide",
|
|
@@ -25,9 +61,32 @@ var Slide = Node.create({
|
|
|
25
61
|
return {
|
|
26
62
|
HTMLAttributes: {},
|
|
27
63
|
injectCSS: true,
|
|
64
|
+
renderMode: "fixed",
|
|
65
|
+
defaultSize: "16x9",
|
|
66
|
+
injectPrintCSS: true,
|
|
28
67
|
injectNonce: void 0
|
|
29
68
|
};
|
|
30
69
|
},
|
|
70
|
+
addAttributes() {
|
|
71
|
+
return {
|
|
72
|
+
size: {
|
|
73
|
+
default: this.options.defaultSize,
|
|
74
|
+
parseHTML: (element) => element.getAttribute("data-size") || this.options.defaultSize,
|
|
75
|
+
renderHTML: (attributes) => {
|
|
76
|
+
if (!attributes.size) {
|
|
77
|
+
return { "data-size": this.options.defaultSize };
|
|
78
|
+
}
|
|
79
|
+
return { "data-size": attributes.size };
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
className: {
|
|
83
|
+
default: ""
|
|
84
|
+
},
|
|
85
|
+
id: {
|
|
86
|
+
default: null
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
},
|
|
31
90
|
parseHTML() {
|
|
32
91
|
return [{ tag: "div.slide" }];
|
|
33
92
|
},
|
|
@@ -49,6 +108,16 @@ var Slide = Node.create({
|
|
|
49
108
|
init: () => {
|
|
50
109
|
if (this.options.injectCSS && typeof document !== "undefined") {
|
|
51
110
|
createStyleTag(slideStyles, this.options.injectNonce, "slide");
|
|
111
|
+
const sizingCss = this.options.renderMode === "dynamic" ? dynamicSizeStyles : fixedSizeStyles;
|
|
112
|
+
if (sizingCss) {
|
|
113
|
+
createStyleTag(sizingCss, this.options.injectNonce, "slide-sizes");
|
|
114
|
+
}
|
|
115
|
+
if (this.options.injectPrintCSS) {
|
|
116
|
+
const printCss = printSizeStyles;
|
|
117
|
+
if (printCss) {
|
|
118
|
+
createStyleTag(printCss, this.options.injectNonce, "slide-print");
|
|
119
|
+
}
|
|
120
|
+
}
|
|
52
121
|
}
|
|
53
122
|
return {};
|
|
54
123
|
},
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/slide.ts"],"sourcesContent":["import { Node, mergeAttributes, createStyleTag } from \"@blockslides/core\";\nimport { Plugin, PluginKey } from \"@blockslides/pm/state\";\n\nconst slideStyles = `\n.slide {\n height: var(--slide-height, 100%);\n min-height: var(--slide-min-height, 250px);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n background-color: var(--slide-bg);\n border-radius: var(--slide-border-radius);\n box-shadow: var(--slide-shadow);\n margin-bottom: var(--slide-margin-bottom);\n}\n`;\n\nexport interface SlideOptions {\n /**\n * The HTML attributes for a slide node.\n * @default {}\n * @example { class: 'foo' }\n */\n HTMLAttributes: Record<string, any>;\n /**\n * Whether to inject CSS styles\n * @default true\n */\n injectCSS: boolean;\n /**\n * Content Security Policy nonce\n */\n injectNonce?: string;\n}\n\nconst SlidePluginKey = new PluginKey(\"slide\");\n\nexport const Slide = Node.create<SlideOptions>({\n name: \"slide\",\n isolating: true,\n content: \"row+\",\n\n group: \"slide\",\n\n defining: true,\n\n addOptions() {\n return {\n HTMLAttributes: {},\n injectCSS: true,\n injectNonce: undefined,\n };\n },\n\n parseHTML() {\n return [{ tag: \"div.slide\" }];\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\n \"div\",\n mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, {\n class: \"slide\",\n \"data-node-type\": \"slide\",\n }),\n 0,\n ];\n },\n\n addProseMirrorPlugins() {\n return [\n new Plugin({\n key: SlidePluginKey,\n state: {\n init: () => {\n if (this.options.injectCSS && typeof document !== \"undefined\") {\n createStyleTag(slideStyles, this.options.injectNonce, \"slide\");\n }\n return {};\n },\n apply: (_tr, pluginState: Record<string, never>) => pluginState,\n },\n }),\n ];\n },\n});\n"],"mappings":";AAAA,SAAS,MAAM,iBAAiB,sBAAsB;AACtD,SAAS,QAAQ,iBAAiB;AAElC,IAAM,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;
|
|
1
|
+
{"version":3,"sources":["../src/slide.ts"],"sourcesContent":["import { Node, mergeAttributes, createStyleTag } from \"@blockslides/core\";\nimport { Plugin, PluginKey } from \"@blockslides/pm/state\";\n\nconst slideStyles = `\n.slide {\n height: var(--slide-height, 100%);\n min-height: var(--slide-min-height, 250px);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n background-color: var(--slide-bg);\n border-radius: var(--slide-border-radius);\n box-shadow: var(--slide-shadow);\n margin-bottom: var(--slide-margin-bottom);\n}\n`;\n\nconst fixedSizeStyles = `\n.slide[data-size=\"16x9\"] { width: 1920px; height: 1080px; }\n.slide[data-size=\"4x3\"] { width: 1600px; height: 1200px; }\n.slide[data-size=\"a4-portrait\"] { width: 210mm; height: 297mm; }\n.slide[data-size=\"a4-landscape\"] { width: 297mm; height: 210mm; }\n.slide[data-size=\"letter-portrait\"] { width: 8.5in; height: 11in; }\n.slide[data-size=\"letter-landscape\"] { width: 11in; height: 8.5in; }\n.slide[data-size=\"linkedin-banner\"] { width: 1584px; height: 396px; }\n`.trim();\n\nconst dynamicSizeStyles = `\n.slide[data-size=\"16x9\"] { width: 100%; height: auto; aspect-ratio: 16 / 9; }\n.slide[data-size=\"4x3\"] { width: 100%; height: auto; aspect-ratio: 4 / 3; }\n.slide[data-size=\"a4-portrait\"] { width: 100%; height: auto; aspect-ratio: 210 / 297; }\n.slide[data-size=\"a4-landscape\"] { width: 100%; height: auto; aspect-ratio: 297 / 210; }\n.slide[data-size=\"letter-portrait\"] { width: 100%; height: auto; aspect-ratio: 8.5 / 11; }\n.slide[data-size=\"letter-landscape\"] { width: 100%; height: auto; aspect-ratio: 11 / 8.5; }\n.slide[data-size=\"linkedin-banner\"] { width: 100%; height: auto; aspect-ratio: 1584 / 396; }\n`.trim();\n\nconst printSizeStyles = `\n@media print {\n .slide[data-size=\"a4-portrait\"] { width: 210mm; height: 297mm; }\n @page { size: A4 portrait; margin: 0; }\n}\n@media print {\n .slide[data-size=\"a4-landscape\"] { width: 297mm; height: 210mm; }\n @page { size: A4 landscape; margin: 0; }\n}\n@media print {\n .slide[data-size=\"letter-portrait\"] { width: 8.5in; height: 11in; }\n @page { size: Letter portrait; margin: 0; }\n}\n@media print {\n .slide[data-size=\"letter-landscape\"] { width: 11in; height: 8.5in; }\n @page { size: Letter landscape; margin: 0; }\n}\n`.trim();\n\nexport interface SlideOptions {\n /**\n * The HTML attributes for a slide node.\n * @default {}\n * @example { class: 'foo' }\n */\n HTMLAttributes: Record<string, any>;\n /**\n * Whether to inject CSS styles\n * @default true\n */\n injectCSS: boolean;\n /**\n * Render mode for sizing\n * - fixed: width/height set from size registry (mm/in/px)\n * - dynamic: width:100% with preserved aspect ratio\n * @default 'fixed'\n */\n renderMode: \"fixed\" | \"dynamic\";\n /**\n * Default size applied when attrs.size is absent\n * @default '16x9'\n */\n defaultSize: \"16x9\" | \"4x3\" | \"a4-portrait\" | \"a4-landscape\" | \"letter-portrait\" | \"letter-landscape\" | \"linkedin-banner\";\n /**\n * Inject @media print/@page CSS for paper sizes\n * @default true\n */\n injectPrintCSS: boolean;\n /**\n * Content Security Policy nonce\n */\n injectNonce?: string;\n}\n\nconst SlidePluginKey = new PluginKey(\"slide\");\n\nexport const Slide = Node.create<SlideOptions>({\n name: \"slide\",\n isolating: true,\n content: \"row+\",\n\n group: \"slide\",\n\n defining: true,\n\n addOptions() {\n return {\n HTMLAttributes: {},\n injectCSS: true,\n renderMode: \"fixed\",\n defaultSize: \"16x9\",\n injectPrintCSS: true,\n injectNonce: undefined,\n };\n },\n\n addAttributes() {\n return {\n size: {\n default: this.options.defaultSize,\n parseHTML: (element) => element.getAttribute(\"data-size\") || this.options.defaultSize,\n renderHTML: (attributes) => {\n if (!attributes.size) {\n return { \"data-size\": this.options.defaultSize };\n }\n return { \"data-size\": attributes.size };\n },\n },\n className: {\n default: \"\",\n },\n id: {\n default: null,\n },\n };\n },\n\n parseHTML() {\n return [{ tag: \"div.slide\" }];\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\n \"div\",\n mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, {\n class: \"slide\",\n \"data-node-type\": \"slide\",\n }),\n 0,\n ];\n },\n\n addProseMirrorPlugins() {\n return [\n new Plugin({\n key: SlidePluginKey,\n state: {\n init: () => {\n if (this.options.injectCSS && typeof document !== \"undefined\") {\n createStyleTag(slideStyles, this.options.injectNonce, \"slide\");\n const sizingCss =\n this.options.renderMode === \"dynamic\" ? dynamicSizeStyles : fixedSizeStyles;\n if (sizingCss) {\n createStyleTag(sizingCss, this.options.injectNonce, \"slide-sizes\");\n }\n if (this.options.injectPrintCSS) {\n const printCss = printSizeStyles;\n if (printCss) {\n createStyleTag(printCss, this.options.injectNonce, \"slide-print\");\n }\n }\n }\n return {};\n },\n apply: (_tr, pluginState: Record<string, never>) => pluginState,\n },\n }),\n ];\n },\n});\n"],"mappings":";AAAA,SAAS,MAAM,iBAAiB,sBAAsB;AACtD,SAAS,QAAQ,iBAAiB;AAElC,IAAM,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAcpB,IAAM,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQtB,KAAK;AAEP,IAAM,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQxB,KAAK;AAEP,IAAM,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBtB,KAAK;AAqCP,IAAM,iBAAiB,IAAI,UAAU,OAAO;AAErC,IAAM,QAAQ,KAAK,OAAqB;AAAA,EAC7C,MAAM;AAAA,EACN,WAAW;AAAA,EACX,SAAS;AAAA,EAET,OAAO;AAAA,EAEP,UAAU;AAAA,EAEV,aAAa;AACX,WAAO;AAAA,MACL,gBAAgB,CAAC;AAAA,MACjB,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,aAAa;AAAA,MACb,gBAAgB;AAAA,MAChB,aAAa;AAAA,IACf;AAAA,EACF;AAAA,EAEA,gBAAgB;AACd,WAAO;AAAA,MACL,MAAM;AAAA,QACJ,SAAS,KAAK,QAAQ;AAAA,QACtB,WAAW,CAAC,YAAY,QAAQ,aAAa,WAAW,KAAK,KAAK,QAAQ;AAAA,QAC1E,YAAY,CAAC,eAAe;AAC1B,cAAI,CAAC,WAAW,MAAM;AACpB,mBAAO,EAAE,aAAa,KAAK,QAAQ,YAAY;AAAA,UACjD;AACA,iBAAO,EAAE,aAAa,WAAW,KAAK;AAAA,QACxC;AAAA,MACF;AAAA,MACA,WAAW;AAAA,QACT,SAAS;AAAA,MACX;AAAA,MACA,IAAI;AAAA,QACF,SAAS;AAAA,MACX;AAAA,IACF;AAAA,EACF;AAAA,EAEA,YAAY;AACV,WAAO,CAAC,EAAE,KAAK,YAAY,CAAC;AAAA,EAC9B;AAAA,EAEA,WAAW,EAAE,eAAe,GAAG;AAC7B,WAAO;AAAA,MACL;AAAA,MACA,gBAAgB,KAAK,QAAQ,gBAAgB,gBAAgB;AAAA,QAC3D,OAAO;AAAA,QACP,kBAAkB;AAAA,MACpB,CAAC;AAAA,MACD;AAAA,IACF;AAAA,EACF;AAAA,EAEA,wBAAwB;AACtB,WAAO;AAAA,MACL,IAAI,OAAO;AAAA,QACT,KAAK;AAAA,QACL,OAAO;AAAA,UACL,MAAM,MAAM;AACV,gBAAI,KAAK,QAAQ,aAAa,OAAO,aAAa,aAAa;AAC7D,6BAAe,aAAa,KAAK,QAAQ,aAAa,OAAO;AAC7D,oBAAM,YACJ,KAAK,QAAQ,eAAe,YAAY,oBAAoB;AAC9D,kBAAI,WAAW;AACb,+BAAe,WAAW,KAAK,QAAQ,aAAa,aAAa;AAAA,cACnE;AACA,kBAAI,KAAK,QAAQ,gBAAgB;AAC/B,sBAAM,WAAW;AACjB,oBAAI,UAAU;AACZ,iCAAe,UAAU,KAAK,QAAQ,aAAa,aAAa;AAAA,gBAClE;AAAA,cACF;AAAA,YACF;AACA,mBAAO,CAAC;AAAA,UACV;AAAA,UACA,OAAO,CAAC,KAAK,gBAAuC;AAAA,QACtD;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACF,CAAC;","names":[]}
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
package/src/slide.ts
CHANGED
|
@@ -15,6 +15,45 @@ const slideStyles = `
|
|
|
15
15
|
}
|
|
16
16
|
`;
|
|
17
17
|
|
|
18
|
+
const fixedSizeStyles = `
|
|
19
|
+
.slide[data-size="16x9"] { width: 1920px; height: 1080px; }
|
|
20
|
+
.slide[data-size="4x3"] { width: 1600px; height: 1200px; }
|
|
21
|
+
.slide[data-size="a4-portrait"] { width: 210mm; height: 297mm; }
|
|
22
|
+
.slide[data-size="a4-landscape"] { width: 297mm; height: 210mm; }
|
|
23
|
+
.slide[data-size="letter-portrait"] { width: 8.5in; height: 11in; }
|
|
24
|
+
.slide[data-size="letter-landscape"] { width: 11in; height: 8.5in; }
|
|
25
|
+
.slide[data-size="linkedin-banner"] { width: 1584px; height: 396px; }
|
|
26
|
+
`.trim();
|
|
27
|
+
|
|
28
|
+
const dynamicSizeStyles = `
|
|
29
|
+
.slide[data-size="16x9"] { width: 100%; height: auto; aspect-ratio: 16 / 9; }
|
|
30
|
+
.slide[data-size="4x3"] { width: 100%; height: auto; aspect-ratio: 4 / 3; }
|
|
31
|
+
.slide[data-size="a4-portrait"] { width: 100%; height: auto; aspect-ratio: 210 / 297; }
|
|
32
|
+
.slide[data-size="a4-landscape"] { width: 100%; height: auto; aspect-ratio: 297 / 210; }
|
|
33
|
+
.slide[data-size="letter-portrait"] { width: 100%; height: auto; aspect-ratio: 8.5 / 11; }
|
|
34
|
+
.slide[data-size="letter-landscape"] { width: 100%; height: auto; aspect-ratio: 11 / 8.5; }
|
|
35
|
+
.slide[data-size="linkedin-banner"] { width: 100%; height: auto; aspect-ratio: 1584 / 396; }
|
|
36
|
+
`.trim();
|
|
37
|
+
|
|
38
|
+
const printSizeStyles = `
|
|
39
|
+
@media print {
|
|
40
|
+
.slide[data-size="a4-portrait"] { width: 210mm; height: 297mm; }
|
|
41
|
+
@page { size: A4 portrait; margin: 0; }
|
|
42
|
+
}
|
|
43
|
+
@media print {
|
|
44
|
+
.slide[data-size="a4-landscape"] { width: 297mm; height: 210mm; }
|
|
45
|
+
@page { size: A4 landscape; margin: 0; }
|
|
46
|
+
}
|
|
47
|
+
@media print {
|
|
48
|
+
.slide[data-size="letter-portrait"] { width: 8.5in; height: 11in; }
|
|
49
|
+
@page { size: Letter portrait; margin: 0; }
|
|
50
|
+
}
|
|
51
|
+
@media print {
|
|
52
|
+
.slide[data-size="letter-landscape"] { width: 11in; height: 8.5in; }
|
|
53
|
+
@page { size: Letter landscape; margin: 0; }
|
|
54
|
+
}
|
|
55
|
+
`.trim();
|
|
56
|
+
|
|
18
57
|
export interface SlideOptions {
|
|
19
58
|
/**
|
|
20
59
|
* The HTML attributes for a slide node.
|
|
@@ -27,6 +66,23 @@ export interface SlideOptions {
|
|
|
27
66
|
* @default true
|
|
28
67
|
*/
|
|
29
68
|
injectCSS: boolean;
|
|
69
|
+
/**
|
|
70
|
+
* Render mode for sizing
|
|
71
|
+
* - fixed: width/height set from size registry (mm/in/px)
|
|
72
|
+
* - dynamic: width:100% with preserved aspect ratio
|
|
73
|
+
* @default 'fixed'
|
|
74
|
+
*/
|
|
75
|
+
renderMode: "fixed" | "dynamic";
|
|
76
|
+
/**
|
|
77
|
+
* Default size applied when attrs.size is absent
|
|
78
|
+
* @default '16x9'
|
|
79
|
+
*/
|
|
80
|
+
defaultSize: "16x9" | "4x3" | "a4-portrait" | "a4-landscape" | "letter-portrait" | "letter-landscape" | "linkedin-banner";
|
|
81
|
+
/**
|
|
82
|
+
* Inject @media print/@page CSS for paper sizes
|
|
83
|
+
* @default true
|
|
84
|
+
*/
|
|
85
|
+
injectPrintCSS: boolean;
|
|
30
86
|
/**
|
|
31
87
|
* Content Security Policy nonce
|
|
32
88
|
*/
|
|
@@ -48,10 +104,34 @@ export const Slide = Node.create<SlideOptions>({
|
|
|
48
104
|
return {
|
|
49
105
|
HTMLAttributes: {},
|
|
50
106
|
injectCSS: true,
|
|
107
|
+
renderMode: "fixed",
|
|
108
|
+
defaultSize: "16x9",
|
|
109
|
+
injectPrintCSS: true,
|
|
51
110
|
injectNonce: undefined,
|
|
52
111
|
};
|
|
53
112
|
},
|
|
54
113
|
|
|
114
|
+
addAttributes() {
|
|
115
|
+
return {
|
|
116
|
+
size: {
|
|
117
|
+
default: this.options.defaultSize,
|
|
118
|
+
parseHTML: (element) => element.getAttribute("data-size") || this.options.defaultSize,
|
|
119
|
+
renderHTML: (attributes) => {
|
|
120
|
+
if (!attributes.size) {
|
|
121
|
+
return { "data-size": this.options.defaultSize };
|
|
122
|
+
}
|
|
123
|
+
return { "data-size": attributes.size };
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
className: {
|
|
127
|
+
default: "",
|
|
128
|
+
},
|
|
129
|
+
id: {
|
|
130
|
+
default: null,
|
|
131
|
+
},
|
|
132
|
+
};
|
|
133
|
+
},
|
|
134
|
+
|
|
55
135
|
parseHTML() {
|
|
56
136
|
return [{ tag: "div.slide" }];
|
|
57
137
|
},
|
|
@@ -75,6 +155,17 @@ export const Slide = Node.create<SlideOptions>({
|
|
|
75
155
|
init: () => {
|
|
76
156
|
if (this.options.injectCSS && typeof document !== "undefined") {
|
|
77
157
|
createStyleTag(slideStyles, this.options.injectNonce, "slide");
|
|
158
|
+
const sizingCss =
|
|
159
|
+
this.options.renderMode === "dynamic" ? dynamicSizeStyles : fixedSizeStyles;
|
|
160
|
+
if (sizingCss) {
|
|
161
|
+
createStyleTag(sizingCss, this.options.injectNonce, "slide-sizes");
|
|
162
|
+
}
|
|
163
|
+
if (this.options.injectPrintCSS) {
|
|
164
|
+
const printCss = printSizeStyles;
|
|
165
|
+
if (printCss) {
|
|
166
|
+
createStyleTag(printCss, this.options.injectNonce, "slide-print");
|
|
167
|
+
}
|
|
168
|
+
}
|
|
78
169
|
}
|
|
79
170
|
return {};
|
|
80
171
|
},
|