Compare commits
No commits in common. "5ab9c48e2c8b6befb288ea2a5ce7e78a499b4674" and "9fd5b1a28ea5c65c79512d39c2dad109dfd69a41" have entirely different histories.
5ab9c48e2c
...
9fd5b1a28e
27 changed files with 124 additions and 243 deletions
|
@ -1 +1 @@
|
|||
1.8.1
|
||||
1.5.0
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
nodejs 16.18.0
|
||||
nodejs 12.14.1
|
||||
crystal 1.5.0
|
||||
|
|
33
CHANGELOG
33
CHANGELOG
|
@ -1,36 +1,3 @@
|
|||
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
|
||||
|
||||
* Fix downloadable config file for Redirector extension
|
||||
|
|
|
@ -5,7 +5,5 @@
|
|||
"https://scribe.bus-hit.me",
|
||||
"https://scribe.froth.zone",
|
||||
"https://scribe.esmailelbob.xyz",
|
||||
"https://scribe.privacydev.net",
|
||||
"https://scribe.rawbit.ninja",
|
||||
"https://sc.vern.cc"
|
||||
"https://scribe.privacydev.net"
|
||||
]
|
||||
|
|
|
@ -7,11 +7,7 @@
|
|||
* <https://scribe.froth.zone>
|
||||
* <https://scribe.esmailelbob.xyz>
|
||||
* <https://scribe.privacydev.net>
|
||||
* <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)
|
||||
* <scribe.lqs5fjmajyp7rvp4qvyubwofzi6d4imua7vs237rkc4m5qogitqwrgyd.onion> (Tor)
|
||||
|
||||
## How do I get my instance on this list?
|
||||
|
||||
|
|
42
shard.lock
42
shard.lock
|
@ -2,27 +2,31 @@ version: 2.0
|
|||
shards:
|
||||
authentic:
|
||||
git: https://github.com/luckyframework/authentic.git
|
||||
version: 1.0.0
|
||||
version: 0.8.2
|
||||
|
||||
avram:
|
||||
git: https://github.com/luckyframework/avram.git
|
||||
version: 1.0.0
|
||||
version: 0.23.0
|
||||
|
||||
backtracer:
|
||||
git: https://github.com/sija/backtracer.cr.git
|
||||
version: 1.2.2
|
||||
version: 1.2.1
|
||||
|
||||
cadmium_transliterator:
|
||||
git: https://github.com/cadmiumcr/transliterator.git
|
||||
version: 0.1.0+git.commit.46c4c14594057dbcfaf27e7e7c8c164d3f0ce3f1
|
||||
|
||||
carbon:
|
||||
git: https://github.com/luckyframework/carbon.git
|
||||
version: 0.2.1
|
||||
|
||||
cry:
|
||||
git: https://github.com/luckyframework/cry.git
|
||||
version: 0.4.3
|
||||
|
||||
crystar:
|
||||
git: https://github.com/naqvis/crystar.git
|
||||
version: 0.2.0+git.commit.56db8bb9dfbd5ed6d7908353405a5fae632a6561
|
||||
version: 0.2.0
|
||||
|
||||
db:
|
||||
git: https://github.com/crystal-lang/crystal-db.git
|
||||
|
@ -34,23 +38,15 @@ shards:
|
|||
|
||||
exception_page:
|
||||
git: https://github.com/crystal-loot/exception_page.git
|
||||
version: 0.3.0
|
||||
|
||||
fnv:
|
||||
git: https://github.com/naqvis/crystal-fnv.git
|
||||
version: 0.1.3
|
||||
version: 0.2.2
|
||||
|
||||
habitat:
|
||||
git: https://github.com/luckyframework/habitat.git
|
||||
version: 0.4.7
|
||||
|
||||
html5:
|
||||
git: https://github.com/naqvis/crystal-html5.git
|
||||
version: 0.4.0
|
||||
|
||||
lucky:
|
||||
git: https://github.com/luckyframework/lucky.git
|
||||
version: 1.0.0
|
||||
version: 0.30.1
|
||||
|
||||
lucky_cache:
|
||||
git: https://github.com/luckyframework/lucky_cache.git
|
||||
|
@ -62,11 +58,11 @@ shards:
|
|||
|
||||
lucky_flow:
|
||||
git: https://github.com/luckyframework/lucky_flow.git
|
||||
version: 0.9.0
|
||||
version: 0.7.3
|
||||
|
||||
lucky_router:
|
||||
git: https://github.com/luckyframework/lucky_router.git
|
||||
version: 0.5.2
|
||||
version: 0.5.1
|
||||
|
||||
lucky_task:
|
||||
git: https://github.com/luckyframework/lucky_task.git
|
||||
|
@ -86,7 +82,7 @@ shards:
|
|||
|
||||
selenium:
|
||||
git: https://github.com/matthewmcgarvey/selenium.cr.git
|
||||
version: 0.10.0
|
||||
version: 0.9.1
|
||||
|
||||
shell-table:
|
||||
git: https://github.com/luckyframework/shell-table.cr.git
|
||||
|
@ -102,17 +98,9 @@ shards:
|
|||
|
||||
webdrivers:
|
||||
git: https://github.com/matthewmcgarvey/webdrivers.cr.git
|
||||
version: 0.4.1
|
||||
|
||||
webless:
|
||||
git: https://github.com/matthewmcgarvey/webless.git
|
||||
version: 0.1.0
|
||||
version: 0.4.0
|
||||
|
||||
wordsmith:
|
||||
git: https://github.com/luckyframework/wordsmith.git
|
||||
version: 0.4.0
|
||||
|
||||
xpath2:
|
||||
git: https://github.com/naqvis/crystal-xpath2.git
|
||||
version: 0.1.3
|
||||
version: 0.3.0
|
||||
|
||||
|
|
14
shard.yml
14
shard.yml
|
@ -8,18 +8,18 @@ targets:
|
|||
scribe:
|
||||
main: src/scribe.cr
|
||||
|
||||
crystal: 1.8.1
|
||||
crystal: 1.5.0
|
||||
|
||||
dependencies:
|
||||
lucky:
|
||||
github: luckyframework/lucky
|
||||
version: ~> 1.0.0
|
||||
avram:
|
||||
github: luckyframework/avram
|
||||
version: ~> 1.0.0
|
||||
version: ~> 0.30.1
|
||||
authentic:
|
||||
github: luckyframework/authentic
|
||||
version: ~> 1.0.0
|
||||
version: ~> 0.8.2
|
||||
carbon:
|
||||
github: luckyframework/carbon
|
||||
version: ~> 0.2.0
|
||||
lucky_env:
|
||||
github: luckyframework/lucky_env
|
||||
version: ~> 0.1.4
|
||||
|
@ -31,4 +31,4 @@ dependencies:
|
|||
development_dependencies:
|
||||
lucky_flow:
|
||||
github: luckyframework/lucky_flow
|
||||
version: ~> 0.9.0
|
||||
version: ~> 0.7.3
|
||||
|
|
|
@ -78,14 +78,6 @@ describe ArticleIdParser do
|
|||
result.should eq(Monads::Just.new("888888abcdef"))
|
||||
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
|
||||
request = resource_request("/@ba5eba11")
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@ describe EmbeddedConverter do
|
|||
store = GistStore.new
|
||||
paragraph = PostResponse::Paragraph.from_json <<-JSON
|
||||
{
|
||||
"name": "ab12",
|
||||
"text": "",
|
||||
"type": "IFRAME",
|
||||
"href": null,
|
||||
|
@ -37,44 +36,6 @@ describe EmbeddedConverter do
|
|||
)
|
||||
)
|
||||
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
|
||||
|
||||
context "when the mediaResource has a blank iframeSrc value" do
|
||||
|
@ -83,7 +44,6 @@ describe EmbeddedConverter do
|
|||
store = GistStore.new
|
||||
paragraph = PostResponse::Paragraph.from_json <<-JSON
|
||||
{
|
||||
"name": "ab12",
|
||||
"text": "",
|
||||
"type": "IFRAME",
|
||||
"href": null,
|
||||
|
@ -113,7 +73,6 @@ describe EmbeddedConverter do
|
|||
store = GistStore.new
|
||||
paragraph = PostResponse::Paragraph.from_json <<-JSON
|
||||
{
|
||||
"name": "ab12",
|
||||
"text": "",
|
||||
"type": "IFRAME",
|
||||
"href": null,
|
||||
|
|
|
@ -12,7 +12,6 @@ describe GistScanner do
|
|||
)
|
||||
paragraphs = [
|
||||
PostResponse::Paragraph.new(
|
||||
name: "ab12",
|
||||
text: "Check out this gist:",
|
||||
type: PostResponse::ParagraphType::P,
|
||||
markups: [] of PostResponse::Markup,
|
||||
|
@ -21,7 +20,6 @@ describe GistScanner do
|
|||
metadata: nil
|
||||
),
|
||||
PostResponse::Paragraph.new(
|
||||
name: "ab13",
|
||||
text: "",
|
||||
type: PostResponse::ParagraphType::IFRAME,
|
||||
markups: [] of PostResponse::Markup,
|
||||
|
@ -47,7 +45,6 @@ describe GistScanner do
|
|||
)
|
||||
paragraphs = [
|
||||
PostResponse::Paragraph.new(
|
||||
name: "ab12",
|
||||
text: "",
|
||||
type: PostResponse::ParagraphType::IFRAME,
|
||||
markups: [] of PostResponse::Markup,
|
||||
|
@ -81,7 +78,6 @@ describe GistScanner do
|
|||
)
|
||||
paragraphs = [
|
||||
PostResponse::Paragraph.new(
|
||||
name: "ab12",
|
||||
text: "",
|
||||
type: PostResponse::ParagraphType::IFRAME,
|
||||
markups: [] of PostResponse::Markup,
|
||||
|
@ -90,7 +86,6 @@ describe GistScanner do
|
|||
metadata: nil
|
||||
),
|
||||
PostResponse::Paragraph.new(
|
||||
name: "ab13",
|
||||
text: "",
|
||||
type: PostResponse::ParagraphType::IFRAME,
|
||||
markups: [] of PostResponse::Markup,
|
||||
|
|
|
@ -8,7 +8,6 @@ describe PageConverter do
|
|||
paragraph_json = <<-JSON
|
||||
[
|
||||
{
|
||||
"name": "ab12",
|
||||
"text": "#{title}",
|
||||
"type": "H3",
|
||||
"markups": [],
|
||||
|
@ -29,7 +28,6 @@ describe PageConverter do
|
|||
it "sets the author" do
|
||||
post_json = <<-JSON
|
||||
{
|
||||
"name": "ab12",
|
||||
"title": "This is a story",
|
||||
"createdAt": 0,
|
||||
"creator": {
|
||||
|
@ -54,7 +52,6 @@ describe PageConverter do
|
|||
it "sets the publish date/time" do
|
||||
post_json = <<-JSON
|
||||
{
|
||||
"name": "ab12",
|
||||
"title": "This is a story",
|
||||
"createdAt": 1000,
|
||||
"creator": {
|
||||
|
@ -80,7 +77,6 @@ describe PageConverter do
|
|||
paragraph_json = <<-JSON
|
||||
[
|
||||
{
|
||||
"name": "ab12",
|
||||
"text": "#{title}",
|
||||
"type": "H3",
|
||||
"markups": [],
|
||||
|
@ -89,7 +85,6 @@ describe PageConverter do
|
|||
"metadata": null
|
||||
},
|
||||
{
|
||||
"name": "ab12",
|
||||
"text": "Content",
|
||||
"type": "P",
|
||||
"markups": [],
|
||||
|
@ -122,7 +117,6 @@ def default_post_json(
|
|||
)
|
||||
<<-JSON
|
||||
{
|
||||
"name": "ab12",
|
||||
"title": "#{title}",
|
||||
"createdAt": 1628974309758,
|
||||
"creator": {
|
||||
|
|
|
@ -8,7 +8,6 @@ describe ParagraphConverter do
|
|||
paragraphs = Array(PostResponse::Paragraph).from_json <<-JSON
|
||||
[
|
||||
{
|
||||
"name": "ab12",
|
||||
"text": "Title",
|
||||
"type": "H3",
|
||||
"markups": [],
|
||||
|
@ -18,7 +17,7 @@ describe ParagraphConverter do
|
|||
}
|
||||
]
|
||||
JSON
|
||||
expected = [Heading3.new(children: [Text.new(content: "Title")] of Child, identifier: "ab12")]
|
||||
expected = [Heading3.new(children: [Text.new(content: "Title")] of Child)]
|
||||
|
||||
result = ParagraphConverter.new.convert(paragraphs, gist_store)
|
||||
|
||||
|
@ -30,7 +29,6 @@ describe ParagraphConverter do
|
|||
paragraphs = Array(PostResponse::Paragraph).from_json <<-JSON
|
||||
[
|
||||
{
|
||||
"name": "ab12",
|
||||
"text": "inline code",
|
||||
"type": "P",
|
||||
"markups": [
|
||||
|
@ -68,7 +66,6 @@ describe ParagraphConverter do
|
|||
paragraphs = Array(PostResponse::Paragraph).from_json <<-JSON
|
||||
[
|
||||
{
|
||||
"name": "ab12",
|
||||
"text": "One",
|
||||
"type": "ULI",
|
||||
"markups": [],
|
||||
|
@ -77,7 +74,6 @@ describe ParagraphConverter do
|
|||
"metadata": null
|
||||
},
|
||||
{
|
||||
"name": "ab13",
|
||||
"text": "Two",
|
||||
"type": "ULI",
|
||||
"markups": [],
|
||||
|
@ -86,7 +82,6 @@ describe ParagraphConverter do
|
|||
"metadata": null
|
||||
},
|
||||
{
|
||||
"name": "ab14",
|
||||
"text": "Not a list item",
|
||||
"type": "P",
|
||||
"markups": [],
|
||||
|
@ -114,7 +109,6 @@ describe ParagraphConverter do
|
|||
paragraphs = Array(PostResponse::Paragraph).from_json <<-JSON
|
||||
[
|
||||
{
|
||||
"name": "ab12",
|
||||
"text": "One",
|
||||
"type": "OLI",
|
||||
"markups": [],
|
||||
|
@ -123,7 +117,6 @@ describe ParagraphConverter do
|
|||
"metadata": null
|
||||
},
|
||||
{
|
||||
"name": "ab13",
|
||||
"text": "Two",
|
||||
"type": "OLI",
|
||||
"markups": [],
|
||||
|
@ -132,7 +125,6 @@ describe ParagraphConverter do
|
|||
"metadata": null
|
||||
},
|
||||
{
|
||||
"name": "ab14",
|
||||
"text": "Not a list item",
|
||||
"type": "P",
|
||||
"markups": [],
|
||||
|
@ -159,7 +151,6 @@ describe ParagraphConverter do
|
|||
gist_store = GistStore.new
|
||||
paragraph = PostResponse::Paragraph.from_json <<-JSON
|
||||
{
|
||||
"name": "ab12",
|
||||
"text": "Image by someuser",
|
||||
"type": "IMG",
|
||||
"markups": [
|
||||
|
@ -206,7 +197,6 @@ describe ParagraphConverter do
|
|||
paragraphs = Array(PostResponse::Paragraph).from_json <<-JSON
|
||||
[
|
||||
{
|
||||
"name": "ab12",
|
||||
"text": "text",
|
||||
"type": "H2",
|
||||
"markups": [],
|
||||
|
@ -215,7 +205,6 @@ describe ParagraphConverter do
|
|||
"metadata": null
|
||||
},
|
||||
{
|
||||
"name": "ab13",
|
||||
"text": "text",
|
||||
"type": "H3",
|
||||
"markups": [],
|
||||
|
@ -224,7 +213,6 @@ describe ParagraphConverter do
|
|||
"metadata": null
|
||||
},
|
||||
{
|
||||
"name": "ab14",
|
||||
"text": "text",
|
||||
"type": "H4",
|
||||
"markups": [],
|
||||
|
@ -233,7 +221,6 @@ describe ParagraphConverter do
|
|||
"metadata": null
|
||||
},
|
||||
{
|
||||
"name": "ab15",
|
||||
"text": "text",
|
||||
"type": "P",
|
||||
"markups": [],
|
||||
|
@ -242,7 +229,6 @@ describe ParagraphConverter do
|
|||
"metadata": null
|
||||
},
|
||||
{
|
||||
"name": "ab16",
|
||||
"text": "text",
|
||||
"type": "PRE",
|
||||
"markups": [],
|
||||
|
@ -251,7 +237,6 @@ describe ParagraphConverter do
|
|||
"metadata": null
|
||||
},
|
||||
{
|
||||
"name": "ab17",
|
||||
"text": "text",
|
||||
"type": "BQ",
|
||||
"markups": [],
|
||||
|
@ -260,7 +245,6 @@ describe ParagraphConverter do
|
|||
"metadata": null
|
||||
},
|
||||
{
|
||||
"name": "ab18",
|
||||
"text": "text",
|
||||
"type": "PQ",
|
||||
"markups": [],
|
||||
|
@ -269,7 +253,6 @@ describe ParagraphConverter do
|
|||
"metadata": null
|
||||
},
|
||||
{
|
||||
"name": "ab19",
|
||||
"text": "text",
|
||||
"type": "ULI",
|
||||
"markups": [],
|
||||
|
@ -278,7 +261,6 @@ describe ParagraphConverter do
|
|||
"metadata": null
|
||||
},
|
||||
{
|
||||
"name": "ab20",
|
||||
"text": "text",
|
||||
"type": "OLI",
|
||||
"markups": [],
|
||||
|
@ -287,7 +269,6 @@ describe ParagraphConverter do
|
|||
"metadata": null
|
||||
},
|
||||
{
|
||||
"name": "ab21",
|
||||
"text": "text",
|
||||
"type": "IMG",
|
||||
"markups": [],
|
||||
|
@ -300,7 +281,6 @@ describe ParagraphConverter do
|
|||
}
|
||||
},
|
||||
{
|
||||
"name": "ab22",
|
||||
"text": "",
|
||||
"type": "IFRAME",
|
||||
"markups": [],
|
||||
|
@ -316,7 +296,6 @@ describe ParagraphConverter do
|
|||
"metadata": null
|
||||
},
|
||||
{
|
||||
"name": "ab23",
|
||||
"text": "Mixtape",
|
||||
"type": "MIXTAPE_EMBED",
|
||||
"href": null,
|
||||
|
@ -338,9 +317,9 @@ describe ParagraphConverter do
|
|||
]
|
||||
JSON
|
||||
expected = [
|
||||
Heading1.new([Text.new("text")] of Child, identifier: "ab12"),
|
||||
Heading2.new([Text.new("text")] of Child, identifier: "ab13"),
|
||||
Heading3.new([Text.new("text")] of Child, identifier: "ab14"),
|
||||
Heading1.new([Text.new("text")] of Child),
|
||||
Heading2.new([Text.new("text")] of Child),
|
||||
Heading3.new([Text.new("text")] of Child),
|
||||
Paragraph.new([Text.new("text")] of Child),
|
||||
Preformatted.new([Text.new("text")] of Child),
|
||||
BlockQuote.new([Text.new("text")] of Child), # BQ
|
||||
|
|
|
@ -184,13 +184,13 @@ describe PageContent do
|
|||
nodes: [
|
||||
Heading1.new(children: [
|
||||
Text.new(content: "Title!"),
|
||||
] of Child, identifier: "ab12"),
|
||||
] of Child),
|
||||
] of Child
|
||||
)
|
||||
|
||||
html = PageContent.new(page: page).render_to_string
|
||||
|
||||
html.should eq %(<h1 id="ab12">Title!</h1>)
|
||||
html.should eq %(<h1>Title!</h1>)
|
||||
end
|
||||
|
||||
it "renders an H3" do
|
||||
|
@ -201,13 +201,13 @@ describe PageContent do
|
|||
nodes: [
|
||||
Heading2.new(children: [
|
||||
Text.new(content: "Title!"),
|
||||
] of Child, identifier: "ab12"),
|
||||
] of Child),
|
||||
] of Child
|
||||
)
|
||||
|
||||
html = PageContent.new(page: page).render_to_string
|
||||
|
||||
html.should eq %(<h2 id="ab12">Title!</h2>)
|
||||
html.should eq %(<h2>Title!</h2>)
|
||||
end
|
||||
|
||||
it "renders an H4" do
|
||||
|
@ -218,13 +218,13 @@ describe PageContent do
|
|||
nodes: [
|
||||
Heading3.new(children: [
|
||||
Text.new(content: "In Conclusion..."),
|
||||
] of Child, identifier: "ab12"),
|
||||
] of Child),
|
||||
] of Child
|
||||
)
|
||||
|
||||
html = PageContent.new(page: page).render_to_string
|
||||
|
||||
html.should eq %(<h3 id="ab12">In Conclusion...</h3>)
|
||||
html.should eq %(<h3>In Conclusion...</h3>)
|
||||
end
|
||||
|
||||
it "renders an image" do
|
||||
|
@ -249,7 +249,6 @@ describe PageContent do
|
|||
end
|
||||
|
||||
it "renders embedded content" do
|
||||
caption_children = [Text.new("Caption")] of Child
|
||||
page = Page.new(
|
||||
title: "Title",
|
||||
author: user_anchor_factory,
|
||||
|
@ -259,7 +258,6 @@ describe PageContent do
|
|||
src: "https://example.com",
|
||||
originalWidth: 1000,
|
||||
originalHeight: 600,
|
||||
caption: FigureCaption.new(children: caption_children)
|
||||
),
|
||||
] of Child
|
||||
)
|
||||
|
@ -270,11 +268,6 @@ describe PageContent do
|
|||
<figure>
|
||||
<iframe src="https://example.com" width="800" height="480" frameborder="0" allowfullscreen="true">
|
||||
</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>
|
||||
HTML
|
||||
end
|
||||
|
|
|
@ -10,4 +10,4 @@ LuckyFlow.configure do |settings|
|
|||
# Be sure to disable for CI.
|
||||
# settings.driver = LuckyFlow::Drivers::Chrome
|
||||
end
|
||||
LuckyFlow::Spec.setup
|
||||
Spec.before_each { LuckyFlow::Server::INSTANCE.reset }
|
||||
|
|
|
@ -2,8 +2,6 @@ ENV["LUCKY_ENV"] = "test"
|
|||
ENV["DEV_PORT"] = "5001"
|
||||
require "spec"
|
||||
require "lucky_flow"
|
||||
require "lucky_flow/ext/lucky"
|
||||
require "lucky_flow/ext/avram"
|
||||
require "../src/app"
|
||||
require "./support/flows/base_flow"
|
||||
require "./support/**"
|
||||
|
|
56
src/actions/redirection_config/index.cr
Normal file
56
src/actions/redirection_config/index.cr
Normal file
|
@ -0,0 +1,56 @@
|
|||
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
|
||||
include Monads
|
||||
|
||||
ID_REGEX = /[\/\-]([0-9a-f]+)\/?$/i
|
||||
ID_REGEX = /[\/\-]([0-9a-f]+)$/i
|
||||
|
||||
def self.parse(request : HTTP::Request)
|
||||
new.parse(request)
|
||||
|
@ -10,7 +10,7 @@ class ArticleIdParser
|
|||
def parse(request : HTTP::Request) : Maybe
|
||||
from_params = post_id_from_params(request.query_params)
|
||||
from_path = post_id_from_path(request.path)
|
||||
from_params.or(from_path)
|
||||
from_path.or(from_params)
|
||||
end
|
||||
|
||||
private def post_id_from_path(request_path : String)
|
||||
|
|
|
@ -34,19 +34,11 @@ class EmbeddedConverter
|
|||
EmbeddedContent.new(
|
||||
src: media.iframeSrc,
|
||||
originalWidth: media.iframeWidth,
|
||||
originalHeight: media.iframeHeight,
|
||||
caption: caption
|
||||
originalHeight: media.iframeHeight
|
||||
)
|
||||
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
|
||||
if media.href.starts_with?(GIST_HOST_AND_SCHEME)
|
||||
GithubGist.new(href: media.href, gist_store: gist_store)
|
||||
|
|
|
@ -16,15 +16,15 @@ class ParagraphConverter
|
|||
when PostResponse::ParagraphType::H2
|
||||
paragraph = paragraphs.shift
|
||||
children = MarkupConverter.convert(paragraph.text, paragraph.markups)
|
||||
node = Heading1.new(children: children, identifier: paragraph.name || "")
|
||||
node = Heading1.new(children: children)
|
||||
when PostResponse::ParagraphType::H3
|
||||
paragraph = paragraphs.shift
|
||||
children = MarkupConverter.convert(paragraph.text, paragraph.markups)
|
||||
node = Heading2.new(children: children, identifier: paragraph.name || "")
|
||||
node = Heading2.new(children: children)
|
||||
when PostResponse::ParagraphType::H4
|
||||
paragraph = paragraphs.shift
|
||||
children = MarkupConverter.convert(paragraph.text, paragraph.markups)
|
||||
node = Heading3.new(children: children, identifier: paragraph.name || "")
|
||||
node = Heading3.new(children: children)
|
||||
when PostResponse::ParagraphType::IFRAME
|
||||
paragraph = paragraphs.shift
|
||||
node = EmbeddedConverter.convert(paragraph, gist_store)
|
||||
|
|
|
@ -27,7 +27,6 @@ class MediumClient
|
|||
content {
|
||||
bodyModel {
|
||||
paragraphs {
|
||||
name
|
||||
text
|
||||
type
|
||||
href
|
||||
|
|
|
@ -40,9 +40,6 @@ class PageContent < BaseComponent
|
|||
frameborder: "0",
|
||||
allowfullscreen: true,
|
||||
)
|
||||
if caption = child.caption
|
||||
render_child(caption)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -96,15 +93,15 @@ class PageContent < BaseComponent
|
|||
end
|
||||
|
||||
def render_child(node : Heading1)
|
||||
h1(id: node.identifier) { render_children(node.children) }
|
||||
h1 { render_children(node.children) }
|
||||
end
|
||||
|
||||
def render_child(node : Heading2)
|
||||
h2(id: node.identifier) { render_children(node.children) }
|
||||
h2 { render_children(node.children) }
|
||||
end
|
||||
|
||||
def render_child(node : Heading3)
|
||||
h3(id: node.identifier) { render_children(node.children) }
|
||||
h3 { render_children(node.children) }
|
||||
end
|
||||
|
||||
def render_child(child : Image)
|
||||
|
|
|
@ -7,22 +7,13 @@ p.meta {
|
|||
line-height: 1;
|
||||
}
|
||||
|
||||
pre {
|
||||
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%;
|
||||
.gist {
|
||||
width: 55%;
|
||||
}
|
||||
|
||||
@media (max-width: 760px) {
|
||||
pre {
|
||||
margin-right: 0;
|
||||
.gist {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -127,3 +118,4 @@ code {
|
|||
h1, .meta {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,24 +41,12 @@ module Nodes
|
|||
end
|
||||
|
||||
class Heading1 < Container
|
||||
getter identifier : String
|
||||
|
||||
def initialize(@children : Children, @identifier : String)
|
||||
end
|
||||
end
|
||||
|
||||
class Heading2 < Container
|
||||
getter identifier : String
|
||||
|
||||
def initialize(@children : Children, @identifier : String)
|
||||
end
|
||||
end
|
||||
|
||||
class Heading3 < Container
|
||||
getter identifier : String
|
||||
|
||||
def initialize(@children : Children, @identifier : String)
|
||||
end
|
||||
end
|
||||
|
||||
class ListItem < Container
|
||||
|
@ -147,14 +135,8 @@ module Nodes
|
|||
MAX_WIDTH = 800
|
||||
|
||||
getter src : String
|
||||
getter caption : FigureCaption?
|
||||
|
||||
def initialize(
|
||||
@src : String,
|
||||
@originalWidth : Int32,
|
||||
@originalHeight : Int32,
|
||||
@caption : FigureCaption? = nil
|
||||
)
|
||||
def initialize(@src : String, @originalWidth : Int32, @originalHeight : Int32)
|
||||
end
|
||||
|
||||
def width
|
||||
|
@ -174,10 +156,7 @@ module Nodes
|
|||
end
|
||||
|
||||
def ==(other : EmbeddedContent)
|
||||
other.src == src &&
|
||||
other.width == width &&
|
||||
other.height == height &&
|
||||
other.caption == caption
|
||||
other.src == src && other.width == width && other.height == height
|
||||
end
|
||||
|
||||
def empty?
|
||||
|
|
|
@ -32,7 +32,6 @@ class PostResponse
|
|||
end
|
||||
|
||||
class Paragraph < Base
|
||||
property name : String?
|
||||
property text : String?
|
||||
property type : ParagraphType
|
||||
property markups : Array(Markup)
|
||||
|
@ -41,7 +40,6 @@ class PostResponse
|
|||
property metadata : Metadata?
|
||||
|
||||
def initialize(
|
||||
@name : String,
|
||||
@text : String?,
|
||||
@type : ParagraphType,
|
||||
@markups : Array(Markup),
|
||||
|
|
|
@ -18,9 +18,19 @@ class Faq::IndexPage < MainLayout
|
|||
section do
|
||||
h2 "How-to Automatically Redirect Medium Articles"
|
||||
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. The "
|
||||
a "LibRedirect extention", href: "https://libredirect.github.io/"
|
||||
text " works well across most browsers, and will also redirect to other alternative services."
|
||||
text "If you don't want to manually change the URL every time, you can use an extension to do it for you. "
|
||||
a "This extension", href: "https://einaregilsson.com/redirector/"
|
||||
text " works well across most browsers."
|
||||
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
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
module Scribe
|
||||
VERSION = "2023-05-06"
|
||||
VERSION = "2022-07-19"
|
||||
end
|
||||
|
|
1
tasks.cr
1
tasks.cr
|
@ -7,6 +7,5 @@ require "lucky_task"
|
|||
require "./tasks/**"
|
||||
require "./db/migrations/**"
|
||||
require "lucky/tasks/**"
|
||||
require "avram/lucky/tasks"
|
||||
|
||||
LuckyTask::Runner.run
|
||||
|
|
Loading…
Reference in a new issue