plain 0.21.1__tar.gz → 0.21.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (160) hide show
  1. plain-0.21.3/PKG-INFO +12 -0
  2. plain-0.21.3/README.md +1 -0
  3. plain-0.21.3/plain/README.md +1 -0
  4. {plain-0.21.1 → plain-0.21.3}/plain/assets/compile.py +26 -26
  5. {plain-0.21.1 → plain-0.21.3}/pyproject.toml +1 -1
  6. plain-0.21.1/PKG-INFO +0 -46
  7. plain-0.21.1/README.md +0 -35
  8. plain-0.21.1/plain/README.md +0 -33
  9. {plain-0.21.1 → plain-0.21.3}/.gitignore +0 -0
  10. {plain-0.21.1 → plain-0.21.3}/LICENSE +0 -0
  11. {plain-0.21.1 → plain-0.21.3}/plain/__main__.py +0 -0
  12. {plain-0.21.1 → plain-0.21.3}/plain/assets/README.md +0 -0
  13. {plain-0.21.1 → plain-0.21.3}/plain/assets/__init__.py +0 -0
  14. {plain-0.21.1 → plain-0.21.3}/plain/assets/finders.py +0 -0
  15. {plain-0.21.1 → plain-0.21.3}/plain/assets/fingerprints.py +0 -0
  16. {plain-0.21.1 → plain-0.21.3}/plain/assets/urls.py +0 -0
  17. {plain-0.21.1 → plain-0.21.3}/plain/assets/views.py +0 -0
  18. {plain-0.21.1 → plain-0.21.3}/plain/cli/README.md +0 -0
  19. {plain-0.21.1 → plain-0.21.3}/plain/cli/__init__.py +0 -0
  20. {plain-0.21.1 → plain-0.21.3}/plain/cli/cli.py +0 -0
  21. {plain-0.21.1 → plain-0.21.3}/plain/cli/formatting.py +0 -0
  22. {plain-0.21.1 → plain-0.21.3}/plain/cli/packages.py +0 -0
  23. {plain-0.21.1 → plain-0.21.3}/plain/cli/print.py +0 -0
  24. {plain-0.21.1 → plain-0.21.3}/plain/cli/startup.py +0 -0
  25. {plain-0.21.1 → plain-0.21.3}/plain/csrf/README.md +0 -0
  26. {plain-0.21.1 → plain-0.21.3}/plain/csrf/middleware.py +0 -0
  27. {plain-0.21.1 → plain-0.21.3}/plain/csrf/views.py +0 -0
  28. {plain-0.21.1 → plain-0.21.3}/plain/debug.py +0 -0
  29. {plain-0.21.1 → plain-0.21.3}/plain/exceptions.py +0 -0
  30. {plain-0.21.1 → plain-0.21.3}/plain/forms/README.md +0 -0
  31. {plain-0.21.1 → plain-0.21.3}/plain/forms/__init__.py +0 -0
  32. {plain-0.21.1 → plain-0.21.3}/plain/forms/boundfield.py +0 -0
  33. {plain-0.21.1 → plain-0.21.3}/plain/forms/exceptions.py +0 -0
  34. {plain-0.21.1 → plain-0.21.3}/plain/forms/fields.py +0 -0
  35. {plain-0.21.1 → plain-0.21.3}/plain/forms/forms.py +0 -0
  36. {plain-0.21.1 → plain-0.21.3}/plain/http/README.md +0 -0
  37. {plain-0.21.1 → plain-0.21.3}/plain/http/__init__.py +0 -0
  38. {plain-0.21.1 → plain-0.21.3}/plain/http/cookie.py +0 -0
  39. {plain-0.21.1 → plain-0.21.3}/plain/http/multipartparser.py +0 -0
  40. {plain-0.21.1 → plain-0.21.3}/plain/http/request.py +0 -0
  41. {plain-0.21.1 → plain-0.21.3}/plain/http/response.py +0 -0
  42. {plain-0.21.1 → plain-0.21.3}/plain/internal/__init__.py +0 -0
  43. {plain-0.21.1 → plain-0.21.3}/plain/internal/files/README.md +0 -0
  44. {plain-0.21.1 → plain-0.21.3}/plain/internal/files/__init__.py +0 -0
  45. {plain-0.21.1 → plain-0.21.3}/plain/internal/files/base.py +0 -0
  46. {plain-0.21.1 → plain-0.21.3}/plain/internal/files/locks.py +0 -0
  47. {plain-0.21.1 → plain-0.21.3}/plain/internal/files/move.py +0 -0
  48. {plain-0.21.1 → plain-0.21.3}/plain/internal/files/temp.py +0 -0
  49. {plain-0.21.1 → plain-0.21.3}/plain/internal/files/uploadedfile.py +0 -0
  50. {plain-0.21.1 → plain-0.21.3}/plain/internal/files/uploadhandler.py +0 -0
  51. {plain-0.21.1 → plain-0.21.3}/plain/internal/files/utils.py +0 -0
  52. {plain-0.21.1 → plain-0.21.3}/plain/internal/handlers/__init__.py +0 -0
  53. {plain-0.21.1 → plain-0.21.3}/plain/internal/handlers/base.py +0 -0
  54. {plain-0.21.1 → plain-0.21.3}/plain/internal/handlers/exception.py +0 -0
  55. {plain-0.21.1 → plain-0.21.3}/plain/internal/handlers/wsgi.py +0 -0
  56. {plain-0.21.1 → plain-0.21.3}/plain/internal/middleware/__init__.py +0 -0
  57. {plain-0.21.1 → plain-0.21.3}/plain/internal/middleware/headers.py +0 -0
  58. {plain-0.21.1 → plain-0.21.3}/plain/internal/middleware/https.py +0 -0
  59. {plain-0.21.1 → plain-0.21.3}/plain/internal/middleware/slash.py +0 -0
  60. {plain-0.21.1 → plain-0.21.3}/plain/json.py +0 -0
  61. {plain-0.21.1 → plain-0.21.3}/plain/logs/README.md +0 -0
  62. {plain-0.21.1 → plain-0.21.3}/plain/logs/__init__.py +0 -0
  63. {plain-0.21.1 → plain-0.21.3}/plain/logs/configure.py +0 -0
  64. {plain-0.21.1 → plain-0.21.3}/plain/logs/loggers.py +0 -0
  65. {plain-0.21.1 → plain-0.21.3}/plain/logs/utils.py +0 -0
  66. {plain-0.21.1 → plain-0.21.3}/plain/packages/README.md +0 -0
  67. {plain-0.21.1 → plain-0.21.3}/plain/packages/__init__.py +0 -0
  68. {plain-0.21.1 → plain-0.21.3}/plain/packages/config.py +0 -0
  69. {plain-0.21.1 → plain-0.21.3}/plain/packages/registry.py +0 -0
  70. {plain-0.21.1 → plain-0.21.3}/plain/paginator.py +0 -0
  71. {plain-0.21.1 → plain-0.21.3}/plain/preflight/README.md +0 -0
  72. {plain-0.21.1 → plain-0.21.3}/plain/preflight/__init__.py +0 -0
  73. {plain-0.21.1 → plain-0.21.3}/plain/preflight/files.py +0 -0
  74. {plain-0.21.1 → plain-0.21.3}/plain/preflight/messages.py +0 -0
  75. {plain-0.21.1 → plain-0.21.3}/plain/preflight/registry.py +0 -0
  76. {plain-0.21.1 → plain-0.21.3}/plain/preflight/security.py +0 -0
  77. {plain-0.21.1 → plain-0.21.3}/plain/preflight/urls.py +0 -0
  78. {plain-0.21.1 → plain-0.21.3}/plain/runtime/README.md +0 -0
  79. {plain-0.21.1 → plain-0.21.3}/plain/runtime/__init__.py +0 -0
  80. {plain-0.21.1 → plain-0.21.3}/plain/runtime/global_settings.py +0 -0
  81. {plain-0.21.1 → plain-0.21.3}/plain/runtime/user_settings.py +0 -0
  82. {plain-0.21.1 → plain-0.21.3}/plain/signals/README.md +0 -0
  83. {plain-0.21.1 → plain-0.21.3}/plain/signals/__init__.py +0 -0
  84. {plain-0.21.1 → plain-0.21.3}/plain/signals/dispatch/__init__.py +0 -0
  85. {plain-0.21.1 → plain-0.21.3}/plain/signals/dispatch/dispatcher.py +0 -0
  86. {plain-0.21.1 → plain-0.21.3}/plain/signals/dispatch/license.txt +0 -0
  87. {plain-0.21.1 → plain-0.21.3}/plain/signing.py +0 -0
  88. {plain-0.21.1 → plain-0.21.3}/plain/templates/README.md +0 -0
  89. {plain-0.21.1 → plain-0.21.3}/plain/templates/__init__.py +0 -0
  90. {plain-0.21.1 → plain-0.21.3}/plain/templates/core.py +0 -0
  91. {plain-0.21.1 → plain-0.21.3}/plain/templates/jinja/README.md +0 -0
  92. {plain-0.21.1 → plain-0.21.3}/plain/templates/jinja/__init__.py +0 -0
  93. {plain-0.21.1 → plain-0.21.3}/plain/templates/jinja/environments.py +0 -0
  94. {plain-0.21.1 → plain-0.21.3}/plain/templates/jinja/extensions.py +0 -0
  95. {plain-0.21.1 → plain-0.21.3}/plain/templates/jinja/filters.py +0 -0
  96. {plain-0.21.1 → plain-0.21.3}/plain/templates/jinja/globals.py +0 -0
  97. {plain-0.21.1 → plain-0.21.3}/plain/test/README.md +0 -0
  98. {plain-0.21.1 → plain-0.21.3}/plain/test/__init__.py +0 -0
  99. {plain-0.21.1 → plain-0.21.3}/plain/test/client.py +0 -0
  100. {plain-0.21.1 → plain-0.21.3}/plain/urls/README.md +0 -0
  101. {plain-0.21.1 → plain-0.21.3}/plain/urls/__init__.py +0 -0
  102. {plain-0.21.1 → plain-0.21.3}/plain/urls/base.py +0 -0
  103. {plain-0.21.1 → plain-0.21.3}/plain/urls/conf.py +0 -0
  104. {plain-0.21.1 → plain-0.21.3}/plain/urls/converters.py +0 -0
  105. {plain-0.21.1 → plain-0.21.3}/plain/urls/exceptions.py +0 -0
  106. {plain-0.21.1 → plain-0.21.3}/plain/urls/resolvers.py +0 -0
  107. {plain-0.21.1 → plain-0.21.3}/plain/utils/README.md +0 -0
  108. {plain-0.21.1 → plain-0.21.3}/plain/utils/__init__.py +0 -0
  109. {plain-0.21.1 → plain-0.21.3}/plain/utils/_os.py +0 -0
  110. {plain-0.21.1 → plain-0.21.3}/plain/utils/cache.py +0 -0
  111. {plain-0.21.1 → plain-0.21.3}/plain/utils/connection.py +0 -0
  112. {plain-0.21.1 → plain-0.21.3}/plain/utils/crypto.py +0 -0
  113. {plain-0.21.1 → plain-0.21.3}/plain/utils/datastructures.py +0 -0
  114. {plain-0.21.1 → plain-0.21.3}/plain/utils/dateformat.py +0 -0
  115. {plain-0.21.1 → plain-0.21.3}/plain/utils/dateparse.py +0 -0
  116. {plain-0.21.1 → plain-0.21.3}/plain/utils/dates.py +0 -0
  117. {plain-0.21.1 → plain-0.21.3}/plain/utils/deconstruct.py +0 -0
  118. {plain-0.21.1 → plain-0.21.3}/plain/utils/decorators.py +0 -0
  119. {plain-0.21.1 → plain-0.21.3}/plain/utils/deprecation.py +0 -0
  120. {plain-0.21.1 → plain-0.21.3}/plain/utils/duration.py +0 -0
  121. {plain-0.21.1 → plain-0.21.3}/plain/utils/email.py +0 -0
  122. {plain-0.21.1 → plain-0.21.3}/plain/utils/encoding.py +0 -0
  123. {plain-0.21.1 → plain-0.21.3}/plain/utils/functional.py +0 -0
  124. {plain-0.21.1 → plain-0.21.3}/plain/utils/hashable.py +0 -0
  125. {plain-0.21.1 → plain-0.21.3}/plain/utils/html.py +0 -0
  126. {plain-0.21.1 → plain-0.21.3}/plain/utils/http.py +0 -0
  127. {plain-0.21.1 → plain-0.21.3}/plain/utils/inspect.py +0 -0
  128. {plain-0.21.1 → plain-0.21.3}/plain/utils/ipv6.py +0 -0
  129. {plain-0.21.1 → plain-0.21.3}/plain/utils/itercompat.py +0 -0
  130. {plain-0.21.1 → plain-0.21.3}/plain/utils/module_loading.py +0 -0
  131. {plain-0.21.1 → plain-0.21.3}/plain/utils/regex_helper.py +0 -0
  132. {plain-0.21.1 → plain-0.21.3}/plain/utils/safestring.py +0 -0
  133. {plain-0.21.1 → plain-0.21.3}/plain/utils/text.py +0 -0
  134. {plain-0.21.1 → plain-0.21.3}/plain/utils/timesince.py +0 -0
  135. {plain-0.21.1 → plain-0.21.3}/plain/utils/timezone.py +0 -0
  136. {plain-0.21.1 → plain-0.21.3}/plain/utils/tree.py +0 -0
  137. {plain-0.21.1 → plain-0.21.3}/plain/validators.py +0 -0
  138. {plain-0.21.1 → plain-0.21.3}/plain/views/README.md +0 -0
  139. {plain-0.21.1 → plain-0.21.3}/plain/views/__init__.py +0 -0
  140. {plain-0.21.1 → plain-0.21.3}/plain/views/base.py +0 -0
  141. {plain-0.21.1 → plain-0.21.3}/plain/views/csrf.py +0 -0
  142. {plain-0.21.1 → plain-0.21.3}/plain/views/errors.py +0 -0
  143. {plain-0.21.1 → plain-0.21.3}/plain/views/exceptions.py +0 -0
  144. {plain-0.21.1 → plain-0.21.3}/plain/views/forms.py +0 -0
  145. {plain-0.21.1 → plain-0.21.3}/plain/views/objects.py +0 -0
  146. {plain-0.21.1 → plain-0.21.3}/plain/views/redirect.py +0 -0
  147. {plain-0.21.1 → plain-0.21.3}/plain/views/templates.py +0 -0
  148. {plain-0.21.1 → plain-0.21.3}/plain/wsgi.py +0 -0
  149. {plain-0.21.1 → plain-0.21.3}/tests/.bolt/assets_collected/assets.json +0 -0
  150. {plain-0.21.1 → plain-0.21.3}/tests/.gitignore +0 -0
  151. {plain-0.21.1 → plain-0.21.3}/tests/app/.gitignore +0 -0
  152. {plain-0.21.1 → plain-0.21.3}/tests/app/settings.py +0 -0
  153. {plain-0.21.1 → plain-0.21.3}/tests/app/test/__init__.py +0 -0
  154. {plain-0.21.1 → plain-0.21.3}/tests/app/test/default_settings.py +0 -0
  155. {plain-0.21.1 → plain-0.21.3}/tests/app/urls.py +0 -0
  156. {plain-0.21.1 → plain-0.21.3}/tests/conftest.py +0 -0
  157. {plain-0.21.1 → plain-0.21.3}/tests/test_cli.py +0 -0
  158. {plain-0.21.1 → plain-0.21.3}/tests/test_runtime.py +0 -0
  159. {plain-0.21.1 → plain-0.21.3}/tests/test_wsgi.py +0 -0
  160. {plain-0.21.1 → plain-0.21.3}/uv.lock +0 -0
