svelte-preprocess-org 0.1.1 → 0.2.1

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.js CHANGED
@@ -1 +1 @@
1
- import{execSync as t}from"node:child_process";import{join as e}from"node:path";function r(r,o){const{latexEnvironmentFormat:n,latexFragmentFormat:m,srcBlockFormat:a,imports:i}=o||{};let s=`/usr/bin/env emacs --script ${e(import.meta.dirname,"lisp","convert.el")}`;var c;return n&&(s+=` --latex-environment-format ${n}`),m&&(s+=` --latex-fragment-format ${m}`),a&&(s+=` --src-block-format ${a}`),i&&(s+=` --preface "(setq og-svelte-component-import-alist ${c=i,`'(${Object.entries(c).map((([t,e])=>`("${t}" . "${e}")`))})`})"`),t(s,{input:r}).toString()}function o(t){const{extensions:e=[".org"],...o}=t||{};return{markup({content:t,filename:n}){if(n&&!e.some((t=>n.endsWith(t))))return{code:t};return{code:r(t,o)}}}}export{o as default,o as orgPreprocess};
1
+ import{execSync as n}from"node:child_process";import{join as r}from"node:path";class t{name;constructor(n){this.name=n}}class e{sexp;constructor(n){this.sexp=n}}function o(n){return n instanceof Object&&"car"in n&&"cdr"in n}function i(n){return null===n}function c(n,r){return{car:n,cdr:r}}function s(...n){if(0===n.length)return null;const[r,...t]=n;return c(r,s(...t))}function u(n){if(o(n))return`(${a(n)})`;if(i(n))return"nil";if("string"==typeof n)return`"${n}"`;if(function(n){return"number"==typeof n}(n))return n.toString();if(function(n){return"boolean"==typeof n}(n))return n?"t":"nil";if(n instanceof t)return n.name;if(n instanceof e)return`'${u(n.sexp)}`;throw new TypeError("Unknown type of S-expression: "+typeof n)}function a(n){let r="";if(o(n.car)?r+=`(${a(n.car)})`:r+=u(n.car),o(n.cdr))r+=` ${a(n.cdr)}`;else{if(i(n.cdr))return r;r+=` . ${u(n.cdr)}`}return r}function f(o){const{extensions:i=[".org"],...a}=o||{};return{markup({content:o,filename:f}){if(f&&!i.some((n=>f.endsWith(n))))return{code:o};const l=function(o,i){const{latexEnvironmentFormat:a,latexFragmentFormat:f,srcBlockFormat:l,imports:m}=i||{};let p=`/usr/bin/env emacs --script ${r(import.meta.dirname,"lisp","convert.el")}`;a&&(p+=` --latex-environment-format ${a}`),f&&(p+=` --latex-fragment-format ${f}`),l&&(p+=` --src-block-format ${l}`),m&&(p+=` --preface '${u(s(new t("setq"),new t("org-svelte-component-import-alist"),new e(s(...Object.entries(m).map((([n,r])=>c(n,r))))))).replaceAll("'","'\\''")}'`);return n(p,{input:o}).toString()}(o,a);return{code:l}}}}export{f as default,f as orgPreprocess};
@@ -0,0 +1,4 @@
1
+ # Org-mode exporter backend for Svelte components
2
+
3
+ `ox-svelte` is an opinionated Org-mode exporter backend that generates a Svelte
4
+ component.
@@ -0,0 +1,19 @@
1
+ import type { SvelteComponent } from 'svelte';
2
+
3
+ declare module 'ox-svelte' {
4
+ export type OrgModule = {
5
+ default: typeof SvelteComponent;
6
+ metadata: OrgMetadata;
7
+ };
8
+
9
+ export type OrgMetadata = {
10
+ title: string?;
11
+ subtitle: string?;
12
+ author: string?;
13
+ date: string?;
14
+ description: string?;
15
+ keywords: string[]?;
16
+ language: string?;
17
+ creator: string?;
18
+ };
19
+ }
@@ -61,6 +61,21 @@ And the generated Svelte file will contain the following import statement:
61
61
  :type '(repeat (cons (string "Component name")
62
62
  (string "Component path"))))
63
63
 
