Initial commit
This commit is contained in:
commit
0c08823178
9
.editorconfig
Normal file
9
.editorconfig
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*.cr]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
trim_trailing_whitespace = true
|
9
.gitignore
vendored
Normal file
9
.gitignore
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
/docs/
|
||||||
|
/lib/
|
||||||
|
/bin/
|
||||||
|
/.shards/
|
||||||
|
*.dwarf
|
||||||
|
|
||||||
|
# Libraries don't need dependency lock
|
||||||
|
# Dependencies will be locked in application that uses them
|
||||||
|
/shard.lock
|
202
LICENSE
Normal file
202
LICENSE
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
41
README.md
Normal file
41
README.md
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
# cryss
|
||||||
|
|
||||||
|
`cryss` is a light wrapper around `XML` for the W3 RSS 2.0 standard.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Add this to your application's `shard.yml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
dependencies:
|
||||||
|
cryss:
|
||||||
|
github: xeals/cryss
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```crystal
|
||||||
|
require "cryss"
|
||||||
|
```
|
||||||
|
|
||||||
|
TODO: Write usage instructions here
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
TODO: Write development instructions here
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
1. Fork it (<https://github.com/xeals/cryss/fork>)
|
||||||
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
||||||
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
||||||
|
4. Push to the branch (`git push origin my-new-feature`)
|
||||||
|
5. Create a new Pull Request
|
||||||
|
|
||||||
|
## Contributors
|
||||||
|
|
||||||
|
- [xeals](https://github.com/xeals) - creator, maintainer
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
cryss is licensed under the [Apache-2.0 license](LICENSE).
|
9
shard.yml
Normal file
9
shard.yml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
name: cryss
|
||||||
|
version: 0.1.0
|
||||||
|
|
||||||
|
authors:
|
||||||
|
- xeals <xeals@pm.me>
|
||||||
|
|
||||||
|
crystal: 0.26.1
|
||||||
|
|
||||||
|
license: Apache-2.0
|
89
spec/cryss_spec.cr
Normal file
89
spec/cryss_spec.cr
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
# Copyright 2018 Alex Smith
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
require "./spec_helper"
|
||||||
|
|
||||||
|
describe RSS do
|
||||||
|
ex_cloud = RSS::Cloud.new(
|
||||||
|
domain: "rpc.sys.com",
|
||||||
|
port: 80,
|
||||||
|
path: "/RPC2",
|
||||||
|
register_procedure: "pingMe",
|
||||||
|
protocol: "soap"
|
||||||
|
)
|
||||||
|
|
||||||
|
ex_enclosure = RSS::Enclosure.new(
|
||||||
|
url: "http://live.curry.com/mp3/celebritySCms.mp3",
|
||||||
|
length: 1069871,
|
||||||
|
type: "audio/mpeg"
|
||||||
|
)
|
||||||
|
|
||||||
|
base_channel = RSS::Channel.new(
|
||||||
|
link: "http://www.goupstate.com/",
|
||||||
|
title: "GoUpstate.com News Headlines",
|
||||||
|
description: "The latest news from GoUpstate.com, a Spartanburg Herald-Journal Web site."
|
||||||
|
)
|
||||||
|
|
||||||
|
it "builds enclosure" do
|
||||||
|
w3 = HEADER + ENCLOSURE_TEST
|
||||||
|
|
||||||
|
ex_enclosure.to_s.strip.should eq w3
|
||||||
|
end
|
||||||
|
|
||||||
|
it "builds cloud" do
|
||||||
|
w3 = HEADER + CLOUD_TEST
|
||||||
|
|
||||||
|
ex_cloud.to_s.strip.should eq w3
|
||||||
|
end
|
||||||
|
|
||||||
|
it "builds item" do
|
||||||
|
item = RSS::Item.new title: "Venice Film Festival Tries to Quit Sinking"
|
||||||
|
|
||||||
|
item.link = URI.parse "http://www.nytimes.com/2002/09/07/movies/07FEST.html"
|
||||||
|
item.description = "Some of the most heated chatter at the Venice Film Festival this week was about the way that the arrival of the stars at the Palazzo del Cinema was being staged."
|
||||||
|
item.author = "oprah@oxygen.net"
|
||||||
|
item.category = RSS::Category.new "Simpsons Characters"
|
||||||
|
item.comments = URI.parse "http://www.myblog.org/cgi-local/mt/mt-comments.cgi?entry_id=290"
|
||||||
|
item.enclosure = ex_enclosure
|
||||||
|
item.guid = URI.parse "http://inessential.com/2002/09/01.php#a2"
|
||||||
|
item.pub_date = Time.parse_iso8601 "2002-05-19T15:21:36Z"
|
||||||
|
item.source = "Quotes of the Day"
|
||||||
|
item.source_url = URI.parse "http://www.quotationspage.com/data/qotd.rss"
|
||||||
|
|
||||||
|
item.to_s.strip.should eq ITEM_TEST
|
||||||
|
end
|
||||||
|
|
||||||
|
it "builds channel" do
|
||||||
|
chan = base_channel
|
||||||
|
chan.language = "en-us"
|
||||||
|
chan.copyright = "Copyright 2002, Spartanburg Herald-Journal"
|
||||||
|
chan.managing_editor = "geo@herald.com (George Matesky)"
|
||||||
|
chan.webmaster = "betty@herald.com (Betty Guernsey)"
|
||||||
|
chan.pub_date = Time.parse_iso8601 "2002-09-07T00:00:01Z"
|
||||||
|
chan.last_build_date = Time.parse_iso8601 "2002-09-07T09:42:31Z"
|
||||||
|
chan.category = [RSS::Category.new "Newspapers"]
|
||||||
|
chan.generator = "MightyInHouse Content System v2.3"
|
||||||
|
chan.docs = URI.parse "http://backend.userland.com/rss"
|
||||||
|
chan.cloud = ex_cloud
|
||||||
|
chan.ttl = 60
|
||||||
|
|
||||||
|
chan.to_s.strip.should eq CHANNEL_TEST
|
||||||
|
end
|
||||||
|
|
||||||
|
it "skips days and hours" do
|
||||||
|
chan = base_channel
|
||||||
|
chan.skip_days = [RSS::Day::Monday, RSS::Day::Wednesday]
|
||||||
|
chan.skip_hours = [2, 6, 18, 22]
|
||||||
|
end
|
||||||
|
end
|
78
spec/spec_helper.cr
Normal file
78
spec/spec_helper.cr
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
# Copyright 2018 Alex Smith
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
require "spec"
|
||||||
|
require "../src/cryss"
|
||||||
|
|
||||||
|
HEADER = "<?xml version=\"1.0\"?>\n"
|
||||||
|
|
||||||
|
CLOUD_TEST = "<cloud domain=\"rpc.sys.com\" port=\"80\" path=\"/RPC2\" registerProcedure=\"pingMe\" protocol=\"soap\"/>"
|
||||||
|
|
||||||
|
ENCLOSURE_TEST = "<enclosure url=\"http://live.curry.com/mp3/celebritySCms.mp3\" length=\"1069871\" type=\"audio/mpeg\"/>"
|
||||||
|
|
||||||
|
ITEM_TEST = HEADER + <<-XML
|
||||||
|
<item>
|
||||||
|
<title>Venice Film Festival Tries to Quit Sinking</title>
|
||||||
|
<link>http://www.nytimes.com/2002/09/07/movies/07FEST.html</link>
|
||||||
|
<description>Some of the most heated chatter at the Venice Film Festival this week was about the way that the arrival of the stars at the Palazzo del Cinema was being staged.</description>
|
||||||
|
<author>oprah@oxygen.net</author>
|
||||||
|
<category>Simpsons Characters</category>
|
||||||
|
<comments>http://www.myblog.org/cgi-local/mt/mt-comments.cgi?entry_id=290</comments>
|
||||||
|
#{ENCLOSURE_TEST}
|
||||||
|
<guid isPermaLink="true">http://inessential.com/2002/09/01.php#a2</guid>
|
||||||
|
<pubDate>Sun, 19 May 2002 15:21:36 +0000</pubDate>
|
||||||
|
<source url="http://www.quotationspage.com/data/qotd.rss">Quotes of the Day</source>
|
||||||
|
</item>
|
||||||
|
XML
|
||||||
|
|
||||||
|
CHANNEL_TEST = HEADER + <<-XML
|
||||||
|
<rss version="2.0">
|
||||||
|
<channel>
|
||||||
|
<title>GoUpstate.com News Headlines</title>
|
||||||
|
<link>http://www.goupstate.com/</link>
|
||||||
|
<description>The latest news from GoUpstate.com, a Spartanburg Herald-Journal Web site.</description>
|
||||||
|
<category>Newspapers</category>
|
||||||
|
#{CLOUD_TEST}
|
||||||
|
<copyright>Copyright 2002, Spartanburg Herald-Journal</copyright>
|
||||||
|
<docs>http://backend.userland.com/rss</docs>
|
||||||
|
<generator>MightyInHouse Content System v2.3</generator>
|
||||||
|
<language>en-us</language>
|
||||||
|
<lastBuildDate>Sat, 7 Sep 2002 09:42:31 +0000</lastBuildDate>
|
||||||
|
<managingEditor>geo@herald.com (George Matesky)</managingEditor>
|
||||||
|
<pubDate>Sat, 7 Sep 2002 00:00:01 +0000</pubDate>
|
||||||
|
<ttl>60</ttl>
|
||||||
|
<webMaster>betty@herald.com (Betty Guernsey)</webMaster>
|
||||||
|
</channel>
|
||||||
|
</rss>
|
||||||
|
XML
|
||||||
|
|
||||||
|
SKIP_DAY_TEST = HEADER + <<-XML
|
||||||
|
<rss version="2.0">
|
||||||
|
<channel>
|
||||||
|
<title>GoUpstate.com News Headlines</title>
|
||||||
|
<link>http://www.goupstate.com/</link>
|
||||||
|
<description>The latest news from GoUpstate.com, a Spartanburg Herald-Journal Web site.</description>
|
||||||
|
<skipHours>
|
||||||
|
<hour>2</hour>
|
||||||
|
<hour>6</hour>
|
||||||
|
<hour>18</hour>
|
||||||
|
<hour>22</hour>
|
||||||
|
</skipHours>
|
||||||
|
<skipDays>
|
||||||
|
<day>Monday</day>
|
||||||
|
<day>Wednesday</day>
|
||||||
|
</skipDays>
|
||||||
|
</channel>
|
||||||
|
</rss>
|
||||||
|
XML
|
17
src/cryss.cr
Normal file
17
src/cryss.cr
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# Copyright 2018 Alex Smith
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
require "./**"
|
||||||
|
|
||||||
|
# https://validator.w3.org/feed/docs/rss2.html
|
43
src/cryss/category.cr
Normal file
43
src/cryss/category.cr
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
# Copyright 2018 Alex Smith
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
require "xml"
|
||||||
|
|
||||||
|
require "./element"
|
||||||
|
|
||||||
|
module RSS
|
||||||
|
class Category < Element
|
||||||
|
# Includes the item in one or more categories.
|
||||||
|
#
|
||||||
|
# The value of the element is a forward-slash-separated string that identifies a hierarchic
|
||||||
|
# location in the indicated taxonomy. Processors may establish conventions for the
|
||||||
|
# interpretation of categories. Two examples are provided below:
|
||||||
|
getter name : String
|
||||||
|
|
||||||
|
# Optional attribute that identifies a categorization taxonomy.
|
||||||
|
getter domain : URI?
|
||||||
|
|
||||||
|
def initialize(@name : String, domain : URI | String | Nil = nil)
|
||||||
|
@domain = domain.is_a?(String) ? URI.parse domain : domain
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_xml(xml : XML::Builder)
|
||||||
|
if @domain
|
||||||
|
xml.element("category", domain: @domain) { xml.text name }
|
||||||
|
else
|
||||||
|
xml.element("category") { xml.text name }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
207
src/cryss/channel.cr
Normal file
207
src/cryss/channel.cr
Normal file
@ -0,0 +1,207 @@
|
|||||||
|
# Copyright 2018 Alex Smith
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
require "xml"
|
||||||
|
|
||||||
|
require "./cloud"
|
||||||
|
require "./day"
|
||||||
|
require "./element"
|
||||||
|
require "./image"
|
||||||
|
require "./item"
|
||||||
|
require "./text_input"
|
||||||
|
|
||||||
|
module RSS
|
||||||
|
# Contains information about an RSS channel (metadata) and its contents.
|
||||||
|
#
|
||||||
|
# For precise documentation, see <https://validator.w3.org/feed/docs/rss2.html>
|
||||||
|
class Channel < Element
|
||||||
|
# The name of the channel.
|
||||||
|
#
|
||||||
|
# It's how people refer to your service. If you have an HTML website that contains the same
|
||||||
|
# information as your RSS file, the title of your channel should be the same as the title of
|
||||||
|
# your website.
|
||||||
|
getter title : String
|
||||||
|
|
||||||
|
# The URL to the HTML website corresponding to the channel.
|
||||||
|
getter link : URI
|
||||||
|
|
||||||
|
# Phrase or sentence describing the channel.
|
||||||
|
getter description : String
|
||||||
|
|
||||||
|
# The language the channel is written in.
|
||||||
|
#
|
||||||
|
# This allows aggregators to group all Italian language sites, for example, on a single page. A
|
||||||
|
# list of allowable values for this element, as provided by Netscape, is
|
||||||
|
# [here](http://backend.userland.com/stories/storyReader$16). You may also use [values
|
||||||
|
# defined](http://www.w3.org/TR/REC-html40/struct/dirlang.html#langcodes) by the W3C.
|
||||||
|
#
|
||||||
|
# Example: en-us
|
||||||
|
getter language : String?
|
||||||
|
|
||||||
|
# Copyright notice for content in the channel.
|
||||||
|
#
|
||||||
|
# Example: Copyright 2002, Spartanburg Herald-Journal
|
||||||
|
getter copyright : String?
|
||||||
|
|
||||||
|
# Email address for person responsible for editorial content.
|
||||||
|
#
|
||||||
|
# Example: geo@herald.com (George Matesky)
|
||||||
|
getter managing_editor : String?
|
||||||
|
|
||||||
|
# Email address for person responsible for technical issues relating to channel.
|
||||||
|
#
|
||||||
|
# Example: betty@herald.com (Betty Guernsey)
|
||||||
|
getter webmaster : String?
|
||||||
|
|
||||||
|
# The publication date for the content in the channel.
|
||||||
|
#
|
||||||
|
# For example, the New York Times publishes on a daily basis, the publication date flips once
|
||||||
|
# every 24 hours. That's when the pubDate of the channel changes. All date-times in RSS conform
|
||||||
|
# to the Date and Time Specification of [RFC 822](http://asg.web.cmu.edu/rfc/rfc822.html), with
|
||||||
|
# the exception that the year may be expressed with two characters or four characters (four
|
||||||
|
# preferred).
|
||||||
|
#
|
||||||
|
# Example: Sat, 07 Sep 2002 0:00:01 GMT
|
||||||
|
getter pub_date : Time?
|
||||||
|
|
||||||
|
# The last time the content of the channel changed.
|
||||||
|
#
|
||||||
|
# Example: Sat, 07 Sep 2002 9:42:31 GMT
|
||||||
|
getter last_build_date : Time?
|
||||||
|
|
||||||
|
# Specify one or more categories that the channel belongs to. Follows the same rules as the
|
||||||
|
# `Item`-level category element. More info.
|
||||||
|
getter category : Array(Category) = [] of Category
|
||||||
|
|
||||||
|
# A string indicating the program used to generate the channel.
|
||||||
|
getter generator : String = "cryss"
|
||||||
|
|
||||||
|
# A URL that points to the documentation for the format used in the RSS file.
|
||||||
|
#
|
||||||
|
# Defaults to the W3 RSS 2.0 specification. It's for people who might stumble across an RSS file
|
||||||
|
# on a Web server 25 years from now and wonder what it is.
|
||||||
|
getter docs : URI = URI.parse "https://validator.w3.org/feed/docs/rss2.html"
|
||||||
|
|
||||||
|
# Allows processes to register with a `Cloud` to be notified of updates to the channel,
|
||||||
|
# implementing a lightweight publish-subscribe protocol for RSS feeds. More info here.
|
||||||
|
getter cloud : Cloud?
|
||||||
|
|
||||||
|
# Time to live.
|
||||||
|
#
|
||||||
|
# It's a number of minutes that indicates how long a channel can be cached before refreshing
|
||||||
|
# from the source. More info here.
|
||||||
|
getter ttl : Int32?
|
||||||
|
|
||||||
|
# Specifies a GIF, JPEG or PNG image that can be displayed with the channel.
|
||||||
|
getter image : Image?
|
||||||
|
|
||||||
|
# Specifies a `TextInput` box that can be displayed with the channel.
|
||||||
|
getter text_input : TextInput?
|
||||||
|
|
||||||
|
# A hint for aggregators telling them which hours they can skip.
|
||||||
|
getter skip_days : Array(Day) = [] of Day
|
||||||
|
|
||||||
|
# A hint for aggregators telling them which days they can skip.
|
||||||
|
getter skip_hours : Array(Int32) = [] of Int32
|
||||||
|
|
||||||
|
setter title,
|
||||||
|
link,
|
||||||
|
description,
|
||||||
|
category,
|
||||||
|
cloud,
|
||||||
|
copyright,
|
||||||
|
docs,
|
||||||
|
generator,
|
||||||
|
image,
|
||||||
|
language,
|
||||||
|
last_build_date,
|
||||||
|
managing_editor,
|
||||||
|
pub_date,
|
||||||
|
skip_days,
|
||||||
|
skip_hours,
|
||||||
|
text_input,
|
||||||
|
ttl,
|
||||||
|
webmaster
|
||||||
|
|
||||||
|
# Contained elements of the channel.
|
||||||
|
getter items : Array(Item) = [] of Item
|
||||||
|
|
||||||
|
def initialize(link : URI | String, @title : String, @description : String)
|
||||||
|
@link = link.is_a?(URI) ? link : URI.parse link
|
||||||
|
end
|
||||||
|
|
||||||
|
def push(item : Item)
|
||||||
|
@items << item
|
||||||
|
end
|
||||||
|
|
||||||
|
def <<(item : Item)
|
||||||
|
push item
|
||||||
|
end
|
||||||
|
|
||||||
|
# Serialises the channel to the XML builder.
|
||||||
|
def to_xml(xml : XML::Builder)
|
||||||
|
xml.element("rss", version: "2.0") do
|
||||||
|
xml.element("channel") do
|
||||||
|
emit title
|
||||||
|
emit link
|
||||||
|
emit description
|
||||||
|
@category.each do |cat|
|
||||||
|
cat.to_xml xml
|
||||||
|
end
|
||||||
|
if cloud = @cloud
|
||||||
|
cloud.to_xml xml
|
||||||
|
end
|
||||||
|
emit copyright if @copyright
|
||||||
|
emit docs if @docs
|
||||||
|
emit generator if @generator
|
||||||
|
if image = @image
|
||||||
|
image.to_xml xml
|
||||||
|
end
|
||||||
|
emit language if @language
|
||||||
|
if lbd = @last_build_date
|
||||||
|
xml.element("lastBuildDate") { xml.text lbd.to_rfc2822 }
|
||||||
|
end
|
||||||
|
emit managing_editor, "managingEditor" if @managing_editor
|
||||||
|
if pub = @pub_date
|
||||||
|
xml.element("pubDate") { xml.text pub.to_rfc2822 }
|
||||||
|
end
|
||||||
|
emit text_input, "textInput" if @text_input
|
||||||
|
emit ttl if @ttl
|
||||||
|
emit webmaster, "webMaster" if @webmaster
|
||||||
|
|
||||||
|
# skips
|
||||||
|
if !@skip_hours.empty?
|
||||||
|
xml.element("skipHours") do
|
||||||
|
@skip_hours.each do |hour|
|
||||||
|
xml.element("hour") { xml.text hour.to_s }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if !@skip_days.empty?
|
||||||
|
xml.element("skipDays") do
|
||||||
|
@skip_days.each do |day|
|
||||||
|
xml.element("day") { xml.text day.to_s }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@items.each do |item|
|
||||||
|
item.to_xml xml
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
72
src/cryss/cloud.cr
Normal file
72
src/cryss/cloud.cr
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
# Copyright 2018 Alex Smith
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
require "xml"
|
||||||
|
|
||||||
|
module RSS
|
||||||
|
# Optional sub-element of a channel.
|
||||||
|
#
|
||||||
|
# It specifies a web service that supports the rssCloud interface which can be implemented in
|
||||||
|
# HTTP-POST, XML-RPC or SOAP 1.1.
|
||||||
|
#
|
||||||
|
# Its purpose is to allow processes to register with a cloud to be notified of updates to the
|
||||||
|
# channel, implementing a lightweight publish-subscribe protocol for RSS feeds.
|
||||||
|
#
|
||||||
|
# ```
|
||||||
|
# <cloud domain="radio.xmlstoragesystem.com" port="80" path="/RPC2" registerProcedure="xmlStorageSystem.rssPleaseNotify" protocol="xml-rpc" />
|
||||||
|
# ```
|
||||||
|
#
|
||||||
|
# In this example, to request notification on the channel it appears in, you would send an XML-RPC
|
||||||
|
# message to radio.xmlstoragesystem.com on port 80, with a path of /RPC2. The procedure to call is
|
||||||
|
# xmlStorageSystem.rssPleaseNotify.
|
||||||
|
#
|
||||||
|
# A full explanation of this element and the rssCloud interface is
|
||||||
|
# [here](http://www.thetwowayweb.com/soapmeetsrss#rsscloudInterface).
|
||||||
|
class Cloud < Element
|
||||||
|
getter domain : URI
|
||||||
|
|
||||||
|
getter port : Int32
|
||||||
|
|
||||||
|
getter path : String
|
||||||
|
|
||||||
|
getter register_procedure : String
|
||||||
|
|
||||||
|
getter protocol : String
|
||||||
|
|
||||||
|
setter domain,
|
||||||
|
port,
|
||||||
|
path,
|
||||||
|
register_procedure,
|
||||||
|
protocol
|
||||||
|
|
||||||
|
def initialize(domain : URI | String,
|
||||||
|
@port : Int32,
|
||||||
|
@path : String,
|
||||||
|
@register_procedure : String,
|
||||||
|
@protocol : String)
|
||||||
|
@domain = domain.is_a?(String) ? URI.parse domain : domain
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_xml(xml : XML::Builder)
|
||||||
|
xml.element(
|
||||||
|
"cloud",
|
||||||
|
domain: @domain.to_s,
|
||||||
|
port: @port.to_s,
|
||||||
|
path: @path,
|
||||||
|
registerProcedure: @register_procedure,
|
||||||
|
protocol: @protocol
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
25
src/cryss/day.cr
Normal file
25
src/cryss/day.cr
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# Copyright 2018 Alex Smith
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
module RSS
|
||||||
|
enum Day
|
||||||
|
Monday
|
||||||
|
Tuesday
|
||||||
|
Wednesday
|
||||||
|
Thursday
|
||||||
|
Friday
|
||||||
|
Saturday
|
||||||
|
Sunday
|
||||||
|
end
|
||||||
|
end
|
41
src/cryss/element.cr
Normal file
41
src/cryss/element.cr
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
# Copyright 2018 Alex Smith
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
require "xml"
|
||||||
|
|
||||||
|
module RSS
|
||||||
|
abstract class Element
|
||||||
|
def to_s(io : IO)
|
||||||
|
to_xml(io)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Writes the generated XML to the provided *io*.
|
||||||
|
def to_xml(io : IO)
|
||||||
|
XML.build(io, version: "1.0", indent: " ") do |xml|
|
||||||
|
to_xml(xml)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Writes the generated XML to the provided *xml* builder.
|
||||||
|
abstract def to_xml(xml : XML::Builder)
|
||||||
|
|
||||||
|
private macro emit(elem)
|
||||||
|
xml.element("{{elem}}") { xml.text @{{elem}}.to_s }
|
||||||
|
end
|
||||||
|
|
||||||
|
private macro emit(elem, name)
|
||||||
|
xml.element({{name}}) { xml.text @{{elem}}.to_s }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
39
src/cryss/enclosure.cr
Normal file
39
src/cryss/enclosure.cr
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
# Copyright 2018 Alex Smith
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
module RSS
|
||||||
|
# Describes a media object that is attached to an item.
|
||||||
|
class Enclosure < Element
|
||||||
|
# Where the enclosure is located.
|
||||||
|
getter url : URI
|
||||||
|
|
||||||
|
# Size in bytes.
|
||||||
|
getter length : Int32
|
||||||
|
|
||||||
|
# MIME type of the media.
|
||||||
|
getter type : String
|
||||||
|
|
||||||
|
setter url,
|
||||||
|
length,
|
||||||
|
type
|
||||||
|
|
||||||
|
def initialize(url : URI | String, @length : Int32, @type : String)
|
||||||
|
@url = url.is_a?(URI) ? url : URI.parse url
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_xml(xml : XML::Builder)
|
||||||
|
xml.element("enclosure", url: @url, length: @length, type: @type)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
77
src/cryss/image.cr
Normal file
77
src/cryss/image.cr
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
# Copyright 2018 Alex Smith
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
require "xml"
|
||||||
|
require "uri"
|
||||||
|
|
||||||
|
require "./element"
|
||||||
|
|
||||||
|
module RSS
|
||||||
|
class Image < Element
|
||||||
|
# URL of a GIF, JPEG or PNG image that represents the channel.
|
||||||
|
getter image : URI
|
||||||
|
|
||||||
|
# Describes the image.
|
||||||
|
#
|
||||||
|
# Used in the ALT attribute of the HTML <img> tag when the channel is rendered in HTML.
|
||||||
|
getter title : String
|
||||||
|
|
||||||
|
# URL of the site, when the channel is rendered, the image is a link to the site. (Note, in
|
||||||
|
# practice the image <title> and <link> should have the same value as the channel's <title> and
|
||||||
|
# <link>.
|
||||||
|
getter link : URI
|
||||||
|
|
||||||
|
# Width of the image in pixels. Default is 88. Maximum of 144.
|
||||||
|
getter width : Float32 = 88
|
||||||
|
|
||||||
|
# Height of the image in pixels. Default is 31. Maximum of 400.
|
||||||
|
getter height : Float32 = 31
|
||||||
|
|
||||||
|
# Description contains text that is included in the TITLE attribute of the link formed around
|
||||||
|
# the image in the HTML rendering.
|
||||||
|
getter description : String?
|
||||||
|
|
||||||
|
setter image,
|
||||||
|
title,
|
||||||
|
link,
|
||||||
|
description
|
||||||
|
|
||||||
|
def initialize(image : URI | String, @title : String, link : URI | String)
|
||||||
|
@image = image.is_a?(URI) ? image : URI.parse image
|
||||||
|
@link = link.is_a?(URI) ? link : URI.parse link
|
||||||
|
end
|
||||||
|
|
||||||
|
def width=(width : Float32)
|
||||||
|
raise Exception.new "maximum width is 144" if width > 144
|
||||||
|
@width = width
|
||||||
|
end
|
||||||
|
|
||||||
|
def height=(height : Float32)
|
||||||
|
raise Exception.new "maximum height is 400" if height > 400
|
||||||
|
@height = height
|
||||||
|
end
|
||||||
|
|
||||||
|
# Serialises the image to the XML builder.
|
||||||
|
def to_xml(xml : XML::Builder)
|
||||||
|
xml.element("image") do
|
||||||
|
emit image
|
||||||
|
emit title
|
||||||
|
emit link
|
||||||
|
emit width if @width
|
||||||
|
emit height if @height
|
||||||
|
emit description if @description
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
141
src/cryss/item.cr
Normal file
141
src/cryss/item.cr
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
# Copyright 2018 Alex Smith
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
require "xml"
|
||||||
|
|
||||||
|
require "./category"
|
||||||
|
require "./element"
|
||||||
|
require "./enclosure"
|
||||||
|
|
||||||
|
module RSS
|
||||||
|
# A channel may contain any number of `Item`s. An item may represent a "story" -- much like a
|
||||||
|
# story in a newspaper or magazine; if so its description is a synopsis of the story, and the link
|
||||||
|
# points to the full story. An item may also be complete in itself, if so, the description
|
||||||
|
# contains the text (entity-encoded HTML is allowed), and the link and title may be omitted. All
|
||||||
|
# elements of an item are optional, however at least one of title or description must be present.
|
||||||
|
class Item < Element
|
||||||
|
# The title of the item.
|
||||||
|
getter title : String?
|
||||||
|
|
||||||
|
# The URL of the item.
|
||||||
|
getter link : URI?
|
||||||
|
|
||||||
|
# The item synopsis.
|
||||||
|
getter description : String?
|
||||||
|
|
||||||
|
# Email address of the author of the item.
|
||||||
|
getter author : String?
|
||||||
|
|
||||||
|
# Includes the item in one or more categories.
|
||||||
|
#
|
||||||
|
# The value of the element is a forward-slash-separated string that identifies a hierarchic
|
||||||
|
# location in the indicated taxonomy. Processors may establish conventions for the
|
||||||
|
# interpretation of categories. Two examples are provided below:
|
||||||
|
# getter category : String?
|
||||||
|
getter category : Category?
|
||||||
|
|
||||||
|
# Optional <category> attribute that identifies a categorization taxonomy.
|
||||||
|
# getter category_domain : URI?
|
||||||
|
|
||||||
|
# Optional URL of the comments page for the item.
|
||||||
|
#
|
||||||
|
# ```
|
||||||
|
# <comments>http://rateyourmusic.com/yaccs/commentsn/blogId=705245&itemId=271</comments>
|
||||||
|
# ```
|
||||||
|
getter comments : URI?
|
||||||
|
|
||||||
|
# Describes a media object that is attached to the item.
|
||||||
|
getter enclosure : Enclosure?
|
||||||
|
|
||||||
|
# Optional globally unique identifier.
|
||||||
|
#
|
||||||
|
# It's a string that uniquely identifies the item. When present, an aggregator may choose to use
|
||||||
|
# this string to determine if an item is new.
|
||||||
|
#
|
||||||
|
# ```
|
||||||
|
# <guid>http://some.server.com/weblogItem3207<guid>
|
||||||
|
# ```
|
||||||
|
#
|
||||||
|
# There are no rules for the syntax of a guid. Aggregators must view them as a string. It's up
|
||||||
|
# to the source of the feed to establish the uniqueness of the string.
|
||||||
|
#
|
||||||
|
# If the guid element has an attribute named "isPermaLink" with a value of true, the reader may
|
||||||
|
# assume that it is a permalink to the item, that is, a url that can be opened in a Web browser,
|
||||||
|
# that points to the full item described by the <item> element. An example:
|
||||||
|
#
|
||||||
|
# ```
|
||||||
|
# <guid isPermaLink="true">http://inessential.com/2002/09/01.php#a2</guid>
|
||||||
|
# ```
|
||||||
|
#
|
||||||
|
# *is_perma_link* is optional and defaults to true. If its value is false, the guid may not be
|
||||||
|
# assumed to be a url, or a url to anything in particular.
|
||||||
|
getter guid : URI?
|
||||||
|
|
||||||
|
# See `#guid`.
|
||||||
|
getter guid_is_perma_link : Bool = true
|
||||||
|
|
||||||
|
# <pubDate> is an optional sub-element of <item>.
|
||||||
|
#
|
||||||
|
# Its value is a date, indicating when the item was published. If it's a date in the future,
|
||||||
|
# aggregators may choose to not display the item until that date.
|
||||||
|
getter pub_date : Time?
|
||||||
|
|
||||||
|
# The RSS channel that the item came from.
|
||||||
|
getter source : String?
|
||||||
|
|
||||||
|
# Required if *source* is non-nil.
|
||||||
|
getter source_url : URI?
|
||||||
|
|
||||||
|
setter title,
|
||||||
|
link,
|
||||||
|
description,
|
||||||
|
author,
|
||||||
|
category,
|
||||||
|
comments,
|
||||||
|
enclosure,
|
||||||
|
guid,
|
||||||
|
guid_is_perma_link,
|
||||||
|
pub_date,
|
||||||
|
source,
|
||||||
|
source_url
|
||||||
|
|
||||||
|
def initialize(@title = nil, @description = nil)
|
||||||
|
raise Exception.new "either title or description are required for RSS item" if !(@title || @description)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Serialises the item to the XML builder.
|
||||||
|
def to_xml(xml : XML::Builder)
|
||||||
|
raise Exception.new "source_url is required if source is non-nil for item" if @source && !@source_url
|
||||||
|
|
||||||
|
xml.element("item") do
|
||||||
|
emit title if @title
|
||||||
|
emit link if @link
|
||||||
|
emit description if @description
|
||||||
|
emit author if @author
|
||||||
|
if category = @category
|
||||||
|
category.to_xml xml
|
||||||
|
end
|
||||||
|
emit comments if @comments
|
||||||
|
if enc = @enclosure
|
||||||
|
enc.to_xml xml
|
||||||
|
end
|
||||||
|
xml.element("guid", isPermaLink: @guid_is_perma_link) { xml.text @guid.to_s } if @guid
|
||||||
|
if pub = @pub_date
|
||||||
|
xml.element("pubDate") { xml.text pub.to_rfc2822 }
|
||||||
|
end
|
||||||
|
xml.element("source", url: @source_url.to_s) { xml.text @source.to_s } if @source
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
51
src/cryss/text_input.cr
Normal file
51
src/cryss/text_input.cr
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
# Copyright 2018 Alex Smith
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
require "xml"
|
||||||
|
|
||||||
|
module RSS
|
||||||
|
# The purpose of the <textInput> element is something of a mystery. You can use it to specify a
|
||||||
|
# search engine box. Or to allow a reader to provide feedback. Most aggregators ignore it.
|
||||||
|
class TextInput < Element
|
||||||
|
# The label of the Submit button in the text input area.
|
||||||
|
getter title : String
|
||||||
|
|
||||||
|
# Explains the text input area.
|
||||||
|
getter description : String
|
||||||
|
|
||||||
|
# The name of the text object in the text input area.
|
||||||
|
getter name : String
|
||||||
|
|
||||||
|
# The URL of the CGI script that processes text input requests.
|
||||||
|
getter link : URI
|
||||||
|
|
||||||
|
setter title,
|
||||||
|
description,
|
||||||
|
name,
|
||||||
|
link
|
||||||
|
|
||||||
|
def initialize(@title : String, @description : String, @name : String, link : URI | String)
|
||||||
|
@link = link.is_a?(URI) ? link : URI.parse link
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_xml(xml : XML::Builder)
|
||||||
|
xml.element("textInput") do
|
||||||
|
emit title
|
||||||
|
emit description
|
||||||
|
emit name
|
||||||
|
emit link
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue
Block a user