|
1 | | -# jcdcdev.Umbraco.ReadingTime |
2 | | - |
3 | | -[](https://marketplace.umbraco.com/package/jcdcdev.umbraco.readingtime) |
4 | | -[](https://github.com/jcdcdev/jcdcdev.Umbraco.ReadingTime/blob/main/LICENSE) |
5 | | -[](https://www.nuget.org/packages/jcdcdev.Umbraco.ReadingTime/) |
6 | | - |
7 | | -Custom Data Type for calculating reading time. With full variant support! |
8 | | - |
9 | | -The following editors are currently supported: |
10 | | - |
11 | | -- Rich Text |
12 | | -- Markdown |
13 | | -- Block Grid |
14 | | -- Block List |
15 | | -- Nested Content |
16 | | -- Textstring |
17 | | -- Textarea |
18 | | - |
19 | | -## Quick Start |
20 | | - |
21 | | -1. Install the [NuGet package](https://www.nuget.org/packages/jcdcdev.Umbraco.ReadingTime) in your Umbraco CMS website project. |
22 | | - ``` |
23 | | - dotnet add package jcdcdev.Umbraco.ReadingTime |
24 | | - ``` |
25 | | -2. Add the Reading Time data type to a document type. You can configure: |
26 | | - - `Words per minute` (default is 200) |
27 | | - - `Min Unit` (default is Minute) |
28 | | - - `Max Unit` (default is Minute) |
29 | | -  |
30 | | -3. Save and publish content. |
31 | | -4. Reading Time will display in the backoffice |
32 | | - |
33 | | -  |
34 | | - |
35 | | -## Using the value in your templates |
36 | | - |
37 | | -In your template, you can accessing the Reading Time property value like any other property: |
38 | | - |
39 | | -```html |
40 | | - @Model.ReadingTime.DisplayTime() |
41 | | -``` |
42 | | - |
43 | | - |
44 | | - |
45 | | -### Overriding the default display |
46 | | -The `DisplayTime` method will format the reading time as a string using [Humanizer](https://github.com/Humanizr/Humanizer). This supports variants, meaning the reading time will be displayed based on the pluralisation rules of the current culture (e.g. "1 minute", "2 minutes", "0 minuter"). |
47 | | - |
48 | | -Min and max `TimeUnit` values are derived from the Data Type settings. The below example shows how you can ensure only seconds are displayed. |
49 | | - |
50 | | -```csharp |
51 | | - Model.ReadingTime.DisplayTime(minUnit: TimeUnit.Second, maxUnit: TimeUnit.Second) |
52 | | -``` |
53 | | - |
54 | | - |
55 | | - |
56 | | -## Configuration |
57 | | - |
58 | | -You can change the average words per minute in the data type settings. |
59 | | - |
60 | | -When creating a new data type, the default will be 200 words per minute. To change this default, adjust your `appsettings.json` file: |
61 | | - |
62 | | -```json |
63 | | -{ |
64 | | - "ReadingTime": { |
65 | | - "WordsPerMinute": 200 |
66 | | - } |
67 | | -} |
68 | | -``` |
69 | | - |
70 | | -## Limitations |
71 | | - |
72 | | -**Values are derived from published content only.** |
73 | | - |
74 | | -Draft content is _not_ included in the calculation. |
75 | | - |
76 | | -**Words per minute applies to all variants.** |
77 | | - |
78 | | -It is not currently possible to configure words per minute per culture. |
79 | | - |
80 | | -## Extending |
81 | | - |
82 | | -You can extend the data type to support additional editors by implementing the `IReadingTimeValueProvider` interface. |
83 | | - |
84 | | -```csharp |
85 | | -public class MyCustomReadingTimeValueProvider : IReadingTimeValueProvider |
86 | | -{ |
87 | | - public bool CanConvert(IPropertyType type) |
88 | | - { |
89 | | - return type.EditorAlias == "MyCustomEditorAlias"; |
90 | | - } |
91 | | - |
92 | | - public TimeSpan? GetReadingTime(IProperty property, string? culture, string? segment, IEnumerable<string> availableCultures, ReadingTimeConfiguration config) |
93 | | - { |
94 | | - var value = property.GetValue(culture, segment, true); |
95 | | - if (value is string text) |
96 | | - { |
97 | | - return text.GetReadingTime(config.WordsPerMinute); |
| 1 | +<!doctype html> |
| 2 | +<html lang="en" class="h-100"> |
| 3 | + |
| 4 | +<head> |
| 5 | + <meta charset="utf-8"> |
| 6 | + <meta name="viewport" content="width=device-width, initial-scale=1"> |
| 7 | + <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" |
| 8 | + integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous"> |
| 9 | + <title>404</title> |
| 10 | +</head> |
| 11 | + |
| 12 | +<body class="h-100"> |
| 13 | + <div class="d-flex align-items-center justify-content-center h-100"> |
| 14 | + <div class=""> |
| 15 | + <h1>404 Not Found</h1> |
| 16 | + <p> Sorry, the page you are looking for could not be found.</p> |
| 17 | + </div> |
| 18 | + </div> |
| 19 | + |
| 20 | + <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous" type="1754ca4fd64cda95fe2fd2c1-text/javascript"></script> |
| 21 | + <script type="1754ca4fd64cda95fe2fd2c1-text/javascript"> |
| 22 | + const darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); |
| 23 | + |
| 24 | + if (darkModeMediaQuery.matches) { |
| 25 | + document.documentElement.setAttribute('data-bs-theme', 'dark'); |
| 26 | + } else { |
| 27 | + document.documentElement.setAttribute('data-bs-theme', 'light'); |
98 | 28 | } |
99 | 29 |
|
100 | | - return null; |
101 | | - } |
102 | | - } |
103 | | -``` |
104 | | - |
105 | | -Don't forget to register your custom value provider: |
106 | | - |
107 | | -```csharp |
108 | | -public class Composer : IComposer |
109 | | -{ |
110 | | - public void Compose(IUmbracoBuilder builder) |
111 | | - { |
112 | | - builder.ReadingTimeValueProviders().Append<MyCustomReadingTimeValueProvider>(); |
113 | | - } |
114 | | -} |
115 | | -``` |
116 | | - |
117 | | -## Contributing |
118 | | - |
119 | | -Contributions to this package are most welcome! Please read the [Contributing Guidelines](https://github.com/jcdcdev/jcdcdev.Umbraco.ReadingTime/blob/main/.github/CONTRIBUTING.md). |
120 | | - |
121 | | -## Acknowledgments (thanks!) |
122 | | - |
123 | | -- LottePitcher - [opinionated-package-starter](https://github.com/LottePitcher/opinionated-package-starter) |
| 30 | + darkModeMediaQuery.addEventListener('change', (event) => { |
| 31 | + if (event.matches) { |
| 32 | + document.documentElement.setAttribute('data-bs-theme', 'dark'); |
| 33 | + } else { |
| 34 | + document.documentElement.setAttribute('data-bs-theme', 'light'); |
| 35 | + } |
| 36 | + }); |
| 37 | + </script> |
| 38 | +<script src="/cdn-cgi/scripts/7d0fa10a/cloudflare-static/rocket-loader.min.js" data-cf-settings="1754ca4fd64cda95fe2fd2c1-|49" defer></script></body> |
| 39 | + |
| 40 | +</html> |
0 commit comments