Compare commits
19 commits
ef8ddb9025
...
4491c6dba1
Author | SHA1 | Date | |
---|---|---|---|
4491c6dba1 | |||
|
6a38a1cebc | ||
|
467f3c3a63 | ||
|
853e9ad50d | ||
|
27faf59549 | ||
|
d1ecb76cdc | ||
|
e86108e18f | ||
|
cef1bc256d | ||
|
761e4ef170 | ||
|
815f5c19f0 | ||
|
bf31305617 | ||
|
e1c70b9db0 | ||
|
d7ea1174ff | ||
|
eca9eb7f13 | ||
|
48204b039b | ||
|
7e927469dc | ||
|
b69fa2f2b1 | ||
|
8240f40719 | ||
|
98de1d24d6 |
27 changed files with 247 additions and 127 deletions
|
@ -1 +1 @@
|
||||||
1.5.0
|
1.8.1
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
nodejs 12.14.1
|
nodejs 16.18.0
|
||||||
crystal 1.5.0
|
crystal 1.5.0
|
||||||
|
|
33
CHANGELOG
33
CHANGELOG
|
@ -1,3 +1,36 @@
|
||||||
|
2023-05-06
|
||||||
|
|
||||||
|
* Upgrade to Lucky framework 1.0.0
|
||||||
|
* Upgrade to Crystal version 1.8.1
|
||||||
|
* If embedded media has a caption, it will now be displayed
|
||||||
|
|
||||||
|
2023-03-25
|
||||||
|
|
||||||
|
* Headings now have an ID so readers can link to a part if an article
|
||||||
|
* If a URL contains `global-identity-2`, Scribe will now correctly parse the article ID.
|
||||||
|
|
||||||
|
2022-11-06
|
||||||
|
|
||||||
|
* Fix viewing articles if the URL has a trailing slash
|
||||||
|
* Update to nodejs 16.18.0
|
||||||
|
|
||||||
|
2022-10-30
|
||||||
|
|
||||||
|
* Update to nodejs 16.18.0
|
||||||
|
|
||||||
|
2022-10-30
|
||||||
|
|
||||||
|
* Fix viewing articles if the URL has a trailing slash
|
||||||
|
|
||||||
|
2022-10-11
|
||||||
|
|
||||||
|
* Don't clip gist contents (CSS fix)
|
||||||
|
|
||||||
|
2022-09-24
|
||||||
|
|
||||||
|
* Replace Redirector extension with LibRedirect
|
||||||
|
* Remove downloadable Redirector config
|
||||||
|
|
||||||
2022-07-19
|
2022-07-19
|
||||||
|
|
||||||
* Fix downloadable config file for Redirector extension
|
* Fix downloadable config file for Redirector extension
|
||||||
|
|
|
@ -5,5 +5,7 @@
|
||||||
"https://scribe.bus-hit.me",
|
"https://scribe.bus-hit.me",
|
||||||
"https://scribe.froth.zone",
|
"https://scribe.froth.zone",
|
||||||
"https://scribe.esmailelbob.xyz",
|
"https://scribe.esmailelbob.xyz",
|
||||||
"https://scribe.privacydev.net"
|
"https://scribe.privacydev.net",
|
||||||
|
"https://scribe.rawbit.ninja",
|
||||||
|
"https://sc.vern.cc"
|
||||||
]
|
]
|
||||||
|
|
|
@ -7,7 +7,11 @@
|
||||||
* <https://scribe.froth.zone>
|
* <https://scribe.froth.zone>
|
||||||
* <https://scribe.esmailelbob.xyz>
|
* <https://scribe.esmailelbob.xyz>
|
||||||
* <https://scribe.privacydev.net>
|
* <https://scribe.privacydev.net>
|
||||||
* <scribe.lqs5fjmajyp7rvp4qvyubwofzi6d4imua7vs237rkc4m5qogitqwrgyd.onion> (Tor)
|
* <https://scribe.rawbit.ninja>
|
||||||
|
* <http://scribe.esmail5pdn24shtvieloeedh7ehz3nrwcdivnfhfcedl7gf4kwddhkqd.onion> (Tor)
|
||||||
|
* <http://w7uhv5lxhgck72hhimdglmusc54t4m6bionlmd5mvyddq3bs53mohqid.onion> (Tor)
|
||||||
|
* <http://scribe.g4c3eya4clenolymqbpgwz3q3tawoxw56yhzk4vugqrl6dtu3ejvhjid.onion> (Tor)
|
||||||
|
* [sc.vern.i2p](http://vern3whzyfmjclq6snhlupma6nrmojghwp37tydfgqotj7sc6izq.b32.i2p) (I2P)
|
||||||
|
|
||||||
## How do I get my instance on this list?
|
## How do I get my instance on this list?
|
||||||
|
|
||||||
|
|
40
shard.lock
40
shard.lock
|
@ -2,15 +2,15 @@ version: 2.0
|
||||||
shards:
|
shards:
|
||||||
authentic:
|
authentic:
|
||||||
git: https://github.com/luckyframework/authentic.git
|
git: https://github.com/luckyframework/authentic.git
|
||||||
version: 0.8.2
|
version: 1.0.0
|
||||||
|
|
||||||
avram:
|
avram:
|
||||||
git: https://github.com/luckyframework/avram.git
|
git: https://github.com/luckyframework/avram.git
|
||||||
version: 0.23.0
|
version: 1.0.0
|
||||||
|
|
||||||
backtracer:
|
backtracer:
|
||||||
git: https://github.com/sija/backtracer.cr.git
|
git: https://github.com/sija/backtracer.cr.git
|
||||||
version: 1.2.1
|
version: 1.2.2
|
||||||
|
|
||||||
cadmium_transliterator:
|
cadmium_transliterator:
|
||||||
git: https://github.com/cadmiumcr/transliterator.git
|
git: https://github.com/cadmiumcr/transliterator.git
|
||||||
|
@ -18,7 +18,7 @@ shards:
|
||||||
|
|
||||||
carbon:
|
carbon:
|
||||||
git: https://github.com/luckyframework/carbon.git
|
git: https://github.com/luckyframework/carbon.git
|
||||||
version: 0.2.1
|
version: 0.3.0
|
||||||
|
|
||||||
cry:
|
cry:
|
||||||
git: https://github.com/luckyframework/cry.git
|
git: https://github.com/luckyframework/cry.git
|
||||||
|
@ -26,7 +26,7 @@ shards:
|
||||||
|
|
||||||
crystar:
|
crystar:
|
||||||
git: https://github.com/naqvis/crystar.git
|
git: https://github.com/naqvis/crystar.git
|
||||||
version: 0.2.0
|
version: 0.2.0+git.commit.56db8bb9dfbd5ed6d7908353405a5fae632a6561
|
||||||
|
|
||||||
db:
|
db:
|
||||||
git: https://github.com/crystal-lang/crystal-db.git
|
git: https://github.com/crystal-lang/crystal-db.git
|
||||||
|
@ -38,15 +38,23 @@ shards:
|
||||||
|
|
||||||
exception_page:
|
exception_page:
|
||||||
git: https://github.com/crystal-loot/exception_page.git
|
git: https://github.com/crystal-loot/exception_page.git
|
||||||
version: 0.2.2
|
version: 0.3.0
|
||||||
|
|
||||||
|
fnv:
|
||||||
|
git: https://github.com/naqvis/crystal-fnv.git
|
||||||
|
version: 0.1.3
|
||||||
|
|
||||||
habitat:
|
habitat:
|
||||||
git: https://github.com/luckyframework/habitat.git
|
git: https://github.com/luckyframework/habitat.git
|
||||||
version: 0.4.7
|
version: 0.4.7
|
||||||
|
|
||||||
|
html5:
|
||||||
|
git: https://github.com/naqvis/crystal-html5.git
|
||||||
|
version: 0.4.0
|
||||||
|
|
||||||
lucky:
|
lucky:
|
||||||
git: https://github.com/luckyframework/lucky.git
|
git: https://github.com/luckyframework/lucky.git
|
||||||
version: 0.30.1
|
version: 1.0.0
|
||||||
|
|
||||||
lucky_cache:
|
lucky_cache:
|
||||||
git: https://github.com/luckyframework/lucky_cache.git
|
git: https://github.com/luckyframework/lucky_cache.git
|
||||||
|
@ -58,11 +66,11 @@ shards:
|
||||||
|
|
||||||
lucky_flow:
|
lucky_flow:
|
||||||
git: https://github.com/luckyframework/lucky_flow.git
|
git: https://github.com/luckyframework/lucky_flow.git
|
||||||
version: 0.7.3
|
version: 0.9.0
|
||||||
|
|
||||||
lucky_router:
|
lucky_router:
|
||||||
git: https://github.com/luckyframework/lucky_router.git
|
git: https://github.com/luckyframework/lucky_router.git
|
||||||
version: 0.5.1
|
version: 0.5.2
|
||||||
|
|
||||||
lucky_task:
|
lucky_task:
|
||||||
git: https://github.com/luckyframework/lucky_task.git
|
git: https://github.com/luckyframework/lucky_task.git
|
||||||
|
@ -82,7 +90,7 @@ shards:
|
||||||
|
|
||||||
selenium:
|
selenium:
|
||||||
git: https://github.com/matthewmcgarvey/selenium.cr.git
|
git: https://github.com/matthewmcgarvey/selenium.cr.git
|
||||||
version: 0.9.1
|
version: 0.10.0
|
||||||
|
|
||||||
shell-table:
|
shell-table:
|
||||||
git: https://github.com/luckyframework/shell-table.cr.git
|
git: https://github.com/luckyframework/shell-table.cr.git
|
||||||
|
@ -98,9 +106,17 @@ shards:
|
||||||
|
|
||||||
webdrivers:
|
webdrivers:
|
||||||
git: https://github.com/matthewmcgarvey/webdrivers.cr.git
|
git: https://github.com/matthewmcgarvey/webdrivers.cr.git
|
||||||
version: 0.4.0
|
version: 0.4.1
|
||||||
|
|
||||||
|
webless:
|
||||||
|
git: https://github.com/matthewmcgarvey/webless.git
|
||||||
|
version: 0.1.0
|
||||||
|
|
||||||
wordsmith:
|
wordsmith:
|
||||||
git: https://github.com/luckyframework/wordsmith.git
|
git: https://github.com/luckyframework/wordsmith.git
|
||||||
version: 0.3.0
|
version: 0.4.0
|
||||||
|
|
||||||
|
xpath2:
|
||||||
|
git: https://github.com/naqvis/crystal-xpath2.git
|
||||||
|
version: 0.1.3
|
||||||
|
|
||||||
|
|
17
shard.yml
17
shard.yml
|
@ -8,27 +8,30 @@ targets:
|
||||||
scribe:
|
scribe:
|
||||||
main: src/scribe.cr
|
main: src/scribe.cr
|
||||||
|
|
||||||
crystal: 1.5.0
|
crystal: 1.8.1
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
lucky:
|
lucky:
|
||||||
github: luckyframework/lucky
|
github: luckyframework/lucky
|
||||||
version: ~> 0.30.1
|
version: ~> 1.0.0
|
||||||
|
avram:
|
||||||
|
github: luckyframework/avram
|
||||||
|
version: ~> 1.0.0
|
||||||
authentic:
|
authentic:
|
||||||
github: luckyframework/authentic
|
github: luckyframework/authentic
|
||||||
version: ~> 0.8.2
|
version: ~> 1.0.0
|
||||||
carbon:
|
|
||||||
github: luckyframework/carbon
|
|
||||||
version: ~> 0.2.0
|
|
||||||
lucky_env:
|
lucky_env:
|
||||||
github: luckyframework/lucky_env
|
github: luckyframework/lucky_env
|
||||||
version: ~> 0.1.4
|
version: ~> 0.1.4
|
||||||
lucky_task:
|
lucky_task:
|
||||||
github: luckyframework/lucky_task
|
github: luckyframework/lucky_task
|
||||||
version: ~> 0.1.1
|
version: ~> 0.1.1
|
||||||
|
carbon:
|
||||||
|
github: luckyframework/carbon
|
||||||
|
version: ~> 0.3.0
|
||||||
monads:
|
monads:
|
||||||
github: alex-lairan/monads
|
github: alex-lairan/monads
|
||||||
development_dependencies:
|
development_dependencies:
|
||||||
lucky_flow:
|
lucky_flow:
|
||||||
github: luckyframework/lucky_flow
|
github: luckyframework/lucky_flow
|
||||||
version: ~> 0.7.3
|
version: ~> 0.9.0
|
||||||
|
|
|
@ -78,6 +78,14 @@ describe ArticleIdParser do
|
||||||
result.should eq(Monads::Just.new("888888abcdef"))
|
result.should eq(Monads::Just.new("888888abcdef"))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "parses the post id for global identity 2 redirects" do
|
||||||
|
request = resource_request("/m/global-identity-2?redirectUrl=https%3A%2F%2Fexample.com%2Fmy-post-999999abcdef")
|
||||||
|
|
||||||
|
result = ArticleIdParser.parse(request)
|
||||||
|
|
||||||
|
result.should eq(Monads::Just.new("999999abcdef"))
|
||||||
|
end
|
||||||
|
|
||||||
it "returns Nothing if path is a username" do
|
it "returns Nothing if path is a username" do
|
||||||
request = resource_request("/@ba5eba11")
|
request = resource_request("/@ba5eba11")
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ describe EmbeddedConverter do
|
||||||
store = GistStore.new
|
store = GistStore.new
|
||||||
paragraph = PostResponse::Paragraph.from_json <<-JSON
|
paragraph = PostResponse::Paragraph.from_json <<-JSON
|
||||||
{
|
{
|
||||||
|
"name": "ab12",
|
||||||
"text": "",
|
"text": "",
|
||||||
"type": "IFRAME",
|
"type": "IFRAME",
|
||||||
"href": null,
|
"href": null,
|
||||||
|
@ -36,6 +37,44 @@ describe EmbeddedConverter do
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "and a caption exists" do
|
||||||
|
it "returns an EmbeddedContent node with caption" do
|
||||||
|
store = GistStore.new
|
||||||
|
paragraph = PostResponse::Paragraph.from_json <<-JSON
|
||||||
|
{
|
||||||
|
"name": "ab12",
|
||||||
|
"text": "Caption",
|
||||||
|
"type": "IFRAME",
|
||||||
|
"href": null,
|
||||||
|
"layout": "INSET_CENTER",
|
||||||
|
"markups": [],
|
||||||
|
"iframe": {
|
||||||
|
"mediaResource": {
|
||||||
|
"id": "abc123",
|
||||||
|
"href": "https://twitter.com/user/status/1",
|
||||||
|
"iframeSrc": "https://cdn.embedly.com/widgets/...",
|
||||||
|
"iframeWidth": 500,
|
||||||
|
"iframeHeight": 281
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"metadata": null
|
||||||
|
}
|
||||||
|
JSON
|
||||||
|
caption = FigureCaption.new(children: [Text.new("Caption")] of Child)
|
||||||
|
|
||||||
|
result = EmbeddedConverter.convert(paragraph, store)
|
||||||
|
|
||||||
|
result.should eq(
|
||||||
|
EmbeddedContent.new(
|
||||||
|
src: "https://cdn.embedly.com/widgets/...",
|
||||||
|
originalWidth: 500,
|
||||||
|
originalHeight: 281,
|
||||||
|
caption: caption,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when the mediaResource has a blank iframeSrc value" do
|
context "when the mediaResource has a blank iframeSrc value" do
|
||||||
|
@ -44,6 +83,7 @@ describe EmbeddedConverter do
|
||||||
store = GistStore.new
|
store = GistStore.new
|
||||||
paragraph = PostResponse::Paragraph.from_json <<-JSON
|
paragraph = PostResponse::Paragraph.from_json <<-JSON
|
||||||
{
|
{
|
||||||
|
"name": "ab12",
|
||||||
"text": "",
|
"text": "",
|
||||||
"type": "IFRAME",
|
"type": "IFRAME",
|
||||||
"href": null,
|
"href": null,
|
||||||
|
@ -73,6 +113,7 @@ describe EmbeddedConverter do
|
||||||
store = GistStore.new
|
store = GistStore.new
|
||||||
paragraph = PostResponse::Paragraph.from_json <<-JSON
|
paragraph = PostResponse::Paragraph.from_json <<-JSON
|
||||||
{
|
{
|
||||||
|
"name": "ab12",
|
||||||
"text": "",
|
"text": "",
|
||||||
"type": "IFRAME",
|
"type": "IFRAME",
|
||||||
"href": null,
|
"href": null,
|
||||||
|
|
|
@ -12,6 +12,7 @@ describe GistScanner do
|
||||||
)
|
)
|
||||||
paragraphs = [
|
paragraphs = [
|
||||||
PostResponse::Paragraph.new(
|
PostResponse::Paragraph.new(
|
||||||
|
name: "ab12",
|
||||||
text: "Check out this gist:",
|
text: "Check out this gist:",
|
||||||
type: PostResponse::ParagraphType::P,
|
type: PostResponse::ParagraphType::P,
|
||||||
markups: [] of PostResponse::Markup,
|
markups: [] of PostResponse::Markup,
|
||||||
|
@ -20,6 +21,7 @@ describe GistScanner do
|
||||||
metadata: nil
|
metadata: nil
|
||||||
),
|
),
|
||||||
PostResponse::Paragraph.new(
|
PostResponse::Paragraph.new(
|
||||||
|
name: "ab13",
|
||||||
text: "",
|
text: "",
|
||||||
type: PostResponse::ParagraphType::IFRAME,
|
type: PostResponse::ParagraphType::IFRAME,
|
||||||
markups: [] of PostResponse::Markup,
|
markups: [] of PostResponse::Markup,
|
||||||
|
@ -45,6 +47,7 @@ describe GistScanner do
|
||||||
)
|
)
|
||||||
paragraphs = [
|
paragraphs = [
|
||||||
PostResponse::Paragraph.new(
|
PostResponse::Paragraph.new(
|
||||||
|
name: "ab12",
|
||||||
text: "",
|
text: "",
|
||||||
type: PostResponse::ParagraphType::IFRAME,
|
type: PostResponse::ParagraphType::IFRAME,
|
||||||
markups: [] of PostResponse::Markup,
|
markups: [] of PostResponse::Markup,
|
||||||
|
@ -78,6 +81,7 @@ describe GistScanner do
|
||||||
)
|
)
|
||||||
paragraphs = [
|
paragraphs = [
|
||||||
PostResponse::Paragraph.new(
|
PostResponse::Paragraph.new(
|
||||||
|
name: "ab12",
|
||||||
text: "",
|
text: "",
|
||||||
type: PostResponse::ParagraphType::IFRAME,
|
type: PostResponse::ParagraphType::IFRAME,
|
||||||
markups: [] of PostResponse::Markup,
|
markups: [] of PostResponse::Markup,
|
||||||
|
@ -86,6 +90,7 @@ describe GistScanner do
|
||||||
metadata: nil
|
metadata: nil
|
||||||
),
|
),
|
||||||
PostResponse::Paragraph.new(
|
PostResponse::Paragraph.new(
|
||||||
|
name: "ab13",
|
||||||
text: "",
|
text: "",
|
||||||
type: PostResponse::ParagraphType::IFRAME,
|
type: PostResponse::ParagraphType::IFRAME,
|
||||||
markups: [] of PostResponse::Markup,
|
markups: [] of PostResponse::Markup,
|
||||||
|
|
|
@ -8,6 +8,7 @@ describe PageConverter do
|
||||||
paragraph_json = <<-JSON
|
paragraph_json = <<-JSON
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
|
"name": "ab12",
|
||||||
"text": "#{title}",
|
"text": "#{title}",
|
||||||
"type": "H3",
|
"type": "H3",
|
||||||
"markups": [],
|
"markups": [],
|
||||||
|
@ -28,6 +29,7 @@ describe PageConverter do
|
||||||
it "sets the author" do
|
it "sets the author" do
|
||||||
post_json = <<-JSON
|
post_json = <<-JSON
|
||||||
{
|
{
|
||||||
|
"name": "ab12",
|
||||||
"title": "This is a story",
|
"title": "This is a story",
|
||||||
"createdAt": 0,
|
"createdAt": 0,
|
||||||
"creator": {
|
"creator": {
|
||||||
|
@ -52,6 +54,7 @@ describe PageConverter do
|
||||||
it "sets the publish date/time" do
|
it "sets the publish date/time" do
|
||||||
post_json = <<-JSON
|
post_json = <<-JSON
|
||||||
{
|
{
|
||||||
|
"name": "ab12",
|
||||||
"title": "This is a story",
|
"title": "This is a story",
|
||||||
"createdAt": 1000,
|
"createdAt": 1000,
|
||||||
"creator": {
|
"creator": {
|
||||||
|
@ -77,6 +80,7 @@ describe PageConverter do
|
||||||
paragraph_json = <<-JSON
|
paragraph_json = <<-JSON
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
|
"name": "ab12",
|
||||||
"text": "#{title}",
|
"text": "#{title}",
|
||||||
"type": "H3",
|
"type": "H3",
|
||||||
"markups": [],
|
"markups": [],
|
||||||
|
@ -85,6 +89,7 @@ describe PageConverter do
|
||||||
"metadata": null
|
"metadata": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"name": "ab12",
|
||||||
"text": "Content",
|
"text": "Content",
|
||||||
"type": "P",
|
"type": "P",
|
||||||
"markups": [],
|
"markups": [],
|
||||||
|
@ -117,6 +122,7 @@ def default_post_json(
|
||||||
)
|
)
|
||||||
<<-JSON
|
<<-JSON
|
||||||
{
|
{
|
||||||
|
"name": "ab12",
|
||||||
"title": "#{title}",
|
"title": "#{title}",
|
||||||
"createdAt": 1628974309758,
|
"createdAt": 1628974309758,
|
||||||
"creator": {
|
"creator": {
|
||||||
|
|
|
@ -8,6 +8,7 @@ describe ParagraphConverter do
|
||||||
paragraphs = Array(PostResponse::Paragraph).from_json <<-JSON
|
paragraphs = Array(PostResponse::Paragraph).from_json <<-JSON
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
|
"name": "ab12",
|
||||||
"text": "Title",
|
"text": "Title",
|
||||||
"type": "H3",
|
"type": "H3",
|
||||||
"markups": [],
|
"markups": [],
|
||||||
|
@ -17,7 +18,7 @@ describe ParagraphConverter do
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
JSON
|
JSON
|
||||||
expected = [Heading3.new(children: [Text.new(content: "Title")] of Child)]
|
expected = [Heading3.new(children: [Text.new(content: "Title")] of Child, identifier: "ab12")]
|
||||||
|
|
||||||
result = ParagraphConverter.new.convert(paragraphs, gist_store)
|
result = ParagraphConverter.new.convert(paragraphs, gist_store)
|
||||||
|
|
||||||
|
@ -29,6 +30,7 @@ describe ParagraphConverter do
|
||||||
paragraphs = Array(PostResponse::Paragraph).from_json <<-JSON
|
paragraphs = Array(PostResponse::Paragraph).from_json <<-JSON
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
|
"name": "ab12",
|
||||||
"text": "inline code",
|
"text": "inline code",
|
||||||
"type": "P",
|
"type": "P",
|
||||||
"markups": [
|
"markups": [
|
||||||
|
@ -66,6 +68,7 @@ describe ParagraphConverter do
|
||||||
paragraphs = Array(PostResponse::Paragraph).from_json <<-JSON
|
paragraphs = Array(PostResponse::Paragraph).from_json <<-JSON
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
|
"name": "ab12",
|
||||||
"text": "One",
|
"text": "One",
|
||||||
"type": "ULI",
|
"type": "ULI",
|
||||||
"markups": [],
|
"markups": [],
|
||||||
|
@ -74,6 +77,7 @@ describe ParagraphConverter do
|
||||||
"metadata": null
|
"metadata": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"name": "ab13",
|
||||||
"text": "Two",
|
"text": "Two",
|
||||||
"type": "ULI",
|
"type": "ULI",
|
||||||
"markups": [],
|
"markups": [],
|
||||||
|
@ -82,6 +86,7 @@ describe ParagraphConverter do
|
||||||
"metadata": null
|
"metadata": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"name": "ab14",
|
||||||
"text": "Not a list item",
|
"text": "Not a list item",
|
||||||
"type": "P",
|
"type": "P",
|
||||||
"markups": [],
|
"markups": [],
|
||||||
|
@ -109,6 +114,7 @@ describe ParagraphConverter do
|
||||||
paragraphs = Array(PostResponse::Paragraph).from_json <<-JSON
|
paragraphs = Array(PostResponse::Paragraph).from_json <<-JSON
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
|
"name": "ab12",
|
||||||
"text": "One",
|
"text": "One",
|
||||||
"type": "OLI",
|
"type": "OLI",
|
||||||
"markups": [],
|
"markups": [],
|
||||||
|
@ -117,6 +123,7 @@ describe ParagraphConverter do
|
||||||
"metadata": null
|
"metadata": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"name": "ab13",
|
||||||
"text": "Two",
|
"text": "Two",
|
||||||
"type": "OLI",
|
"type": "OLI",
|
||||||
"markups": [],
|
"markups": [],
|
||||||
|
@ -125,6 +132,7 @@ describe ParagraphConverter do
|
||||||
"metadata": null
|
"metadata": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"name": "ab14",
|
||||||
"text": "Not a list item",
|
"text": "Not a list item",
|
||||||
"type": "P",
|
"type": "P",
|
||||||
"markups": [],
|
"markups": [],
|
||||||
|
@ -151,6 +159,7 @@ describe ParagraphConverter do
|
||||||
gist_store = GistStore.new
|
gist_store = GistStore.new
|
||||||
paragraph = PostResponse::Paragraph.from_json <<-JSON
|
paragraph = PostResponse::Paragraph.from_json <<-JSON
|
||||||
{
|
{
|
||||||
|
"name": "ab12",
|
||||||
"text": "Image by someuser",
|
"text": "Image by someuser",
|
||||||
"type": "IMG",
|
"type": "IMG",
|
||||||
"markups": [
|
"markups": [
|
||||||
|
@ -197,6 +206,7 @@ describe ParagraphConverter do
|
||||||
paragraphs = Array(PostResponse::Paragraph).from_json <<-JSON
|
paragraphs = Array(PostResponse::Paragraph).from_json <<-JSON
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
|
"name": "ab12",
|
||||||
"text": "text",
|
"text": "text",
|
||||||
"type": "H2",
|
"type": "H2",
|
||||||
"markups": [],
|
"markups": [],
|
||||||
|
@ -205,6 +215,7 @@ describe ParagraphConverter do
|
||||||
"metadata": null
|
"metadata": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"name": "ab13",
|
||||||
"text": "text",
|
"text": "text",
|
||||||
"type": "H3",
|
"type": "H3",
|
||||||
"markups": [],
|
"markups": [],
|
||||||
|
@ -213,6 +224,7 @@ describe ParagraphConverter do
|
||||||
"metadata": null
|
"metadata": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"name": "ab14",
|
||||||
"text": "text",
|
"text": "text",
|
||||||
"type": "H4",
|
"type": "H4",
|
||||||
"markups": [],
|
"markups": [],
|
||||||
|
@ -221,6 +233,7 @@ describe ParagraphConverter do
|
||||||
"metadata": null
|
"metadata": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"name": "ab15",
|
||||||
"text": "text",
|
"text": "text",
|
||||||
"type": "P",
|
"type": "P",
|
||||||
"markups": [],
|
"markups": [],
|
||||||
|
@ -229,6 +242,7 @@ describe ParagraphConverter do
|
||||||
"metadata": null
|
"metadata": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"name": "ab16",
|
||||||
"text": "text",
|
"text": "text",
|
||||||
"type": "PRE",
|
"type": "PRE",
|
||||||
"markups": [],
|
"markups": [],
|
||||||
|
@ -237,6 +251,7 @@ describe ParagraphConverter do
|
||||||
"metadata": null
|
"metadata": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"name": "ab17",
|
||||||
"text": "text",
|
"text": "text",
|
||||||
"type": "BQ",
|
"type": "BQ",
|
||||||
"markups": [],
|
"markups": [],
|
||||||
|
@ -245,6 +260,7 @@ describe ParagraphConverter do
|
||||||
"metadata": null
|
"metadata": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"name": "ab18",
|
||||||
"text": "text",
|
"text": "text",
|
||||||
"type": "PQ",
|
"type": "PQ",
|
||||||
"markups": [],
|
"markups": [],
|
||||||
|
@ -253,6 +269,7 @@ describe ParagraphConverter do
|
||||||
"metadata": null
|
"metadata": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"name": "ab19",
|
||||||
"text": "text",
|
"text": "text",
|
||||||
"type": "ULI",
|
"type": "ULI",
|
||||||
"markups": [],
|
"markups": [],
|
||||||
|
@ -261,6 +278,7 @@ describe ParagraphConverter do
|
||||||
"metadata": null
|
"metadata": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"name": "ab20",
|
||||||
"text": "text",
|
"text": "text",
|
||||||
"type": "OLI",
|
"type": "OLI",
|
||||||
"markups": [],
|
"markups": [],
|
||||||
|
@ -269,6 +287,7 @@ describe ParagraphConverter do
|
||||||
"metadata": null
|
"metadata": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"name": "ab21",
|
||||||
"text": "text",
|
"text": "text",
|
||||||
"type": "IMG",
|
"type": "IMG",
|
||||||
"markups": [],
|
"markups": [],
|
||||||
|
@ -281,6 +300,7 @@ describe ParagraphConverter do
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"name": "ab22",
|
||||||
"text": "",
|
"text": "",
|
||||||
"type": "IFRAME",
|
"type": "IFRAME",
|
||||||
"markups": [],
|
"markups": [],
|
||||||
|
@ -296,6 +316,7 @@ describe ParagraphConverter do
|
||||||
"metadata": null
|
"metadata": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"name": "ab23",
|
||||||
"text": "Mixtape",
|
"text": "Mixtape",
|
||||||
"type": "MIXTAPE_EMBED",
|
"type": "MIXTAPE_EMBED",
|
||||||
"href": null,
|
"href": null,
|
||||||
|
@ -317,9 +338,9 @@ describe ParagraphConverter do
|
||||||
]
|
]
|
||||||
JSON
|
JSON
|
||||||
expected = [
|
expected = [
|
||||||
Heading1.new([Text.new("text")] of Child),
|
Heading1.new([Text.new("text")] of Child, identifier: "ab12"),
|
||||||
Heading2.new([Text.new("text")] of Child),
|
Heading2.new([Text.new("text")] of Child, identifier: "ab13"),
|
||||||
Heading3.new([Text.new("text")] of Child),
|
Heading3.new([Text.new("text")] of Child, identifier: "ab14"),
|
||||||
Paragraph.new([Text.new("text")] of Child),
|
Paragraph.new([Text.new("text")] of Child),
|
||||||
Preformatted.new([Text.new("text")] of Child),
|
Preformatted.new([Text.new("text")] of Child),
|
||||||
BlockQuote.new([Text.new("text")] of Child), # BQ
|
BlockQuote.new([Text.new("text")] of Child), # BQ
|
||||||
|
|
|
@ -184,13 +184,13 @@ describe PageContent do
|
||||||
nodes: [
|
nodes: [
|
||||||
Heading1.new(children: [
|
Heading1.new(children: [
|
||||||
Text.new(content: "Title!"),
|
Text.new(content: "Title!"),
|
||||||
] of Child),
|
] of Child, identifier: "ab12"),
|
||||||
] of Child
|
] of Child
|
||||||
)
|
)
|
||||||
|
|
||||||
html = PageContent.new(page: page).render_to_string
|
html = PageContent.new(page: page).render_to_string
|
||||||
|
|
||||||
html.should eq %(<h1>Title!</h1>)
|
html.should eq %(<h1 id="ab12">Title!</h1>)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "renders an H3" do
|
it "renders an H3" do
|
||||||
|
@ -201,13 +201,13 @@ describe PageContent do
|
||||||
nodes: [
|
nodes: [
|
||||||
Heading2.new(children: [
|
Heading2.new(children: [
|
||||||
Text.new(content: "Title!"),
|
Text.new(content: "Title!"),
|
||||||
] of Child),
|
] of Child, identifier: "ab12"),
|
||||||
] of Child
|
] of Child
|
||||||
)
|
)
|
||||||
|
|
||||||
html = PageContent.new(page: page).render_to_string
|
html = PageContent.new(page: page).render_to_string
|
||||||
|
|
||||||
html.should eq %(<h2>Title!</h2>)
|
html.should eq %(<h2 id="ab12">Title!</h2>)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "renders an H4" do
|
it "renders an H4" do
|
||||||
|
@ -218,13 +218,13 @@ describe PageContent do
|
||||||
nodes: [
|
nodes: [
|
||||||
Heading3.new(children: [
|
Heading3.new(children: [
|
||||||
Text.new(content: "In Conclusion..."),
|
Text.new(content: "In Conclusion..."),
|
||||||
] of Child),
|
] of Child, identifier: "ab12"),
|
||||||
] of Child
|
] of Child
|
||||||
)
|
)
|
||||||
|
|
||||||
html = PageContent.new(page: page).render_to_string
|
html = PageContent.new(page: page).render_to_string
|
||||||
|
|
||||||
html.should eq %(<h3>In Conclusion...</h3>)
|
html.should eq %(<h3 id="ab12">In Conclusion...</h3>)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "renders an image" do
|
it "renders an image" do
|
||||||
|
@ -249,6 +249,7 @@ describe PageContent do
|
||||||
end
|
end
|
||||||
|
|
||||||
it "renders embedded content" do
|
it "renders embedded content" do
|
||||||
|
caption_children = [Text.new("Caption")] of Child
|
||||||
page = Page.new(
|
page = Page.new(
|
||||||
title: "Title",
|
title: "Title",
|
||||||
author: user_anchor_factory,
|
author: user_anchor_factory,
|
||||||
|
@ -258,6 +259,7 @@ describe PageContent do
|
||||||
src: "https://example.com",
|
src: "https://example.com",
|
||||||
originalWidth: 1000,
|
originalWidth: 1000,
|
||||||
originalHeight: 600,
|
originalHeight: 600,
|
||||||
|
caption: FigureCaption.new(children: caption_children)
|
||||||
),
|
),
|
||||||
] of Child
|
] of Child
|
||||||
)
|
)
|
||||||
|
@ -268,6 +270,11 @@ describe PageContent do
|
||||||
<figure>
|
<figure>
|
||||||
<iframe src="https://example.com" width="800" height="480" frameborder="0" allowfullscreen="true">
|
<iframe src="https://example.com" width="800" height="480" frameborder="0" allowfullscreen="true">
|
||||||
</iframe>
|
</iframe>
|
||||||
|
<label class="margin-toggle" for="#{caption_children.hash}">✍︎</label>
|
||||||
|
<input class="margin-toggle" type="checkbox" id="#{caption_children.hash}">
|
||||||
|
<span class="marginnote">
|
||||||
|
Caption
|
||||||
|
</span>
|
||||||
</figure>
|
</figure>
|
||||||
HTML
|
HTML
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,4 +10,4 @@ LuckyFlow.configure do |settings|
|
||||||
# Be sure to disable for CI.
|
# Be sure to disable for CI.
|
||||||
# settings.driver = LuckyFlow::Drivers::Chrome
|
# settings.driver = LuckyFlow::Drivers::Chrome
|
||||||
end
|
end
|
||||||
Spec.before_each { LuckyFlow::Server::INSTANCE.reset }
|
LuckyFlow::Spec.setup
|
|
@ -2,6 +2,8 @@ ENV["LUCKY_ENV"] = "test"
|
||||||
ENV["DEV_PORT"] = "5001"
|
ENV["DEV_PORT"] = "5001"
|
||||||
require "spec"
|
require "spec"
|
||||||
require "lucky_flow"
|
require "lucky_flow"
|
||||||
|
require "lucky_flow/ext/lucky"
|
||||||
|
require "lucky_flow/ext/avram"
|
||||||
require "../src/app"
|
require "../src/app"
|
||||||
require "./support/flows/base_flow"
|
require "./support/flows/base_flow"
|
||||||
require "./support/**"
|
require "./support/**"
|
||||||
|
|
|
@ -1,56 +0,0 @@
|
||||||
class RedirectionConfig::Index < Lucky::Action
|
|
||||||
include Lucky::ProtectFromForgery
|
|
||||||
include Lucky::EnforceUnderscoredRoute
|
|
||||||
include Lucky::SecureHeaders::DisableFLoC
|
|
||||||
|
|
||||||
default_format :json
|
|
||||||
|
|
||||||
get "/redirection_config" do
|
|
||||||
data(
|
|
||||||
data: config_json,
|
|
||||||
content_type: "application/json",
|
|
||||||
disposition: "attachment",
|
|
||||||
filename: "redirector-config.json"
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
private def config_json
|
|
||||||
double_escaped_pattern = "^https?://(?:.*\\\\.)*(?<!(link\\\\.|cdn\\\\-images\\\\-\\\\d+\\\\.))medium\\\\.com(/.*)?$"
|
|
||||||
<<-JSON
|
|
||||||
{
|
|
||||||
"createdBy": "Redirector v3.5.3",
|
|
||||||
"createdAt": "2022-07-17T00:00:00.000Z",
|
|
||||||
"redirects": [
|
|
||||||
{
|
|
||||||
"description": "Medium -> Scribe",
|
|
||||||
"exampleUrl": "https://medium.com/@user/post-123456abcdef",
|
|
||||||
"exampleResult": "https://#{app_domain}/@user/post-123456abcdef",
|
|
||||||
"error": null,
|
|
||||||
"includePattern": "#{double_escaped_pattern}",
|
|
||||||
"excludePattern": "",
|
|
||||||
"patternDesc": "",
|
|
||||||
"redirectUrl": "https://#{app_domain}$2",
|
|
||||||
"patternType": "R",
|
|
||||||
"processMatches": "noProcessing",
|
|
||||||
"disabled": false,
|
|
||||||
"grouped": false,
|
|
||||||
"appliesTo": [
|
|
||||||
"main_frame",
|
|
||||||
"sub_frame",
|
|
||||||
"xmlhttprequest",
|
|
||||||
"history",
|
|
||||||
"other"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
JSON
|
|
||||||
end
|
|
||||||
|
|
||||||
private def app_domain
|
|
||||||
URI.parse(Home::Index.url).normalize
|
|
||||||
.to_s
|
|
||||||
.sub(/\/$/, "")
|
|
||||||
.sub(/^https?:\/\//, "")
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,7 +1,7 @@
|
||||||
class ArticleIdParser
|
class ArticleIdParser
|
||||||
include Monads
|
include Monads
|
||||||
|
|
||||||
ID_REGEX = /[\/\-]([0-9a-f]+)$/i
|
ID_REGEX = /[\/\-]([0-9a-f]+)\/?$/i
|
||||||
|
|
||||||
def self.parse(request : HTTP::Request)
|
def self.parse(request : HTTP::Request)
|
||||||
new.parse(request)
|
new.parse(request)
|
||||||
|
@ -10,7 +10,7 @@ class ArticleIdParser
|
||||||
def parse(request : HTTP::Request) : Maybe
|
def parse(request : HTTP::Request) : Maybe
|
||||||
from_params = post_id_from_params(request.query_params)
|
from_params = post_id_from_params(request.query_params)
|
||||||
from_path = post_id_from_path(request.path)
|
from_path = post_id_from_path(request.path)
|
||||||
from_path.or(from_params)
|
from_params.or(from_path)
|
||||||
end
|
end
|
||||||
|
|
||||||
private def post_id_from_path(request_path : String)
|
private def post_id_from_path(request_path : String)
|
||||||
|
|
|
@ -34,11 +34,19 @@ class EmbeddedConverter
|
||||||
EmbeddedContent.new(
|
EmbeddedContent.new(
|
||||||
src: media.iframeSrc,
|
src: media.iframeSrc,
|
||||||
originalWidth: media.iframeWidth,
|
originalWidth: media.iframeWidth,
|
||||||
originalHeight: media.iframeHeight
|
originalHeight: media.iframeHeight,
|
||||||
|
caption: caption
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private def caption : FigureCaption?
|
||||||
|
if !paragraph.text.blank?
|
||||||
|
children = [Text.new(paragraph.text || "")] of Child
|
||||||
|
FigureCaption.new(children: children)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
private def custom_embed(media : PostResponse::MediaResource) : Embedded
|
private def custom_embed(media : PostResponse::MediaResource) : Embedded
|
||||||
if media.href.starts_with?(GIST_HOST_AND_SCHEME)
|
if media.href.starts_with?(GIST_HOST_AND_SCHEME)
|
||||||
GithubGist.new(href: media.href, gist_store: gist_store)
|
GithubGist.new(href: media.href, gist_store: gist_store)
|
||||||
|
|
|
@ -16,15 +16,15 @@ class ParagraphConverter
|
||||||
when PostResponse::ParagraphType::H2
|
when PostResponse::ParagraphType::H2
|
||||||
paragraph = paragraphs.shift
|
paragraph = paragraphs.shift
|
||||||
children = MarkupConverter.convert(paragraph.text, paragraph.markups)
|
children = MarkupConverter.convert(paragraph.text, paragraph.markups)
|
||||||
node = Heading1.new(children: children)
|
node = Heading1.new(children: children, identifier: paragraph.name || "")
|
||||||
when PostResponse::ParagraphType::H3
|
when PostResponse::ParagraphType::H3
|
||||||
paragraph = paragraphs.shift
|
paragraph = paragraphs.shift
|
||||||
children = MarkupConverter.convert(paragraph.text, paragraph.markups)
|
children = MarkupConverter.convert(paragraph.text, paragraph.markups)
|
||||||
node = Heading2.new(children: children)
|
node = Heading2.new(children: children, identifier: paragraph.name || "")
|
||||||
when PostResponse::ParagraphType::H4
|
when PostResponse::ParagraphType::H4
|
||||||
paragraph = paragraphs.shift
|
paragraph = paragraphs.shift
|
||||||
children = MarkupConverter.convert(paragraph.text, paragraph.markups)
|
children = MarkupConverter.convert(paragraph.text, paragraph.markups)
|
||||||
node = Heading3.new(children: children)
|
node = Heading3.new(children: children, identifier: paragraph.name || "")
|
||||||
when PostResponse::ParagraphType::IFRAME
|
when PostResponse::ParagraphType::IFRAME
|
||||||
paragraph = paragraphs.shift
|
paragraph = paragraphs.shift
|
||||||
node = EmbeddedConverter.convert(paragraph, gist_store)
|
node = EmbeddedConverter.convert(paragraph, gist_store)
|
||||||
|
|
|
@ -27,6 +27,7 @@ class MediumClient
|
||||||
content {
|
content {
|
||||||
bodyModel {
|
bodyModel {
|
||||||
paragraphs {
|
paragraphs {
|
||||||
|
name
|
||||||
text
|
text
|
||||||
type
|
type
|
||||||
href
|
href
|
||||||
|
|
|
@ -40,6 +40,9 @@ class PageContent < BaseComponent
|
||||||
frameborder: "0",
|
frameborder: "0",
|
||||||
allowfullscreen: true,
|
allowfullscreen: true,
|
||||||
)
|
)
|
||||||
|
if caption = child.caption
|
||||||
|
render_child(caption)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -93,15 +96,15 @@ class PageContent < BaseComponent
|
||||||
end
|
end
|
||||||
|
|
||||||
def render_child(node : Heading1)
|
def render_child(node : Heading1)
|
||||||
h1 { render_children(node.children) }
|
h1(id: node.identifier) { render_children(node.children) }
|
||||||
end
|
end
|
||||||
|
|
||||||
def render_child(node : Heading2)
|
def render_child(node : Heading2)
|
||||||
h2 { render_children(node.children) }
|
h2(id: node.identifier) { render_children(node.children) }
|
||||||
end
|
end
|
||||||
|
|
||||||
def render_child(node : Heading3)
|
def render_child(node : Heading3)
|
||||||
h3 { render_children(node.children) }
|
h3(id: node.identifier) { render_children(node.children) }
|
||||||
end
|
end
|
||||||
|
|
||||||
def render_child(child : Image)
|
def render_child(child : Image)
|
||||||
|
|
|
@ -7,13 +7,22 @@ p.meta {
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.gist {
|
pre {
|
||||||
width: 55%;
|
background-color: rgba(127, 127, 127, 0.1);
|
||||||
|
margin-right: 1em;
|
||||||
|
padding: 1em;
|
||||||
|
padding-left: 2em;
|
||||||
|
overflow-x: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre > code {
|
||||||
|
margin-left: 0;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 760px) {
|
@media (max-width: 760px) {
|
||||||
.gist {
|
pre {
|
||||||
width: 100%;
|
margin-right: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,10 +43,3 @@ figure iframe {
|
||||||
footer p span {
|
footer p span {
|
||||||
margin-right: 1em;
|
margin-right: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
|
||||||
background-color: rgba(127, 127, 127, 0.1);
|
|
||||||
padding: 1em;
|
|
||||||
overflow-x: scroll;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
|
@ -41,12 +41,24 @@ module Nodes
|
||||||
end
|
end
|
||||||
|
|
||||||
class Heading1 < Container
|
class Heading1 < Container
|
||||||
|
getter identifier : String
|
||||||
|
|
||||||
|
def initialize(@children : Children, @identifier : String)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class Heading2 < Container
|
class Heading2 < Container
|
||||||
|
getter identifier : String
|
||||||
|
|
||||||
|
def initialize(@children : Children, @identifier : String)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class Heading3 < Container
|
class Heading3 < Container
|
||||||
|
getter identifier : String
|
||||||
|
|
||||||
|
def initialize(@children : Children, @identifier : String)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class ListItem < Container
|
class ListItem < Container
|
||||||
|
@ -135,8 +147,14 @@ module Nodes
|
||||||
MAX_WIDTH = 800
|
MAX_WIDTH = 800
|
||||||
|
|
||||||
getter src : String
|
getter src : String
|
||||||
|
getter caption : FigureCaption?
|
||||||
|
|
||||||
def initialize(@src : String, @originalWidth : Int32, @originalHeight : Int32)
|
def initialize(
|
||||||
|
@src : String,
|
||||||
|
@originalWidth : Int32,
|
||||||
|
@originalHeight : Int32,
|
||||||
|
@caption : FigureCaption? = nil
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
def width
|
def width
|
||||||
|
@ -156,7 +174,10 @@ module Nodes
|
||||||
end
|
end
|
||||||
|
|
||||||
def ==(other : EmbeddedContent)
|
def ==(other : EmbeddedContent)
|
||||||
other.src == src && other.width == width && other.height == height
|
other.src == src &&
|
||||||
|
other.width == width &&
|
||||||
|
other.height == height &&
|
||||||
|
other.caption == caption
|
||||||
end
|
end
|
||||||
|
|
||||||
def empty?
|
def empty?
|
||||||
|
|
|
@ -32,6 +32,7 @@ class PostResponse
|
||||||
end
|
end
|
||||||
|
|
||||||
class Paragraph < Base
|
class Paragraph < Base
|
||||||
|
property name : String?
|
||||||
property text : String?
|
property text : String?
|
||||||
property type : ParagraphType
|
property type : ParagraphType
|
||||||
property markups : Array(Markup)
|
property markups : Array(Markup)
|
||||||
|
@ -40,6 +41,7 @@ class PostResponse
|
||||||
property metadata : Metadata?
|
property metadata : Metadata?
|
||||||
|
|
||||||
def initialize(
|
def initialize(
|
||||||
|
@name : String,
|
||||||
@text : String?,
|
@text : String?,
|
||||||
@type : ParagraphType,
|
@type : ParagraphType,
|
||||||
@markups : Array(Markup),
|
@markups : Array(Markup),
|
||||||
|
|
|
@ -18,19 +18,9 @@ class Faq::IndexPage < MainLayout
|
||||||
section do
|
section do
|
||||||
h2 "How-to Automatically Redirect Medium Articles"
|
h2 "How-to Automatically Redirect Medium Articles"
|
||||||
para do
|
para do
|
||||||
text "If you don't want to manually change the URL every time, you can use an extension to do it for you. "
|
text "If you don't want to manually change the URL every time, you can use an extension to do it for you. The "
|
||||||
a "This extension", href: "https://einaregilsson.com/redirector/"
|
a "LibRedirect extention", href: "https://libredirect.github.io/"
|
||||||
text " works well across most browsers."
|
text " works well across most browsers, and will also redirect to other alternative services."
|
||||||
end
|
|
||||||
para do
|
|
||||||
text "Once installed download a configuration file by "
|
|
||||||
link "clicking here", to: RedirectionConfig::Index
|
|
||||||
text "."
|
|
||||||
end
|
|
||||||
para do
|
|
||||||
text "Install it by opening the extension preferences, editing redirects, clicking "
|
|
||||||
code "Import"
|
|
||||||
text " and selecting the downloaded file. This will add a new redirection and not overwrite any existing ones. Now visiting any medium.com site (including user.medium.com subdomains) should redirect to Scribe instead!"
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
module Scribe
|
module Scribe
|
||||||
VERSION = "2022-07-19"
|
VERSION = "2023-05-06"
|
||||||
end
|
end
|
||||||
|
|
1
tasks.cr
1
tasks.cr
|
@ -7,5 +7,6 @@ require "lucky_task"
|
||||||
require "./tasks/**"
|
require "./tasks/**"
|
||||||
require "./db/migrations/**"
|
require "./db/migrations/**"
|
||||||
require "lucky/tasks/**"
|
require "lucky/tasks/**"
|
||||||
|
require "avram/lucky/tasks"
|
||||||
|
|
||||||
LuckyTask::Runner.run
|
LuckyTask::Runner.run
|
||||||
|
|
Loading…
Reference in a new issue