aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/views/FilterPanel.tsx4
-rw-r--r--src/client/views/PropertiesView.tsx150
-rw-r--r--src/client/views/StyleProvider.tsx4
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx15
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx5
-rw-r--r--src/client/views/nodes/CollectionFreeFormDocumentView.tsx7
-rw-r--r--src/client/views/nodes/DocumentView.tsx2
-rw-r--r--src/client/views/nodes/button/FontIconBox.tsx20
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx2
-rw-r--r--src/client/views/nodes/formattedText/RichTextRules.ts10
-rw-r--r--src/fields/Doc.ts3
11 files changed, 85 insertions, 137 deletions
diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx
index a237249c1..d17a4ea25 100644
--- a/src/client/views/FilterPanel.tsx
+++ b/src/client/views/FilterPanel.tsx
@@ -145,8 +145,8 @@ export class FilterPanel extends React.Component<filterProps> {
const set = new Set<string>([String.fromCharCode(127) + '--undefined--']);
if (facetHeader === 'tags')
allCollectionDocs.forEach(child =>
- Field.toString(child[facetHeader] as Field)
- .split(':')
+ StrListCast(child[facetHeader])
+ .filter(h => h)
.forEach(key => set.add(key))
);
else
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx
index 6582c3f2a..fff8390b3 100644
--- a/src/client/views/PropertiesView.tsx
+++ b/src/client/views/PropertiesView.tsx
@@ -7,7 +7,7 @@ import { intersection } from 'lodash';
import { action, computed, Lambda, observable } from 'mobx';
import { observer } from 'mobx-react';
import { ColorState, SketchPicker } from 'react-color';
-import { AclAdmin, AclSym, DataSym, Doc, Field, HeightSym, HierarchyMapping, NumListCast, Opt, StrListCast, WidthSym } from '../../fields/Doc';
+import { AclAdmin, AclSym, DataSym, Doc, Field, FieldResult, HeightSym, HierarchyMapping, NumListCast, Opt, StrListCast, WidthSym } from '../../fields/Doc';
import { Id } from '../../fields/FieldSymbols';
import { InkField } from '../../fields/InkField';
import { List } from '../../fields/List';
@@ -152,116 +152,55 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
return 0;
};
- @computed get expandedField() {
+ editableFields = (filter: (key: string) => boolean, reqdKeys: string[]) => {
+ const rows: JSX.Element[] = [];
if (this.dataDoc && this.selectedDoc) {
- const ids: { [key: string]: string } = {};
- const docs = SelectionManager.Views().length < 2 ? [this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc] : SelectionManager.Views().map(dv => (this.layoutFields ? dv.layoutDoc : dv.dataDoc));
- docs.forEach(doc => Object.keys(doc).forEach(key => !(key in ids) && doc[key] !== ComputedField.undefined && (ids[key] = key)));
- const rows: JSX.Element[] = [];
- for (const key of Object.keys(ids).slice().sort()) {
- const docvals = new Set<any>();
- docs.forEach(doc => docvals.add(doc[key]));
- const contents = Array.from(docvals.keys()).length > 1 ? '-multiple' : docs[0][key];
- if (key[0] === '#') {
- rows.push(
- <div style={{ display: 'flex', overflowY: 'visible', marginBottom: '2px' }} key={key}>
- <span style={{ fontWeight: 'bold', whiteSpace: 'nowrap' }}>{key}</span>
- &nbsp;
- </div>
- );
- } else {
- const contentElement = (
- <EditableView
- key="editableView"
- contents={contents !== undefined ? Field.toString(contents as Field) : 'null'}
- height={13}
- fontSize={10}
- GetValue={() => (contents !== undefined ? Field.toString(contents as Field) : 'null')}
- SetValue={(value: string) => {
- docs.map(doc => KeyValueBox.SetField(doc, key, value, true));
- return true;
- }}
- />
- );
- rows.push(
- <div style={{ display: 'flex', overflowY: 'visible', marginBottom: '-1px' }} key={key}>
- <span style={{ fontWeight: 'bold', whiteSpace: 'nowrap' }}>{key + ':'}</span>
- &nbsp;
- {contentElement}
- </div>
- );
- }
- }
+ const ids = new Set<string>(reqdKeys);
+ const docs: Doc[] = SelectionManager.Views().length < 2 ? [this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc] : SelectionManager.Views().map(dv => (this.layoutFields ? dv.layoutDoc : dv.dataDoc));
+ docs.forEach(doc => Object.keys(doc).forEach(key => doc[key] !== ComputedField.undefined && ids.add(key)));
+
+ // prettier-ignore
+ Array.from(ids).filter(filter).sort().map(key => {
+ const multiple = Array.from(docs.reduce((set,doc) => set.add(doc[key]), new Set<FieldResult>()).keys()).length > 1;
+ const editableContents = multiple ? '-multiple-' : Field.toKeyValueString(docs[0], key);
+ const displayContents = multiple ? '-multiple-' : Field.toString(docs[0][key] as Field);
+ const contentElement = key[0] === '#' ? <></> : (
+ <EditableView
+ key="editableView"
+ contents={displayContents}
+ height={13}
+ fontSize={10}
+ GetValue={() => editableContents}
+ SetValue={(value: string) => {
+ value !== '-multiple-' && docs.map(doc => KeyValueBox.SetField(doc, key, value, true));
+ return true;
+ }}
+ />);
+ rows.push(
+ <div style={{ display: 'flex', overflowY: 'visible', marginBottom: '-1px' }} key={key}>
+ <span style={{ fontWeight: 'bold', whiteSpace: 'nowrap' }}>{key + ':'}</span>
+ &nbsp;
+ {contentElement}
+ </div>
+ );
+ });
+
rows.push(
- <div className="propertiesView-field" key={'newKeyValue'} style={{ marginTop: '3px' }}>
+ <div className="propertiesView-field" key="newKeyValue" style={{ marginTop: '3px' }}>
<EditableView key="editableView" oneLine contents={'add key:value or #tags'} height={13} fontSize={10} GetValue={() => ''} SetValue={this.setKeyValue} />
</div>
);
- return rows;
}
+ return rows;
+ };
+
+ @computed get expandedField() {
+ return this.editableFields(returnTrue, []);
}
@computed get noviceFields() {
- if (this.dataDoc) {
- const ids: { [key: string]: string } = {};
- const docs = SelectionManager.Views().length < 2 ? [this.dataDoc] : SelectionManager.Views().map(dv => dv.dataDoc);
- docs.forEach(doc => Object.keys(doc).forEach(key => !(key in ids) && doc[key] !== ComputedField.undefined && (ids[key] = key)));
- const rows: JSX.Element[] = [];
- const noviceReqFields = ['author', 'creationDate', 'tags'];
- const noviceLayoutFields = ['_curPage'];
- const noviceKeys = [...Array.from(Object.keys(ids)).filter(key => key[0] === '#' || key.indexOf('lastModified') !== -1 || (key[0] === key[0].toUpperCase() && !key.startsWith('acl'))), ...noviceReqFields, ...noviceLayoutFields];
- for (const key of noviceKeys.sort()) {
- const docvals = new Set<any>();
- docs.forEach(doc => docvals.add(doc[key]));
- const contents = Array.from(docvals.keys()).length > 1 ? '-multiple' : docs[0][key];
- if (key[0] === '#') {
- rows.push(
- <div className="propertiesView-uneditable-field" key={key}>
- <span style={{ fontWeight: 'bold', whiteSpace: 'nowrap' }}>{key}</span>
- &nbsp;
- </div>
- );
- } else if (contents !== undefined) {
- const value = Field.toString(contents as Field);
- if (noviceReqFields.includes(key) || key.indexOf('lastModified') !== -1) {
- rows.push(
- <div className="propertiesView-uneditable-field" key={key}>
- <span style={{ fontWeight: 'bold', whiteSpace: 'nowrap' }}>{key + ': '}</span>
- <div style={{ whiteSpace: 'nowrap', overflowX: 'hidden' }}>{value}</div>
- </div>
- );
- } else {
- const contentElement = (
- <EditableView
- key="editableView"
- contents={value}
- height={13}
- fontSize={10}
- GetValue={() => (contents !== undefined ? Field.toString(contents as Field) : 'null')}
- SetValue={(value: string) => {
- docs.map(doc => KeyValueBox.SetField(doc, key, value, true));
- return true;
- }}
- />
- );
-
- rows.push(
- <div style={{ display: 'flex', overflowY: 'visible', marginBottom: '-1px' }} key={key}>
- <span style={{ fontWeight: 'bold', whiteSpace: 'nowrap' }}>{key + ':'}</span>
- &nbsp;
- {contentElement}
- </div>
- );
- }
- }
- }
- rows.push(
- <div className="propertiesView-field" key={'newKeyValue'} style={{ marginTop: '3px' }}>
- <EditableView key="editableView" oneLine contents={'add key:value or #tags'} height={13} fontSize={10} GetValue={() => ''} SetValue={this.setKeyValue} />
- </div>
- );
- return rows;
- }
+ const noviceReqFields = ['author', 'creationDate', 'tags', '_curPage'];
+ return this.editableFields(key => key[0] === '#' || key.indexOf('lastModified') !== -1 || (key[0] === key[0].toUpperCase() && !key.startsWith('acl')), noviceReqFields);
}
@undoBatch
@@ -280,9 +219,10 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
} else if (value[0] === '#') {
const newVal = value + `:'${value}'`;
doc[DataSym][value] = value;
- const tags = StrCast(doc.tags, ':');
- if (!tags.includes(`${value}:`)) {
- doc[DataSym].tags = `${tags + value + ':'}`;
+ const tags = StrListCast(doc.tags);
+ if (!tags.includes(value)) {
+ tags.push(value);
+ doc[DataSym].tags = tags.length ? new List<string>(tags) : undefined;
}
return true;
}
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index d13052f71..192a501f2 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -303,13 +303,13 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
}
}
case StyleProp.PointerEvents:
- const isInk = doc && StrCast(Doc.Layout(doc).layout).includes(InkingStroke.name);
+ const isInk = doc && StrCast(Doc.Layout(doc).layout).includes(InkingStroke.name) && !props?.LayoutTemplateString;
if (docProps?.DocumentView?.().ComponentView?.overridePointerEvents?.() !== undefined) return docProps?.DocumentView?.().ComponentView?.overridePointerEvents?.();
if (MainView.Instance._exploreMode || doc?.unrendered) return isInk ? 'visiblePainted' : 'all';
if (doc?.pointerEvents) return StrCast(doc.pointerEvents);
if (props?.contentPointerEvents) return StrCast(props.contentPointerEvents);
if (props?.pointerEvents?.() === 'none') return 'none';
- if (opacity() === 0 || doc?.isInkMask) return 'none';
+ if (opacity() === 0) return 'none';
if (props?.isDocumentActive?.()) return isInk ? 'visiblePainted' : 'all';
return undefined; // fixes problem with tree view elements getting pointer events when the tree view is not active
case StyleProp.Decorations:
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
index c1f3c5aa6..fee4705e6 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
@@ -133,20 +133,15 @@ export function computePivotLayout(poolData: Map<string, PoolData>, pivotDoc: Do
let nonNumbers = 0;
const pivotFieldKey = toLabel(engineProps?.pivotField ?? pivotDoc._pivotField) || 'author';
childPairs.map(pair => {
- const lval =
- pivotFieldKey === '#' || pivotFieldKey === 'tags'
- ? Array.from(Object.keys(Doc.GetProto(pair.layout)))
- .filter(k => k.startsWith('#'))
- .map(k => k.substring(1))
- : Cast(pair.layout[pivotFieldKey], listSpec('string'), null);
+ const listValue = Cast(pair.layout[pivotFieldKey], listSpec('string'), null);
const num = toNumber(pair.layout[pivotFieldKey]);
if (num === undefined || Number.isNaN(num)) {
nonNumbers++;
}
const val = Field.toString(pair.layout[pivotFieldKey] as Field);
- if (lval) {
- lval.forEach((val, i) => {
+ if (listValue) {
+ listValue.forEach((val, i) => {
!pivotColumnGroups.get(val) && pivotColumnGroups.set(val, { docs: [], filters: [val], replicas: [] });
pivotColumnGroups.get(val)!.docs.push(pair.layout);
pivotColumnGroups.get(val)!.replicas.push(i.toString());
@@ -159,8 +154,8 @@ export function computePivotLayout(poolData: Map<string, PoolData>, pivotDoc: Do
docMap.set(pair.layout[Id], {
x: 0,
y: 0,
- zIndex: -99,
- width: 0,
+ zIndex: 0,
+ width: 0, // should make doc hidden in CollectionFreefromDocumentView
height: 0,
pair,
replica: '',
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 9cc732008..25da868e0 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1158,7 +1158,10 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
@action
bringToFront = (doc: Doc, sendToBack?: boolean) => {
if (sendToBack) {
- doc.zIndex = 0;
+ const docs = this.childLayoutPairs.map(pair => pair.layout).slice();
+ docs.sort((doc1, doc2) => NumCast(doc1.zIndex) - NumCast(doc2.zIndex));
+ let zfirst = docs.length ? NumCast(docs[0].zIndex) : 0;
+ doc.zIndex = zfirst - 1;
} else if (doc.isInkMask) {
doc.zIndex = 5000;
} else {
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 24b9f3b25..b68bcc263 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -16,6 +16,8 @@ import { StyleProp } from '../StyleProvider';
import './CollectionFreeFormDocumentView.scss';
import { DocumentView, DocumentViewProps, OpenWhere } from './DocumentView';
import React = require('react');
+import { DocumentType } from '../../documents/DocumentTypes';
+import { InkingStroke } from '../InkingStroke';
export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps {
dataProvider?: (doc: Doc, replica: string) => { x: number; y: number; zIndex?: number; rotation?: number; color?: string; backgroundColor?: string; opacity?: number; highlight?: boolean; z: number; transition?: string } | undefined;
@@ -201,9 +203,10 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
PanelWidth: this.panelWidth,
PanelHeight: this.panelHeight,
};
+ const isInk = StrCast(this.layoutDoc.layout).includes(InkingStroke.name) && !this.props.LayoutTemplateString && !this.layoutDoc._isInkMask;
return (
<div
- className={'collectionFreeFormDocumentView-container'}
+ className="collectionFreeFormDocumentView-container"
style={{
width: this.panelWidth(),
height: this.panelHeight(),
@@ -211,7 +214,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
transformOrigin: '50% 50%',
transition: this.dataProvider?.transition ?? (this.props.dataTransition ? this.props.dataTransition : this.dataProvider ? this.dataProvider.transition : StrCast(this.layoutDoc.dataTransition)),
zIndex: this.ZInd,
- display: this.ZInd === -99 ? 'none' : undefined,
+ pointerEvents: isInk ? 'none' : undefined,
}}>
{this.props.renderCutoffProvider(this.props.Document) ? (
<div style={{ position: 'absolute', width: this.panelWidth(), height: this.panelHeight(), background: 'lightGreen' }} />
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 3bdd2bf6e..f1f5f7e10 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -870,7 +870,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
contentPointerEvents = () => (!this.disableClickScriptFunc && this.onClickHandler ? 'none' : this.pointerEvents);
@computed get contents() {
TraceMobx();
- const isInk = StrCast(this.layoutDoc.layout).includes(InkingStroke.name);
+ const isInk = StrCast(this.layoutDoc.layout).includes(InkingStroke.name) && !this.props.LayoutTemplateString;
return (
<div
className="documentView-contentsView"
diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx
index f04678d8b..26515da30 100644
--- a/src/client/views/nodes/button/FontIconBox.tsx
+++ b/src/client/views/nodes/button/FontIconBox.tsx
@@ -224,12 +224,12 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
</div>
<div
className="dropbox-background"
- onClick={e => {
+ onClick={action(e => {
e.stopPropagation();
this.rootDoc.dropDownOpen = false;
this.noTooltip = false;
Doc.UnBrushAllDocs();
- }}
+ })}
/>
</div>
) : null}
@@ -336,11 +336,11 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
style={{ backgroundColor: this.rootDoc.dropDownOpen ? Colors.MEDIUM_BLUE : backgroundColor, color: color, display: dropdown ? undefined : 'flex' }}
onClick={
dropdown
- ? () => {
+ ? action(() => {
this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen;
this.noTooltip = this.rootDoc.dropDownOpen;
Doc.UnBrushAllDocs();
- }
+ })
: undefined
}>
{dropdown ? null : <FontAwesomeIcon style={{ marginLeft: 5 }} className={`fontIconBox-icon-${this.type}`} icon={icon} color={color} />}
@@ -358,12 +358,12 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
</div>
<div
className="dropbox-background"
- onClick={e => {
+ onClick={action(e => {
e.stopPropagation();
this.rootDoc.dropDownOpen = false;
this.noTooltip = false;
Doc.UnBrushAllDocs();
- }}
+ })}
/>
</div>
) : null}
@@ -582,17 +582,19 @@ ScriptingGlobals.add(function setBackgroundColor(color?: string, checkResult?: b
} else if (selectedViews.length) {
if (checkResult) {
const selView = selectedViews.lastElement();
+ const fieldKey = selView.rootDoc.type === DocumentType.INK ? 'fillColor' : 'backgroundColor';
const layoutFrameNumber = Cast(selView.props.docViewPath().lastElement()?.rootDoc?._currentFrame, 'number'); // frame number that container is at which determines layout frame values
const contentFrameNumber = Cast(selView.rootDoc?._currentFrame, 'number', layoutFrameNumber ?? null); // frame number that content is at which determines what content is displayed
- return CollectionFreeFormDocumentView.getStringValues(selView?.rootDoc, contentFrameNumber).backgroundColor ?? 'transparent';
+ return CollectionFreeFormDocumentView.getStringValues(selView?.rootDoc, contentFrameNumber)[fieldKey] ?? 'transparent';
}
selectedViews.forEach(dv => {
+ const fieldKey = dv.rootDoc.type === DocumentType.INK ? 'fillColor' : 'backgroundColor';
const layoutFrameNumber = Cast(dv.props.docViewPath().lastElement()?.rootDoc?._currentFrame, 'number'); // frame number that container is at which determines layout frame values
const contentFrameNumber = Cast(dv.rootDoc?._currentFrame, 'number', layoutFrameNumber ?? null); // frame number that content is at which determines what content is displayed
if (contentFrameNumber !== undefined) {
- CollectionFreeFormDocumentView.setStringValues(contentFrameNumber, dv.rootDoc, { backgroundColor: color });
+ CollectionFreeFormDocumentView.setStringValues(contentFrameNumber, dv.rootDoc, { fieldKey: color });
} else {
- dv.rootDoc._backgroundColor = color;
+ dv.rootDoc['_' + fieldKey] = color;
}
});
} else {
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index eb28ffbd7..1d668d6a9 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -69,6 +69,7 @@ import { SummaryView } from './SummaryView';
import applyDevTools = require('prosemirror-dev-tools');
import React = require('react');
import { RTFMarkup } from '../../../util/RTFMarkup';
+import { List } from '../../../../fields/List';
const translateGoogleApi = require('translate-google-api');
export const GoogleRef = 'googleDocId';
type PullHandler = (exportState: Opt<GoogleApiClientUtils.Docs.ImportResult>, dataDoc: Doc) => void;
@@ -318,6 +319,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
const removed = curTags.filter(tag => !accumTags.includes(tag));
removed.forEach(r => (dataDoc[r] = undefined));
added.forEach(a => (dataDoc[a] = a));
+ dataDoc.tags = curTags.length ? new List<string>(curTags) : undefined;
let unchanged = true;
if (this._applyingChange !== this.fieldKey && removeSelection(json) !== removeSelection(curProto?.Data)) {
diff --git a/src/client/views/nodes/formattedText/RichTextRules.ts b/src/client/views/nodes/formattedText/RichTextRules.ts
index cc19d12bd..68b209332 100644
--- a/src/client/views/nodes/formattedText/RichTextRules.ts
+++ b/src/client/views/nodes/formattedText/RichTextRules.ts
@@ -1,7 +1,8 @@
import { ellipsis, emDash, InputRule, smartQuotes, textblockTypeInputRule } from 'prosemirror-inputrules';
import { NodeSelection, TextSelection } from 'prosemirror-state';
-import { DataSym, Doc } from '../../../../fields/Doc';
+import { DataSym, Doc, StrListCast } from '../../../../fields/Doc';
import { Id } from '../../../../fields/FieldSymbols';
+import { List } from '../../../../fields/List';
import { ComputedField } from '../../../../fields/ScriptField';
import { NumCast, StrCast } from '../../../../fields/Types';
import { normalizeEmail } from '../../../../fields/util';
@@ -325,9 +326,10 @@ export class RichTextRules {
const tag = match[1];
if (!tag) return state.tr;
this.Document[DataSym]['#' + tag] = '#' + tag;
- const tags = StrCast(this.Document[DataSym].tags, ':');
- if (!tags.includes(`#${tag}:`)) {
- this.Document[DataSym].tags = `${tags + '#' + tag + ':'}`;
+ const tags = StrListCast(this.Document[DataSym].tags);
+ if (!tags.includes(tag)) {
+ tags.push(tag);
+ this.Document[DataSym].tags = new List<string>(tags);
}
const fieldView = state.schema.nodes.dashField.create({ fieldKey: '#' + tag });
return state.tr
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index a9be24c8b..03ae91c50 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -1387,7 +1387,8 @@ export namespace Doc {
if (typeof value === 'string') {
value = value.replace(`,${Utils.noRecursionHack}`, '');
}
- const fieldVal = key === '#' ? (StrCast(doc.tags).includes(':#' + value + ':') ? StrCast(doc.tags) : undefined) : doc[key];
+ const tagsString = doc.tags ? ':' + StrListCast(doc.tags).join(':') + ':' : '';
+ const fieldVal = key === '#' ? (tagsString.includes(':#' + value + ':') ? tagsString : undefined) : doc[key];
if (Cast(fieldVal, listSpec('string'), []).length) {
const vals = Cast(fieldVal, listSpec('string'), []);
const docs = vals.some(v => (v as any) instanceof Doc);