plain-0.21.3/PKG-INFO ADDED
@@ -0,0 +1,12 @@
1
+ Metadata-Version: 2.4
2
+ Name: plain
3
+ Version: 0.21.3
4
+ Summary: A web framework for building products with Python.
5
+ Author-email: Dave Gaeddert <dave.gaeddert@dropseed.dev>
6
+ License-File: LICENSE
7
+ Requires-Python: >=3.11
8
+ Requires-Dist: click>=8.0.0
9
+ Requires-Dist: jinja2>=3.1.2
10
+ Description-Content-Type: text/markdown
11
+
12
+ # Plain
plain-0.21.3/README.md ADDED
@@ -0,0 +1 @@
1
+ ./plain/README.md
@@ -0,0 +1 @@
1
+ # Plain
@@ -12,34 +12,34 @@ FINGERPRINT_LENGTH = 7
12
12
 
13
13
  SKIP_COMPRESS_EXTENSIONS = (
14
14
  # Images
15
- "jpg",
16
- "jpeg",
17
- "png",
18
- "gif",
19
- "webp",
15
+ ".jpg",
16
+ ".jpeg",
17
+ ".png",
18
+ ".gif",
19
+ ".webp",
20
20
  # Compressed files
21
- "zip",
22
- "gz",
23
- "tgz",
24
- "bz2",
25
- "tbz",
26
- "xz",
27
- "br",
21
+ ".zip",
22
+ ".gz",
23
+ ".tgz",
24
+ ".bz2",
25
+ ".tbz",
26
+ ".xz",
27
+ ".br",
28
28
  # Fonts
29
- "woff",
30
- "woff2",
29
+ ".woff",
30
+ ".woff2",
31
31
  # Video
32
- "3gp",
33
- "3gpp",
34
- "asf",
35
- "avi",
36
- "m4v",
37
- "mov",
38
- "mp4",
39
- "mpeg",
40
- "mpg",
41
- "webm",
42
- "wmv",
32
+ ".3gp",
33
+ ".3gpp",
34
+ ".asf",
35
+ ".avi",
36
+ ".m4v",
37
+ ".mov",
38
+ ".mp4",
39
+ ".mpeg",
40
+ ".mpg",
41
+ ".webm",
42
+ ".wmv",
43
43
  )