64
+ (defcustom org-svelte-raw-script-content
65
+ ""
66
+ "JavaScript code that will be included in the module context script verbatim.
67
+
68
+ The content of this variable will be inserted right after the generated import
69
+ statements. It must contain a valid JavaScript code, as this Emacs module will
70
+ perform no validation.
71
+
72
+ In the similar sense, it is highly recommended that you always use semicolons
73
+ at least for this section. Your script, combined with automatically generated
74
+ import statements and metadata storage, may be parsed unexpectedly if you rely
75
+ on JavaScript semicolon correction mechanism."
76
+ :group 'org-export-svelte
77
+ :type 'string)
78
+
64
79
  (defconst org-svelte--component-import-format
65
80
  "import %s from '%s';"
66
81
  "Format string that will be used to generate the import statement.")
@@ -73,6 +88,16 @@ And the generated Svelte file will contain the following import statement:
73
88
  "<script context=\"module\">"
74
89
  "Regexp that matches the opening tag of the module-context script.")
75
90
 
91
+ (defcustom org-svelte-id-attribute-type
92
+ nil
93
+ "Type of ID attribute to use in the generated Svelte code.
94
+
95
+ This option can be nil (the default) or t to remove all ID attributes or to use
96
+ the default ID generation algorithm."
97
+ :group 'org-export-svelte
98
+ :type '(choice (const :tag "Default" nil)
99
+ (const :tag "Remove all" t)))
100
+
76
101
  (defcustom org-svelte-latex-environment-format
77
102
  "{@html %s}"
78
103
  "Format string that will be used to generate the LaTeX environment.
@@ -116,10 +141,13 @@ class inside a <pre> tag."
116
141
  (?s "As Svelte file"
117
142
  (lambda (a s v _b)
118
143
  (org-svelte-export-to-svelte a s v)))))
119
- :translate-alist '((latex-environment . org-svelte-latex-environment)
144
+ :translate-alist '((export-block . org-svelte-export-block)
145
+ (export-snippet . org-svelte-export-snippet)
146
+ (inner-template . org-svelte-inner-template)
147
+ (keyword . org-svelte-keyword)
148
+ (latex-environment . org-svelte-latex-environment)
120
149
  (latex-fragment . org-svelte-latex-fragment)
121
150
  (src-block . org-svelte-src-block)
122
- (inner-template . org-svelte-inner-template)
123
151
  (template . org-svelte-template))
124
152
  :options-alist '( ; Overriding HTML options
125
153
  (:html-doctype "HTML_DOCTYPE" nil "html5")
@@ -150,6 +178,27 @@ Where the result would be:
150
178
  escaped-string)))
151
179
  (format "String.raw`%s`" escaped-string)))
152
180
 
