diff options
| -rw-r--r-- | I2R.LightNews.sln | 22 | ||||
| -rw-r--r-- | src/Pages/Index.cshtml | 6 | ||||
| -rw-r--r-- | src/Pages/Read.cshtml | 17 | ||||
| -rw-r--r-- | src/Pages/Read.cshtml.cs | 2 | ||||
| -rw-r--r-- | src/Pages/Shared/_Layout.cshtml | 1 | ||||
| -rw-r--r-- | src/Services/GrabberService.cs | 93 | ||||
| -rw-r--r-- | src/wwwroot/index.css | 91 | ||||
| -rw-r--r-- | src/wwwroot/reset.css | 74 |
8 files changed, 176 insertions, 130 deletions
diff --git a/I2R.LightNews.sln b/I2R.LightNews.sln new file mode 100644 index 0000000..49b242c --- /dev/null +++ b/I2R.LightNews.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "I2R.LightNews", "src\I2R.LightNews.csproj", "{B302C2CC-E18F-460A-8BDA-2EC59F73F33C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B302C2CC-E18F-460A-8BDA-2EC59F73F33C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B302C2CC-E18F-460A-8BDA-2EC59F73F33C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B302C2CC-E18F-460A-8BDA-2EC59F73F33C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B302C2CC-E18F-460A-8BDA-2EC59F73F33C}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/src/Pages/Index.cshtml b/src/Pages/Index.cshtml index d809043..f01b263 100644 --- a/src/Pages/Index.cshtml +++ b/src/Pages/Index.cshtml @@ -5,11 +5,11 @@ } @foreach (var article in Model.Source.Articles) { - <section style="margin-bottom: 8px;display: flex; flex-direction: column"> + <section class="news-link"> <a href="/les/@Model.Source.Name?url=@article.Href"> - <h2 style="font-size: 18px">@Html.Raw(article.Title)</h2> + <h2>@Html.Raw(article.Title)</h2> </a> - <a href="@article.Href" style="font-size: 14px;display:flex;justify-content: end" rel="noreferrer">Les på nrk.no</a> + <a href="@article.Href" class="source-link" rel="noreferrer">Les på nrk.no</a> </section> } <footer> diff --git a/src/Pages/Read.cshtml b/src/Pages/Read.cshtml index 63543aa..9cff853 100644 --- a/src/Pages/Read.cshtml +++ b/src/Pages/Read.cshtml @@ -11,9 +11,10 @@ </div> </div> -<div id="art-body"> +<article id="art-body"> @Html.Raw(Model.Source.Content) -</div> +</article> + <footer> <p> <div style="display: flex; flex-direction: column; flex-wrap: nowrap;"> @@ -33,9 +34,17 @@ } <br/> <small> - <a href="@Model.Source.Href">Les på nrk.no</a> + <a href="@Model.Source.Href" no-interception>Les på nrk.no</a> </small> </div> </div> </p> -</footer>
\ No newline at end of file +</footer> + +<script> +document.addEventListener("DOMContentLoaded", () => { + document.querySelectorAll("a:not([no-interception])").forEach(el => { + if (el.href.indexOf("nrk.no") !== -1) el.href = "/les/nrk?url=" + el.href; + }); +}) +</script>
\ No newline at end of file diff --git a/src/Pages/Read.cshtml.cs b/src/Pages/Read.cshtml.cs index 16a1055..1a13ec0 100644 --- a/src/Pages/Read.cshtml.cs +++ b/src/Pages/Read.cshtml.cs @@ -18,7 +18,7 @@ public class ReadModel : PageModel "nrk" => await _grabber.GrabNrkArticleAsync(url), _ => default }; - if (Source == default) return Redirect("/"); + if (Source == default) return Redirect(url); return Page(); } }
\ No newline at end of file diff --git a/src/Pages/Shared/_Layout.cshtml b/src/Pages/Shared/_Layout.cshtml index 7831774..09babeb 100644 --- a/src/Pages/Shared/_Layout.cshtml +++ b/src/Pages/Shared/_Layout.cshtml @@ -3,7 +3,6 @@ <head> <meta charset="utf-8"/> <meta name="viewport" content="width=device-width, initial-scale=1.0"/> - <link rel="stylesheet" href="/reset.css"> <link rel="stylesheet" href="/index.css"> <title>@ViewData["Title"] - Lettnytt</title> </head> diff --git a/src/Services/GrabberService.cs b/src/Services/GrabberService.cs index 3974a9e..4886023 100644 --- a/src/Services/GrabberService.cs +++ b/src/Services/GrabberService.cs @@ -44,56 +44,59 @@ public class GrabberService using var md5 = MD5.Create(); var articleFilePrefix = "art-" + NrkPrefix + "-" + Convert.ToHexString(md5.ComputeHash(Encoding.UTF8.GetBytes(url))); return await _memoryCache.GetOrCreateAsync(articleFilePrefix, async entry => { - entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(10); - var source = await GrabSourceAsync(url, articleFilePrefix); - var parser = new HtmlParser(); - var doc = await parser.ParseDocumentAsync(source.Content); - var result = new NewsArticle() { - CachedAt = source.CacheFileCreatedAt, - Href = url, - Title = doc.QuerySelector("h1.title")?.TextContent, - Subtitle = doc.QuerySelector(".article-lead p")?.TextContent, - Authors = new List<NewsArticle.Author>() - }; - - foreach (var authorNode in doc.QuerySelectorAll(".authors .author")) { - var author = new NewsArticle.Author() { - Name = authorNode.QuerySelector(".author__name")?.TextContent, - Title = authorNode.QuerySelector(".author__role")?.TextContent + entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(10); + var source = await GrabSourceAsync(url, articleFilePrefix); + var parser = new HtmlParser(); + var doc = await parser.ParseDocumentAsync(source.Content); + var result = new NewsArticle() { + CachedAt = source.CacheFileCreatedAt, + Href = url, + Title = doc.QuerySelector("h1.title")?.TextContent, + Subtitle = doc.QuerySelector(".article-lead p")?.TextContent, + Authors = new List<NewsArticle.Author>() }; - result.Authors.Add(author); - } - DateTime.TryParse(doc.QuerySelector("time.datePublished")?.Attributes["datetime"]?.Value, out var published); - DateTime.TryParse(doc.QuerySelector("time.dateModified")?.Attributes["datetime"]?.Value, out var modified); + foreach (var authorNode in doc.QuerySelectorAll(".authors .author")) { + var author = new NewsArticle.Author() { + Name = authorNode.QuerySelector(".author__name")?.TextContent, + Title = authorNode.QuerySelector(".author__role")?.TextContent + }; + result.Authors.Add(author); + } - result.UpdatedAt = modified; - result.PublishedAt = published; + DateTime.TryParse(doc.QuerySelector("time.datePublished")?.Attributes["datetime"]?.Value, out var published); + DateTime.TryParse(doc.QuerySelector("time.dateModified")?.Attributes["datetime"]?.Value, out var modified); - if (doc.QuerySelector("kortstokk-app") != default) { - var excludes = new List<string>() { - ".dhks-background", - ".dhks-actions", - ".dhks-credits", - ".dhks-sticky-reset", - ".dhks-byline" - }; - result.Content = HtmlSanitiser.SanitizeHtmlFragment(doc.QuerySelector(".dhks-cardSection").InnerHtml, string.Join(',', excludes)); - } else { - var excludes = new List<string>() { - ".compilation-reference", - ".section-reference", - ".widget", - ".image-reference", - ".video-reference", - ".article-body--updating", - ".reference" - }; - result.Content = HtmlSanitiser.SanitizeHtmlFragment(doc.QuerySelector(".article-body").InnerHtml, string.Join(',', excludes)); - } + result.UpdatedAt = modified; + result.PublishedAt = published; - return result; - }); + if (doc.QuerySelector("kortstokk-app") != default) { + var excludes = new List<string>() { + ".dhks-background", + ".dhks-actions", + ".dhks-credits", + ".dhks-sticky-reset", + ".dhks-byline" + }; + result.Content = HtmlSanitiser.SanitizeHtmlFragment(doc.QuerySelector(".dhks-cardSection").InnerHtml, string.Join(',', excludes)); + } else if (url.Contains("nrk.no/nyheter")) { + result.Content = HtmlSanitiser.SanitizeHtmlFragment(doc.QuerySelector(".bulletin-text").InnerHtml); + } else { + var excludes = new List<string>() { + ".compilation-reference", + ".section-reference", + ".widget", + ".image-reference", + ".video-reference", + ".article-body--updating", + ".reference" + }; + result.Content = HtmlSanitiser.SanitizeHtmlFragment(doc.QuerySelector(".article-body").InnerHtml, string.Join(',', excludes)); + } + + return result; + }) + ; } public async Task<NewsSource> GrabNrkAsync() { diff --git a/src/wwwroot/index.css b/src/wwwroot/index.css index 0296036..2c5ac3f 100644 --- a/src/wwwroot/index.css +++ b/src/wwwroot/index.css @@ -1,10 +1,81 @@ +/* Box sizing rules */ +*, +*::before, +*::after { + box-sizing: border-box; +} + +/* Remove default margin */ +body, +h1, +h2, +h3, +h4, +p, +a, +figure, +blockquote, +dl, +dd { + margin: 0; +} + +/* Remove list styles on ul, ol elements with a list role, which suggests default styling will be removed */ +ul[role="list"], +ol[role="list"] { + list-style: none; +} + +/* Set core root defaults */ +html:focus-within { + scroll-behavior: smooth; +} + +/* A elements that don't have a class get default styles */ +a:not([class]) { + text-decoration-skip-ink: auto; +} + +/* Make images easier to work with */ +img, +picture { + max-width: 100%; + display: block; +} + +/* Inherit fonts for inputs and buttons */ +input, +button, +textarea, +select { + font: inherit; +} + +/* Remove all animations and transitions for people that prefer not to see them */ +@media (prefers-reduced-motion: reduce) { + html:focus-within { + scroll-behavior: auto; + } + + *, + *::before, + *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + scroll-behavior: auto !important; + } +} + + body { + min-height: 100vh; + text-rendering: optimizeSpeed; + line-height: 1.5; display: flex; flex-direction: column; - min-height: 100vh; padding: 5vh clamp(1rem, 5vw, 3rem) 1rem; font-family: system-ui, sans-serif; - line-height: 1.5; color: #222; background: white; } @@ -53,4 +124,20 @@ article * + * { .quote-source { padding-left: 20px; +} + +.news-link { + margin-bottom: 8px; + display: flex; + flex-direction: column +} + +.news-link h2 { + font-size: 18px; +} + +.news-link .source-link { + font-size: 14px; + display: flex; + justify-content: end }
\ No newline at end of file diff --git a/src/wwwroot/reset.css b/src/wwwroot/reset.css deleted file mode 100644 index ae5fad7..0000000 --- a/src/wwwroot/reset.css +++ /dev/null @@ -1,74 +0,0 @@ -/* Box sizing rules */ -*, -*::before, -*::after { - box-sizing: border-box; -} - -/* Remove default margin */ -body, -h1, -h2, -h3, -h4, -p, -figure, -blockquote, -dl, -dd { - margin: 0; -} - -/* Remove list styles on ul, ol elements with a list role, which suggests default styling will be removed */ -ul[role="list"], -ol[role="list"] { - list-style: none; -} - -/* Set core root defaults */ -html:focus-within { - scroll-behavior: smooth; -} - -/* Set core body defaults */ -body { - min-height: 100vh; - text-rendering: optimizeSpeed; - line-height: 1.5; -} - -/* A elements that don't have a class get default styles */ -a:not([class]) { - text-decoration-skip-ink: auto; -} - -/* Make images easier to work with */ -img, -picture { - max-width: 100%; - display: block; -} - -/* Inherit fonts for inputs and buttons */ -input, -button, -textarea, -select { - font: inherit; -} - -/* Remove all animations and transitions for people that prefer not to see them */ -@media (prefers-reduced-motion: reduce) { - html:focus-within { - scroll-behavior: auto; - } - - *, - *::before, - *::after { - animation-duration: 0.01ms !important; - animation-iteration-count: 1 !important; - transition-duration: 0.01ms !important; - scroll-behavior: auto !important; - } -} |
