Skip to content

Commit 73b263a

Browse files
authored
Merge branch '6.0' into 6-dev--module-federation
2 parents cfe78b0 + 0422d3f commit 73b263a

29 files changed

+742
-269
lines changed

.github/workflows/rtd-pr-preview.yml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# .github/workflows/rtd-pr-preview.yml
2+
name: readthedocs/actions
3+
on:
4+
pull_request_target:
5+
types:
6+
- opened
7+
# Execute this action only on PRs that touch
8+
# documentation files.
9+
# paths:
10+
# - "docs/**"
11+
12+
permissions:
13+
pull-requests: write
14+
15+
jobs:
16+
documentation-links:
17+
runs-on: ubuntu-latest
18+
steps:
19+
- uses: readthedocs/actions/preview@v1
20+
with:
21+
project-slug: "plone6"
22+
single-version: "true"

.readthedocs.yaml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# .readthedocs.yaml
2+
# Read the Docs configuration file
3+
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
4+
5+
# Required
6+
version: 2
7+
8+
# Set the OS, Python version and other tools you might need
9+
build:
10+
os: ubuntu-22.04
11+
tools:
12+
python: "3.12"
13+
commands:
14+
# Cancel building pull requests when there aren't changes in the docs directory or YAML file.
15+
# You can add any other files or directories that you'd like here as well,
16+
# like your docs requirements file, or other files that will change your docs build.
17+
#
18+
# If there are no changes (git diff exits with 0) we force the command to return with 183.
19+
# This is a special exit code on Read the Docs that will cancel the build immediately.
20+
- |
21+
if [ "$READTHEDOCS_VERSION_TYPE" = "external" ] && git diff --quiet origin/main -- docs/ .readthedocs.yaml requirements-initial.txt requirements.txt;
22+
then
23+
exit 183;
24+
fi
25+
- make rtd-pr-preview

Makefile

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -224,18 +224,17 @@ livehtml: deps ## Rebuild Sphinx documentation on changes, with live-reload in
224224
--port 8050 \
225225
-b html . "$(BUILDDIR)/html" $(SPHINXOPTS) $(O)
226226

227-
.PHONY: netlify
228-
netlify:
227+
.PHONY: rtd-pr-preview
228+
rtd-pr-preview: ## Build pull request preview on Read the Docs
229229
pip install -r requirements-initial.txt
230230
pip install -r requirements.txt
231-
pip install -r requirements-netlify.txt
232-
git submodule init; \
233-
git submodule update; \
234-
pip install -e submodules/plone.api[test]; \
231+
git submodule init
232+
git submodule update
233+
pip install -e submodules/plone.api[test]
235234
ln -s ../submodules/volto/docs/source ./docs/volto
236235
ln -s ../submodules/plone.restapi ./docs/plone.restapi
237236
ln -s ../submodules/plone.api/docs ./docs/plone.api
238-
cd $(DOCS_DIR) && sphinx-build -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html && cp ./netlify_robots.txt $(BUILDDIR)/html/robots.txt
237+
cd $(DOCS_DIR) && sphinx-build -b html $(ALLSPHINXOPTS) ${READTHEDOCS_OUTPUT}/html/
239238

240239
.PHONY: storybook
241240
storybook:

coredev/packages-dependencies.md

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ This document shows the current state as an orientation.
2323

2424
There are multiple level of dependencies:
2525

26-
- package level (`setup.py`/`setup.cfg`)
26+
- package level (`setup.py`/`setup.cfg`/`pyproject.toml`)
2727
- Python level (imports)
2828
- ZCML level (includes)
2929
- testing (need for layers, such as functional testing)
@@ -41,22 +41,35 @@ A base mental model for how Plone is organized in Plone 6 since alpha 4 is shown
4141