181
+ (defun org-svelte-export-block (export-block _contents _info)
182
+ "Transcode an EXPORT-BLOCK element from Org to Svelte.
183
+ CONTENTS is nil. INFO is a plist holding contextual information."
184
+ (when (or (string= (org-element-property :type export-block) "HTML")
185
+ (string= (org-element-property :type export-block) "SVELTE"))
186
+ (org-remove-indentation (org-element-property :value export-block))))
187
+
188
+ (defun org-svelte-export-snippet (export-snippet _contents _info)
189
+ "Transcode an EXPORT-SNIPPET element from Org to Svelte.
190
+ CONTENTS is nil. INFO is a plist holding contextual information."
191
+ (when (or (eq (org-export-snippet-backend export-snippet) 'svelte)
192
+ (eq (org-export-snippet-backend export-snippet) 'html))
193
+ (org-element-property :value export-snippet)))
194
+
195
+ (defun org-svelte-keyword (keyword _contents _info)
196
+ "Transcode a KEYWORD element from Org to Svelte.
197
+ CONTENTS is nil. INFO is a plist holding contextual information."
198
+ (when (or (string= (org-element-property :key keyword) "HTML")
199
+ (string= (org-element-property :key keyword) "SVELTE"))
200
+ (org-element-property :value keyword)))
201
+
153
202
  (defun org-svelte-latex-environment (latex-environment _contents info)
154
203
  "Transcode a LATEX-ENVIRONMENT element from Org to Svelte.
155
204
  CONTENTS is nil. INFO is a plist holding contextual information."
@@ -223,15 +272,22 @@ INFO is a plist holding contextual information."
223
272
  INFO is a plist holding contextual information."
224
273
  (let ((imports (org-svelte--generate-imports info))
225
274
  (metadata (org-svelte--generate-metadata-export info)))
226
- (format "<script context=\"module\">\n%s\n%s\n</script>\n"
275
+ (format "<script context=\"module\">\n%s\n%s\n%s\n</script>\n"
227
276
  imports
277
+ org-svelte-raw-script-content
228
278
  metadata)))
229
279
 
230
280
  (defun org-svelte-inner-template (contents _info)
231
281
  "Return body of document after converting it to Svelte.
232
282
  CONTENTS is the transcoded contents string. INFO is a plist holding export
233
283
  options."
234
- contents)
284
+ (let* ((contents (if (not org-svelte-id-attribute-type)
285
+ (replace-regexp-in-string
286
+ " id=\"[[:alpha:]-]*org[[:alnum:]]\\{7\\}\""
287
+ ""
288
+ contents t)
289
+ contents)))
290
+ contents))
235
291
 
236
292
  (defun org-svelte-template (contents info)
237
293
  "Return complete document string after Svelte conversion.
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "ox-svelte",
3
+ "version": "0.1.0",
4
+ "description": "Org-mode exporter backend for Svelte components (type definitions)",
5
+ "types": "index.d.ts",
6
+ "author": "RangHo Lee <hello@rangho.me>",
7
+ "license": "GPL-3.0-or-later",
8
+ "devDependencies": {
9
+ "svelte": "^4.2.12"
10
+ }
11
+ }
@@ -0,0 +1,155 @@
1
+ lockfileVersion: '6.0'
2
+
3
+ settings:
4
+ autoInstallPeers: true
5
+ excludeLinksFromLockfile: false
6
+
7
+ devDependencies:
8
+ svelte:
9
+ specifier: ^4.2.12
10
+ version: 4.2.12
11
+
12
+ packages:
13
+
14
+ /@ampproject/remapping@2.2.1:
15
+ resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==}
16
+ engines: {node: '>=6.0.0'}
17
+ dependencies:
18
+ '@jridgewell/gen-mapping': 0.3.4
19
+ '@jridgewell/trace-mapping': 0.3.23
20
+ dev: true
21
+
22
+ /@jridgewell/gen-mapping@0.3.4:
23
+ resolution: {integrity: sha512-Oud2QPM5dHviZNn4y/WhhYKSXksv+1xLEIsNrAbGcFzUN3ubqWRFT5gwPchNc5NuzILOU4tPBDTZ4VwhL8Y7cw==}
24
+ engines: {node: '>=6.0.0'}
25
+ dependencies:
26
+ '@jridgewell/set-array': 1.1.2
27
+ '@jridgewell/sourcemap-codec': 1.4.15
28
+ '@jridgewell/trace-mapping': 0.3.23
29
+ dev: true
30
+
31
+ /@jridgewell/resolve-uri@3.1.2:
32
+ resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
33
+ engines: {node: '>=6.0.0'}
34
+ dev: true
35
+
36
+ /@jridgewell/set-array@1.1.2:
37
+ resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==}
38
+ engines: {node: '>=6.0.0'}
39
+ dev: true
40
+
41
+ /@jridgewell/sourcemap-codec@1.4.15:
42
+ resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==}
43
+ dev: true
44
+
45
+ /@jridgewell/trace-mapping@0.3.23:
46
+ resolution: {integrity: sha512-9/4foRoUKp8s96tSkh8DlAAc5A0Ty8vLXld+l9gjKKY6ckwI8G15f0hskGmuLZu78ZlGa1vtsfOa+lnB4vG6Jg==}
47
+ dependencies:
48
+ '@jridgewell/resolve-uri': 3.1.2
49
+ '@jridgewell/sourcemap-codec': 1.4.15
50
+ dev: true
51
+
52
+ /@types/estree@1.0.5:
53
+ resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==}
54
+ dev: true
55
+
56
+ /acorn@8.11.3:
57
+ resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==}
58
+ engines: {node: '>=0.4.0'}
59
+ hasBin: true
60
+ dev: true
61
+
62
+ /aria-query@5.3.0:
63
+ resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==}
64
+ dependencies:
65
+ dequal: 2.0.3
66
+ dev: true
67
+
68
+ /axobject-query@4.0.0:
69
+ resolution: {integrity: sha512-+60uv1hiVFhHZeO+Lz0RYzsVHy5Wr1ayX0mwda9KPDVLNJgZ1T9Ny7VmFbLDzxsH0D87I86vgj3gFrjTJUYznw==}
70
+ dependencies:
71
+ dequal: 2.0.3
72
+ dev: true
73
+
74
+ /code-red@1.0.4:
75
+ resolution: {integrity: sha512-7qJWqItLA8/VPVlKJlFXU+NBlo/qyfs39aJcuMT/2ere32ZqvF5OSxgdM5xOfJJ7O429gg2HM47y8v9P+9wrNw==}
76
+ dependencies:
77
+ '@jridgewell/sourcemap-codec': 1.4.15
78
+ '@types/estree': 1.0.5
79
+ acorn: 8.11.3
80
+ estree-walker: 3.0.3
81
+ periscopic: 3.1.0
82
+ dev: true
83
+
84
+ /css-tree@2.3.1:
85
+ resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==}
86
+ engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0}
87
+ dependencies:
88
+ mdn-data: 2.0.30
89
+ source-map-js: 1.0.2
90
+ dev: true
91
+
92
+ /dequal@2.0.3:
93
+ resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
94
+ engines: {node: '>=6'}
95
+ dev: true
96
+
97
+ /estree-walker@3.0.3:
98
+ resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
99
+ dependencies:
100
+ '@types/estree': 1.0.5
101
+ dev: true
102
+
103
+ /is-reference@3.0.2:
104
+ resolution: {integrity: sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==}
105
+ dependencies:
106
+ '@types/estree': 1.0.5
107
+ dev: true
108
+
109
+ /locate-character@3.0.0:
110
+ resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==}
111
+ dev: true
112
+
113
+ /magic-string@0.30.7:
114
+ resolution: {integrity: sha512-8vBuFF/I/+OSLRmdf2wwFCJCz+nSn0m6DPvGH1fS/KiQoSaR+sETbov0eIk9KhEKy8CYqIkIAnbohxT/4H0kuA==}
115
+ engines: {node: '>=12'}
116
+ dependencies:
117
+ '@jridgewell/sourcemap-codec': 1.4.15
118
+ dev: true
119
+
120
+ /mdn-data@2.0.30:
121
+ resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==}
122
+ dev: true
123
+
124
+ /periscopic@3.1.0:
125
+ resolution: {integrity: sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==}
126
+ dependencies:
127
+ '@types/estree': 1.0.5
128
+ estree-walker: 3.0.3
129
+ is-reference: 3.0.2
130
+ dev: true
131
+
132
+ /source-map-js@1.0.2:
133
+ resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==}
134
+ engines: {node: '>=0.10.0'}
135
+ dev: true
136
+
137
+ /svelte@4.2.12:
138
+ resolution: {integrity: sha512-d8+wsh5TfPwqVzbm4/HCXC783/KPHV60NvwitJnyTA5lWn1elhXMNWhXGCJ7PwPa8qFUnyJNIyuIRt2mT0WMug==}
139
+ engines: {node: '>=16'}
140
+ dependencies:
141
+ '@ampproject/remapping': 2.2.1
142
+ '@jridgewell/sourcemap-codec': 1.4.15
143
+ '@jridgewell/trace-mapping': 0.3.23
144
+ '@types/estree': 1.0.5
145
+ acorn: 8.11.3
146
+ aria-query: 5.3.0
147
+ axobject-query: 4.0.0
148
+ code-red: 1.0.4
149
+ css-tree: 2.3.1
150
+ estree-walker: 3.0.3
151
+ is-reference: 3.0.2
152
+ locate-character: 3.0.0
153
+ magic-string: 0.30.7
154
+ periscopic: 3.1.0
155
+ dev: true
package/dist/sexp.d.ts ADDED
@@ -0,0 +1,17 @@
1
+ export type Sexp = Value | Cell;
2
+ export type Value = Atom | Quote | string | number | boolean | null;
3
+ export type Cell = {
4
+ car: Sexp;
5
+ cdr: Sexp;
6
+ };
7
+ export declare class Atom {
8
+ name: string;
9
+ constructor(name: string);
10
+ }
11
+ export declare class Quote {
12
+ sexp: Sexp;
13
+ constructor(sexp: Sexp);
14
+ }
15
+ export declare function cons(car: Sexp, cdr: Sexp): Cell;
16
+ export declare function list(...args: Sexp[]): Sexp;
17
+ export declare function stringify(sexp: Sexp): string;
@@ -0,0 +1,9 @@
1
+ import eslint from "@eslint/js";
2
+ import tslint from "typescript-eslint";
3
+
4
+ const config = tslint.config(
5
+ eslint.configs.recommended,
6
+ ...tslint.configs.recommended,
7
+ );
8
+
9
+ export default config;
package/jest.config.js ADDED
@@ -0,0 +1,11 @@
1
+ /** @type {import('ts-jest').JestConfigWithTsJest} */
2
+ const config = {
3
+ preset: "ts-jest/presets/default-esm",
4
+ moduleDirectories: ["node_modules", "src"],
5
+ moduleNameMapper: {
6
+ "^@/.*": "<rootDir>/src/$1",
7
+ "^(\\.{1,2}/.*)\\.js$": "$1",
8
+ },
9
+ };
10
+
11
+ export default config;
package/package.json CHANGED
@@ -1,30 +1,33 @@
1
1
  {
2
2
  "name": "svelte-preprocess-org",
3
3
  "type": "module",
4
- "version": "0.1.1",
4
+ "version": "0.2.1",
5
5
  "description": "Svelte preprocessor for Org-mode",
6
6
  "author": "RangHo Lee <hello@rangho.me>",
7
7
  "homepage": "https://github.com/RangHo/svelte-preprocess-org",
8
8
  "license": "GPL-3.0-or-later",
9
9
  "main": "dist/index.js",
10
10
  "types": "dist/index.d.ts",
11
+ "files": "dist/*",
11
12
  "devDependencies": {
12
13
  "@rollup/plugin-commonjs": "^25.0.7",
13
14
  "@rollup/plugin-node-resolve": "^15.2.3",
14
15
  "@rollup/plugin-terser": "^0.4.4",
15
16
  "@rollup/plugin-typescript": "^11.1.6",
16
17
  "@tsconfig/node-lts": "^20.1.1",
18
+ "@types/jest": "^29.5.12",
17
19
  "@types/node": "^20.11.19",
18
- "@typescript-eslint/eslint-plugin": "^6.15.0",
19
- "@typescript-eslint/parser": "^6.15.0",
20
20
  "eslint": "^8.56.0",
21
+ "jest": "^29.7.0",
21
22
  "ox-svelte": "^0.1.0",
22
23
  "prettier": "^3.1.1",
23
24
  "rollup": "^4.12.0",
24
25
  "rollup-plugin-copy": "^3.5.0",
25
26
  "svelte": "^4.2.12",
27
+ "ts-jest": "^29.1.2",
26
28
  "tslib": "^2.6.2",
27
- "typescript": "^5.3.3"
29
+ "typescript": "^5.3.3",
30
+ "typescript-eslint": "^7.2.0"
28
31
  },
29
32
  "peerDependencies": {
30
33
  "ox-svelte": "^0.1.0",
@@ -32,7 +35,7 @@
32
35
  },
33
36
  "scripts": {
34
37
  "build": "rollup -c",
35
- "test": "jest",
38
+ "test": "NODE_OPTIONS='--experimental-vm-modules' jest",
36
39
  "format": "prettier --write .",
37
40
  "lint": "eslint ."
38
41
  }
@@ -1,3 +1,5 @@
1
- module.exports = {
1
+ const config = {
2
2
  // Use default Prettier configuration
3
3
  };
4
+
5
+ export default config;
package/src/emacs.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  import { execSync } from "node:child_process";
2
2
  import { join } from "node:path";
3
3
 
4
+ import { Atom, Quote, cons, list, stringify } from "./sexp.js";
5
+
4
6
  export interface OxSvelteOptions {
5
7
  latexEnvironmentFormat?: string;
6
8
  latexFragmentFormat?: string;
@@ -8,12 +10,6 @@ export interface OxSvelteOptions {
8
10
  imports?: Record<string, string>;
9
11
  }
10
12
 
11
- function recordToAlist(target: Record<string, string>): string {
12
- const entries = Object.entries(target);
13
- const alist = entries.map(([key, val]) => `("${key}" . "${val}")`);
14
- return `'(${alist})`;
15
- }
16
-
17
13
  export function convert(content: string, options?: OxSvelteOptions): string {
18
14
  const {
19
15
  latexEnvironmentFormat,
@@ -37,10 +33,17 @@ export function convert(content: string, options?: OxSvelteOptions): string {
37
33
  command += ` --src-block-format ${srcBlockFormat}`;
38
34
  }
39
35
  if (imports) {
40
- command += ` --preface "(setq og-svelte-component-import-alist ${recordToAlist(
41
- imports,
42
- )})"`;
36
+ const sexp = list(
37
+ new Atom("setq"),
38
+ new Atom("org-svelte-component-import-alist"),
39
+ new Quote(
40
+ list(...Object.entries(imports).map(([key, val]) => cons(key, val))),
41
+ ),
42
+ );
43
+ command += ` --preface '${stringify(sexp).replaceAll("'", "'\\''")}'`;
43
44
  }
44
45
 
45
- return execSync(command, { input: content }).toString();
46
+ const result = execSync(command, { input: content }).toString();
47
+
48
+ return result;
46
49
  }
@@ -0,0 +1,4 @@
1
+ # Org-mode exporter backend for Svelte components
2
+
3
+ `ox-svelte` is an opinionated Org-mode exporter backend that generates a Svelte
4
+ component.
@@ -0,0 +1,19 @@
1
+ import type { SvelteComponent } from 'svelte';
2
+
3
+ declare module 'ox-svelte' {
4
+ export type OrgModule = {
5
+ default: typeof SvelteComponent;
6
+ metadata: OrgMetadata;
7
+ };
8
+
9
+ export type OrgMetadata = {
10
+ title: string?;
11
+ subtitle: string?;
12
+ author: string?;
13
+ date: string?;
14
+ description: string?;
15
+ keywords: string[]?;
16
+ language: string?;
17
+ creator: string?;
18
+ };
19
+ }
@@ -61,6 +61,21 @@ And the generated Svelte file will contain the following import statement:
61
61
  :type '(repeat (cons (string "Component name")
62
62
  (string "Component path"))))
63
63
 
64
+ (defcustom org-svelte-raw-script-content
65
+ ""
66
+ "JavaScript code that will be included in the module context script verbatim.
67
+
68
+ The content of this variable will be inserted right after the generated import
69
+ statements. It must contain a valid JavaScript code, as this Emacs module will
70
+ perform no validation.
71
+
72
+ In the similar sense, it is highly recommended that you always use semicolons
73
+ at least for this section. Your script, combined with automatically generated
74
+ import statements and metadata storage, may be parsed unexpectedly if you rely
75
+ on JavaScript semicolon correction mechanism."
76
+ :group 'org-export-svelte
77
+ :type 'string)
78
+
64
79
  (defconst org-svelte--component-import-format
65
80
  "import %s from '%s';"
66
81
  "Format string that will be used to generate the import statement.")
@@ -73,6 +88,16 @@ And the generated Svelte file will contain the following import statement:
73
88
  "<script context=\"module\">"
74
89
  "Regexp that matches the opening tag of the module-context script.")
75
90
 
91
+ (defcustom org-svelte-id-attribute-type
92
+ nil
93
+ "Type of ID attribute to use in the generated Svelte code.
94
+
95
+ This option can be nil (the default) or t to remove all ID attributes or to use
96
+ the default ID generation algorithm."
97
+ :group 'org-export-svelte
98
+ :type '(choice (const :tag "Default" nil)
99
+ (const :tag "Remove all" t)))
100
+
76
101
  (defcustom org-svelte-latex-environment-format
77
102
  "{@html %s}"
78
103
  "Format string that will be used to generate the LaTeX environment.
@@ -116,10 +141,13 @@ class inside a <pre> tag."
116
141
  (?s "As Svelte file"
117
142
  (lambda (a s v _b)
118
143
  (org-svelte-export-to-svelte a s v)))))
