Skip to content

Commit 8ad60fa

Browse files
committed
Added support for Base64 encoded extra files
1 parent 26b3fd9 commit 8ad60fa

File tree

2 files changed

+68
-32
lines changed

2 files changed

+68
-32
lines changed

SCHEMA.md

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
```
55
pde:///path/to/sketch.pde
66
```
7+
Attention: The 3rd slash is import to trigger local files.
78

89
## Sketch Operations
910

@@ -17,27 +18,37 @@ pde://sketch/new
1718
pde://sketch/base64/<base64_encoded_content>
1819
```
1920
Optional query parameters:
20-
- `data`: Comma-separated URLs of data files to download
21-
- `code`: Comma-separated URLs of code files to download
22-
- `pde`: Comma-separated URLs of Processing sketch files to download
23-
- `mode`: Processing mode identifier
21+
- `data`: Comma-separated {File} that should be placed in the data folder
22+
- `code`: Comma-separated {File} that should be placed in the code folder
23+
- `pde`: Comma-separated {File} that should be placed in the sketch folder
24+
- `mode`: Processing mode identifier, e.g. `processing.mode.android.AndroidMode` You can find this in the sketch.properties file when switching modes on a sketch
2425

2526
### Load Sketch from URL
27+
2628
```
27-
pde://sketch/url/domain.com/path/to/sketch.pde
29+
pde://sketch/url/github.com/processing/processing-examples/raw/refs/heads/main/Basics/Arrays/Array/Array.pde
2830
```
31+
[Click to here to test](pde://sketch/url/github.com/processing/processing-examples/raw/refs/heads/main/Basics/Arrays/Array/Array.pde)
32+
2933
Supports the same query parameters as base64 endpoint.
3034
Optional query parameters:
31-
32-
- `data`: Comma-separated URLs of data files to download
33-
- `code`: Comma-separated URLs of code files to download
34-
- `pde`: Comma-separated URLs of Processing sketch files to download
35-
- `mode`: Processing mode identifier
35+
- `data`: Comma-separated {File} that should be placed in the data folder
36+
- `code`: Comma-separated {File} that should be placed in the code folder
37+
- `pde`: Comma-separated {File} that should be placed in the sketch folder
38+
- `mode`: Processing mode identifier, e.g. `processing.mode.android.AndroidMode` You can find this in the sketch.properties file when switching modes on a sketch
3639

3740
Example with query parameters:
41+
3842
```
39-
pde://sketch/url/example.com/sketch.pde?data=image1.png,sound1.mp3&mode=java
43+
pde://sketch/url/github.com/processing/processing-examples/raw/refs/heads/main/Basics/Image/Alphamask/Alphamask.pde?data=data/moonwalk.jpg,data/mask.jpg,processing.org/img/processing-web.png
4044
```
45+
[Click to here to test](pde://sketch/url/github.com/processing/processing-examples/raw/refs/heads/main/Basics/Image/Alphamask/Alphamask.pde?data=data/moonwalk.jpg,data/mask.jpg,processing.org/img/processing-web.png)
46+
47+
#### A {File}
48+
A {File} is a string that represents a file in the sketch and has a couple of options, it always starts with the filename followed by a colon, e.g. `file.pde:example.com/path/to/file.pde`. The following options are available:
49+
- `example.com/path/to/file.pde`: A remote file that should be downloaded
50+
- `file.pde`: A remote file that should be downloaded with a path relative to the sketch (only available in loading the sketch from url)
51+
- a base64 encoded file: A base64 encoded file
4152

4253
## Preferences
4354
```

app/src/processing/app/Schema.kt

Lines changed: 46 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import java.net.URI
77
import java.net.URL
88
import java.net.URLDecoder
99
import java.nio.charset.StandardCharsets
10+
import java.util.*
1011

1112

1213
class Schema {
@@ -44,7 +45,7 @@ class Schema {
4445
tempSketchFolder.mkdirs()
4546
val tempSketchFile = File(tempSketchFolder, "${tempSketchFolder.name}.pde")
4647
val sketchB64 = uri.path.replace("/base64/", "")
47-
val sketch = java.util.Base64.getDecoder().decode(sketchB64)
48+
val sketch = Base64.getDecoder().decode(sketchB64)
4849
tempSketchFile.writeBytes(sketch)
4950
handleSketchOptions(uri, tempSketchFolder)
5051
return base?.handleOpenUntitled(tempSketchFile.absolutePath)
@@ -73,7 +74,6 @@ class Schema {
7374
URLDecoder.decode(it[1], StandardCharsets.UTF_8)
7475
}
7576
?: emptyMap()
76-
7777
options["data"]?.let{ data ->
7878
downloadFiles(uri, data, File(sketchFolder, "data"))
7979
}
@@ -89,31 +89,56 @@ class Schema {
8989
}
9090

9191
}
92-
private fun downloadFiles(uri: URI, urlList: String, sketchFolder: File){
92+
private fun downloadFiles(uri: URI, urlList: String, targetFolder: File){
9393
Thread{
94-
val base = uri.path.split("/").drop(2).dropLast(1).joinToString("/")
94+
targetFolder.mkdirs()
95+
96+
val base = uri.path.split("/")
97+
.drop(2) // drop the /sketch/base64/ or /sketch/url/ etc...
98+
.dropLast(1) // drop the file name
99+
.joinToString("/")
100+
95101
val files = urlList.split(",")
96-
.map {
97-
val fileUrl = URI.create(it)
98-
if(fileUrl.host == null){
99-
return@map "https://$base/$it"
100-
}
101-
if(fileUrl.scheme == null){
102-
return@map "https://$it"
102+
103+
files.filter { it.isNotBlank() }
104+
.map{ it.split(":", limit = 2) }
105+
.map{ segments ->
106+
if(segments.size == 2){
107+
if(segments[0].isBlank()){
108+
return@map listOf(null, segments[1])
109+
}
110+
return@map segments
103111
}
104-
return@map it
112+
return@map listOf(null, segments[0])
105113
}
106-
sketchFolder.mkdirs()
107-
for(file in files){
108-
val url = URL(file)
109-
val name = url.path.split("/").last()
110-
val dataFile = File(sketchFolder, name)
111-
URL(file).openStream().use { input ->
112-
FileOutputStream(dataFile).use { output ->
113-
input.copyTo(output)
114+
.forEach { (name, content) ->
115+
try{
116+
// Try to decode the content as base64
117+
val file = Base64.getDecoder().decode(content)
118+
if(name == null){
119+
Messages.err("Base64 files needs to start with a file name followed by a colon")
120+
return@forEach
121+
}
122+
File(targetFolder, name).writeBytes(file)
123+
}catch(_: IllegalArgumentException){
124+
// Assume it's a URL and download it
125+
var url = URI.create(content)
126+
if(url.host == null){
127+
url = URI.create("https://$base/$content")
128+
}
129+
if(url.scheme == null){
130+
url = URI.create("https://$content")
131+
}
132+
133+
val target = File(targetFolder, name ?: url.path.split("/").last())
134+
url.toURL().openStream().use { input ->
135+
target.outputStream().use { output ->
136+
input.copyTo(output)
137+
}
138+
}
114139
}
140+
115141
}
116-
}
117142
}.start()
118143
}
119144

0 commit comments

Comments
 (0)