4242
```
4343
┌────────────────────────────┐
44-
│ │
45-
│ On top of Products.CMFPlone│
46-
│ like: │
47-
│ - Plone │
48-
│ - plone.api │
49-
│ - plone.volto │
44+
│ "Plone" |
45+
| The Integration of both |
46+
| distributions in one |
47+
| Release |
48+
├────────────────────────────┤
49+
| Distributions: |
50+
| - plone.volto |
51+
| - plone.classicui |
52+
├────────────────────────────┤
53+
│ Core-Addons │
54+
│ - plone.distribution │
55+
│ - plone.app.exportimport │
56+
│ - plone.app.discussion │
57+
│ - plone.app.multilingual │
58+
│ - plone.app.caching │
5059
│ - plone.app.iterate │
5160
│ - plone.app.update │
5261
│ │
5362
├────────────────────────────┤
63+
│ Core-APIs │
64+
│ - plone.restapi │
65+
│ - plone.api │
66+
├────────────────────────────┤
5467
│ │
5568
│ Products.CMFPlone │
5669
│ │
5770
├────────────────────────────┤
5871
│ │
59-
│ The space between
72+
│ The space between (core )
6073
│ │
6174
│ - most of plone.app.* │
6275
│ - but also some other │
@@ -75,6 +88,7 @@ A base mental model for how Plone is organized in Plone 6 since alpha 4 is shown
7588
│ - plone.registry │
7689
│ - plone.dexterity │
7790
│ - plone.behavior │
91+
│ - plone.rest │
7892
│ - .... │
7993
│ │
8094
└────────────────────────────┘

docs/backend/fields.md

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,25 @@ See [`plone.namedfile`](https://pypi.org/project/plone.namedfile/) and [plone.fo
103103
| `NamedBlobFile` | `NamedBlobFile` | A binary uploaded file stored as a ZODB blob. Requires the `blobs` extra to `plone.namedfile`. Otherwise identical to `NamedFile`. | `IField` |
104104
| `NamedBlobImage` | `NamedBlobImage` | A binary uploaded image stored as a ZODB blob. Requires the `blobs` extra to `plone.namedfile`. Otherwise identical to `NamedImage`. | `IField` |
105105

106+
#### `NamedBlobImage`
107+
108+
The following example shows how to create an `Image` object, and attach the image file to it.
109+
110+
```python
111+
img_obj = api.content.create(
112+
container=ww_article,
113+
type="Image",
114+
id="test.jpg",
115+
image=NamedBlobImage(
116+
data=img_file,
117+
filename="test.jpg",
118+
)
119+
)
120+
```
121+
122+
123+
124+
106125

107126
### Fields in `z3c.relationfield.schema`
108127

@@ -115,6 +134,8 @@ See [`z3c.relationfield`](https://pypi.org/project/z3c.relationfield/) for more
115134
| `RelationChoice` | `RelationValue` | A `Choice` field intended to store `RelationValue`s | See {ref}`Choice <fields-in-zope-schema-label>` |
116135

117136

137+
(backend-fields-richtext-label)=
138+
118139
### Fields in `plone.app.textfield`
119140

120141
See [`plone.app.textfield`](https://pypi.org/project/plone.app.textfield/) for more details.
@@ -124,6 +145,172 @@ See [`plone.app.textfield`](https://pypi.org/project/plone.app.textfield/) for m
124145
| `RichText` | `RichTextValue` | Stores a `RichTextValue`, which encapsulates a raw text value, the source MIME type, and a cached copy of the raw text transformed to the default output MIME type. | `IField`, `IRichText` |
125146

126147

148+
The `RichText` field allows for alternative markups and content filtering.
149+
The following code sample shows how to create a schema with a `RichText` field.
150+
151+
```python
152+
from plone.app.textfield import RichText
153+
from plone.supermodel import model
154+
155+
class ITestSchema(model.Schema):
156+
157+
body = RichText(title="Body text")
158+
```
159+
160+
The `RichText` field constructor can take the following arguments, in addition to the usual arguments for a `Text` field.
161+
162+
`default_mime_type`
163+
: A string representing the default MIME type of the input markup.
164+
This defaults to `text/html`.
165+
166+
`output_mime_type`
167+
: A string representing the default output MIME type.
168+
This defaults to `text/x-html-safe`, which is a Plone-specific MIME type that disallows certain tags.
169+
Use the {guilabel}`HTML Filtering` control panel in Plone to control the tags.
170+
171+
`allowed_mime_types`
172+
: A tuple of strings giving a vocabulary of allowed input MIME types.
173+
If this is `None` (the default), the allowable types will be restricted to those set in Plone's {guilabel}`Markup` control panel.
174+
175+
The *default* field can be set to either a Unicode object (in which case it will be assumed to be a string of the default MIME type) or a {ref}`backend-fields-richtextvalue-label`.
176+
177+
178+
#### reStructuredText transformation
179+
180+
Below is an example of a field that allows StructuredText and reStructuredText, transformed to HTML by default.
181+
182+
```python
183+
from plone.app.textfield import RichText
184+
from plone.supermodel import model
185+
186+
defaultBody = """\
187+
Background
188+
==========
189+
190+
Please fill this in
191+
192+
Details
193+
-------
194+
195+
And this
196+
"""
197+
198+
class ITestSchema(model.Schema):
199+
200+
body = RichText(
201+
title="Body text",
202+
default_mime_type="text/x-rst",
203+
output_mime_type="text/x-html",
204+
allowed_mime_types=("text/x-rst", "text/structured",),
205+
default=defaultBody,
206+
)
207+
```
208+
209+
210+
(backend-fields-richtextvalue-label)=
211+
212+
#### `RichTextValue`
213+
214+
The `RichText` field usually does not store a string.
215+
Instead, it stores a `RichTextValue` object.
216+
This is an immutable object that has the following properties.
217+
218+
`raw`
219+
: A Unicode string with the original input markup.
220+
221+
`mimeType`
222+
: The MIME type of the original markup, for example, `text/html` or `text/structured`.
223+
224+
`encoding`
225+
: The default character encoding used when transforming the input markup.
226+
Most likely, this will be UTF-8.
227+
228+
`raw_encoded`
229+
: The raw input encoded in the given encoding.
230+
231+
`outputMimeType`
232+
: The MIME type of the default output, taken from the field at the time of instantiation.
233+
234+
`output`
235+
: A Unicode object representing the transformed output.
236+
If possible, this is cached persistently, until the `RichTextValue` is replaced with a new one (as happens when an edit form is saved, for example).
237+
238+
The storage of the `RichTextValue` object is optimized for the case where the transformed output will be read frequently (for example, on the view screen of the content object) and the raw value will be read infrequently (for example, on the edit screen).
239+
Because the output value is cached indefinitely, you will need to replace the `RichTextValue` object with a new one if any of the transformation parameters change.
240+
However, as we will see below, it is possible to apply a different transformation on demand, if you need to.
241+
242+
The code snippet below shows how a `RichTextValue` object can be constructed in code.
243+
In this case, we have a raw input string of type `text/plain` that will be transformed to a default output of `text/html`.
244+
Note that we would normally look up the default output type from the field instance.
245+
246+
```python
247+
from plone.app.textfield.value import RichTextValue
248+
249+
context.body = RichTextValue("Some input text", mimeType="text/html", outputMimeType="text/x-html-safe")
250+
```
251+
252+
The standard widget used for a `RichText` field will correctly store this type of object for you, so it is rarely necessary to create one yourself.
253+
254+
255+
##### `RichText` fields in templates
256+
257+
If you use a `DisplayForm`, the display widget for the `RichText` field will render the transformed output markup automatically.
258+
If you write TAL manually, you may try something like the following.
259+
260+
```xml
261+
<div tal:content="structure context/body" />
262+
```
263+
264+
This, however, will render a string as follows.
265+
266+
```html
267+
RichTextValue object. (Did you mean <attribute>.raw or <attribute>.output?)
268+
```
269+
270+
The correct syntax is:
271+
272+
```xml
273+
<div tal:content="structure context/body/output" />
274+
```
275+
276+
This will render the cached, transformed output.
277+
This operation is approximately as efficient as rendering a simple `Text` field, since the transformation is only applied once, when the value is first saved.
278+
279+
280+
##### Alternative transformations
281+
282+
Sometimes, you may want to invoke alternative transformations.
283+
Under the hood, the default implementation uses the `portal_transforms` tool to calculate a transform chain from the raw value's input MIME type to the desired output MIME type.
284+
If you need to write your own transforms, take a look at [Changing Portal Transforms Settings via Python](https://5.docs.plone.org/develop/plone/misc/portal_transforms.html).
285+
This is abstracted behind an `ITransformer` adapter to allow alternative implementations.
286+
287+
To invoke a transformation in code, you can use the following syntax.
288+
289+
```python
290+
from plone.app.textfield.interfaces import ITransformer
291+
292+
transformer = ITransformer(context)
293+
transformedValue = transformer(context.body, "text/plain")
294+
```
295+
296+
The `__call__()` method of the `ITransformer` adapter takes a `RichTextValue` object and an output MIME type as parameters.
297+
298+
If you write a page template, there is an even more convenient syntax.
299+
300+
```xml
301+
<div tal:content="structure context/@@text-transform/body/text/plain" />
302+
```
303+
304+
The first traversal name segment gives the name of the field on the context (`body` in this case).
305+
The second and third segments give the output MIME type.
306+
If the MIME type is omitted, the default output MIME type will be used.
307+
308+
```{note}
309+
Unlike the `output` property, the value is not cached, and so will be calculated each time the page is rendered.
310+
```
311+
312+
313+
127314
### Fields in `plone.schema`
128315

129316
See {ref}`backend-ploneschema-label` for more details.

docs/backend/upgrading/version-specific-migration/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,6 @@ upgrade-to-52
2626
upgrade-to-python3
2727
upgrade-zodb-to-python3
2828
upgrade-to-60
29+
upgrade-to-61
2930
migrate-to-volto
3031
```

0 commit comments

Comments
 (0)