119
- :translate-alist '((latex-environment . org-svelte-latex-environment)
144
+ :translate-alist '((export-block . org-svelte-export-block)
145
+ (export-snippet . org-svelte-export-snippet)
146
+ (inner-template . org-svelte-inner-template)
147
+ (keyword . org-svelte-keyword)
148
+ (latex-environment . org-svelte-latex-environment)
120
149
  (latex-fragment . org-svelte-latex-fragment)
121
150
  (src-block . org-svelte-src-block)
122
- (inner-template . org-svelte-inner-template)
123
151
  (template . org-svelte-template))
124
152
  :options-alist '( ; Overriding HTML options
125
153
  (:html-doctype "HTML_DOCTYPE" nil "html5")
@@ -150,6 +178,27 @@ Where the result would be:
150
178
  escaped-string)))
151
179
  (format "String.raw`%s`" escaped-string)))
152
180
 
181
+ (defun org-svelte-export-block (export-block _contents _info)
182
+ "Transcode an EXPORT-BLOCK element from Org to Svelte.
183
+ CONTENTS is nil. INFO is a plist holding contextual information."
184
+ (when (or (string= (org-element-property :type export-block) "HTML")
185
+ (string= (org-element-property :type export-block) "SVELTE"))
186
+ (org-remove-indentation (org-element-property :value export-block))))
187
+
188
+ (defun org-svelte-export-snippet (export-snippet _contents _info)
189
+ "Transcode an EXPORT-SNIPPET element from Org to Svelte.
190
+ CONTENTS is nil. INFO is a plist holding contextual information."
191
+ (when (or (eq (org-export-snippet-backend export-snippet) 'svelte)
192
+ (eq (org-export-snippet-backend export-snippet) 'html))
193
+ (org-element-property :value export-snippet)))
194
+
195
+ (defun org-svelte-keyword (keyword _contents _info)
196
+ "Transcode a KEYWORD element from Org to Svelte.
197
+ CONTENTS is nil. INFO is a plist holding contextual information."
198
+ (when (or (string= (org-element-property :key keyword) "HTML")
199
+ (string= (org-element-property :key keyword) "SVELTE"))
200
+ (org-element-property :value keyword)))
201
+
153
202
  (defun org-svelte-latex-environment (latex-environment _contents info)
154
203
  "Transcode a LATEX-ENVIRONMENT element from Org to Svelte.
155
204
  CONTENTS is nil. INFO is a plist holding contextual information."
@@ -223,15 +272,22 @@ INFO is a plist holding contextual information."
223
272
  INFO is a plist holding contextual information."
224
273
  (let ((imports (org-svelte--generate-imports info))
225
274
  (metadata (org-svelte--generate-metadata-export info)))
226
- (format "<script context=\"module\">\n%s\n%s\n</script>\n"
275
+ (format "<script context=\"module\">\n%s\n%s\n%s\n</script>\n"
227
276
  imports
277
+ org-svelte-raw-script-content
228
278
  metadata)))
229
279
 
230
280
  (defun org-svelte-inner-template (contents _info)
231
281
  "Return body of document after converting it to Svelte.
232
282
  CONTENTS is the transcoded contents string. INFO is a plist holding export
233
283
  options."
234
- contents)
284
+ (let* ((contents (if (not org-svelte-id-attribute-type)
285
+ (replace-regexp-in-string
286
+ " id=\"[[:alpha:]-]*org[[:alnum:]]\\{7\\}\""
287
+ ""
288
+ contents t)
289
+ contents)))
290
+ contents))
235
291
 
236
292
  (defun org-svelte-template (contents info)
237
293
  "Return complete document string after Svelte conversion.
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "ox-svelte",
3
+ "version": "0.1.0",
4
+ "description": "Org-mode exporter backend for Svelte components (type definitions)",
5
+ "types": "index.d.ts",
6
+ "author": "RangHo Lee <hello@rangho.me>",
7
+ "license": "GPL-3.0-or-later",
8
+ "devDependencies": {
9
+ "svelte": "^4.2.12"
10
+ }
11
+ }