44
44
 
45
45
 
@@ -111,7 +111,7 @@ def compile_asset(*, asset, target_dir, keep_original, fingerprint, compress):
111
111
 
112
112
  resolved_url_path = os.path.relpath(fingerprinted_path, target_dir)
113
113
 
114
- if compress and extension not in SKIP_COMPRESS_EXTENSIONS:
114
+ if compress and extension.lower() not in SKIP_COMPRESS_EXTENSIONS:
115
115
  for path in compiled_paths.copy():
116
116
  gzip_path = f"{path}.gz"
117
117
  with gzip.GzipFile(gzip_path, "wb") as f:
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "plain"
3
- version = "0.21.1"
3
+ version = "0.21.3"
4
4
  description = "A web framework for building products with Python."
5
5
  authors = [{name = "Dave Gaeddert", email = "dave.gaeddert@dropseed.dev"}]
6
6
  readme = "README.md"
plain-0.21.1/PKG-INFO DELETED
@@ -1,46 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: plain
3
- Version: 0.21.1
4
- Summary: A web framework for building products with Python.
5
- Author-email: Dave Gaeddert <dave.gaeddert@dropseed.dev>
6
- License-File: LICENSE
7
- Requires-Python: >=3.11
8
- Requires-Dist: click>=8.0.0
9
- Requires-Dist: jinja2>=3.1.2
10
- Description-Content-Type: text/markdown
11
-
12
- <!-- This file is compiled from plain/plain/README.md. Do not edit this file directly. -->
13
-
14
- # Plain
15
-
16
- Plain is a web framework for building products with Python.
17
-
18
- With the core `plain` package you can build an app that:
19
-
20
- - Matches [URL patterns](https://plainframework.com/docs/plain/plain/urls) to Python [views](https://plainframework.com/docs/plain/plain/views)
21
- - Handles [HTTP requests and responses](https://plainframework.com/docs/plain/plain/http)
22
- - Renders [HTML templates](https://plainframework.com/docs/plain/plain/templates) with Jinja
23
- - Processes user input via [forms](https://plainframework.com/docs/plain/plain/forms)
24
- - Has a [CLI interface](https://plainframework.com/docs/plain/plain/cli)
25
- - Serves static [assets](https://plainframework.com/docs/plain/plain/assets) (CSS, JS, images)
26
- - Can be modified with [middleware](https://plainframework.com/docs/plain/plain/middleware)
27
- - Integrates first-party and third-party [packages](https://plainframework.com/docs/plain/plain/packages)
28
- - Has a [preflight check system](https://plainframework.com/docs/plain/plain/preflight)
29
-
30
- With the official Plain ecosystem packages you can:
31
-
32
- - Integrate a full-featured [database ORM](https://plainframework.com/docs/plain-models/)
33
- - Use a built-in [user authentication](https://plainframework.com/docs/plain-auth/) system
34
- - [Lint and format code](https://plainframework.com/docs/plain-code/)
35
- - Run a [database-backed cache](https://plainframework.com/docs/plain-cache/)
36
- - [Send emails](https://plainframework.com/docs/plain-mail/)
37
- - Streamline [local development](https://plainframework.com/docs/plain-dev/)
38
- - Manage [feature flags](https://plainframework.com/docs/plain-flags/)
39
- - Integrate [HTMX](https://plainframework.com/docs/plain-htmx/)
40
- - Style with [Tailwind CSS](https://plainframework.com/docs/plain-tailwind/)
41
- - Add [OAuth login](https://plainframework.com/docs/plain-oauth/) and API access
42
- - Run tests with [pytest](https://plainframework.com/docs/plain-test/)
43
- - Run a [background job worker](https://plainframework.com/docs/plain-worker/)
44
- - Build [staff tooling and admin dashboards](https://plainframework.com/docs/plain-staff/)
45
-
46
- Learn more at [plainframework.com](https://plainframework.com).
plain-0.21.1/README.md DELETED
@@ -1,35 +0,0 @@
1
- <!-- This file is compiled from plain/plain/README.md. Do not edit this file directly. -->
2
-
3
- # Plain
4
-
5
- Plain is a web framework for building products with Python.
6
-
7
- With the core `plain` package you can build an app that:
8
-
9
- - Matches [URL patterns](https://plainframework.com/docs/plain/plain/urls) to Python [views](https://plainframework.com/docs/plain/plain/views)
10
- - Handles [HTTP requests and responses](https://plainframework.com/docs/plain/plain/http)
11
- - Renders [HTML templates](https://plainframework.com/docs/plain/plain/templates) with Jinja
12
- - Processes user input via [forms](https://plainframework.com/docs/plain/plain/forms)
13
- - Has a [CLI interface](https://plainframework.com/docs/plain/plain/cli)
14
- - Serves static [assets](https://plainframework.com/docs/plain/plain/assets) (CSS, JS, images)
15
- - Can be modified with [middleware](https://plainframework.com/docs/plain/plain/middleware)
16
- - Integrates first-party and third-party [packages](https://plainframework.com/docs/plain/plain/packages)
17
- - Has a [preflight check system](https://plainframework.com/docs/plain/plain/preflight)
18
-
19
- With the official Plain ecosystem packages you can:
20
-
21
- - Integrate a full-featured [database ORM](https://plainframework.com/docs/plain-models/)
22
- - Use a built-in [user authentication](https://plainframework.com/docs/plain-auth/) system
23
- - [Lint and format code](https://plainframework.com/docs/plain-code/)
24
- - Run a [database-backed cache](https://plainframework.com/docs/plain-cache/)
25
- - [Send emails](https://plainframework.com/docs/plain-mail/)
26
- - Streamline [local development](https://plainframework.com/docs/plain-dev/)
27
- - Manage [feature flags](https://plainframework.com/docs/plain-flags/)
28
- - Integrate [HTMX](https://plainframework.com/docs/plain-htmx/)
29
- - Style with [Tailwind CSS](https://plainframework.com/docs/plain-tailwind/)
30
- - Add [OAuth login](https://plainframework.com/docs/plain-oauth/) and API access
31
- - Run tests with [pytest](https://plainframework.com/docs/plain-test/)
32
- - Run a [background job worker](https://plainframework.com/docs/plain-worker/)
33
- - Build [staff tooling and admin dashboards](https://plainframework.com/docs/plain-staff/)
34
-
35
- Learn more at [plainframework.com](https://plainframework.com).
@@ -1,33 +0,0 @@
1
- # Plain
2
-
3
- Plain is a web framework for building products with Python.
4
-
5
- With the core `plain` package you can build an app that:
6
-
7
- - Matches [URL patterns](./urls) to Python [views](./views)
8
- - Handles [HTTP requests and responses](./http)
9
- - Renders [HTML templates](./templates) with Jinja
10
- - Processes user input via [forms](./forms)
11
- - Has a [CLI interface](./cli)
12
- - Serves static [assets](./assets) (CSS, JS, images)
13
- - Can be modified with [middleware](./middleware)
14
- - Integrates first-party and third-party [packages](./packages)
15
- - Has a [preflight check system](./preflight)
16
-
17
- With the official Plain ecosystem packages you can:
18
-
19
- - Integrate a full-featured [database ORM](https://plainframework.com/docs/plain-models/)
20
- - Use a built-in [user authentication](https://plainframework.com/docs/plain-auth/) system
21
- - [Lint and format code](https://plainframework.com/docs/plain-code/)
22
- - Run a [database-backed cache](https://plainframework.com/docs/plain-cache/)
23
- - [Send emails](https://plainframework.com/docs/plain-mail/)
24
- - Streamline [local development](https://plainframework.com/docs/plain-dev/)
25
- - Manage [feature flags](https://plainframework.com/docs/plain-flags/)
26
- - Integrate [HTMX](https://plainframework.com/docs/plain-htmx/)
27
- - Style with [Tailwind CSS](https://plainframework.com/docs/plain-tailwind/)
28
- - Add [OAuth login](https://plainframework.com/docs/plain-oauth/) and API access
29
- - Run tests with [pytest](https://plainframework.com/docs/plain-test/)
30
- - Run a [background job worker](https://plainframework.com/docs/plain-worker/)
31
- - Build [staff tooling and admin dashboards](https://plainframework.com/docs/plain-staff/)
32
-
33
- Learn more at [plainframework.com](https://plainframework.com).
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes