├── .github
└── workflows
│ └── build.yml
├── .gitignore
├── .husky
└── pre-commit
├── .prettierignore
├── .prettierrc
├── .versionrc
├── .vscode
└── settings.json
├── CHANGELOG.md
├── README.md
├── dev
├── 1_annotations.json
├── 1_config.json
├── 2_annotations.json
├── 2_config.json
├── 3_annotations.json
├── 4_annotations.json
├── attributes_with_no_required_properties_config.json
├── development-sever.js
├── development.html
├── dummy_auth_page.html
├── elon.md
├── favicon.ico
├── for_import.txt
├── invalid.json
├── invalid_attributes_annotation.json
├── invalid_blocks_only.json
├── invalid_color_annotation.json
├── invalid_color_config.json
├── invalid_multi.json
├── multi_tracks.json
├── outer.css
├── prefix.json
├── private.json
├── target.txt
├── warning_not_integer_span.json
└── ゆりかごのうた.json
├── dist
├── demo
│ ├── bionlp-st-ge
│ │ ├── demo-annotations.json
│ │ ├── demo-cdn.html
│ │ ├── demo-config.json
│ │ ├── demo-empty.html
│ │ ├── demo-local.html
│ │ └── demo-multi.html
│ ├── development.html
│ └── initial_load_error.html
├── editor.html
└── lib
│ ├── css
│ ├── images
│ │ ├── btn_adjust_lineheight_16.png
│ │ ├── btn_auto_adjust_lineheight_16.png
│ │ ├── btn_auto_replicate_16.png
│ │ ├── btn_block_edit_mode_16.png
│ │ ├── btn_boundary_detection_16.png
│ │ ├── btn_copy_16.png
│ │ ├── btn_create_span_by_touch_16.png
│ │ ├── btn_cut_16.png
│ │ ├── btn_delete_16.png
│ │ ├── btn_edit_properties_16.png
│ │ ├── btn_edit_text_by_touch_16.png
│ │ ├── btn_expand_span_by_touch_16.png
│ │ ├── btn_help_16.png
│ │ ├── btn_import_16.png
│ │ ├── btn_new_entity_16.png
│ │ ├── btn_pallet_16.png
│ │ ├── btn_pallet_modified_16.png
│ │ ├── btn_paste_16.png
│ │ ├── btn_redo_16.png
│ │ ├── btn_relation_edit_mode_16.png
│ │ ├── btn_replicate_span_annotation_16.png
│ │ ├── btn_setting_16.png
│ │ ├── btn_shrink_span_by_touch_16.png
│ │ ├── btn_simple_view_16.png
│ │ ├── btn_term_edit_mode_16.png
│ │ ├── btn_text_edit_mode_16.png
│ │ ├── btn_undo_16.png
│ │ ├── btn_upload_16.png
│ │ ├── btn_upload_automatically_16.png
│ │ ├── btn_upload_modified_16.png
│ │ ├── btn_view_mode_16.png
│ │ ├── keyhelp.png
│ │ ├── link.png
│ │ ├── ui-bg_diagonals-thick_18_b81900_40x40.png
│ │ ├── ui-bg_diagonals-thick_20_666666_40x40.png
│ │ ├── ui-bg_glass_100_f6f6f6_1x400.png
│ │ ├── ui-bg_glass_100_fdf5ce_1x400.png
│ │ ├── ui-bg_glass_65_ffffff_1x400.png
│ │ ├── ui-bg_gloss-wave_35_f6a828_500x100.png
│ │ ├── ui-bg_highlight-soft_100_eeeeee_1x100.png
│ │ ├── ui-bg_highlight-soft_75_ffe45c_1x100.png
│ │ ├── ui-icons_222222_256x240.png
│ │ ├── ui-icons_228ef1_256x240.png
│ │ ├── ui-icons_ef8c08_256x240.png
│ │ ├── ui-icons_ffd27a_256x240.png
│ │ └── ui-icons_ffffff_256x240.png
│ ├── textae-14.0.1.css
│ └── textae-14.0.1.min.css
│ ├── fonts
│ ├── FontAwesome.otf
│ ├── fontawesome-webfont.eot
│ ├── fontawesome-webfont.svg
│ ├── fontawesome-webfont.ttf
│ ├── fontawesome-webfont.woff
│ └── fontawesome-webfont.woff2
│ ├── textae-14.0.1.js
│ └── textae-14.0.1.min.js
├── eslint.config.mjs
├── package-lock.json
├── package.json
├── scripts
└── postinstall.js
├── src
├── app
│ └── editor.html
├── demo
│ ├── bionlp-st-ge
│ │ ├── demo-annotations.json
│ │ ├── demo-cdn.html
│ │ ├── demo-config.json
│ │ ├── demo-empty.html
│ │ ├── demo-local.html
│ │ └── demo-multi.html
│ ├── development.html
│ └── initial_load_error.html
├── index.js
└── lib
│ ├── AttributeDefinition.js
│ ├── Editor
│ ├── AnnotationModel
│ │ ├── AnnotationEvaluator
│ │ │ ├── getAllSpansIn.js
│ │ │ ├── getAllSpansOf.js
│ │ │ ├── index.js
│ │ │ ├── parseTracks.js
│ │ │ ├── readAcceptedAnnotationTo
│ │ │ │ ├── IDConflictResolver.js
│ │ │ │ ├── convertBeginAndEndOfSpanToInteger.js
│ │ │ │ └── index.js
│ │ │ └── validateAnnotation
│ │ │ │ ├── ChainValidation
│ │ │ │ ├── index.js
│ │ │ │ └── setSourceProperty.js
│ │ │ │ ├── ErrorMap.js
│ │ │ │ ├── debugLogCrossing.js
│ │ │ │ ├── getSpanValidation
│ │ │ │ ├── index.js
│ │ │ │ └── isBeginAndEndIn
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── isInText.js
│ │ │ │ ├── index.js
│ │ │ │ ├── isContains.js
│ │ │ │ ├── isIDUnique.js
│ │ │ │ ├── transformToReferencedEntitiesError.js
│ │ │ │ ├── validateAttribute
│ │ │ │ ├── index.js
│ │ │ │ └── isUniqueIn.js
│ │ │ │ ├── validateBlock.js
│ │ │ │ ├── validateDenotation.js
│ │ │ │ ├── validateRelation.js
│ │ │ │ └── validateTypeSettings.js
│ │ ├── AttributeInstanceContainer
│ │ │ ├── AttributeInstance.js
│ │ │ ├── MediaDictionary.js
│ │ │ └── index.js
│ │ ├── DefinedType.js
│ │ ├── DefinitionContainer
│ │ │ ├── DefinedTypeContainer
│ │ │ │ ├── getForwardMatchID
│ │ │ │ │ ├── getForwardMatchTypes.js
│ │ │ │ │ ├── getLongestIdMatchType.js
│ │ │ │ │ └── index.js
│ │ │ │ └── index.js
│ │ │ ├── countUsage.js
│ │ │ ├── formatForPallet
│ │ │ │ ├── createTypesWithoutInstance.js
│ │ │ │ └── index.js
│ │ │ ├── index.js
│ │ │ └── sortByCountAndName.js
│ │ ├── EntityInstanceContainer.js
│ │ ├── IdIssueContainer
│ │ │ └── index.js
│ │ ├── InstanceContainer
│ │ │ ├── index.js
│ │ │ └── isFunction.js
│ │ ├── LineHeightAuto.js
│ │ ├── RelationInstanceContainer
│ │ │ ├── RelationInstance
│ │ │ │ ├── Arrow
│ │ │ │ │ ├── CurveAlgorithmFactory
│ │ │ │ │ │ ├── ArchedCurveAlgorithm.js
│ │ │ │ │ │ ├── BentOnSourceCurveAlgorithm.js
│ │ │ │ │ │ ├── BentOnTargetCurveAlgorithm.js
│ │ │ │ │ │ ├── CurveAlgorithm.js
│ │ │ │ │ │ ├── CutOffOnSourceArchedCurveAlgorithm.js
│ │ │ │ │ │ ├── CutOffOnSourceBentOnSourceCurveAlgorithm.js
│ │ │ │ │ │ ├── CutOffOnSourceBentOnTargetCurveAlgorithm.js
│ │ │ │ │ │ ├── CutOffOnTargetArchedCurveAlgorithm.js
│ │ │ │ │ │ ├── CutOffOnTargetBentOnSourceCurveAlgorithm.js
│ │ │ │ │ │ ├── CutOffOnTargetBentOnTargetCurveAlgorithm.js
│ │ │ │ │ │ ├── PointingDownCurveAlgorithm.js
│ │ │ │ │ │ ├── PointingUpCurveAlgorithm.js
│ │ │ │ │ │ ├── StartAndEnd.js
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── MarkerHeight.js
│ │ │ │ │ ├── createJetty.js
│ │ │ │ │ ├── createPath.js
│ │ │ │ │ ├── createSourceBollard.js
│ │ │ │ │ ├── createTargetBollard.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── moveJetty.js
│ │ │ │ │ └── updatePath.js
│ │ │ │ ├── Label.js
│ │ │ │ ├── NS.js
│ │ │ │ ├── index.js
│ │ │ │ └── toDisplayName
│ │ │ │ │ ├── getDisplayNameTag.js
│ │ │ │ │ └── index.js
│ │ │ └── index.js
│ │ ├── SpanInstanceContainer
│ │ │ ├── BlockSpanInstance
│ │ │ │ ├── index.js
│ │ │ │ ├── renderBackground.js
│ │ │ │ └── setPosition.js
│ │ │ ├── DenotationSpanInstance
│ │ │ │ ├── getGridHeightIncludeDescendantGrids.js
│ │ │ │ └── index.js
│ │ │ ├── SELECTED.js
│ │ │ ├── SpanInstance
│ │ │ │ ├── createGridHtml.js
│ │ │ │ ├── getRightGrid.js
│ │ │ │ ├── index.js
│ │ │ │ └── updateGridPosition
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── isStaying.js
│ │ │ ├── SpanMap.js
│ │ │ ├── StyleSpanInstance.js
│ │ │ ├── TextSelection
│ │ │ │ ├── getOffsetFromParent.js
│ │ │ │ ├── getParentOffset.js
│ │ │ │ └── index.js
│ │ │ ├── createRangeToSpan
│ │ │ │ ├── createRange.js
│ │ │ │ ├── getRenderingPosition
│ │ │ │ │ ├── getOffset.js
│ │ │ │ │ ├── getRenderingPositionFromBigBrother.js
│ │ │ │ │ ├── getRenderingPositionFromParent.js
│ │ │ │ │ └── index.js
│ │ │ │ └── index.js
│ │ │ ├── getCurrentMaxHeight.js
│ │ │ ├── index.js
│ │ │ ├── rangeFrom.js
│ │ │ ├── spanComparator.js
│ │ │ └── updateSpanTree
│ │ │ │ ├── getParent
│ │ │ │ ├── index.js
│ │ │ │ └── isChildOf.js
│ │ │ │ └── index.js
│ │ ├── TypeDictionary.js
│ │ ├── TypeGap.js
│ │ ├── createTextBox
│ │ │ ├── TextBox
│ │ │ │ ├── getLineHeight.js
│ │ │ │ ├── index.js
│ │ │ │ ├── pixelToInt.js
│ │ │ │ ├── setLineHeight.js
│ │ │ │ └── updateTextBoxHeight.js
│ │ │ ├── focusEditorWhenFocusedChildRemoved.js
│ │ │ └── index.js
│ │ ├── getAnnotationBox.js
│ │ ├── getBoundaryCrossingSpans.js
│ │ ├── getReplicationRanges
│ │ │ ├── getDuplicateSentenceFromText.js
│ │ │ ├── index.js
│ │ │ └── isWord.js
│ │ ├── index.js
│ │ ├── isBoundaryCrossingWithOtherSpans.js
│ │ ├── toBlocks.js
│ │ ├── toDenotations.js
│ │ └── toRelations.js
│ ├── AnnotationModelEventsObserver.js
│ ├── AttributeDefinitionContainer
│ │ ├── createAttributeDefinition
│ │ │ ├── FlagAttributeDefinition.js
│ │ │ ├── SelectionAttributeDefinition.js
│ │ │ ├── StringAttributeDefinition.js
│ │ │ └── index.js
│ │ └── index.js
│ ├── BrowserEventListener.js
│ ├── DataSource.js
│ ├── EditorCSSClass.js
│ ├── EditorEventListener.js
│ ├── EntityInstance.js
│ ├── RESOURCE_TYPE.js
│ ├── RemoteResource
│ │ ├── AnnotationLoader
│ │ │ ├── index.js
│ │ │ └── parseResponse
│ │ │ │ ├── index.js
│ │ │ │ └── responseTypes.js
│ │ ├── AnnotationSaver
│ │ │ ├── index.js
│ │ │ ├── prepareRequestBody.js
│ │ │ └── waitForPopUpClose.js
│ │ ├── ConfigurationLoader.js
│ │ ├── ConfigurationSaver.js
│ │ ├── index.js
│ │ ├── isServerPageAuthRequired.js
│ │ └── openPopUp.js
│ ├── SelectionModel
│ │ ├── SelectedItems.js
│ │ ├── SelectedItemsWithAttributes.js
│ │ └── index.js
│ ├── SignboardHTMLElement.js
│ ├── StartUpOptions
│ │ ├── AnnotationResource.js
│ │ └── index.js
│ ├── UseCase
│ │ ├── AnnotationAutoSaver.js
│ │ ├── Clipboard
│ │ │ └── index.js
│ │ ├── Commander
│ │ │ ├── Factory
│ │ │ │ ├── AddValueToAttributeDefinitionCommand.js
│ │ │ │ ├── AnnotationCommand.js
│ │ │ │ ├── BaseCommand.js
│ │ │ │ ├── ChangeAnnotationCommand.js
│ │ │ │ ├── ChangeAttributeCommand.js
│ │ │ │ ├── ChangeAttributeDefinitionAndReflectInstancesCommand
│ │ │ │ │ ├── ChangeAttributeDefinitionCommand
│ │ │ │ │ │ ├── applyChangedProperties.js
│ │ │ │ │ │ └── index.js
│ │ │ │ │ └── index.js
│ │ │ │ ├── ChangeAttributeObjOfItemsCommand.js
│ │ │ │ ├── ChangeStringAttributeObjOfItemsCommand.js
│ │ │ │ ├── ChangeTextAndMoveSpanCommand.js
│ │ │ │ ├── ChangeTextCommand.js
│ │ │ │ ├── ChangeTypeDefinitionAndReflectInstancesCommand
│ │ │ │ │ ├── createChangeAnnotationCommands.js
│ │ │ │ │ └── index.js
│ │ │ │ ├── ChangeTypeDefinitionCommand
│ │ │ │ │ ├── applyChangedProperties.js
│ │ │ │ │ └── index.js
│ │ │ │ ├── ChangeTypeNameAndAttributeOfSelectedItemsCommand
│ │ │ │ │ ├── getChangeAttributeCommands.js
│ │ │ │ │ └── index.js
│ │ │ │ ├── ChangeTypeOfSelectedItemsCommand.js
│ │ │ │ ├── ChangeTypeValuesCommand.js
│ │ │ │ ├── ChangeValueOfAttributeDefinitionAndObjectOfAttributeCommand
│ │ │ │ │ ├── ChangeValueOfAttributeDefinitionCommand.js
│ │ │ │ │ └── index.js
│ │ │ │ ├── CompositeCommand.js
│ │ │ │ ├── ConfigurationCommand.js
│ │ │ │ ├── CreateAttributeDefinitionCommand.js
│ │ │ │ ├── CreateAttributeToItemsCommand.js
│ │ │ │ ├── CreateBlockSpanCommand.js
│ │ │ │ ├── CreateDefaultTypeEntityToSelectedSpansCommand.js
│ │ │ │ ├── CreateDenotationSpanAndTypesCommand.js
│ │ │ │ ├── CreateEntityAndAttributesCommand
│ │ │ │ │ ├── CreateAttributeToTheLatestEntityCommand.js
│ │ │ │ │ └── index.js
│ │ │ │ ├── CreateSpanAndAutoReplicateCommand.js
│ │ │ │ ├── CreateTypeDefinitionCommand.js
│ │ │ │ ├── DeleteAttributeDefinitionCommand.js
│ │ │ │ ├── MoveAttributeDefinitionCommand.js
│ │ │ │ ├── MoveBlockSpanCommand.js
│ │ │ │ ├── MoveDenotationSpanCommand.js
│ │ │ │ ├── MoveEntitiesToSelectedDenotationSpanCommand
│ │ │ │ │ ├── MoveEntitiesToSpanCommand
│ │ │ │ │ │ ├── RevertMoveEntitiesCommand.js
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── areAllEntitiesOfSpan.js
│ │ │ │ │ └── index.js
│ │ │ │ ├── PasteTypesToSelectedDenotationSpansCommand.js
│ │ │ │ ├── RemoveAttributesFromItemsByPredCommand.js
│ │ │ │ ├── RemoveEntityAndAssociatesCommand.js
│ │ │ │ ├── RemoveRelationAndAssociatesCommand.js
│ │ │ │ ├── RemoveSelectedCommand.js
│ │ │ │ ├── RemoveSpanCommand.js
│ │ │ │ ├── RemoveTypeDefinitionCommand.js
│ │ │ │ ├── RemoveValueFromAttributeDefinitionCommand.js
│ │ │ │ ├── ReplicateSpanCommand.js
│ │ │ │ ├── ToggleFlagAttributeToItemsCommand.js
│ │ │ │ ├── aggregateTargetEntities.js
│ │ │ │ ├── aggregateTargetRelations.js
│ │ │ │ ├── commandLog.js
│ │ │ │ ├── commandTemplate.js
│ │ │ │ ├── createChangeConfigCommand.js
│ │ │ │ ├── getAddPatternToStringAttributeDefinitionCommand.js
│ │ │ │ ├── getCreateAttributeToItemsCommands.js
│ │ │ │ ├── getRemoveAttributesByPredCommands.js
│ │ │ │ └── index.js
│ │ │ ├── History.js
│ │ │ └── index.js
│ │ ├── EditModeState.js
│ │ ├── FunctionAvailability
│ │ │ ├── Translator.js
│ │ │ └── index.js
│ │ ├── IconEventMap.js
│ │ ├── KeyEventMap.js
│ │ ├── MenuState
│ │ │ ├── BlankSkipAdjuster.js
│ │ │ ├── Buttons
│ │ │ │ ├── Button.js
│ │ │ │ ├── Section.js
│ │ │ │ ├── definition.js
│ │ │ │ └── index.js
│ │ │ ├── DelimiterDetectAdjuster
│ │ │ │ ├── backToDelimiter.js
│ │ │ │ ├── backToWord.js
│ │ │ │ ├── getNext.js
│ │ │ │ ├── getPrev.js
│ │ │ │ ├── index.js
│ │ │ │ ├── isNotWord.js
│ │ │ │ ├── skipToDelimiter.js
│ │ │ │ └── skipToWord.js
│ │ │ ├── EnableState.js
│ │ │ ├── PushButtons
│ │ │ │ ├── PushButton.js
│ │ │ │ └── index.js
│ │ │ ├── TextSelectionAdjuster.js
│ │ │ ├── index.js
│ │ │ ├── reduce2hash.js
│ │ │ ├── skipBlank.js
│ │ │ └── skipCharacters.js
│ │ ├── OriginalData
│ │ │ ├── StatusBar
│ │ │ │ ├── getAreaIn.js
│ │ │ │ ├── html.js
│ │ │ │ └── index.js
│ │ │ └── index.js
│ │ ├── PersistenceInterface
│ │ │ ├── LastLoadedFilename.js
│ │ │ ├── LastLoadedURL.js
│ │ │ ├── index.js
│ │ │ ├── isTxtFile.js
│ │ │ ├── readAnnotationFile
│ │ │ │ ├── index.js
│ │ │ │ └── parseFileContent.js
│ │ │ ├── readAnnotationText.js
│ │ │ ├── readConfigurationFile.js
│ │ │ └── readFile.js
│ │ ├── Presenter
│ │ │ ├── EditModeSwitch
│ │ │ │ ├── AttributeEditor
│ │ │ │ │ ├── createNumericAttributeOrShowEditNumericAttributeDialog.js
│ │ │ │ │ ├── createStringAttributeOrShowEditStringAttributeDialog.js
│ │ │ │ │ └── index.js
│ │ │ │ ├── BlockEditMode
│ │ │ │ │ ├── MouseEventHandler.js
│ │ │ │ │ ├── SpanEditor.js
│ │ │ │ │ ├── create.js
│ │ │ │ │ └── index.js
│ │ │ │ ├── EditMode
│ │ │ │ │ ├── PropertyEditor.js
│ │ │ │ │ └── index.js
│ │ │ │ ├── ModeTransitionReactor
│ │ │ │ │ ├── EditorCSS.js
│ │ │ │ │ └── index.js
│ │ │ │ ├── PalletFactory
│ │ │ │ │ ├── bindPalletEvents
│ │ │ │ │ │ ├── checkButtonEnable.js
│ │ │ │ │ │ └── index.js
│ │ │ │ │ └── index.js
│ │ │ │ ├── RelationEditMode
│ │ │ │ │ ├── MouseEventHandler
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ └── typeValuesClicked
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ └── updateSelectionOfEntity.js
│ │ │ │ │ └── index.js
│ │ │ │ ├── SelectionWrapper
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── isNodeBlockSpan.js
│ │ │ │ │ ├── isNodeDenotationSpan.js
│ │ │ │ │ ├── isNodeStyleSpan.js
│ │ │ │ │ └── isNodeTextBox.js
│ │ │ │ ├── TermEditMode
│ │ │ │ │ ├── MouseEventHandler.js
│ │ │ │ │ ├── SpanEditor
│ │ │ │ │ │ ├── create.js
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── isInSelected.js
│ │ │ │ │ │ └── isPositionBetweenSpan.js
│ │ │ │ │ └── index.js
│ │ │ │ ├── TextEditMode
│ │ │ │ │ ├── TextEditDialog.js
│ │ │ │ │ └── index.js
│ │ │ │ ├── clearTextSelection.js
│ │ │ │ ├── index.js
│ │ │ │ ├── isTextSelectionInTextBox.js
│ │ │ │ ├── selectSpan.js
│ │ │ │ └── shrinkSpan
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── shrinkSpanToSelection.js
│ │ │ ├── Horizontal.js
│ │ │ ├── Vertical.js
│ │ │ ├── getIsDelimiterFunc.js
│ │ │ └── index.js
│ │ ├── SpanConfig.js
│ │ ├── getEntityHTMLelementFromChild.js
│ │ ├── index.js
│ │ ├── initAnnotation
│ │ │ ├── index.js
│ │ │ └── setLoadedAnnotation.js
│ │ ├── patchConfiguration
│ │ │ ├── AttributeConfigurationGenerator
│ │ │ │ ├── AnnotationsForPred
│ │ │ │ │ ├── getMostFrequentObject.js
│ │ │ │ │ ├── getStep.js
│ │ │ │ │ ├── getValueType.js
│ │ │ │ │ └── index.js
│ │ │ │ ├── fillDefaultValueOfSelectionAttributes
│ │ │ │ │ ├── getSelectionAttributes.js
│ │ │ │ │ └── index.js
│ │ │ │ ├── fillInferDefinitionFromAnnotation
│ │ │ │ │ ├── fill.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── inferDefinitionFromAnnotation
│ │ │ │ │ │ └── index.js
│ │ │ │ ├── fillMandatoryValueOfNumericAttributes.js
│ │ │ │ ├── getAnnotationMap.js
│ │ │ │ └── index.js
│ │ │ ├── clone.js
│ │ │ └── index.js
│ │ ├── setAnnotationAndConfiguration.js
│ │ ├── validateAttributeDefinitionAndAlert
│ │ │ ├── hasAllValueDefinitionOfSelectionAttributes.js
│ │ │ └── index.js
│ │ ├── validateConfigurationAndAlert
│ │ │ ├── index.js
│ │ │ └── validateConfiguration
│ │ │ │ ├── index.js
│ │ │ │ └── toErrorMessage.js
│ │ └── warningIfBeginEndOfSpanAreNotInteger
│ │ │ ├── areNotBeginAndEndInteger.js
│ │ │ └── index.js
│ ├── control
│ │ ├── ContextMenu
│ │ │ ├── index.js
│ │ │ └── toContextMenuItem.js
│ │ ├── Menu
│ │ │ ├── bindEventHandler.js
│ │ │ └── index.js
│ │ ├── ToolBar
│ │ │ ├── index.js
│ │ │ └── toButtonGroup
│ │ │ │ ├── index.js
│ │ │ │ └── toButtonIcon.js
│ │ └── classify.js
│ ├── diffOfAnnotation
│ │ ├── byID.js
│ │ ├── index.js
│ │ └── sortByID.js
│ ├── editorCSSClassObserve.js
│ ├── filterIfModelModified.js
│ ├── forwardMethods.js
│ ├── getDisplayName
│ │ ├── getDisplayNameFromUri.js
│ │ └── index.js
│ ├── getLabelBackgroundColor.js
│ ├── getMatchPrefix.js
│ ├── getPalletButtonTitleFor.js
│ ├── getRightElement.js
│ ├── getRightSpanElement.js
│ ├── getURI.js
│ ├── getUrlMatches.js
│ ├── hexToRGBA.js
│ ├── index.js
│ ├── isAndroid.js
│ ├── isBoundaryCrossing.js
│ ├── isTouchable.js
│ ├── loadAnnotation.js
│ ├── observeElement.js
│ ├── observeEventEmitter.js
│ ├── round.js
│ └── toAnchorElement.js
│ ├── IntervalNotation
│ ├── getLowwerCond.js
│ ├── getUpperCond.js
│ ├── gt.js
│ ├── gte.js
│ └── index.js
│ ├── MODE.js
│ ├── NumericAttributeDefinition.js
│ ├── TypeValues.js
│ ├── component
│ ├── CreateAttributeDefinitionDialog
│ │ ├── index.js
│ │ └── template.js
│ ├── CreateOrEditValueOfAttributeDefinitionDialog
│ │ ├── index.js
│ │ ├── inputDefault.js
│ │ └── template.js
│ ├── CreateTypeDefinitionDialog.js
│ ├── Dialog.js
│ ├── EditAttributeDefinitionDialog
│ │ ├── index.js
│ │ ├── isChanged.js
│ │ └── template.js
│ ├── EditNumericAttributeDialog.js
│ ├── EditPropertiesDialog
│ │ ├── EditAttributeButtonHandler.js
│ │ ├── createContentHTML
│ │ │ ├── index.js
│ │ │ ├── toAddAttributeButton.js
│ │ │ ├── toAttributeHTML
│ │ │ │ ├── getLabelOf.js
│ │ │ │ └── index.js
│ │ │ └── toEntityHTML.js
│ │ ├── getValues.js
│ │ ├── index.js
│ │ └── mergedTypeValuesOf.js
│ ├── EditStringAttributeDialog.js
│ ├── EditTypeDefinitionDialog
│ │ ├── getDifference.js
│ │ └── index.js
│ ├── HelpDialog.js
│ ├── LoadAnnotationDialog
│ │ ├── index.js
│ │ └── initInlineEditor.js
│ ├── LoadConfigurationDialog.js
│ ├── LoadDialogLocalComponent.js
│ ├── LoadDialogURLComponent.js
│ ├── Pallet
│ │ ├── enableJqueryDraggable.js
│ │ ├── index.js
│ │ ├── setHeightWithin.js
│ │ └── setWidthWithin.js
│ ├── PromiseDialog.js
│ ├── SaveAnnotationDialog
│ │ ├── bind
│ │ │ ├── createDownloadPathForFormat.js
│ │ │ ├── downloadAnnotationFile
│ │ │ │ ├── downloadAnnotation.js
│ │ │ │ └── index.js
│ │ │ ├── index.js
│ │ │ └── viewSource.js
│ │ └── index.js
│ ├── SaveConfigurationDialog
│ │ ├── bind.js
│ │ ├── index.js
│ │ └── jsonDiff.js
│ ├── SelectionAttributePallet
│ │ ├── index.js
│ │ ├── template.js
│ │ └── toBodyRow.js
│ ├── SettingDialog
│ │ ├── EscapeSequence.js
│ │ ├── bindAddCharacter
│ │ │ ├── addCharacterRow
│ │ │ │ ├── index.js
│ │ │ │ └── validateCharacter.js
│ │ │ └── index.js
│ │ ├── bindDeleteCharacter.js
│ │ ├── index.js
│ │ ├── reflectImmediately
│ │ │ ├── bindChangeFunctionAvailability.js
│ │ │ ├── bindChangeLineHeight.js
│ │ │ ├── bindChangeLockConfig.js
│ │ │ ├── bindChangeTypeGap.js
│ │ │ ├── debounce300.js
│ │ │ ├── index.js
│ │ │ └── redrawAllEditor.js
│ │ ├── saveAutocompletionWs.js
│ │ ├── saveSpanConfig.js
│ │ ├── template
│ │ │ ├── escapeForDisplay.js
│ │ │ ├── index.js
│ │ │ ├── toBlankCharacterRowElement.js
│ │ │ ├── toDelimiterCharacterRowElement.js
│ │ │ └── toFunctionAvailabilityLabelElement.js
│ │ └── validateConfiguration.js
│ ├── TipsDialog.js
│ ├── TypeDefinitionDialog
│ │ ├── index.js
│ │ └── template.js
│ ├── TypeValuesPallet
│ │ ├── bindAttributeEvent
│ │ │ ├── enableAttributeTabDrag
│ │ │ │ ├── hideDropTargets.js
│ │ │ │ ├── index.js
│ │ │ │ └── showDropTargets.js
│ │ │ ├── enableAttributeTabDrop.js
│ │ │ └── index.js
│ │ ├── createContentHtml
│ │ │ ├── flagAttributeTemplate.js
│ │ │ ├── headerTemplate
│ │ │ │ ├── addAttributeButtonTemplate.js
│ │ │ │ ├── addNewAttributeTabTemplate.js
│ │ │ │ ├── attributeTabTemplate.js
│ │ │ │ ├── editAttributeButtonTemplate.js
│ │ │ │ ├── getSelectedEntityLabel.js
│ │ │ │ ├── index.js
│ │ │ │ └── removeAttributeButtonTemplate.js
│ │ │ ├── index.js
│ │ │ ├── numericAttributeTemplate
│ │ │ │ ├── index.js
│ │ │ │ └── toBodyRow.js
│ │ │ ├── predicateControllerTemplate
│ │ │ │ ├── editAttributeDefinitionBlockTemplate.js
│ │ │ │ ├── index.js
│ │ │ │ └── toDeleteButton.js
│ │ │ ├── selectionAttributeTemplate
│ │ │ │ ├── index.js
│ │ │ │ └── toBodyRow.js
│ │ │ ├── showAddAttributeValueButton.js
│ │ │ ├── stringAttributeTemplate
│ │ │ │ ├── index.js
│ │ │ │ └── toBodyRow.js
│ │ │ ├── typeTemplate
│ │ │ │ ├── editButtonsTemplate.js
│ │ │ │ ├── index.js
│ │ │ │ └── toTypeRow.js
│ │ │ └── valueButtonsTemplate.js
│ │ ├── enableDrag.js
│ │ └── index.js
│ ├── ValidationDialog
│ │ ├── boundaryCrossingSpansTemplate.js
│ │ ├── duplicateRangeBlocksTemplate.js
│ │ ├── duplicatedAttributesTemplate.js
│ │ ├── duplicatedIDsTemplate.js
│ │ ├── index.js
│ │ ├── outOfTextBlocksTemplate.js
│ │ ├── outOfTextDenotationsTemplate.js
│ │ ├── outOfTextTypesettingsTemplate.js
│ │ ├── referencedEntitiesDoNotExistTemplate.js
│ │ ├── wrongRangeBlocksTemplate.js
│ │ ├── wrongRangeDenotationsTemplate.js
│ │ └── wrongRangeTypesettingsTemplate.js
│ ├── anemone.js
│ ├── createDownloadPath.js
│ ├── enableHTMLElement.js
│ ├── fetchAutocompleteCandidates.js
│ ├── getInputElementValue.js
│ ├── getRandomColorString.js
│ ├── initJSONEditor.js
│ ├── inputAttributeDefinition
│ │ ├── index.js
│ │ ├── inputAutocompletionWs.js
│ │ ├── inputDefault.js
│ │ ├── inputLabelAndColor.js
│ │ ├── inputMediaHeight.js
│ │ └── inputNumeric.js
│ ├── isUserConfirm.js
│ ├── maximizeOverlay.js
│ └── revertMaximizeOverlay.js
│ ├── configurationScheme.json
│ ├── createEditor.js
│ ├── css
│ ├── images
│ │ ├── btn_adjust_lineheight_16.png
│ │ ├── btn_auto_adjust_lineheight_16.png
│ │ ├── btn_auto_replicate_16.png
│ │ ├── btn_block_edit_mode_16.png
│ │ ├── btn_boundary_detection_16.png
│ │ ├── btn_copy_16.png
│ │ ├── btn_create_span_by_touch_16.png
│ │ ├── btn_cut_16.png
│ │ ├── btn_delete_16.png
│ │ ├── btn_edit_properties_16.png
│ │ ├── btn_edit_text_by_touch_16.png
│ │ ├── btn_expand_span_by_touch_16.png
│ │ ├── btn_help_16.png
│ │ ├── btn_import_16.png
│ │ ├── btn_new_entity_16.png
│ │ ├── btn_pallet_16.png
│ │ ├── btn_pallet_modified_16.png
│ │ ├── btn_paste_16.png
│ │ ├── btn_redo_16.png
│ │ ├── btn_relation_edit_mode_16.png
│ │ ├── btn_replicate_span_annotation_16.png
│ │ ├── btn_setting_16.png
│ │ ├── btn_shrink_span_by_touch_16.png
│ │ ├── btn_simple_view_16.png
│ │ ├── btn_term_edit_mode_16.png
│ │ ├── btn_text_edit_mode_16.png
│ │ ├── btn_undo_16.png
│ │ ├── btn_upload_16.png
│ │ ├── btn_upload_automatically_16.png
│ │ ├── btn_upload_modified_16.png
│ │ ├── btn_view_mode_16.png
│ │ ├── keyhelp.png
│ │ ├── keyhelp.psd
│ │ ├── link.png
│ │ ├── ui-bg_diagonals-thick_18_b81900_40x40.png
│ │ ├── ui-bg_diagonals-thick_20_666666_40x40.png
│ │ ├── ui-bg_glass_100_f6f6f6_1x400.png
│ │ ├── ui-bg_glass_100_fdf5ce_1x400.png
│ │ ├── ui-bg_glass_65_ffffff_1x400.png
│ │ ├── ui-bg_gloss-wave_35_f6a828_500x100.png
│ │ ├── ui-bg_highlight-soft_100_eeeeee_1x100.png
│ │ ├── ui-bg_highlight-soft_75_ffe45c_1x100.png
│ │ ├── ui-icons_222222_256x240.png
│ │ ├── ui-icons_228ef1_256x240.png
│ │ ├── ui-icons_ef8c08_256x240.png
│ │ ├── ui-icons_ffd27a_256x240.png
│ │ └── ui-icons_ffffff_256x240.png
│ ├── modules
│ │ └── jquery-ui.min.less
│ ├── textae-const.less
│ ├── textae-control.less
│ ├── textae-editor-dialog-autocomplete.less
│ ├── textae-editor-dialog.less
│ ├── textae-editor-entity.less
│ ├── textae-editor-fontawsome.less
│ ├── textae-editor-pallet.less
│ ├── textae-editor.less
│ ├── textae-text-edit-dialog.less
│ └── textae.less
│ ├── exceptions
│ └── FormatConversionError.js
│ ├── isAbleToParseFloat.js
│ ├── isJSON.js
│ ├── isURI.js
│ ├── openEditNumericAttributeDialog.js
│ ├── openEditStringAttributeDialog.js
│ └── textae
│ ├── API.js
│ ├── Tool
│ ├── EditorContainer
│ │ ├── index.js
│ │ └── isTextFields.js
│ ├── Veil.js
│ ├── getMousePoint.js
│ ├── index.js
│ └── observeBodyEvents.js
│ ├── index.js
│ └── toEditor.js
├── tmp
└── .keep
├── userAcceptanceTest
├── 20210716_02.md
├── 20210720_01.md
├── 20210720_02_mouse.md
├── 20210720_03.md
├── 20210720_04.md
├── 20210720_06.md
├── 20210727_02.md
├── 20210727_03.md
├── 20210728_01.md
├── 20210730_01.md
├── 20210803_01.md
├── 20210803_02.md
├── 20210804_01.md
├── 20210805_01.md
├── 20210805_02.md
├── 20210805_03.md
├── 20210805_04.md
├── 20210805_05_keyboard.md
├── 20210806_01.md
├── 20210806_02.md
├── 20210806_03.md
├── 20210806_04.md
├── 20210810_01.md
├── 20210811_01.md
├── 20210812_02.md
├── 20210813_01.md
├── 20210816_01.md
├── 20210817_01.md
├── 20210817_02.md
├── 20210818_01.md
├── 20210819_01.md
├── 20210820_01.md
├── 20210824_01.md
├── 20210825_01.md
├── 20210825_02.md
├── 20210826_01.md
├── 20210826_02.md
├── 20210827_01.md
├── 20210827_02.md
├── 20210831_01.md
├── 20210901_01.md
├── 20210901_02.md
├── 20210902_01.md
├── 20210902_02.md
├── 20210902_03.md
├── 20210902_04.md
├── 20210902_05.md
├── 20210907_01.md
├── 20210907_02.md
├── 20210908_01.md
├── 20210908_02.md
├── 20210914_01.md
├── 20210914_02.md
├── 20210921_01.md
├── 20210921_02.md
├── 20210922_01.md
├── 20210922_02.md
├── 20210922_03.md
├── 20210928_01.md
├── 20210929_01.md
├── 20210929_02.md
├── 20210929_03.md
├── 20210929_04.md
├── 20210930_01.md
├── 20210930_02.md
├── 20210930_03.md
├── 20210930_04.md
├── 20210930_05.md
├── 20211028_01.md
├── 20211028_02.md
├── 20211029_01.md
├── 20211102_01.md
├── 20211102_02.md
├── 20211102_03.md
├── 20211102_04.md
├── 20211104_01.md
├── 20211105_01.md
├── 20211109_01.md
├── 20211109_02.md
├── 20211109_03.md
├── 20211109_04.md
├── 20211109_05.md
├── 20211109_06.md
├── 20211110_01.md
├── 20211110_02.md
├── 20211110_03.md
├── 20211110_04.md
├── 20211110_05.md
├── 20211116_01.md
├── 20211116_02.md
├── 20211117_01.md
├── 20211117_02.md
├── 20211118_01.md
├── 20211118_02.md
├── 20211118_03.md
├── 20211118_04.md
├── 20211124_01.md
├── 20211124_02.md
├── 20211124_03.md
├── 20211124_04.md
├── 20211125_01.md
├── 20211125_02.md
├── 20211130_01.md
├── 20211201_01.md
├── 20211207_01.md
├── 20211207_02.md
├── 20211207_03.md
├── 20211207_04.md
├── 20211207_05.md
├── 20211207_06.md
├── 20211207_07.md
├── 20211208_01.md
├── 20211208_02.md
├── 20211208_03.md
├── 20211208_04.md
├── 20211208_05.md
├── 20211208_06.md
├── 20211208_07.md
├── 20211208_08.md
├── 20211208_09.md
├── 20211208_10.md
├── 20211209_01.md
├── 20211209_02.md
├── 20211209_03.md
├── 20211214_01.md
├── 20211215_01.md
├── 20211215_02.md
├── 20211215_03.md
├── 20211215_04.md
├── 20211215_05.md
├── 20211215_06.md
├── 20211215_07.md
├── 20211216_01.md
├── 20211221_01.md
├── 20211222_01.md
├── 20211223_01.md
├── 20211224_01.md
├── 20211224_02.md
├── 20211224_03.md
├── 20211224_04.md
├── 20220105_01.md
├── 20220105_02.md
├── 20220105_03.md
├── 20220106_01.md
├── 20220106_02.md
├── 20220106_03.md
├── 20220106_04.md
├── 20220106_05.md
├── 20220106_06.md
├── 20220106_07.md
├── 20220108_02.md
├── 20220112_01.md
├── 20220112_02.md
├── 20220112_03.md
├── 20220112_04.md
├── 20220112_05.md
├── 20220112_06.md
├── 20220112_07.md
├── 20220113_01.md
├── 20220113_02.md
├── 20220113_03.md
├── 20220118_01.md
├── 20220118_02.md
├── 20220118_03.md
├── 20220119_01.md
├── 20220119_02.md
├── 20220119_03.md
├── 20220119_04.md
├── 20220119_05.md
├── 20220119_06.md
├── 20220120_01.md
├── 20220121_01.md
├── 20220121_02.md
├── 20220121_03.md
├── 20220121_04.md
├── 20220125_01.md
├── 20220125_02.md
├── 20220125_03.md
├── 20220127_01.md
├── 20220127_02.md
├── 20220127_03.md
├── 20220127_04.md
├── 20220202_01.md
├── 20220202_02.md
├── 20220202_03.md
├── 20220202_04.md
├── 20220202_05.md
├── 20220203_01.md
├── 20220203_02.md
├── 20220207_01.md
├── 20220207_02.md
├── 20220207_03.md
├── 20220207_04.md
├── 20220208_01.md
├── 20220208_03.md
├── 20220210_01.md
├── 20220210_02.md
├── 20220215_01.md
├── 20220215_02.md
├── 20220215_03.md
├── 20220215_04.md
├── 20220215_05.md
├── 20220216_01.md
├── 20220216_02.md
├── 20220216_03.md
├── 20220216_04.md
├── 20220216_05.md
├── 20220217_01.md
├── 20220217_02.md
├── 20220222_01_mouse.md
├── 20220222_02_mouse.md
├── 20220222_03_mouse.md
├── 20220222_04_mouse.md
├── 20220302_01.md
├── 20220302_02.md
├── 20220302_03.md
├── 20220302_04.md
├── 20220302_05.md
├── 20220302_06.md
├── 20220302_07.md
├── 20220302_08.md
├── 20220303_01_mouse.md
├── 20220303_02_mouse.md
├── 20220304_01.md
├── 20220304_02.md
├── 20220308_01.md
├── 20220308_02.md
├── 20220308_03.md
├── 20220309_01_mouse.md
├── 20220309_02_keyboard.md
├── 20220309_03_monuse.md
├── 20220309_04_keyboard.md
├── 20220309_05_keyborard.md
├── 20220310_01.md
├── 20220310_02.md
├── 20220314_01.md
├── 20220315_01_mouse.md
├── 20220315_02_keyboard.md
├── 20220315_03_keyboard.md
├── 20220318_01.md
├── 20220318_02.md
├── 20220318_03.md
├── 20220318_04.md
├── 20220318_05.md
├── 20220318_06.md
├── 20220407_01.md
├── 20220407_01_mouse.md
├── 20220412_01.md
├── 20220412_02.md
├── 20220413_01_mouse.md
├── 20220415_01.md
├── 20220415_02.md
├── 20220415_03.md
├── 20220419_01.md
├── 20220419_02.md
├── 20220503_01_firefox.md
├── 20220503_02.md
├── 20220506_01.md
├── choice_test_devices.rb
├── rareUserAcceptanceTest.md
├── todoTest.md
└── userAcceptanceTest.md
├── webpack.dev.mjs
└── webpack.prod.mjs
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: Build and Dist
2 |
3 | on:
4 | push:
5 | branches:
6 | - stable/4
7 | pull_request:
8 | branches:
9 | - stable/4
10 |
11 | jobs:
12 | build:
13 | runs-on: ubuntu-latest
14 |
15 | steps:
16 | - name: Checkout repository
17 | uses: actions/checkout@v4
18 |
19 | - name: Set up Node.js
20 | uses: actions/setup-node@v4
21 | with:
22 | node-version: '22'
23 |
24 | - name: Install dependencies
25 | run: npm install
26 |
27 | - name: Run dist:build
28 | run: npm run dist:build
29 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | npm-debug.log
3 | *.dev_data.json
4 | src/lib/fonts/
5 | src/lib/css/textae.css
6 | dev/bundle.js
7 | /tmp/*
8 | !/tmp/.keep
9 | textae-*.tgz
10 |
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | npx lint-staged
2 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | src/lib/modules/jquery.jsPlumb-1.5.5-min.js
2 | src/lib/modules/jquery.jsPlumb-1.5.5.js
3 | dist/lib/textae-*.min.js
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "trailingComma": "none",
3 | "semi": false,
4 | "singleQuote": true,
5 | "arrowParens": "always"
6 | }
7 |
--------------------------------------------------------------------------------
/.versionrc:
--------------------------------------------------------------------------------
1 | {
2 | "types": [
3 | {"type": "feature", "section": "Features"},
4 | {"type": "fix", "section": "Bug Fixes"},
5 | {"type": "refactor", "hidden": true},
6 | {"type": "chore", "hidden": true},
7 | {"type": "misc", "hidden": true},
8 | {"type": "test", "hidden": true}
9 | ]
10 | }
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "cSpell.words": [
3 | "alertifyjs",
4 | "colspan",
5 | "delgate",
6 | "dohtml",
7 | "eskape",
8 | "jsondiffpatch",
9 | "lifesciencedb",
10 | "observ",
11 | "rowspan",
12 | "textae"
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/dev/2_annotations.json:
--------------------------------------------------------------------------------
1 | {
2 | "text": "Downregulation is the process by which a cell decreases the quantity of a cellular component, such as RNA or protein, in response to an external variable. An increase of a cellular component is called upregulation."
3 | }
4 |
--------------------------------------------------------------------------------
/dev/attributes_with_no_required_properties_config.json:
--------------------------------------------------------------------------------
1 | {
2 | "attribute types": [
3 | {
4 | "pred": "category",
5 | "value type": "string"
6 | },
7 | {
8 | "pred": "tags",
9 | "value type": "selection"
10 | },
11 | {
12 | "pred": "rate",
13 | "value type": "numeric"
14 | }
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/dev/dummy_auth_page.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | This is a dummy auth page!
4 |
5 |
--------------------------------------------------------------------------------
/dev/elon.md:
--------------------------------------------------------------------------------
1 | [Elon Musk][Person] is a member of the [PayPal Mafia][Organization].
2 |
3 | [Person]: https://example.com/Person
4 | [Organization]: https://example.com/Organization
5 |
--------------------------------------------------------------------------------
/dev/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dev/favicon.ico
--------------------------------------------------------------------------------
/dev/for_import.txt:
--------------------------------------------------------------------------------
1 | This file is a text file.
--------------------------------------------------------------------------------
/dev/invalid_attributes_annotation.json:
--------------------------------------------------------------------------------
1 | {
2 | "config": {
3 | "attribute types": [
4 | {
5 | "pred": "rate",
6 | "value type": "numeric"
7 | }
8 | ]
9 | },
10 | "text": "dummy string"
11 | }
12 |
--------------------------------------------------------------------------------
/dev/invalid_color_annotation.json:
--------------------------------------------------------------------------------
1 | {
2 | "config": {
3 | "attribute types": [
4 | {
5 | "pred": "bad color",
6 | "value type": "selection",
7 | "values": [
8 | {
9 | "color": "Invalid color format",
10 | "id": "id"
11 | }
12 | ]
13 | }
14 | ]
15 | },
16 | "text": "dummy string"
17 | }
18 |
--------------------------------------------------------------------------------
/dev/invalid_color_config.json:
--------------------------------------------------------------------------------
1 | {
2 | "attribute types": [
3 | {
4 | "pred": "bad color",
5 | "value type": "selection",
6 | "values": [
7 | {
8 | "color": "Invalid color format",
9 | "id": "id"
10 | }
11 | ]
12 | }
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/dev/outer.css:
--------------------------------------------------------------------------------
1 | /* Emulate an outer css file */
2 | p {
3 | line-height:1.5em;
4 | }
--------------------------------------------------------------------------------
/dev/target.txt:
--------------------------------------------------------------------------------
1 | An annotation is a metadatum (e.g. a post, explanation, markup) attached to location or other data.
2 |
--------------------------------------------------------------------------------
/dev/warning_not_integer_span.json:
--------------------------------------------------------------------------------
1 | {
2 | "text": "Ribonucleic acid (RNA) is a ubiquitous family of large biological molecules.",
3 | "denotations": [
4 | {
5 | "id": "E1",
6 | "span": {
7 | "begin": "0",
8 | "end": 16
9 | },
10 | "obj": "リボ核酸"
11 | },
12 | {
13 | "id": "E2",
14 | "span": {
15 | "begin": 49.5,
16 | "end": 75
17 | },
18 | "obj": "大きな生体分子"
19 | }
20 | ]
21 | }
22 |
--------------------------------------------------------------------------------
/dist/demo/bionlp-st-ge/demo-cdn.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/dist/demo/bionlp-st-ge/demo-empty.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/dist/demo/bionlp-st-ge/demo-local.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/dist/lib/css/images/btn_adjust_lineheight_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/btn_adjust_lineheight_16.png
--------------------------------------------------------------------------------
/dist/lib/css/images/btn_auto_adjust_lineheight_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/btn_auto_adjust_lineheight_16.png
--------------------------------------------------------------------------------
/dist/lib/css/images/btn_auto_replicate_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/btn_auto_replicate_16.png
--------------------------------------------------------------------------------
/dist/lib/css/images/btn_block_edit_mode_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/btn_block_edit_mode_16.png
--------------------------------------------------------------------------------
/dist/lib/css/images/btn_boundary_detection_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/btn_boundary_detection_16.png
--------------------------------------------------------------------------------
/dist/lib/css/images/btn_copy_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/btn_copy_16.png
--------------------------------------------------------------------------------
/dist/lib/css/images/btn_create_span_by_touch_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/btn_create_span_by_touch_16.png
--------------------------------------------------------------------------------
/dist/lib/css/images/btn_cut_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/btn_cut_16.png
--------------------------------------------------------------------------------
/dist/lib/css/images/btn_delete_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/btn_delete_16.png
--------------------------------------------------------------------------------
/dist/lib/css/images/btn_edit_properties_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/btn_edit_properties_16.png
--------------------------------------------------------------------------------
/dist/lib/css/images/btn_edit_text_by_touch_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/btn_edit_text_by_touch_16.png
--------------------------------------------------------------------------------
/dist/lib/css/images/btn_expand_span_by_touch_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/btn_expand_span_by_touch_16.png
--------------------------------------------------------------------------------
/dist/lib/css/images/btn_help_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/btn_help_16.png
--------------------------------------------------------------------------------
/dist/lib/css/images/btn_import_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/btn_import_16.png
--------------------------------------------------------------------------------
/dist/lib/css/images/btn_new_entity_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/btn_new_entity_16.png
--------------------------------------------------------------------------------
/dist/lib/css/images/btn_pallet_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/btn_pallet_16.png
--------------------------------------------------------------------------------
/dist/lib/css/images/btn_pallet_modified_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/btn_pallet_modified_16.png
--------------------------------------------------------------------------------
/dist/lib/css/images/btn_paste_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/btn_paste_16.png
--------------------------------------------------------------------------------
/dist/lib/css/images/btn_redo_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/btn_redo_16.png
--------------------------------------------------------------------------------
/dist/lib/css/images/btn_relation_edit_mode_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/btn_relation_edit_mode_16.png
--------------------------------------------------------------------------------
/dist/lib/css/images/btn_replicate_span_annotation_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/btn_replicate_span_annotation_16.png
--------------------------------------------------------------------------------
/dist/lib/css/images/btn_setting_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/btn_setting_16.png
--------------------------------------------------------------------------------
/dist/lib/css/images/btn_shrink_span_by_touch_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/btn_shrink_span_by_touch_16.png
--------------------------------------------------------------------------------
/dist/lib/css/images/btn_simple_view_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/btn_simple_view_16.png
--------------------------------------------------------------------------------
/dist/lib/css/images/btn_term_edit_mode_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/btn_term_edit_mode_16.png
--------------------------------------------------------------------------------
/dist/lib/css/images/btn_text_edit_mode_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/btn_text_edit_mode_16.png
--------------------------------------------------------------------------------
/dist/lib/css/images/btn_undo_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/btn_undo_16.png
--------------------------------------------------------------------------------
/dist/lib/css/images/btn_upload_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/btn_upload_16.png
--------------------------------------------------------------------------------
/dist/lib/css/images/btn_upload_automatically_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/btn_upload_automatically_16.png
--------------------------------------------------------------------------------
/dist/lib/css/images/btn_upload_modified_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/btn_upload_modified_16.png
--------------------------------------------------------------------------------
/dist/lib/css/images/btn_view_mode_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/btn_view_mode_16.png
--------------------------------------------------------------------------------
/dist/lib/css/images/keyhelp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/keyhelp.png
--------------------------------------------------------------------------------
/dist/lib/css/images/link.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/link.png
--------------------------------------------------------------------------------
/dist/lib/css/images/ui-bg_diagonals-thick_18_b81900_40x40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/ui-bg_diagonals-thick_18_b81900_40x40.png
--------------------------------------------------------------------------------
/dist/lib/css/images/ui-bg_diagonals-thick_20_666666_40x40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/ui-bg_diagonals-thick_20_666666_40x40.png
--------------------------------------------------------------------------------
/dist/lib/css/images/ui-bg_glass_100_f6f6f6_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/ui-bg_glass_100_f6f6f6_1x400.png
--------------------------------------------------------------------------------
/dist/lib/css/images/ui-bg_glass_100_fdf5ce_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/ui-bg_glass_100_fdf5ce_1x400.png
--------------------------------------------------------------------------------
/dist/lib/css/images/ui-bg_glass_65_ffffff_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/ui-bg_glass_65_ffffff_1x400.png
--------------------------------------------------------------------------------
/dist/lib/css/images/ui-bg_gloss-wave_35_f6a828_500x100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/ui-bg_gloss-wave_35_f6a828_500x100.png
--------------------------------------------------------------------------------
/dist/lib/css/images/ui-bg_highlight-soft_100_eeeeee_1x100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/ui-bg_highlight-soft_100_eeeeee_1x100.png
--------------------------------------------------------------------------------
/dist/lib/css/images/ui-bg_highlight-soft_75_ffe45c_1x100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/ui-bg_highlight-soft_75_ffe45c_1x100.png
--------------------------------------------------------------------------------
/dist/lib/css/images/ui-icons_222222_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/ui-icons_222222_256x240.png
--------------------------------------------------------------------------------
/dist/lib/css/images/ui-icons_228ef1_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/ui-icons_228ef1_256x240.png
--------------------------------------------------------------------------------
/dist/lib/css/images/ui-icons_ef8c08_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/ui-icons_ef8c08_256x240.png
--------------------------------------------------------------------------------
/dist/lib/css/images/ui-icons_ffd27a_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/ui-icons_ffd27a_256x240.png
--------------------------------------------------------------------------------
/dist/lib/css/images/ui-icons_ffffff_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/css/images/ui-icons_ffffff_256x240.png
--------------------------------------------------------------------------------
/dist/lib/fonts/FontAwesome.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/fonts/FontAwesome.otf
--------------------------------------------------------------------------------
/dist/lib/fonts/fontawesome-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/fonts/fontawesome-webfont.eot
--------------------------------------------------------------------------------
/dist/lib/fonts/fontawesome-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/fonts/fontawesome-webfont.ttf
--------------------------------------------------------------------------------
/dist/lib/fonts/fontawesome-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/fonts/fontawesome-webfont.woff
--------------------------------------------------------------------------------
/dist/lib/fonts/fontawesome-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/dist/lib/fonts/fontawesome-webfont.woff2
--------------------------------------------------------------------------------
/src/demo/bionlp-st-ge/demo-cdn.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/demo/bionlp-st-ge/demo-empty.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/demo/bionlp-st-ge/demo-local.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import textae from './lib/textae'
2 | import packageJson from '../package.json'
3 |
4 | document.addEventListener('DOMContentLoaded', textae)
5 |
6 | // This function is experimental.
7 | // It is being released to verify its feasibility for integration into React.
8 | window.initializeTextAEEditor = textae
9 |
10 | console.log(`TextAE Version ${packageJson.version} loaded.`)
11 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/AnnotationEvaluator/getAllSpansIn.js:
--------------------------------------------------------------------------------
1 | export default function (track) {
2 | const { typesettings, denotations, blocks } = track
3 | return (typesettings || []).concat(denotations || []).concat(blocks || [])
4 | }
5 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/AnnotationEvaluator/getAllSpansOf.js:
--------------------------------------------------------------------------------
1 | // The boundaries of elements in the typesetings and
2 | // the denotations and blocks cannot cross each other.
3 |
4 | import getAllSpansIn from './getAllSpansIn'
5 |
6 | // The same is true when across the tracks.
7 | export default function (rowData) {
8 | let spans = getAllSpansIn(rowData)
9 |
10 | if (rowData.tracks) {
11 | for (const track of rowData.tracks) {
12 | spans = spans.concat(getAllSpansIn(track))
13 | }
14 | }
15 |
16 | return spans
17 | }
18 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/AnnotationEvaluator/validateAnnotation/ChainValidation/setSourceProperty.js:
--------------------------------------------------------------------------------
1 | export default function (n, name) {
2 | n.sourceProperty = name
3 | return n
4 | }
5 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/AnnotationEvaluator/validateAnnotation/debugLogCrossing.js:
--------------------------------------------------------------------------------
1 | export default function (name, errors) {
2 | for (const [key, values] of errors.getInhibitors('isNotCrossing')) {
3 | console.warn(
4 | `Crossing ${name}: [${key.span.begin}:${key.span.end}](${
5 | key.id
6 | }) crosses with ${values
7 | .map(({ id, span }) => `[${span.begin}:${span.end}](${id})`)
8 | .join(', ')}`
9 | )
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/AnnotationEvaluator/validateAnnotation/getSpanValidation/isBeginAndEndIn/index.js:
--------------------------------------------------------------------------------
1 | import isInText from './isInText'
2 |
3 | export default function (text, span) {
4 | return isInText(span.begin, text) && isInText(span.end, text)
5 | }
6 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/AnnotationEvaluator/validateAnnotation/getSpanValidation/isBeginAndEndIn/isInText.js:
--------------------------------------------------------------------------------
1 | export default function (boundary, text) {
2 | return 0 <= boundary && boundary <= text.length
3 | }
4 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/AnnotationEvaluator/validateAnnotation/isContains.js:
--------------------------------------------------------------------------------
1 | export default function (dictionary, referedEntityId) {
2 | return dictionary.some((entry) => entry.id === referedEntityId)
3 | }
4 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/AnnotationEvaluator/validateAnnotation/isIDUnique.js:
--------------------------------------------------------------------------------
1 | export default function (spans, node) {
2 | // Span without ID is acceptable.
3 | return (
4 | node.id === undefined ||
5 | spans.filter((d) => node.id && node.id === d.id).length === 1
6 | )
7 | }
8 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/AnnotationEvaluator/validateAnnotation/validateAttribute/index.js:
--------------------------------------------------------------------------------
1 | import isContains from '../isContains'
2 | import ChainValidation from '../ChainValidation'
3 | import isUniqueIn from './isUniqueIn'
4 |
5 | export default function (subjects, attributes) {
6 | return new ChainValidation(attributes)
7 | .and('subject', (a) => isContains(subjects, a.subj))
8 | .and('unique', (node) => isUniqueIn(attributes, node))
9 | .validateAll()
10 | }
11 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/AnnotationEvaluator/validateAnnotation/validateAttribute/isUniqueIn.js:
--------------------------------------------------------------------------------
1 | export default function (attributes, node) {
2 | return (
3 | attributes.filter(
4 | (a) => a.subj === node.subj && a.pred === node.pred && a.obj === node.obj
5 | ).length === 1
6 | )
7 | }
8 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/AnnotationEvaluator/validateAnnotation/validateDenotation.js:
--------------------------------------------------------------------------------
1 | import getSpanValidation from './getSpanValidation'
2 | import isIDUnique from './isIDUnique'
3 |
4 | export default function (text, denotations, spanOfAllTracks, spansInTrack) {
5 | return getSpanValidation(denotations, text, spanOfAllTracks, 'denotations')
6 | .and('uniqueID', (n) => isIDUnique(spansInTrack, n))
7 | .validateAll()
8 | }
9 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/AnnotationEvaluator/validateAnnotation/validateRelation.js:
--------------------------------------------------------------------------------
1 | import isContains from './isContains'
2 | import ChainValidation from './ChainValidation'
3 |
4 | export default function (denotations, relations) {
5 | return new ChainValidation(relations)
6 | .and('object', (r) => isContains(denotations, r.obj))
7 | .and('subject', (r) => isContains(denotations, r.subj))
8 | .validateAll()
9 | }
10 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/AnnotationEvaluator/validateAnnotation/validateTypeSettings.js:
--------------------------------------------------------------------------------
1 | import getSpanValidation from './getSpanValidation'
2 |
3 | export default function (text, targetSpans, allSpans) {
4 | return getSpanValidation(
5 | targetSpans,
6 | text,
7 | allSpans,
8 | 'typesettings'
9 | ).validateAll()
10 | }
11 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/DefinitionContainer/DefinedTypeContainer/getForwardMatchID/getForwardMatchTypes.js:
--------------------------------------------------------------------------------
1 | export default function getForwardMatchTypes(typeIds, id) {
2 | const forwardMatchTypes = []
3 |
4 | for (const definedType of typeIds) {
5 | if (
6 | definedType.indexOf('*') !== -1 &&
7 | id.indexOf(definedType.slice(0, -1)) === 0
8 | ) {
9 | forwardMatchTypes.push(definedType)
10 | }
11 | }
12 |
13 | return forwardMatchTypes
14 | }
15 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/DefinitionContainer/DefinedTypeContainer/getForwardMatchID/getLongestIdMatchType.js:
--------------------------------------------------------------------------------
1 | export default function getLongestIdMatchType(typeIds) {
2 | let longestMatchId = ''
3 |
4 | for (const id of typeIds) {
5 | if (id.length > longestMatchId.length) {
6 | longestMatchId = id
7 | }
8 | }
9 |
10 | return longestMatchId
11 | }
12 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/DefinitionContainer/DefinedTypeContainer/getForwardMatchID/index.js:
--------------------------------------------------------------------------------
1 | import getForwardMatchTypes from './getForwardMatchTypes'
2 | import getLongestIdMatchType from './getLongestIdMatchType'
3 |
4 | export default function getForwardMatchID(typeIds, id) {
5 | // '*' at the last char of id means wildcard.
6 | const forwardMatchTypes = getForwardMatchTypes(typeIds, id)
7 |
8 | if (forwardMatchTypes.length === 0) {
9 | return null
10 | }
11 |
12 | // If some wildcard-id are matched, return the id of the most longest matched.
13 | return getLongestIdMatchType(forwardMatchTypes)
14 | }
15 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/DefinitionContainer/countUsage.js:
--------------------------------------------------------------------------------
1 | export default function countUsage(map, instances) {
2 | for (const [key, value] of map.entries()) {
3 | map.set(key, { ...value, usage: 0 })
4 | }
5 |
6 | return instances.reduce((countMap, { typeName }) => {
7 | countMap.get(typeName).usage += 1
8 |
9 | return countMap
10 | }, map)
11 | }
12 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/DefinitionContainer/formatForPallet/createTypesWithoutInstance.js:
--------------------------------------------------------------------------------
1 | export default function (defindTypeNames, countMap) {
2 | const typesWithoutInstance = []
3 | for (const type of defindTypeNames) {
4 | if (!countMap.has(type)) {
5 | typesWithoutInstance.push(type)
6 | }
7 | }
8 |
9 | // Sort by name
10 | typesWithoutInstance.sort((a, b) => {
11 | return a > b ? 1 : a < b ? -1 : 0
12 | })
13 |
14 | return typesWithoutInstance
15 | }
16 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/DefinitionContainer/formatForPallet/index.js:
--------------------------------------------------------------------------------
1 | import getUrlMatches from '../../../getUrlMatches'
2 |
3 | export default function formatForPallet(
4 | types,
5 | countMap,
6 | definedTypes,
7 | defaultType,
8 | defaultColor
9 | ) {
10 | return types.map((id) => ({
11 | id,
12 | label: definedTypes.getLabelOf(id) || undefined,
13 | defaultType: id === defaultType,
14 | uri: getUrlMatches(id) ? id : undefined,
15 | color: definedTypes.getColorOf(id) || defaultColor,
16 | useNumber: countMap.get(id).usage
17 | }))
18 | }
19 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/DefinitionContainer/sortByCountAndName.js:
--------------------------------------------------------------------------------
1 | export default function (countTypeUse) {
2 | // Sort by number of types, and by name if numbers are same.
3 | const typeNames = Array.from(countTypeUse.keys())
4 |
5 | typeNames.sort((a, b) => {
6 | const diff = countTypeUse.get(b).usage - countTypeUse.get(a).usage
7 | return diff !== 0 ? diff : a > b ? 1 : a < b ? -1 : 0
8 | })
9 |
10 | return typeNames
11 | }
12 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/InstanceContainer/isFunction.js:
--------------------------------------------------------------------------------
1 | // see: https://stackoverflow.com/questions/5999998/check-if-a-variable-is-of-function-type
2 | export default function isFunction(functionToCheck) {
3 | return (
4 | functionToCheck && {}.toString.call(functionToCheck) === '[object Function]'
5 | )
6 | }
7 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/RelationInstanceContainer/RelationInstance/Arrow/CurveAlgorithmFactory/ArchedCurveAlgorithm.js:
--------------------------------------------------------------------------------
1 | import CurveAlgorithm from './CurveAlgorithm'
2 |
3 | export default class ArchedCurveAlgorithm extends CurveAlgorithm {
4 | get isSourceJettyVisible() {
5 | return true
6 | }
7 |
8 | get isTargetJettyVisible() {
9 | return true
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/RelationInstanceContainer/RelationInstance/Arrow/MarkerHeight.js:
--------------------------------------------------------------------------------
1 | export const MarkerHeight = 6
2 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/RelationInstanceContainer/RelationInstance/Arrow/createJetty.js:
--------------------------------------------------------------------------------
1 | import { NS } from '../NS'
2 | import moveJetty from './moveJetty'
3 |
4 | export default function (x, y, entity) {
5 | const jetty = document.createElementNS(NS.SVG, 'polyline')
6 |
7 | moveJetty(jetty, x, y, entity)
8 |
9 | return jetty
10 | }
11 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/RelationInstanceContainer/RelationInstance/Arrow/createPath.js:
--------------------------------------------------------------------------------
1 | import { NS } from '../NS'
2 |
3 | /**
4 | *
5 | * @returns {SVGGraphicsElement} path
6 | */
7 | export default function () {
8 | const path = document.createElementNS(NS.SVG, 'path')
9 | path.classList.add('textae-editor__relation')
10 | return path
11 | }
12 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/RelationInstanceContainer/RelationInstance/Arrow/createSourceBollard.js:
--------------------------------------------------------------------------------
1 | import { NS } from '../NS'
2 | import { MarkerHeight } from './MarkerHeight'
3 |
4 | export default function () {
5 | const bollard = document.createElementNS(NS.SVG, 'polygon')
6 | bollard.setAttribute('points', `-4 ${MarkerHeight}, 4 ${MarkerHeight}, 0 0`)
7 |
8 | return bollard
9 | }
10 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/RelationInstanceContainer/RelationInstance/Arrow/createTargetBollard.js:
--------------------------------------------------------------------------------
1 | import { NS } from '../NS'
2 | import { MarkerHeight } from './MarkerHeight'
3 |
4 | export default function () {
5 | const bollard = document.createElementNS(NS.SVG, 'polygon')
6 | bollard.setAttribute('points', `-4 0, 4 0, 0 ${MarkerHeight}`)
7 |
8 | return bollard
9 | }
10 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/RelationInstanceContainer/RelationInstance/Arrow/moveJetty.js:
--------------------------------------------------------------------------------
1 | import { MarkerHeight } from './MarkerHeight'
2 |
3 | /**
4 | *
5 | * @param {Element} jetty
6 | * @param {number} x
7 | * @param {number} y
8 | * @param {import('../../../../../EntityInstance').default} entity
9 | */
10 | export default function (jetty, x, y, entity) {
11 | jetty.setAttribute(
12 | 'points',
13 | `${x} ${y + MarkerHeight}, ${entity.offsetCenter} ${y + MarkerHeight}, ${
14 | entity.offsetCenter
15 | } ${entity.offsetTop}`
16 | )
17 | }
18 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/RelationInstanceContainer/RelationInstance/Arrow/updatePath.js:
--------------------------------------------------------------------------------
1 | export default function (path, curveAlgorithm, color, isBold) {
2 | path.setAttribute('d', curveAlgorithm.pathCommands)
3 |
4 | path.setAttribute('style', `stroke: ${color};`)
5 |
6 | if (isBold) {
7 | path.classList.add('textae-editor__relation--isBold')
8 | } else {
9 | path.classList.remove('textae-editor__relation--isBold')
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/RelationInstanceContainer/RelationInstance/NS.js:
--------------------------------------------------------------------------------
1 | export const NS = {
2 | SVG: 'http://www.w3.org/2000/svg'
3 | }
4 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/RelationInstanceContainer/RelationInstance/toDisplayName/getDisplayNameTag.js:
--------------------------------------------------------------------------------
1 | import getDisplayName from '../../../../getDisplayName'
2 | import getURI from '../../../../getURI'
3 | import anemone from '../../../../../component/anemone'
4 |
5 | export default function (namespace, definitionContainer, value) {
6 | const displayName = getDisplayName(
7 | namespace,
8 | value,
9 | definitionContainer.getLabel(value)
10 | )
11 | const href = getURI(namespace, value, definitionContainer.getURI(value))
12 | return href
13 | ? anemone`${displayName}`
14 | : anemone`${displayName}`
15 | }
16 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/RelationInstanceContainer/RelationInstance/toDisplayName/index.js:
--------------------------------------------------------------------------------
1 | import getDisplayNameTag from './getDisplayNameTag'
2 |
3 | export default function toDisplayName(
4 | relation,
5 | namespace,
6 | definitionContainer
7 | ) {
8 | return `[${relation.id}] ${getDisplayNameTag(
9 | namespace,
10 | definitionContainer,
11 | relation.typeName
12 | )}`
13 | }
14 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/SpanInstanceContainer/BlockSpanInstance/renderBackground.js:
--------------------------------------------------------------------------------
1 | import dohtml from 'dohtml'
2 |
3 | export default function (parentElement, id) {
4 | const div = dohtml.create(`
5 |
6 | `)
7 |
8 | // Always add to the top of the annotation box to place it behind the grid.
9 | parentElement.insertAdjacentElement('afterbegin', div)
10 | }
11 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/SpanInstanceContainer/BlockSpanInstance/setPosition.js:
--------------------------------------------------------------------------------
1 | export default function (element, top, left, width, height) {
2 | element.style.top = `${top}px`
3 | element.style.left = `${left}px`
4 | element.style.width = `${width}px`
5 | element.style.height = `${height}px`
6 | }
7 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/SpanInstanceContainer/SELECTED.js:
--------------------------------------------------------------------------------
1 | const SELECTED = 'ui-selected'
2 | export default SELECTED
3 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/SpanInstanceContainer/SpanInstance/createGridHtml.js:
--------------------------------------------------------------------------------
1 | export default function (spanId, top, left, width) {
2 | return `
3 |
7 |
8 | `
9 | }
10 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/SpanInstanceContainer/SpanInstance/getRightGrid.js:
--------------------------------------------------------------------------------
1 | import getRightSpanElement from '../../../getRightSpanElement'
2 |
3 | export default function (editorHTMLElement, spanId) {
4 | const rightSpan = getRightSpanElement(editorHTMLElement, spanId)
5 |
6 | if (rightSpan) {
7 | return document.querySelector(`#G${rightSpan.id}`)
8 | }
9 |
10 | return null
11 | }
12 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/SpanInstanceContainer/SpanInstance/updateGridPosition/index.js:
--------------------------------------------------------------------------------
1 | import isStaying from './isStaying'
2 |
3 | export default function (gridElement, top, left) {
4 | if (!isStaying(gridElement, top, left)) {
5 | gridElement.style.top = `${top}px`
6 | gridElement.style.left = `${left}px`
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/SpanInstanceContainer/SpanInstance/updateGridPosition/isStaying.js:
--------------------------------------------------------------------------------
1 | export default function (gridElement, top, left) {
2 | if (
3 | gridElement.style &&
4 | parseFloat(gridElement.style.top) === top &&
5 | parseFloat(gridElement.style.left) === left
6 | ) {
7 | return true
8 | }
9 | return false
10 | }
11 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/SpanInstanceContainer/TextSelection/getOffsetFromParent.js:
--------------------------------------------------------------------------------
1 | export default function (node) {
2 | let offset = 0
3 |
4 | for (const prevNode of node.parentElement.childNodes) {
5 | // until the focus node
6 | if (prevNode == node) {
7 | break
8 | }
9 |
10 | if (prevNode.nodeName === '#text') {
11 | offset += prevNode.nodeValue.length
12 | } else {
13 | offset += prevNode.textContent.length
14 | }
15 | }
16 |
17 | return offset
18 | }
19 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/SpanInstanceContainer/createRangeToSpan/createRange.js:
--------------------------------------------------------------------------------
1 | export default function (textNode, start, end) {
2 | const range = document.createRange()
3 |
4 | range.setStart(textNode, start)
5 | range.setEnd(textNode, end)
6 |
7 | return range
8 | }
9 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/SpanInstanceContainer/createRangeToSpan/getRenderingPosition/getOffset.js:
--------------------------------------------------------------------------------
1 | export default function (span, startOfTextNode) {
2 | const start = span.begin - startOfTextNode
3 | const end = span.end - startOfTextNode
4 |
5 | return {
6 | start,
7 | end
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/SpanInstanceContainer/createRangeToSpan/getRenderingPosition/getRenderingPositionFromParent.js:
--------------------------------------------------------------------------------
1 | import getOffset from './getOffset'
2 |
3 | export default function (span) {
4 | const { start, end } = getOffset(span, span.parent.begin)
5 |
6 | return {
7 | textNode: span.parent.element.firstChild,
8 | start,
9 | end
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/SpanInstanceContainer/getCurrentMaxHeight.js:
--------------------------------------------------------------------------------
1 | export default function (spans) {
2 | const maxHeight = Math.max(
3 | ...spans.map((span) => span.heightIncludeDescendantGrids)
4 | )
5 | return maxHeight
6 | }
7 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/SpanInstanceContainer/spanComparator.js:
--------------------------------------------------------------------------------
1 | export default function (a, b) {
2 | return a.begin - b.begin || b.end - a.end
3 | }
4 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/SpanInstanceContainer/updateSpanTree/getParent/index.js:
--------------------------------------------------------------------------------
1 | import isChildOf from './isChildOf'
2 |
3 | export default function getParet(span, parent) {
4 | if (isChildOf(span, parent)) {
5 | return parent
6 | } else if (parent.parent) {
7 | return getParet(span, parent.parent)
8 | } else {
9 | return null
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/SpanInstanceContainer/updateSpanTree/getParent/isChildOf.js:
--------------------------------------------------------------------------------
1 | export default function (span, maybeParent) {
2 | if (!maybeParent) {
3 | return false
4 | }
5 |
6 | return maybeParent.begin <= span.begin && span.end <= maybeParent.end
7 | }
8 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/createTextBox/TextBox/getLineHeight.js:
--------------------------------------------------------------------------------
1 | import pixelToInt from './pixelToInt'
2 |
3 | export default function (textBox) {
4 | const style = window.getComputedStyle(textBox)
5 | return pixelToInt(style.lineHeight)
6 | }
7 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/createTextBox/TextBox/pixelToInt.js:
--------------------------------------------------------------------------------
1 | export default function (str) {
2 | // The default value of google chrome line-height is "normal".
3 | // "normal" cannot be converted to an integer.
4 | const i = parseInt(str, 10)
5 | return isNaN(i) ? 0 : i
6 | }
7 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/createTextBox/TextBox/setLineHeight.js:
--------------------------------------------------------------------------------
1 | export default function (textBox, heightValue, additionalPaddingTop) {
2 | textBox.style.lineHeight = `${heightValue}px`
3 | textBox.style.paddingTop = `${heightValue / 2 + additionalPaddingTop}px`
4 | }
5 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/createTextBox/TextBox/updateTextBoxHeight.js:
--------------------------------------------------------------------------------
1 | import pixelToInt from './pixelToInt'
2 |
3 | // Reduce the space under the .textae-editor__text-box same as padding-top.
4 | export default function (textBox, additionalPaddingTop) {
5 | const style = window.getComputedStyle(textBox)
6 |
7 | // The height calculated by auto is exclude the value of the padding top.
8 | // Rest small space.
9 | textBox.style.height = 'auto'
10 | textBox.style.height = `${
11 | textBox.offsetHeight -
12 | pixelToInt(style.paddingTop) +
13 | 20 +
14 | additionalPaddingTop
15 | }px`
16 | }
17 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/getAnnotationBox.js:
--------------------------------------------------------------------------------
1 | // Get the display area for denotations and relations.
2 | export default function (editorHTMLElement) {
3 | return editorHTMLElement.querySelector('.textae-editor__annotation-box')
4 | }
5 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/getBoundaryCrossingSpans.js:
--------------------------------------------------------------------------------
1 | import isBoundaryCrossing from '../isBoundaryCrossing'
2 |
3 | export default function (spans, begin, end) {
4 | return spans.filter(({ span }) => isBoundaryCrossing(begin, end, span))
5 | }
6 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/getReplicationRanges/getDuplicateSentenceFromText.js:
--------------------------------------------------------------------------------
1 | export default function (text, beginOfSentence, endOfSentence) {
2 | const searchSentence = text.substring(beginOfSentence, endOfSentence)
3 | const sentenceLength = endOfSentence - beginOfSentence
4 | const findRanges = []
5 |
6 | let end = 0
7 |
8 | for (
9 | let begin = text.indexOf(searchSentence);
10 | begin !== -1;
11 | begin = text.indexOf(searchSentence, end)
12 | ) {
13 | end = begin + sentenceLength
14 |
15 | findRanges.push({
16 | begin,
17 | end
18 | })
19 | }
20 |
21 | return findRanges
22 | }
23 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/getReplicationRanges/isWord.js:
--------------------------------------------------------------------------------
1 | // The preceding character and the following of a word character are delimiter.
2 | // For example, 't' ,a part of 'that', is not same with an origin span when it is 't'.
3 | export default function (sourceDoc, begin, end, isDelimiterFunc) {
4 | const precedingChar = sourceDoc.charAt(begin - 1)
5 | const followingChar = sourceDoc.charAt(end)
6 |
7 | return isDelimiterFunc(precedingChar) && isDelimiterFunc(followingChar)
8 | }
9 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/isBoundaryCrossingWithOtherSpans.js:
--------------------------------------------------------------------------------
1 | import getBoundaryCrossingSpans from './getBoundaryCrossingSpans'
2 |
3 | // A span its range is coross over with other spans are not able to rendered.
4 | // Because spans are renderd with span tag. Html tags can not be cross over.
5 | export default function (spans, begin, end) {
6 | console.assert(end !== undefined, 'end is necessary.')
7 |
8 | return (
9 | getBoundaryCrossingSpans(
10 | spans.map((span) => ({ span })),
11 | begin,
12 | end
13 | ).length > 0
14 | )
15 | }
16 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/toBlocks.js:
--------------------------------------------------------------------------------
1 | export default function (annotationModel) {
2 | return annotationModel.entityInstanceContainer.blocks.map((entity) => ({
3 | id: entity.id,
4 | span: {
5 | begin: entity.span.begin,
6 | end: entity.span.end
7 | },
8 | obj: entity.typeName
9 | }))
10 | }
11 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/toDenotations.js:
--------------------------------------------------------------------------------
1 | export default function (annotationModel) {
2 | return annotationModel.entityInstanceContainer.denotations.map((entity) => ({
3 | id: entity.id,
4 | span: {
5 | begin: entity.span.begin,
6 | end: entity.span.end
7 | },
8 | obj: entity.typeName
9 | }))
10 | }
11 |
--------------------------------------------------------------------------------
/src/lib/Editor/AnnotationModel/toRelations.js:
--------------------------------------------------------------------------------
1 | export default function (annotationModel) {
2 | return annotationModel.relationInstanceContainer.all.map((r) => {
3 | return {
4 | id: r.id,
5 | pred: r.typeName,
6 | subj: r.subj,
7 | obj: r.obj
8 | }
9 | })
10 | }
11 |
--------------------------------------------------------------------------------
/src/lib/Editor/BrowserEventListener.js:
--------------------------------------------------------------------------------
1 | export default class BrowserEventListener {
2 | #target
3 | #event
4 | #listener
5 |
6 | constructor(target, event, listener) {
7 | this.#target = target
8 | this.#event = event
9 | this.#listener = listener
10 |
11 | this.#bind()
12 | }
13 |
14 | dispose() {
15 | this.#target.removeEventListener(this.#event, this.#listener)
16 | }
17 |
18 | #bind() {
19 | this.#target.addEventListener(this.#event, this.#listener)
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/lib/Editor/EditorCSSClass.js:
--------------------------------------------------------------------------------
1 | export default class EditorCSSClass {
2 | constructor(editorHTMLElement) {
3 | this._editorHTMLElement = editorHTMLElement
4 | }
5 | startWait() {
6 | this._editorHTMLElement.classList.add('textae-editor--wait')
7 | }
8 | endWait() {
9 | this._editorHTMLElement.classList.remove('textae-editor--wait')
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/lib/Editor/EditorEventListener.js:
--------------------------------------------------------------------------------
1 | export default class EditorEventListener {
2 | #eventEmitter
3 | #event
4 | #listener
5 |
6 | constructor(eventEmitter, event, listener) {
7 | this.#eventEmitter = eventEmitter
8 | this.#event = event
9 | this.#listener = listener
10 |
11 | eventEmitter.on(event, this.#listener)
12 | }
13 |
14 | dispose() {
15 | this.#eventEmitter.off(this.#event, this.#listener)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/lib/Editor/RESOURCE_TYPE.js:
--------------------------------------------------------------------------------
1 | export const RESOURCE_TYPE = Object.freeze({
2 | QUERY_PARAMETER: 'parameter', // The annotation data is passed as a query parameter.
3 | INLINE: 'inline', // The annotation data is written in the HTML.
4 | REMOTE_URL: 'remote', // The annotation data is set by remote URL.
5 | INSTANT: 'instant', // The annotation data is set by the data load dialog as json string.
6 | LOCAL_FILE: 'local file', // The annotation data is set by the data load dialog as a local file.
7 | UNKNOWN: 'unknown'
8 | })
9 |
--------------------------------------------------------------------------------
/src/lib/Editor/RemoteResource/AnnotationLoader/parseResponse/index.js:
--------------------------------------------------------------------------------
1 | import { isJsonResponse, isTxtResponse } from './responseTypes'
2 | import SimpleInlineTextAnnotation from '@pubann/simple-inline-text-annotation'
3 |
4 | export default async function parseResponse(response, url) {
5 | if (isJsonResponse(response, url)) {
6 | return await response.json()
7 | } else if (isTxtResponse(response, url)) {
8 | const inline_annotation = await response.text()
9 | return SimpleInlineTextAnnotation.parse(inline_annotation)
10 | } else {
11 | throw new Error('The content type of the loaded content is not supported.')
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/lib/Editor/RemoteResource/AnnotationSaver/prepareRequestBody.js:
--------------------------------------------------------------------------------
1 | import SimpleInlineTextAnnotation from '@pubann/simple-inline-text-annotation'
2 |
3 | export default function prepareRequestBody(editedData, format) {
4 | if (format === 'json') {
5 | return JSON.stringify(editedData)
6 | } else if (format === 'inline') {
7 | return SimpleInlineTextAnnotation.generate(editedData)
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/lib/Editor/RemoteResource/AnnotationSaver/waitForPopUpClose.js:
--------------------------------------------------------------------------------
1 | // Watching for cross-domain pop-up windows to close.
2 | // https://stackoverflow.com/questions/9388380/capture-the-close-event-of-popup-window-in-javascript/48240128#48240128
3 |
4 | export default async function waitForPopUpClose(window) {
5 | return new Promise((resolve) => {
6 | const timer = setInterval(() => {
7 | if (window.closed) {
8 | clearInterval(timer)
9 | resolve()
10 | }
11 | }, 1000)
12 | })
13 | }
14 |
--------------------------------------------------------------------------------
/src/lib/Editor/RemoteResource/openPopUp.js:
--------------------------------------------------------------------------------
1 | export default function (url) {
2 | const width = 600
3 | const height = 500
4 |
5 | return window.open(url, '_blank', `width=${width}, height=${height}`)
6 | }
7 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/Commander/Factory/AnnotationCommand.js:
--------------------------------------------------------------------------------
1 | import BaseCommand from './BaseCommand'
2 |
3 | export default class AnnotationCommand extends BaseCommand {
4 | get kind() {
5 | return new Set(['annotation_command'])
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/Commander/Factory/BaseCommand.js:
--------------------------------------------------------------------------------
1 | export default class BaseCommand {
2 | get isEmpty() {
3 | return false
4 | }
5 |
6 | isExactly(kind) {
7 | return this.kind.has(kind) && this.kind.size === 1
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/Commander/Factory/ChangeTextAndMoveSpanCommand.js:
--------------------------------------------------------------------------------
1 | import ChangeTextCommand from './ChangeTextCommand'
2 | import CompositeCommand from './CompositeCommand'
3 |
4 | export default class ChangeTextAndMoveSpanCommand extends CompositeCommand {
5 | constructor(annotationModel, begin, end, newText) {
6 | super()
7 |
8 | this._isExecuteSubCommandsInReverseOrderWhenRevert = false
9 |
10 | this._subCommands = [
11 | new ChangeTextCommand(annotationModel, { begin, end }, newText)
12 | ]
13 |
14 | this._logMessage = `change text from ${begin} to ${end} to ${newText}`
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/Commander/Factory/ConfigurationCommand.js:
--------------------------------------------------------------------------------
1 | import BaseCommand from './BaseCommand'
2 |
3 | export default class ConfigurationCommand extends BaseCommand {
4 | get kind() {
5 | return new Set(['configuration_command'])
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/Commander/Factory/CreateEntityAndAttributesCommand/CreateAttributeToTheLatestEntityCommand.js:
--------------------------------------------------------------------------------
1 | import { CreateCommand } from '../commandTemplate'
2 |
3 | export default class CreateAttributeToTheLatestEntityCommand extends CreateCommand {
4 | constructor(annotationModel, obj, pred) {
5 | super(annotationModel, 'attribute', {
6 | obj,
7 | pred
8 | })
9 | }
10 |
11 | execute() {
12 | const subj = this._annotationModel.entityInstanceContainer.all.pop().id
13 | this._instance.subj = subj
14 | return super.execute()
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/Commander/Factory/MoveEntitiesToSelectedDenotationSpanCommand/areAllEntitiesOfSpan.js:
--------------------------------------------------------------------------------
1 | export default function (span, entities) {
2 | return span.entities.every((entity) => entities.includes(entity))
3 | }
4 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/Commander/Factory/aggregateTargetEntities.js:
--------------------------------------------------------------------------------
1 | import aggregateTargetRelations from './aggregateTargetRelations'
2 |
3 | export default function (
4 | targetEntities,
5 | targetRelations,
6 | targetAttributes,
7 | entity
8 | ) {
9 | targetEntities.add(entity)
10 | for (const attribute of entity.attributes) {
11 | targetAttributes.add(attribute)
12 | }
13 | for (const relation of entity.relations) {
14 | aggregateTargetRelations(targetRelations, targetAttributes, relation)
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/Commander/Factory/aggregateTargetRelations.js:
--------------------------------------------------------------------------------
1 | export default function (targetRelations, targetAttributes, relation) {
2 | targetRelations.add(relation)
3 | for (const attribute of relation.attributes) {
4 | targetAttributes.add(attribute)
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/Commander/Factory/commandLog.js:
--------------------------------------------------------------------------------
1 | export default function (self, message, object) {
2 | // For debug
3 | if (object) {
4 | console.log(`[${self.constructor.name}]`, message, object)
5 | } else {
6 | console.log(`[${self.constructor.name}]`, message)
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/Commander/Factory/getCreateAttributeToItemsCommands.js:
--------------------------------------------------------------------------------
1 | import { CreateCommand } from './commandTemplate'
2 |
3 | export default function (annotationModel, items, pred, obj) {
4 | return items
5 | .filter((i) => !i.typeValues.hasSpecificPredicateAttribute(pred))
6 | .map(({ id }) => {
7 | return new CreateCommand(annotationModel, 'attribute', {
8 | id: null,
9 | subj: id,
10 | pred,
11 | obj
12 | })
13 | })
14 | }
15 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/Commander/Factory/getRemoveAttributesByPredCommands.js:
--------------------------------------------------------------------------------
1 | import { RemoveCommand } from './commandTemplate'
2 |
3 | export default function (annotationModel, items, pred) {
4 | return items
5 | .reduce((attrs, { attributes }) => attrs.concat(attributes), [])
6 | .filter((a) => a.pred === pred)
7 | .map((a) => new RemoveCommand(annotationModel, 'attribute', a))
8 | }
9 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/MenuState/DelimiterDetectAdjuster/backToDelimiter.js:
--------------------------------------------------------------------------------
1 | import skipCharacters from '../skipCharacters'
2 | import getPrev from './getPrev'
3 |
4 | export default function (str, position, isDelimiter) {
5 | return skipCharacters(getPrev, -1, str, position, (chars) => {
6 | // Proceed the position between two characters as (!delimiter delimiter) || (delimiter !delimiter) || (!delimiter !delimiter).
7 | return chars[1] && !isDelimiter(chars[0]) && !isDelimiter(chars[1])
8 | })
9 | }
10 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/MenuState/DelimiterDetectAdjuster/backToWord.js:
--------------------------------------------------------------------------------
1 | import skipCharacters from '../skipCharacters'
2 | import getNext from './getNext'
3 |
4 | export default function (str, position, isWordEdge) {
5 | return skipCharacters(getNext, -1, str, position, isWordEdge)
6 | }
7 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/MenuState/DelimiterDetectAdjuster/getNext.js:
--------------------------------------------------------------------------------
1 | export default function (str, position) {
2 | return [str.charAt(position), str.charAt(position + 1)]
3 | }
4 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/MenuState/DelimiterDetectAdjuster/getPrev.js:
--------------------------------------------------------------------------------
1 | export default function (str, position) {
2 | return [str.charAt(position), str.charAt(position - 1)]
3 | }
4 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/MenuState/DelimiterDetectAdjuster/isNotWord.js:
--------------------------------------------------------------------------------
1 | export default function (isBlankCharacter, isDelimiter, chars) {
2 | // The word is (no charactor || blank || delimiter)(!delimiter).
3 | return (
4 | (chars[0] !== '' &&
5 | !isBlankCharacter(chars[1]) &&
6 | !isDelimiter(chars[1])) ||
7 | isDelimiter(chars[0])
8 | )
9 | }
10 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/MenuState/DelimiterDetectAdjuster/skipToDelimiter.js:
--------------------------------------------------------------------------------
1 | import skipCharacters from '../skipCharacters'
2 | import getNext from './getNext'
3 |
4 | export default function skipToDelimiter(str, position, isDelimiter) {
5 | return skipCharacters(getNext, 1, str, position, (chars) => {
6 | // Proceed the position between two characters as (!delimiter delimiter) || (delimiter !delimiter) || (!delimiter !delimiter).
7 | // Return false to stop an infinite loop when the character undefined.
8 | return chars[1] && !isDelimiter(chars[0]) && !isDelimiter(chars[1])
9 | })
10 | }
11 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/MenuState/DelimiterDetectAdjuster/skipToWord.js:
--------------------------------------------------------------------------------
1 | import skipCharacters from '../skipCharacters'
2 | import getPrev from './getPrev'
3 |
4 | export default function (str, position, isWordEdge) {
5 | return skipCharacters(getPrev, 1, str, position, isWordEdge)
6 | }
7 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/MenuState/TextSelectionAdjuster.js:
--------------------------------------------------------------------------------
1 | export default class TextSelectionAdjuster {
2 | backFromBegin(str, position, spanConfig) {}
3 |
4 | forwardFromEnd(str, position, spanConfig) {}
5 |
6 | forwardFromBegin(str, position, spanConfig) {}
7 |
8 | backFromEnd(str, position, spanConfig) {}
9 | }
10 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/MenuState/reduce2hash.js:
--------------------------------------------------------------------------------
1 | export default function (key = 'name') {
2 | return function (hash, element) {
3 | hash[element[key]] = element
4 | return hash
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/MenuState/skipBlank.js:
--------------------------------------------------------------------------------
1 | import skipCharacters from './skipCharacters'
2 |
3 | const getNow = function (str, position) {
4 | return str.charAt(position)
5 | }
6 | const skipForwardBlank = function (str, position, isBlankCharacter) {
7 | return skipCharacters(getNow, 1, str, position, isBlankCharacter)
8 | }
9 | const skipBackBlank = function (str, position, isBlankCharacter) {
10 | return skipCharacters(getNow, -1, str, position, isBlankCharacter)
11 | }
12 |
13 | export default {
14 | forward: skipForwardBlank,
15 | back: skipBackBlank
16 | }
17 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/MenuState/skipCharacters.js:
--------------------------------------------------------------------------------
1 | export default function (getChars, step, str, position, predicate) {
2 | while (predicate(getChars(str, position))) position += step
3 |
4 | return position
5 | }
6 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/OriginalData/StatusBar/html.js:
--------------------------------------------------------------------------------
1 | const html = `
2 |
5 | `
6 |
7 | export default html
8 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/PersistenceInterface/isTxtFile.js:
--------------------------------------------------------------------------------
1 | import path from 'path-browserify'
2 |
3 | export default function (fileName) {
4 | return path.extname(fileName) === '.txt'
5 | }
6 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/PersistenceInterface/readAnnotationFile/parseFileContent.js:
--------------------------------------------------------------------------------
1 | import SimpleInlineTextAnnotation from '@pubann/simple-inline-text-annotation'
2 |
3 | export default function parseFileContent(fileContent) {
4 | try {
5 | const annotation = SimpleInlineTextAnnotation.parse(fileContent)
6 |
7 | return annotation
8 | } catch {
9 | return null
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/PersistenceInterface/readFile.js:
--------------------------------------------------------------------------------
1 | export default async function (file) {
2 | return new Promise((resolve) => {
3 | const reader = new FileReader()
4 |
5 | reader.onload = (event) => resolve(event)
6 | reader.readAsText(file)
7 | })
8 | }
9 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/Presenter/EditModeSwitch/BlockEditMode/create.js:
--------------------------------------------------------------------------------
1 | export default function (
2 | annotationModel,
3 | commander,
4 | textSelectionAdjuster,
5 | spanConfig
6 | ) {
7 | const { begin, end } = annotationModel.getTextSelection(
8 | spanConfig,
9 | textSelectionAdjuster
10 | )
11 |
12 | if (annotationModel.validateNewBlockSpan(begin, end)) {
13 | const command = commander.factory.createBlockSpanCommand({
14 | begin,
15 | end
16 | })
17 |
18 | commander.invoke(command)
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/Presenter/EditModeSwitch/EditMode/index.js:
--------------------------------------------------------------------------------
1 | export default class EditMode {
2 | // Interface methods
3 | createSpanWithTouchDevice() {}
4 | expandSpanWithTouchDevice() {}
5 | shrinkSpanWithTouchDevice() {}
6 | editTextWithTouchDevice() {}
7 | editProperties() {}
8 | relationClicked() {}
9 | relationBollardClicked(entity) {
10 | entity.focus()
11 | }
12 | applyTextSelectionWithTouchDevice() {}
13 | manipulateAttribute() {}
14 | showPallet() {}
15 | hidePallet() {}
16 | get isPalletShown() {
17 | return false
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/Presenter/EditModeSwitch/ModeTransitionReactor/EditorCSS.js:
--------------------------------------------------------------------------------
1 | export default class EditorCSS {
2 | constructor(editorHTMLElement) {
3 | this._editorHTMLElement = editorHTMLElement
4 | }
5 |
6 | clear() {
7 | for (const cssClass of this._editorHTMLElement.classList) {
8 | if (cssClass.startsWith('textae-editor__mode')) {
9 | this._editorHTMLElement.classList.remove(cssClass)
10 | }
11 | }
12 | }
13 |
14 | setFor(mode) {
15 | this._editorHTMLElement.classList.add(`textae-editor__mode--${mode}`)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/Presenter/EditModeSwitch/PalletFactory/bindPalletEvents/checkButtonEnable.js:
--------------------------------------------------------------------------------
1 | export default function (targetNode) {
2 | return !targetNode.classList.contains(
3 | 'textae-editor__pallet__table-button--disabled'
4 | )
5 | }
6 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/Presenter/EditModeSwitch/SelectionWrapper/isNodeBlockSpan.js:
--------------------------------------------------------------------------------
1 | export default function (node) {
2 | return node.classList.contains('textae-editor__block')
3 | }
4 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/Presenter/EditModeSwitch/SelectionWrapper/isNodeDenotationSpan.js:
--------------------------------------------------------------------------------
1 | export default function (node) {
2 | return node.classList.contains('textae-editor__span')
3 | }
4 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/Presenter/EditModeSwitch/SelectionWrapper/isNodeStyleSpan.js:
--------------------------------------------------------------------------------
1 | export default function (node) {
2 | return node.classList.contains('textae-editor__style')
3 | }
4 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/Presenter/EditModeSwitch/SelectionWrapper/isNodeTextBox.js:
--------------------------------------------------------------------------------
1 | export default function (node) {
2 | return node.classList.contains('textae-editor__text-box')
3 | }
4 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/Presenter/EditModeSwitch/TermEditMode/SpanEditor/isInSelected.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/Editor/UseCase/Presenter/EditModeSwitch/TermEditMode/SpanEditor/isInSelected.js
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/Presenter/EditModeSwitch/TermEditMode/SpanEditor/isPositionBetweenSpan.js:
--------------------------------------------------------------------------------
1 | export default function (span, position) {
2 | if (!span) {
3 | return false
4 | }
5 |
6 | return span.begin < position && position < span.end
7 | }
8 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/Presenter/EditModeSwitch/clearTextSelection.js:
--------------------------------------------------------------------------------
1 | export default function () {
2 | window.getSelection().removeAllRanges()
3 | }
4 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/Presenter/EditModeSwitch/isTextSelectionInTextBox.js:
--------------------------------------------------------------------------------
1 | export default function isTextSelectionInTextBox(textBoxHTMLElement) {
2 | const selection = window.getSelection()
3 | return (
4 | selection.type === 'Range' &&
5 | textBoxHTMLElement.contains(selection.anchorNode) &&
6 | textBoxHTMLElement.contains(selection.focusNode)
7 | )
8 | }
9 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/Presenter/EditModeSwitch/selectSpan.js:
--------------------------------------------------------------------------------
1 | export default function (selectionModel, rangeOfSpans, event, spanID) {
2 | if (rangeOfSpans.length) {
3 | selectionModel.selectSpanRange(rangeOfSpans)
4 | return
5 | }
6 |
7 | if (event.ctrlKey || event.metaKey) {
8 | selectionModel.span.toggle(spanID)
9 | return
10 | }
11 |
12 | selectionModel.selectSpan(spanID)
13 | }
14 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/Presenter/getIsDelimiterFunc.js:
--------------------------------------------------------------------------------
1 | export default function (menuState, spanConfig) {
2 | if (menuState.isPushed('boundary detection')) {
3 | return (char) => spanConfig.isDelimiter(char)
4 | } else {
5 | return () => true
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/getEntityHTMLelementFromChild.js:
--------------------------------------------------------------------------------
1 | export default function (elementInEntityHtmlelement) {
2 | return elementInEntityHtmlelement.closest('.textae-editor__signboard')
3 | }
4 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/patchConfiguration/AttributeConfigurationGenerator/AnnotationsForPred/getValueType.js:
--------------------------------------------------------------------------------
1 | export default function (obj) {
2 | if (obj === true) {
3 | return 'flag'
4 | } else if (typeof obj === 'number') {
5 | return 'numeric'
6 | } else if (typeof obj === 'string') {
7 | return 'string'
8 | } else {
9 | throw `${JSON.stringify(obj)} is an unexpected value for an Attribute.`
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/patchConfiguration/AttributeConfigurationGenerator/fillDefaultValueOfSelectionAttributes/getSelectionAttributes.js:
--------------------------------------------------------------------------------
1 | export default function (config) {
2 | return config.filter((a) => a['value type'] === 'selection')
3 | }
4 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/patchConfiguration/AttributeConfigurationGenerator/fillInferDefinitionFromAnnotation/fill.js:
--------------------------------------------------------------------------------
1 | // Complement the config with the generated Attribute definition.
2 | // Does not override the existing Attribute definition.
3 | export default function (config, newAttributeDefinitions) {
4 | for (const newDef of newAttributeDefinitions) {
5 | const index = config.findIndex((a) => a.pred === newDef.pred)
6 | if (index !== -1) {
7 | config[index] = { ...newDef, ...config[index] }
8 | } else {
9 | config.push(newDef)
10 | }
11 | }
12 |
13 | return config
14 | }
15 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/patchConfiguration/AttributeConfigurationGenerator/fillInferDefinitionFromAnnotation/index.js:
--------------------------------------------------------------------------------
1 | import fill from './fill'
2 | import inferDefinitionFromAnnotation from './inferDefinitionFromAnnotation'
3 |
4 | export default function (config, annotations) {
5 | const inferDefinitions = inferDefinitionFromAnnotation(annotations)
6 | return fill(config, inferDefinitions)
7 | }
8 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/patchConfiguration/AttributeConfigurationGenerator/fillInferDefinitionFromAnnotation/inferDefinitionFromAnnotation/index.js:
--------------------------------------------------------------------------------
1 | import getAnnotationMap from '../../getAnnotationMap'
2 |
3 | // Generates a definition of an attribute by inferring a definition from the value of an annotation.
4 | export default function (annotations) {
5 | return [...getAnnotationMap(annotations).values()].map((a) => a.definition)
6 | }
7 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/patchConfiguration/AttributeConfigurationGenerator/fillMandatoryValueOfNumericAttributes.js:
--------------------------------------------------------------------------------
1 | import clone from '../clone'
2 | import { DEFAULT, STEP } from '../../../../NumericAttributeDefinition'
3 |
4 | export default function (config) {
5 | config = clone(config)
6 |
7 | for (const a of config.filter((a) => a['value type'] === 'numeric')) {
8 | if (!Object.prototype.hasOwnProperty.call(a, 'default')) {
9 | a.default = DEFAULT
10 | }
11 | if (!Object.prototype.hasOwnProperty.call(a, 'step')) {
12 | a.step = STEP
13 | }
14 | }
15 |
16 | return config
17 | }
18 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/patchConfiguration/AttributeConfigurationGenerator/getAnnotationMap.js:
--------------------------------------------------------------------------------
1 | import AnnotationsForPred from './AnnotationsForPred'
2 |
3 | export default function (annotations) {
4 | return annotations.reduce((map, attr) => {
5 | if (map.has(attr.pred)) {
6 | map.get(attr.pred).push(attr.obj)
7 | } else {
8 | map.set(attr.pred, new AnnotationsForPred(attr))
9 | }
10 | return map
11 | }, new Map())
12 | }
13 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/patchConfiguration/clone.js:
--------------------------------------------------------------------------------
1 | export default function (config) {
2 | return config ? JSON.parse(JSON.stringify(config)) : {}
3 | }
4 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/setAnnotationAndConfiguration.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | * @param {import('./MenuState').MenuState} menuState
4 | * @param {import('../AnnotationModel').AnnotationModel} annotationModel
5 | */
6 | export default function setAnnotationAndConfiguration(
7 | validConfig,
8 | menuState,
9 | spanConfig,
10 | annotationModel,
11 | annotation,
12 | functionAvailability
13 | ) {
14 | menuState.setPushButtons(validConfig)
15 | spanConfig.set(validConfig)
16 | annotationModel.reset(annotation, validConfig)
17 | functionAvailability.availability = validConfig['function availability']
18 | }
19 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/validateAttributeDefinitionAndAlert/index.js:
--------------------------------------------------------------------------------
1 | import alertifyjs from 'alertifyjs'
2 | import hasAllValueDefinitionOfSelectionAttributes from './hasAllValueDefinitionOfSelectionAttributes'
3 |
4 | export default function (annotation, config) {
5 | const error = hasAllValueDefinitionOfSelectionAttributes(annotation, config)
6 |
7 | if (error) {
8 | alertifyjs.error(error)
9 | return
10 | }
11 |
12 | return config
13 | }
14 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/validateConfigurationAndAlert/validateConfiguration/toErrorMessage.js:
--------------------------------------------------------------------------------
1 | import anemone from '../../../../component/anemone'
2 |
3 | export default function (errors) {
4 | for (const e of errors) {
5 | if (e.keyword === 'required') {
6 | return `Invalid configuration: The attribute type whose predicate is '${e.data.pred}' misses a mandatory property, '${e.params.missingProperty}'.`
7 | } else if (e.instancePath.includes('color')) {
8 | return anemone`Invalid configuration: '${e.data}' is invalid color format.`
9 | }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/warningIfBeginEndOfSpanAreNotInteger/areNotBeginAndEndInteger.js:
--------------------------------------------------------------------------------
1 | export default function (annotation) {
2 | if (annotation.denotations) {
3 | for (const denotation of annotation.denotations) {
4 | if (denotation.span.begin !== parseInt(denotation.span.begin)) {
5 | return true
6 | }
7 |
8 | if (denotation.span.end !== parseInt(denotation.span.end)) {
9 | return true
10 | }
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/lib/Editor/UseCase/warningIfBeginEndOfSpanAreNotInteger/index.js:
--------------------------------------------------------------------------------
1 | import alertifyjs from 'alertifyjs'
2 | import areNotBeginAndEndInteger from './areNotBeginAndEndInteger'
3 |
4 | export default function (annotation) {
5 | if (areNotBeginAndEndInteger(annotation)) {
6 | alertifyjs.warning(
7 | `In the annotation file, some of the begin and end offsets of denotations were not integer values.
8 | TextAE converted them to integer values.
9 | However, to avoid a chance of unexpected rendering, please fix them.`,
10 | 15
11 | )
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/lib/Editor/control/ContextMenu/toContextMenuItem.js:
--------------------------------------------------------------------------------
1 | export default function ({ type, title, classList }) {
2 | return `${title}
5 |
`
6 | }
7 |
--------------------------------------------------------------------------------
/src/lib/Editor/control/Menu/index.js:
--------------------------------------------------------------------------------
1 | import dohtml from 'dohtml'
2 | import bindEventHandler from './bindEventHandler'
3 |
4 | // The control is a control bar in an editor.
5 | export default class Menu {
6 | #el
7 |
8 | constructor(html, iconEventMap) {
9 | const el = dohtml.create(html)
10 |
11 | this.#el = el
12 | bindEventHandler(this.#el, iconEventMap)
13 | }
14 |
15 | get el() {
16 | return this.#el
17 | }
18 |
19 | // protected method
20 | _querySelector(selector) {
21 | return this.#el.querySelector(selector)
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/lib/Editor/control/ToolBar/toButtonGroup/index.js:
--------------------------------------------------------------------------------
1 | import toButtonIcon from './toButtonIcon'
2 |
3 | export default function () {
4 | return (list) => `
5 |
6 | ${list.map(toButtonIcon).join('\n')}
7 | `
8 | }
9 |
--------------------------------------------------------------------------------
/src/lib/Editor/control/ToolBar/toButtonGroup/toButtonIcon.js:
--------------------------------------------------------------------------------
1 | export default function ({ type, title, classList }) {
2 | return `
3 |
7 |
8 | `
9 | }
10 |
--------------------------------------------------------------------------------
/src/lib/Editor/diffOfAnnotation/byID.js:
--------------------------------------------------------------------------------
1 | export default function byID(a, b) {
2 | if (a.id < b.id) {
3 | return -1
4 | }
5 | if (a.id > b.id) {
6 | return 1
7 | }
8 | return 0
9 | }
10 |
--------------------------------------------------------------------------------
/src/lib/Editor/diffOfAnnotation/index.js:
--------------------------------------------------------------------------------
1 | import { diff } from 'jsondiffpatch'
2 | import sortByID from './sortByID'
3 |
4 | export default function diffOfAnnotation(oldAnnotation, newAnnotation) {
5 | return diff(sortByID(oldAnnotation), sortByID(newAnnotation))
6 | }
7 |
--------------------------------------------------------------------------------
/src/lib/Editor/diffOfAnnotation/sortByID.js:
--------------------------------------------------------------------------------
1 | import byID from './byID'
2 |
3 | export default function sortByID({
4 | text,
5 | denotations = [],
6 | attributes = [],
7 | relations = [],
8 | blocks = []
9 | }) {
10 | return {
11 | text,
12 | denotations: denotations.sort(byID),
13 | attributes: attributes.sort(byID),
14 | relations: relations.sort(byID),
15 | blocks: blocks.sort(byID)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/lib/Editor/editorCSSClassObserve.js:
--------------------------------------------------------------------------------
1 | export default function (eventEmitter, editorCSSClass) {
2 | eventEmitter
3 | .on('textae-event.resource.startLoad', () => editorCSSClass.startWait())
4 | .on('textae-event.resource.endLoad', () => editorCSSClass.endWait())
5 | .on('textae-event.resource.startSave', () => editorCSSClass.startWait())
6 | .on('textae-event.resource.endSave', () => editorCSSClass.endWait())
7 | }
8 |
--------------------------------------------------------------------------------
/src/lib/Editor/forwardMethods.js:
--------------------------------------------------------------------------------
1 | export default function (delegator, getTargetFunction, methods) {
2 | for (const method of methods) {
3 | delegator[method] = (...args) => {
4 | const target = getTargetFunction()
5 | console.assert(target[method], `No ${method} method to forward`, target)
6 |
7 | return target[method].apply(target, args)
8 | }
9 | }
10 |
11 | return delegator
12 | }
13 |
--------------------------------------------------------------------------------
/src/lib/Editor/getLabelBackgroundColor.js:
--------------------------------------------------------------------------------
1 | import hexToRGBA from './hexToRGBA'
2 |
3 | export default function () {
4 | return hexToRGBA('#FFFFFF', 0.6)
5 | }
6 |
--------------------------------------------------------------------------------
/src/lib/Editor/getMatchPrefix.js:
--------------------------------------------------------------------------------
1 | export default function (namespace, type) {
2 | const namespaces = namespace.all
3 | const matchs = namespaces
4 | .filter((namespace) => namespace.prefix !== '_base')
5 | .filter((namespace) => {
6 | return type.indexOf(`${namespace.prefix}:`) === 0
7 | })
8 | if (matchs.length === 1) return matchs[0]
9 | return null
10 | }
11 |
--------------------------------------------------------------------------------
/src/lib/Editor/getPalletButtonTitleFor.js:
--------------------------------------------------------------------------------
1 | import { MODE } from '../MODE'
2 |
3 | export default function getPalletButtonTitleFor(mode) {
4 | switch (mode) {
5 | case MODE.EDIT_DENOTATION:
6 | return 'Term Configuration'
7 | case MODE.EDIT_BLOCK:
8 | return 'Block Configuration'
9 | case MODE.EDIT_RELATION:
10 | return 'Relation Configuration'
11 | default:
12 | return ''
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/lib/Editor/getRightElement.js:
--------------------------------------------------------------------------------
1 | export default function (editorHTMLElement, element, className) {
2 | console.assert(element, 'element MUST exists.')
3 |
4 | const all = editorHTMLElement.querySelectorAll(`.${className}`)
5 | const index = Array.from(all).indexOf(element)
6 |
7 | if (all.length - index > 1) {
8 | return all[index + 1]
9 | }
10 |
11 | return null
12 | }
13 |
--------------------------------------------------------------------------------
/src/lib/Editor/getRightSpanElement.js:
--------------------------------------------------------------------------------
1 | import getRightElement from './getRightElement'
2 |
3 | export default function (editorHTMLElement, spanId) {
4 | return getRightElement(
5 | editorHTMLElement,
6 | document.querySelector(`#${spanId}`),
7 | 'textae-editor__span'
8 | )
9 | }
10 |
--------------------------------------------------------------------------------
/src/lib/Editor/getUrlMatches.js:
--------------------------------------------------------------------------------
1 | export default function (type) {
2 | // The regular-expression to parse URL.
3 | // See detail:
4 | // http://someweblog.com/url-regular-expression-javascript-link-shortener/
5 | const urlRegex =
6 | /\(?(?:(http|https|ftp):\/\/)?(?:((?:[^\W\s]|\.|-|[:]{1})+)@{1})?((?:www.)?(?:[^\W\s]|\.|-)+[.][^\W\s]{2,4}|localhost|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(?::(\d*))?([/]?[^\s?]*[/]{1})*(?:\/?([^\s\n?[\]{}#]*(?:(?=\.)){1}|[^\s\n?[\]{}.#]*)?([.]{1}[^\s?#]*)?)?(?:\?{1}([^\s\n#[\]]*))?([#][^\s\n]*)?\)?/gi
7 | return urlRegex.exec(type)
8 | }
9 |
--------------------------------------------------------------------------------
/src/lib/Editor/hexToRGBA.js:
--------------------------------------------------------------------------------
1 | export default function (hex, alpha) {
2 | const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)
3 | console.assert(result, `${hex} is not a hexadecimal color values!`)
4 |
5 | return `rgba(${parseInt(result[1], 16)}, ${parseInt(
6 | result[2],
7 | 16
8 | )}, ${parseInt(result[3], 16)}, ${alpha})`
9 | }
10 |
--------------------------------------------------------------------------------
/src/lib/Editor/isAndroid.js:
--------------------------------------------------------------------------------
1 | export default function () {
2 | // For development environments, Use the navigator.userAgent.
3 | // Because the navigator.userAgentData only work in the secure context(HTTPS).
4 | // https://developer.mozilla.org/en-US/docs/Web/API/Navigator/userAgentData
5 | return /Android/.test(navigator.userAgent)
6 | }
7 |
--------------------------------------------------------------------------------
/src/lib/Editor/isBoundaryCrossing.js:
--------------------------------------------------------------------------------
1 | export default function (begin, end, existSpan) {
2 | const isStartOfCandidateSpanBetweenExistsSpan =
3 | existSpan.begin < begin && begin < existSpan.end && existSpan.end < end
4 |
5 | const isEndOfCandidateSpanBetweenExistSpan =
6 | begin < existSpan.begin && existSpan.begin < end && end < existSpan.end
7 |
8 | return (
9 | isStartOfCandidateSpanBetweenExistsSpan ||
10 | isEndOfCandidateSpanBetweenExistSpan
11 | )
12 | }
13 |
--------------------------------------------------------------------------------
/src/lib/Editor/isTouchable.js:
--------------------------------------------------------------------------------
1 | // https://stackoverflow.com/questions/4817029/whats-the-best-way-to-detect-a-touch-screen-device-using-javascript/4819886#4819886
2 | export default function () {
3 | return (
4 | 'ontouchstart' in window ||
5 | navigator.maxTouchPoints > 0 ||
6 | navigator.msMaxTouchPoints > 0
7 | )
8 | }
9 |
--------------------------------------------------------------------------------
/src/lib/Editor/loadAnnotation.js:
--------------------------------------------------------------------------------
1 | import DataSource from './DataSource'
2 |
3 | export default function loadAnnotation(eventEmitter, annotation) {
4 | if (!annotation.text) {
5 | return false
6 | }
7 |
8 | eventEmitter.emit(
9 | 'textae-event.resource.annotation.load.success',
10 | DataSource.createInstantSource(annotation)
11 | )
12 |
13 | return true
14 | }
15 |
--------------------------------------------------------------------------------
/src/lib/Editor/observeElement.js:
--------------------------------------------------------------------------------
1 | import delegate from 'delegate'
2 |
3 | export default function (element) {
4 | // Prevent a selection text with shift keies.
5 | element.addEventListener('mousedown', (e) => {
6 | if (e.shiftKey) {
7 | e.preventDefault()
8 | }
9 | })
10 |
11 | // Prevent a selection of an entity by the double-click.
12 | delegate(element, '.textae-editor__signboard', 'mousedown', (e) =>
13 | e.preventDefault()
14 | )
15 | }
16 |
--------------------------------------------------------------------------------
/src/lib/Editor/round.js:
--------------------------------------------------------------------------------
1 | // The value of getBoundingClientRect may contain 13 decimal places.
2 | // It's too fine to use as a style attribute,
3 | // so I'll round it to 2 decimal places,
4 | // which is below the rounding accuracy of Google Chrome and Firefox.
5 | export default function (val) {
6 | return Math.round(val * 100) / 100
7 | }
8 |
--------------------------------------------------------------------------------
/src/lib/Editor/toAnchorElement.js:
--------------------------------------------------------------------------------
1 | import anemone from '../component/anemone'
2 |
3 | export default function (displayName, href) {
4 | return () =>
5 | href
6 | ? anemone`${displayName}`
7 | : anemone`${displayName}`
8 | }
9 |
--------------------------------------------------------------------------------
/src/lib/IntervalNotation/getLowwerCond.js:
--------------------------------------------------------------------------------
1 | import gte from './gte'
2 | import gt from './gt'
3 |
4 | export default function (str) {
5 | if (str.startsWith('[')) {
6 | return (right) => gte(new Number(str.replace('[', '')), right)
7 | }
8 | if (str.startsWith('(')) {
9 | return (right) => gt(new Number(str.replace('(', '')), right)
10 | }
11 | throw `${str} is not valid interval notation`
12 | }
13 |
--------------------------------------------------------------------------------
/src/lib/IntervalNotation/getUpperCond.js:
--------------------------------------------------------------------------------
1 | import gte from './gte'
2 | import gt from './gt'
3 |
4 | export default function (str) {
5 | if (str.endsWith(']')) {
6 | return (left) => gte(left, new Number(str.replace(']', '')))
7 | }
8 | if (str.endsWith(')')) {
9 | return (left) => gt(left, new Number(str.replace(')', '')))
10 | }
11 | throw `${str} is not valid interval notation`
12 | }
13 |
--------------------------------------------------------------------------------
/src/lib/IntervalNotation/gt.js:
--------------------------------------------------------------------------------
1 | export default function (left, right) {
2 | return left < right
3 | }
4 |
--------------------------------------------------------------------------------
/src/lib/IntervalNotation/gte.js:
--------------------------------------------------------------------------------
1 | export default function (left, right) {
2 | return left <= right
3 | }
4 |
--------------------------------------------------------------------------------
/src/lib/MODE.js:
--------------------------------------------------------------------------------
1 | export const MODE = {
2 | INIT: 'Init',
3 | VIEW: 'View',
4 | EDIT_DENOTATION: 'Term',
5 | EDIT_BLOCK: 'Block',
6 | EDIT_RELATION: 'Relation',
7 | EDIT_TEXT: 'Text'
8 | }
9 |
--------------------------------------------------------------------------------
/src/lib/component/CreateOrEditValueOfAttributeDefinitionDialog/inputDefault.js:
--------------------------------------------------------------------------------
1 | import anemone from '../anemone'
2 |
3 | export default function (showDefault, isDefault) {
4 | return () =>
5 | showDefault
6 | ? anemone`
7 |
8 |
16 |
17 | `
18 | : ``
19 | }
20 |
--------------------------------------------------------------------------------
/src/lib/component/EditAttributeDefinitionDialog/isChanged.js:
--------------------------------------------------------------------------------
1 | export default function (orig, changed) {
2 | // Ignore non number value.
3 | return !Number.isNaN(parseFloat(changed)) && orig !== parseFloat(changed)
4 | }
5 |
--------------------------------------------------------------------------------
/src/lib/component/EditAttributeDefinitionDialog/template.js:
--------------------------------------------------------------------------------
1 | import inputAttributeDefinition from '../inputAttributeDefinition'
2 |
3 | export default function (componentClassName, context) {
4 | return `
5 |
6 | ${inputAttributeDefinition(componentClassName, context)}
7 |
`
8 | }
9 |
--------------------------------------------------------------------------------
/src/lib/component/HelpDialog.js:
--------------------------------------------------------------------------------
1 | import Dialog from './Dialog'
2 |
3 | export default class HelpDialog extends Dialog {
4 | constructor() {
5 | super(
6 | 'Help (Keyboard short-cuts)',
7 | `
8 |
9 | -
10 | cut
11 | : Ctrl+x
12 |
13 | -
14 | copy
15 | : Ctrl+c
16 |
17 | -
18 | paste
19 | : Ctrl+v
20 |
21 |
22 | `,
23 |
24 | {
25 | maxWidth: 523
26 | }
27 | )
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/lib/component/Pallet/enableJqueryDraggable.js:
--------------------------------------------------------------------------------
1 | import $ from 'jquery'
2 | import 'jquery-ui/ui/widgets/draggable'
3 |
4 | export default function (element, editorHTMLElement) {
5 | $(element).draggable({
6 | containment: editorHTMLElement
7 | })
8 | }
9 |
--------------------------------------------------------------------------------
/src/lib/component/Pallet/setHeightWithin.js:
--------------------------------------------------------------------------------
1 | const BORDER_HEIGHT = 7 * 2
2 |
3 | export default function (pallet, height) {
4 | if (height - BORDER_HEIGHT <= pallet.offsetHeight) {
5 | pallet.style.height = `${height - BORDER_HEIGHT}px`
6 | } else {
7 | pallet.style.height = null
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/lib/component/Pallet/setWidthWithin.js:
--------------------------------------------------------------------------------
1 | export default function (pallet, width) {
2 | pallet.style.width = 'auto'
3 |
4 | if (width - 2 <= pallet.offsetWidth) {
5 | pallet.style.width = `${width - 4}px`
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/lib/component/SaveAnnotationDialog/bind/createDownloadPathForFormat.js:
--------------------------------------------------------------------------------
1 | import createDownloadPath from '../../createDownloadPath'
2 | import SimpleInlineTextAnnotation from '@pubann/simple-inline-text-annotation'
3 |
4 | export default function createDownloadPathForFormat(data, format) {
5 | if (format === 'json') {
6 | return createDownloadPath(data)
7 | } else if (format === 'inline') {
8 | const inlineData = SimpleInlineTextAnnotation.generate(data)
9 |
10 | const blob = new Blob([inlineData], { type: 'text/plain;charset=utf-8' })
11 | return URL.createObjectURL(blob)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/lib/component/SaveAnnotationDialog/bind/downloadAnnotationFile/downloadAnnotation.js:
--------------------------------------------------------------------------------
1 | // Using an existing tag to following process, it cause the click event to fire twice, resulting an error.
2 | // Creating and using a temporary link (tempLink) prevents the re-triggering event.
3 |
4 | export default function downloadAnnotation(downloadPath, fileName) {
5 | const tempLink = document.createElement('a')
6 | tempLink.setAttribute('href', downloadPath)
7 | tempLink.setAttribute('download', fileName)
8 | document.body.appendChild(tempLink)
9 | tempLink.click()
10 | document.body.removeChild(tempLink)
11 | }
12 |
--------------------------------------------------------------------------------
/src/lib/component/SaveAnnotationDialog/bind/downloadAnnotationFile/index.js:
--------------------------------------------------------------------------------
1 | import createDownloadPathForFormat from '../createDownloadPathForFormat'
2 | import downloadAnnotation from './downloadAnnotation'
3 |
4 | export default function downloadAnnotationFile(e, data, format, eventEmitter) {
5 | e.preventDefault()
6 |
7 | const downloadPath = createDownloadPathForFormat(data, format)
8 | downloadAnnotation(downloadPath, e.target.previousElementSibling.value)
9 |
10 | eventEmitter.emit('textae-event.resource.annotation.save', data)
11 | }
12 |
--------------------------------------------------------------------------------
/src/lib/component/SaveAnnotationDialog/bind/viewSource.js:
--------------------------------------------------------------------------------
1 | import createDownloadPathForFormat from './createDownloadPathForFormat'
2 |
3 | export default function viewSource(data, format, eventEmitter) {
4 | const downloadPath = createDownloadPathForFormat(data, format)
5 | window.open(downloadPath, '_blank')
6 |
7 | eventEmitter.emit('textae-event.resource.annotation.save', data)
8 | }
9 |
--------------------------------------------------------------------------------
/src/lib/component/SaveConfigurationDialog/jsonDiff.js:
--------------------------------------------------------------------------------
1 | import { create } from 'jsondiffpatch'
2 | import { format } from 'jsondiffpatch/formatters/html'
3 |
4 | const jsond = create({
5 | objectHash(obj, index) {
6 | return obj.id || `$$index:${index}`
7 | }
8 | })
9 |
10 | export default function (originalConfig, editedConfig) {
11 | const delta = jsond.diff(originalConfig, editedConfig)
12 | return format(delta, originalConfig)
13 | }
14 |
--------------------------------------------------------------------------------
/src/lib/component/SettingDialog/EscapeSequence.js:
--------------------------------------------------------------------------------
1 | export default class EscapeSequence {
2 | static escape(str) {
3 | return str.replace(/\n/g, '\\n').replace(/\t/g, '\\t').replace(/\r/g, '\\r')
4 | }
5 |
6 | static decode(str) {
7 | return str.replace(/\\n/g, '\n').replace(/\\t/g, '\t').replace(/\\r/g, '\r')
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/lib/component/SettingDialog/bindAddCharacter/addCharacterRow/validateCharacter.js:
--------------------------------------------------------------------------------
1 | import alertifyjs from 'alertifyjs'
2 | import EscapeSequence from '../../EscapeSequence'
3 |
4 | export default function validateCharacter(char, currentCharacters) {
5 | if (currentCharacters.includes(char)) {
6 | alertifyjs.warning(`${char} is already added.`)
7 | return false
8 | }
9 |
10 | if (EscapeSequence.decode(char).length > 1) {
11 | alertifyjs.warning('Only one character is allowed.')
12 | return false
13 | }
14 |
15 | return true
16 | }
17 |
--------------------------------------------------------------------------------
/src/lib/component/SettingDialog/bindAddCharacter/index.js:
--------------------------------------------------------------------------------
1 | import delegate from 'delegate'
2 | import addCharacterRow from './addCharacterRow'
3 |
4 | export default function bindAddCharacter(content) {
5 | delegate(
6 | content,
7 | '.textae-editor__setting-dialog__delimiter-character-add-button',
8 | 'click',
9 | () => addCharacterRow(content, 'delimiter')
10 | )
11 |
12 | delegate(
13 | content,
14 | '.textae-editor__setting-dialog__blank-character-add-button',
15 | 'click',
16 | () => addCharacterRow(content, 'blank')
17 | )
18 | }
19 |
--------------------------------------------------------------------------------
/src/lib/component/SettingDialog/reflectImmediately/bindChangeLineHeight.js:
--------------------------------------------------------------------------------
1 | import delgate from 'delegate'
2 | import debounce300 from './debounce300'
3 | import redrawAllEditor from './redrawAllEditor'
4 |
5 | export default function (content, textBox) {
6 | delgate(
7 | content,
8 | '.textae-editor__setting-dialog__line-height-text',
9 | 'change',
10 | debounce300((e) => {
11 | textBox.lineHeight = e.target.value
12 | redrawAllEditor()
13 | })
14 | )
15 | }
16 |
--------------------------------------------------------------------------------
/src/lib/component/SettingDialog/reflectImmediately/bindChangeLockConfig.js:
--------------------------------------------------------------------------------
1 | import delgate from 'delegate'
2 | import debounce300 from './debounce300'
3 |
4 | export default function (content, typeDictionary) {
5 | delgate(
6 | content,
7 | '.textae-editor__setting-dialog__lock-config-text',
8 | 'change',
9 | debounce300((e) => {
10 | if (e.target.checked) {
11 | typeDictionary.lockEdit()
12 | } else {
13 | typeDictionary.unlockEdit()
14 | }
15 | })
16 | )
17 | }
18 |
--------------------------------------------------------------------------------
/src/lib/component/SettingDialog/reflectImmediately/bindChangeTypeGap.js:
--------------------------------------------------------------------------------
1 | import delgate from 'delegate'
2 | import debounce300 from './debounce300'
3 |
4 | export default function (content, typeGap, textBox) {
5 | delgate(
6 | content,
7 | '.textae-editor__setting-dialog__type-gap-text',
8 | 'change',
9 | debounce300((e) => {
10 | typeGap.value = Number(e.target.value)
11 | content.querySelector(
12 | '.textae-editor__setting-dialog__line-height-text'
13 | ).value = textBox.lineHeight
14 | })
15 | )
16 | }
17 |
--------------------------------------------------------------------------------
/src/lib/component/SettingDialog/reflectImmediately/debounce300.js:
--------------------------------------------------------------------------------
1 | import debounce from 'debounce'
2 |
3 | export default function (func) {
4 | return debounce(func, 300)
5 | }
6 |
--------------------------------------------------------------------------------
/src/lib/component/SettingDialog/reflectImmediately/redrawAllEditor.js:
--------------------------------------------------------------------------------
1 | // Redraw all editors in tha windows.
2 | export default function redrawAllEditor() {
3 | const event = new Event('resize')
4 | window.dispatchEvent(event)
5 | }
6 |
--------------------------------------------------------------------------------
/src/lib/component/SettingDialog/saveAutocompletionWs.js:
--------------------------------------------------------------------------------
1 | import validateConfiguration from './validateConfiguration'
2 |
3 | export default function bindChangeAutocompletionWs(content, typeDictionary) {
4 | const newValue = content.querySelector(
5 | '.textae-editor__setting-dialog__autocompletion_ws-text'
6 | ).value
7 |
8 | validateConfiguration({
9 | autocompletion_ws: newValue
10 | })
11 |
12 | typeDictionary.autocompletionWs = newValue
13 | }
14 |
--------------------------------------------------------------------------------
/src/lib/component/SettingDialog/template/escapeForDisplay.js:
--------------------------------------------------------------------------------
1 | import escape from 'lodash.escape'
2 | import EscapeSequence from '../EscapeSequence'
3 |
4 | export default function escapeForDisplay(str) {
5 | // First, escape newline, tab, and carriage returns to display them.
6 | const replaced = EscapeSequence.escape(str)
7 |
8 | // Then, escape special HTML characters to ensure safe rendering in HTML.
9 | return escape(replaced)
10 | }
11 |
--------------------------------------------------------------------------------
/src/lib/component/SettingDialog/template/toBlankCharacterRowElement.js:
--------------------------------------------------------------------------------
1 | import escapeForDisplay from './escapeForDisplay'
2 |
3 | export default function toBlankCharacterRowElement(char) {
4 | return `
5 |
6 |
7 | ${escapeForDisplay(char)}
8 | |
9 | |
10 |
`
11 | }
12 |
--------------------------------------------------------------------------------
/src/lib/component/SettingDialog/template/toDelimiterCharacterRowElement.js:
--------------------------------------------------------------------------------
1 | import escapeForDisplay from './escapeForDisplay'
2 |
3 | export default function toDelimiterCharacterRowElement(char) {
4 | return `
5 |
6 |
7 | ${escapeForDisplay(char)}
8 | |
9 | |
10 |
`
11 | }
12 |
--------------------------------------------------------------------------------
/src/lib/component/SettingDialog/template/toFunctionAvailabilityLabelElement.js:
--------------------------------------------------------------------------------
1 | export default function toFunctionAvailabilityLabelElement(
2 | functionAvailability,
3 | name
4 | ) {
5 | return `
6 | `
13 | }
14 |
--------------------------------------------------------------------------------
/src/lib/component/SettingDialog/validateConfiguration.js:
--------------------------------------------------------------------------------
1 | import Ajv from 'ajv'
2 | import addFormats from 'ajv-formats'
3 | import configurationScheme from '../../configurationScheme.json'
4 |
5 | const ajv = new Ajv({ verbose: true })
6 | addFormats(ajv, ['uri-reference', 'regex'])
7 | const validate = ajv.compile(configurationScheme)
8 |
9 | export default function validateConfiguration(config) {
10 | if (!validate(config)) {
11 | console.warn(validate.errors)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/lib/component/TypeValuesPallet/bindAttributeEvent/enableAttributeTabDrag/hideDropTargets.js:
--------------------------------------------------------------------------------
1 | export default function (e) {
2 | e.target
3 | .closest('.textae-editor__pallet__content')
4 | .classList.remove('textae-editor__pallet__content--dragging')
5 | }
6 |
--------------------------------------------------------------------------------
/src/lib/component/TypeValuesPallet/bindAttributeEvent/enableAttributeTabDrag/index.js:
--------------------------------------------------------------------------------
1 | import delegate from 'delegate'
2 | import showDropTargets from './showDropTargets'
3 | import hideDropTargets from './hideDropTargets'
4 |
5 | export default function (el) {
6 | delegate(el, '.textae-editor__pallet__attribute', 'dragstart', (e) => {
7 | e.dataTransfer.setData(
8 | 'application/x-textae-attribute-tab-old-index',
9 | e.target.dataset.index
10 | )
11 | showDropTargets(e)
12 | })
13 |
14 | delegate(el, '.textae-editor__pallet__attribute', 'dragend', (e) => {
15 | hideDropTargets(e)
16 | })
17 | }
18 |
--------------------------------------------------------------------------------
/src/lib/component/TypeValuesPallet/bindAttributeEvent/enableAttributeTabDrag/showDropTargets.js:
--------------------------------------------------------------------------------
1 | export default function (e) {
2 | e.target
3 | .closest('.textae-editor__pallet__content')
4 | .classList.add('textae-editor__pallet__content--dragging')
5 | }
6 |
--------------------------------------------------------------------------------
/src/lib/component/TypeValuesPallet/createContentHtml/flagAttributeTemplate.js:
--------------------------------------------------------------------------------
1 | import headerTemplate from './headerTemplate'
2 | import predicateControllerTemplate from './predicateControllerTemplate'
3 | import anemone from '../../anemone'
4 |
5 | export default function (context) {
6 | const { label, color } = context.attrDef
7 |
8 | return anemone`
9 | ${headerTemplate(context)}
10 |
11 |
12 | ${predicateControllerTemplate(context)}
13 | label: "${label || ''}"
14 | color: "${color || ''}"
15 |
16 |
17 | `
18 | }
19 |
--------------------------------------------------------------------------------
/src/lib/component/TypeValuesPallet/createContentHtml/headerTemplate/getSelectedEntityLabel.js:
--------------------------------------------------------------------------------
1 | export default function (numberOfSelectedItems) {
2 | return numberOfSelectedItems === 1
3 | ? '1 item selected'
4 | : numberOfSelectedItems > 1
5 | ? `${numberOfSelectedItems} items selected`
6 | : ''
7 | }
8 |
--------------------------------------------------------------------------------
/src/lib/component/TypeValuesPallet/createContentHtml/showAddAttributeValueButton.js:
--------------------------------------------------------------------------------
1 | export default function (isLock) {
2 | return isLock
3 | ? ''
4 | : () => `
5 |
6 |
7 | | `
8 | }
9 |
--------------------------------------------------------------------------------
/src/lib/component/TypeValuesPallet/enableDrag.js:
--------------------------------------------------------------------------------
1 | export default function (el) {
2 | for (const attributeTab of el.querySelectorAll(
3 | '.textae-editor__pallet__attribute'
4 | )) {
5 | attributeTab.addEventListener('mousedown', (e) => {
6 | // Stop event propagation to prevent the jQueryUI.dragging widget
7 | // from disabling the default handling of mousedown events.
8 | e.stopPropagation()
9 | })
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/lib/component/createDownloadPath.js:
--------------------------------------------------------------------------------
1 | export default function (dataObject) {
2 | const blob = new Blob([JSON.stringify(dataObject)], {
3 | type: 'application/json'
4 | })
5 |
6 | return URL.createObjectURL(blob)
7 | }
8 |
--------------------------------------------------------------------------------
/src/lib/component/enableHTMLElement.js:
--------------------------------------------------------------------------------
1 | // Since the style is specified by [disabled = "disabled"],
2 | // set the attribute to disabled without using the disable property.
3 | export default function (element, enable) {
4 | if (enable) {
5 | element.removeAttribute('disabled')
6 | } else {
7 | element.setAttribute('disabled', 'disabled')
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/lib/component/fetchAutocompleteCandidates.js:
--------------------------------------------------------------------------------
1 | export default function fetchAutocompleteCandidates(autocompletionWs, term) {
2 | const url = new URL(autocompletionWs, location)
3 | url.searchParams.append('term', term)
4 |
5 | return fetch(url.href).then((response) => {
6 | if (response.ok) {
7 | return response.json()
8 | }
9 | return []
10 | })
11 | }
12 |
--------------------------------------------------------------------------------
/src/lib/component/getInputElementValue.js:
--------------------------------------------------------------------------------
1 | export default function (el, selector) {
2 | return (
3 | el.querySelector(`input${selector}`) &&
4 | el.querySelector(`input${selector}`).value
5 | )
6 | }
7 |
--------------------------------------------------------------------------------
/src/lib/component/getRandomColorString.js:
--------------------------------------------------------------------------------
1 | export default function () {
2 | return `#${getRandomHEXFrom64ToFF()}${getRandomHEXFrom64ToFF()}${getRandomHEXFrom64ToFF()}`
3 | }
4 |
5 | function getRandomHEXFrom64ToFF() {
6 | return Math.floor(Math.random() * 155 + 100).toString(16)
7 | }
8 |
--------------------------------------------------------------------------------
/src/lib/component/inputAttributeDefinition/inputAutocompletionWs.js:
--------------------------------------------------------------------------------
1 | import anemone from '../anemone'
2 |
3 | export default function inputAutocomletionWs(
4 | componentClassName,
5 | autocompletionWs
6 | ) {
7 | return () => anemone`
8 |
9 |
10 |
14 |
15 | `
16 | }
17 |
--------------------------------------------------------------------------------
/src/lib/component/inputAttributeDefinition/inputDefault.js:
--------------------------------------------------------------------------------
1 | import anemone from '../anemone'
2 |
3 | export default function (componentClassName, defaultValue) {
4 | return () => anemone`
5 |
6 |
7 |
11 |
12 | `
13 | }
14 |
--------------------------------------------------------------------------------
/src/lib/component/inputAttributeDefinition/inputMediaHeight.js:
--------------------------------------------------------------------------------
1 | import anemone from '../anemone'
2 |
3 | export default function (componentClassName, mediaHeight) {
4 | return () => anemone`
5 |
6 |
7 |
12 |
13 | `
14 | }
15 |
--------------------------------------------------------------------------------
/src/lib/component/isUserConfirm.js:
--------------------------------------------------------------------------------
1 | export default function isUserConfirm(hasChange) {
2 | const CONFIRM_DISCARD_CHANGE_MESSAGE =
3 | 'There is a change that has not been saved. If you proceed now, you will lose it.'
4 |
5 | return !hasChange || window.confirm(CONFIRM_DISCARD_CHANGE_MESSAGE)
6 | }
7 |
--------------------------------------------------------------------------------
/src/lib/component/maximizeOverlay.js:
--------------------------------------------------------------------------------
1 | export default function (overlayDropzone) {
2 | const { element } = overlayDropzone
3 | element.classList.add(
4 | 'textae-editor__load-dialog__overlay-dropzone--maximized'
5 | )
6 | element.style.zIndex = parseInt(element.style.zIndex) + 1
7 | }
8 |
--------------------------------------------------------------------------------
/src/lib/component/revertMaximizeOverlay.js:
--------------------------------------------------------------------------------
1 | export default function (overlayDropzone, zIndexOfOverlayDropzone) {
2 | overlayDropzone.element.classList.remove(
3 | 'textae-editor__load-dialog__overlay-dropzone--maximized'
4 | )
5 | overlayDropzone.element.style.zIndex = zIndexOfOverlayDropzone
6 | }
7 |
--------------------------------------------------------------------------------
/src/lib/css/images/btn_adjust_lineheight_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/btn_adjust_lineheight_16.png
--------------------------------------------------------------------------------
/src/lib/css/images/btn_auto_adjust_lineheight_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/btn_auto_adjust_lineheight_16.png
--------------------------------------------------------------------------------
/src/lib/css/images/btn_auto_replicate_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/btn_auto_replicate_16.png
--------------------------------------------------------------------------------
/src/lib/css/images/btn_block_edit_mode_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/btn_block_edit_mode_16.png
--------------------------------------------------------------------------------
/src/lib/css/images/btn_boundary_detection_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/btn_boundary_detection_16.png
--------------------------------------------------------------------------------
/src/lib/css/images/btn_copy_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/btn_copy_16.png
--------------------------------------------------------------------------------
/src/lib/css/images/btn_create_span_by_touch_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/btn_create_span_by_touch_16.png
--------------------------------------------------------------------------------
/src/lib/css/images/btn_cut_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/btn_cut_16.png
--------------------------------------------------------------------------------
/src/lib/css/images/btn_delete_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/btn_delete_16.png
--------------------------------------------------------------------------------
/src/lib/css/images/btn_edit_properties_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/btn_edit_properties_16.png
--------------------------------------------------------------------------------
/src/lib/css/images/btn_edit_text_by_touch_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/btn_edit_text_by_touch_16.png
--------------------------------------------------------------------------------
/src/lib/css/images/btn_expand_span_by_touch_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/btn_expand_span_by_touch_16.png
--------------------------------------------------------------------------------
/src/lib/css/images/btn_help_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/btn_help_16.png
--------------------------------------------------------------------------------
/src/lib/css/images/btn_import_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/btn_import_16.png
--------------------------------------------------------------------------------
/src/lib/css/images/btn_new_entity_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/btn_new_entity_16.png
--------------------------------------------------------------------------------
/src/lib/css/images/btn_pallet_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/btn_pallet_16.png
--------------------------------------------------------------------------------
/src/lib/css/images/btn_pallet_modified_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/btn_pallet_modified_16.png
--------------------------------------------------------------------------------
/src/lib/css/images/btn_paste_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/btn_paste_16.png
--------------------------------------------------------------------------------
/src/lib/css/images/btn_redo_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/btn_redo_16.png
--------------------------------------------------------------------------------
/src/lib/css/images/btn_relation_edit_mode_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/btn_relation_edit_mode_16.png
--------------------------------------------------------------------------------
/src/lib/css/images/btn_replicate_span_annotation_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/btn_replicate_span_annotation_16.png
--------------------------------------------------------------------------------
/src/lib/css/images/btn_setting_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/btn_setting_16.png
--------------------------------------------------------------------------------
/src/lib/css/images/btn_shrink_span_by_touch_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/btn_shrink_span_by_touch_16.png
--------------------------------------------------------------------------------
/src/lib/css/images/btn_simple_view_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/btn_simple_view_16.png
--------------------------------------------------------------------------------
/src/lib/css/images/btn_term_edit_mode_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/btn_term_edit_mode_16.png
--------------------------------------------------------------------------------
/src/lib/css/images/btn_text_edit_mode_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/btn_text_edit_mode_16.png
--------------------------------------------------------------------------------
/src/lib/css/images/btn_undo_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/btn_undo_16.png
--------------------------------------------------------------------------------
/src/lib/css/images/btn_upload_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/btn_upload_16.png
--------------------------------------------------------------------------------
/src/lib/css/images/btn_upload_automatically_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/btn_upload_automatically_16.png
--------------------------------------------------------------------------------
/src/lib/css/images/btn_upload_modified_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/btn_upload_modified_16.png
--------------------------------------------------------------------------------
/src/lib/css/images/btn_view_mode_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/btn_view_mode_16.png
--------------------------------------------------------------------------------
/src/lib/css/images/keyhelp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/keyhelp.png
--------------------------------------------------------------------------------
/src/lib/css/images/keyhelp.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/keyhelp.psd
--------------------------------------------------------------------------------
/src/lib/css/images/link.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/link.png
--------------------------------------------------------------------------------
/src/lib/css/images/ui-bg_diagonals-thick_18_b81900_40x40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/ui-bg_diagonals-thick_18_b81900_40x40.png
--------------------------------------------------------------------------------
/src/lib/css/images/ui-bg_diagonals-thick_20_666666_40x40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/ui-bg_diagonals-thick_20_666666_40x40.png
--------------------------------------------------------------------------------
/src/lib/css/images/ui-bg_glass_100_f6f6f6_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/ui-bg_glass_100_f6f6f6_1x400.png
--------------------------------------------------------------------------------
/src/lib/css/images/ui-bg_glass_100_fdf5ce_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/ui-bg_glass_100_fdf5ce_1x400.png
--------------------------------------------------------------------------------
/src/lib/css/images/ui-bg_glass_65_ffffff_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/ui-bg_glass_65_ffffff_1x400.png
--------------------------------------------------------------------------------
/src/lib/css/images/ui-bg_gloss-wave_35_f6a828_500x100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/ui-bg_gloss-wave_35_f6a828_500x100.png
--------------------------------------------------------------------------------
/src/lib/css/images/ui-bg_highlight-soft_100_eeeeee_1x100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/ui-bg_highlight-soft_100_eeeeee_1x100.png
--------------------------------------------------------------------------------
/src/lib/css/images/ui-bg_highlight-soft_75_ffe45c_1x100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/ui-bg_highlight-soft_75_ffe45c_1x100.png
--------------------------------------------------------------------------------
/src/lib/css/images/ui-icons_222222_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/ui-icons_222222_256x240.png
--------------------------------------------------------------------------------
/src/lib/css/images/ui-icons_228ef1_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/ui-icons_228ef1_256x240.png
--------------------------------------------------------------------------------
/src/lib/css/images/ui-icons_ef8c08_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/ui-icons_ef8c08_256x240.png
--------------------------------------------------------------------------------
/src/lib/css/images/ui-icons_ffd27a_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/ui-icons_ffd27a_256x240.png
--------------------------------------------------------------------------------
/src/lib/css/images/ui-icons_ffffff_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/src/lib/css/images/ui-icons_ffffff_256x240.png
--------------------------------------------------------------------------------
/src/lib/css/textae-const.less:
--------------------------------------------------------------------------------
1 | @baseColor: rgb(100, 100, 215);
2 | @selected: red;
3 |
--------------------------------------------------------------------------------
/src/lib/css/textae-editor-fontawsome.less:
--------------------------------------------------------------------------------
1 | .fontAwesomeIcon(@content) {
2 | position: relative;
3 | display: inline-block;
4 | font-family: FontAwesome;
5 | content: @content;
6 | }
7 |
8 | .attributeIcons() {
9 | &--flag:before {
10 | .fontAwesomeIcon('\f024');
11 | }
12 | &--selection:before {
13 | .fontAwesomeIcon('\f0ca');
14 | }
15 | &--numeric:before {
16 | .fontAwesomeIcon('\f2c9');
17 | }
18 | &--string:before {
19 | .fontAwesomeIcon('\f27a');
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/lib/css/textae-text-edit-dialog.less:
--------------------------------------------------------------------------------
1 | .textae-editor__text-edit-dialog {
2 | width: calc(100% - 300px);
3 | min-width: 360px;
4 | padding: 10px;
5 | border: 1px solid black;
6 | border-radius: 5px;
7 | background-color: #f0f0f0;
8 |
9 | &__title-bar {
10 | display: flex;
11 | justify-content: space-between;
12 | align-items: flex-start;
13 | margin-bottom: 10px;
14 | }
15 |
16 | &__text-box {
17 | width: 100%;
18 | margin-bottom: 10px;
19 | min-height: 150px;
20 | }
21 |
22 | &__button-bar {
23 | display: flex;
24 | justify-content: flex-end;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/lib/exceptions/FormatConversionError.js:
--------------------------------------------------------------------------------
1 | export default class FormatConversionError extends Error {
2 | constructor(message) {
3 | super(message)
4 | this.name = 'FormatConversionError'
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/src/lib/isAbleToParseFloat.js:
--------------------------------------------------------------------------------
1 | export default function (str) {
2 | return !Number.isNaN(parseFloat(str))
3 | }
4 |
--------------------------------------------------------------------------------
/src/lib/isJSON.js:
--------------------------------------------------------------------------------
1 | export default function (arg) {
2 | if (typeof arg !== 'string') {
3 | return false
4 | }
5 |
6 | try {
7 | JSON.parse(arg)
8 | } catch (e) {
9 | return false
10 | }
11 |
12 | return true
13 | }
14 |
--------------------------------------------------------------------------------
/src/lib/isURI.js:
--------------------------------------------------------------------------------
1 | export default function (type) {
2 | return type.trim().startsWith('http')
3 | }
4 |
--------------------------------------------------------------------------------
/src/lib/textae/Tool/EditorContainer/isTextFields.js:
--------------------------------------------------------------------------------
1 | export default function (htmlElement) {
2 | return (
3 | htmlElement instanceof HTMLInputElement ||
4 | htmlElement instanceof HTMLTextAreaElement
5 | )
6 | }
7 |
--------------------------------------------------------------------------------
/src/lib/textae/Tool/getMousePoint.js:
--------------------------------------------------------------------------------
1 | // Observe and record mouse position to return it.
2 | const lastMousePoint = {}
3 |
4 | document.querySelector('html').addEventListener('mousemove', (e) => {
5 | lastMousePoint.clientY = e.clientY
6 | lastMousePoint.pageY = e.pageY
7 | lastMousePoint.clientX = e.clientX
8 | })
9 |
10 | export default function () {
11 | return lastMousePoint
12 | }
13 |
--------------------------------------------------------------------------------
/src/lib/textae/index.js:
--------------------------------------------------------------------------------
1 | import alertifyjs from 'alertifyjs'
2 | import Tool from './Tool'
3 | import toEditor from './toEditor'
4 | import API from './API'
5 |
6 | export const tool = new Tool()
7 |
8 | export default function initializeTextAEEditor() {
9 | // Set position of toast messages.
10 | alertifyjs.set('notifier', 'position', 'top-right')
11 |
12 | return Array.from(document.querySelectorAll('.textae-editor'))
13 | .filter((element) => !element.dataset.textaeInitialized)
14 | .map((element) => toEditor(tool, element))
15 | .map((editor) => new API(editor))
16 | }
17 |
--------------------------------------------------------------------------------
/src/lib/textae/toEditor.js:
--------------------------------------------------------------------------------
1 | import createEditor from '../createEditor'
2 |
3 | export default function toEditor(tool, element) {
4 | // Create an editor
5 | const editor = createEditor(element, tool)
6 | // Register an editor
7 | tool.registerEditor(element, editor)
8 |
9 | // Mark as initiated.
10 | element.dataset.textaeInitialized = true
11 |
12 | return editor
13 | }
14 |
--------------------------------------------------------------------------------
/tmp/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubannotation/textae/4e173e6a73f53bbed48a0694bcab5c44562b72bb/tmp/.keep
--------------------------------------------------------------------------------
/userAcceptanceTest/20210716_02.md:
--------------------------------------------------------------------------------
1 | ## Lock Edit Config 有効時のパレットの表示項目
2 |
3 | ### 背景
4 |
5 | 1. 6.4.52 で `Lock Edit Config`有効時に、Attribute タブの、定義削除ボタン、定義編集ボタンを無効にしました。
6 |
7 | ### -- 手段 --
8 |
9 | 1. Editor1 を選択
10 | 2. Term モードにする
11 | 3. 設定ダイアログをひらく`Lock Edit Config`にチェックを入れる
12 | 4. パレットを開く
13 | 5. 全選択ボタンが表示されないこと
14 | 6. 編集ボタンが表示されないこと
15 | 7. 削除ボタンが表示されないこと
16 | 8. Attirbute 追加タブが表示されないこと
17 | 9. `denote` タブを選ぶ
18 | 10. `Delete this predicate.`ボタンが無効であること
19 | 11. `Edit this predicate.`ボタンが無効であること
20 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20210720_01.md:
--------------------------------------------------------------------------------
1 | ## パレットはマウスカーソルの近くに開く
2 |
3 | 1. Term モードにする
4 | 2. `Show label list editor [Q]`ボタンをクリックする
5 | 3. パレットがボタンの近くに開くこと
6 | 4. `Q`キーを押す
7 | 5. パレットがマウスカーソルの近くに開くこと
8 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20210720_02_mouse.md:
--------------------------------------------------------------------------------
1 | ## パレットはドラッグできる
2 |
3 | 1. Term モードにする
4 | 2. Entity を選択する
5 | 3. `Q`キーを押す
6 | 4. パレットがドラッグアンドドロップで移動できること
7 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20210720_04.md:
--------------------------------------------------------------------------------
1 | ## Entity 選択時の Entity の見た目の変化
2 |
3 | ### 背景
4 |
5 | 1. 6.2.28 で Entity のエンドポイントの表示をやめました。
6 | 2. 6.4.63 で、Block モード以外のモードでも、背景色を薄くつける対応をしました
7 | 3. このとき BlockEntity を選択肢ときにボーダーが赤色にならなくなりました
8 | 4. 6.4.72 で、対応しました
9 |
10 | ### DenotationEntity
11 |
12 | 1. Term モードにする
13 | 2. Entity を選択する
14 | 3. Entity のラベルのボーダーが赤色になること
15 |
16 | ### BlockEntity
17 |
18 | 1. Editor1 を選択
19 | 2. Block モードにする
20 | 3. Entity を選択する
21 | 4. Entity のラベルのボーダーが赤色になること
22 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20210805_01.md:
--------------------------------------------------------------------------------
1 | ## 保存ファイル名は、読み込んだコンフィグレーションのファイル名
2 |
3 | ### 背景
4 |
5 | 1. コンフィグレーション保存ダイアログの保存ファイルの初期値は、最後に読み込んだコンフィグレーションのファイル名です
6 | 2. 6.1.4 で対応しました
7 |
8 | ### -- 手段 --
9 |
10 | 1. Editor0 を選択
11 | 2. `Show label list editor [Q]`ボタンをクリックする
12 | 3. コンフィグレーション読込ダイアログを開く
13 | 4. ローカルファイルから`1_config.json`を読み込む
14 | 5. `Show label list editor [Q]`ボタンをクリックする
15 | 6. コンフィグレーション保存ダイアログを開く
16 | 7. Local 欄に`1_config.json`が表示されていること
17 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20210805_03.md:
--------------------------------------------------------------------------------
1 | ## 境界検知はデフォルトで有効
2 |
3 | ### 背景
4 |
5 | 1. 6.1.5 から、config の `boundarydetection` の値で境界検知の有効無効を指定できるようになりました
6 | 2. 7.15.0 で境界検知をデフォルトで有効にしました
7 |
8 | ### -- 手段 --
9 |
10 | 1. 境界検知が有効であること
11 | 2. `ゆりかごのうた.json`を読み込む
12 | 3. 境界検知が無効になること
13 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20210805_04.md:
--------------------------------------------------------------------------------
1 | ## 行の高さ自動調整はデフォルトで有効
2 |
3 | ### 背景
4 |
5 | 1. 6.1.5 から、config の `autolineheight` の値で行の高さ自動調整の有効無効を指定できるようになりました
6 | 2. 7.15.0 で行の高さ自動調整をデフォルトで有効にしました
7 |
8 | ### -- 手段 --
9 |
10 | 1. Editor1 を選択
11 | 2. 行の高さ自動調整が無効であること
12 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20210805_05_keyboard.md:
--------------------------------------------------------------------------------
1 | ## シュートカットキーでパレットを開いたときに画面からはみ出ないこと
2 |
3 | ### 背景
4 |
5 | 1. 6.4.78 でパレットをエディターの右端からはみ出ないようにしました
6 | 2. 横スクロールバーが表示されているときに、パレットが下からはみ出ます
7 | 3. windew.innerHeight を使うとスクロールバーを考慮しない高さがとれます
8 | 4. document.documentElement.clientHeight を使えばスクロールバーを考慮した高さがとれます
9 | 5. 6.4.122 で対応しました
10 |
11 | ### -- 手段 --
12 |
13 | 1. Term モードにする
14 | 2. ブラウザの横スクロールバーが表示されるまで、ブラウザの幅を縮める
15 | 3. エディターのブラウザの下端ギリギリ、右端ギリギリをクリックする
16 | 4. `Q`キーを押す
17 | 5. パレットがブラウザからはみ出ないこと
18 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20210806_01.md:
--------------------------------------------------------------------------------
1 | ## Ctrl/Cmd を押して複数選択、Term モードで
2 |
3 | 1. Term モードにする
4 | 2. Span と Span を同時に複数選択する
5 | 3. Entity と Entity を同時に複数選択する
6 | 4. Span と Entity を同時に複数選択する
7 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20210806_02.md:
--------------------------------------------------------------------------------
1 | ## Ctrl/Cmd を押しながら、新しく作った Relation をラベルを使って複数選択
2 |
3 | 1. 新規に Relation を作る
4 | 2. 他の Relation を選択
5 | 3. Ctrl を押しながら新しく作った Relation のラベルをクリック
6 | 4. 両方の Relation が選択されること
7 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20210812_02.md:
--------------------------------------------------------------------------------
1 | ## 自動レプリケーション機能
2 |
3 | ### Boundary Detection 有効時の動作
4 |
5 | 1. `Auto Replicate`ボタンを押下状態にする
6 | 2. 単語の一部を選択する
7 | 3. 単語単位でレプリカが作られること
8 |
9 | ### Boundary Detection 無効時の動作
10 |
11 | 1. `Auto Replicate`ボタンを押下状態にする
12 | 2. 単語の一部を選択する
13 | 3. 文字単位でレプリカが作られること
14 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20210817_02.md:
--------------------------------------------------------------------------------
1 | ## multi tracks
2 |
3 | ### Edit モード
4 |
5 | #### 背景
6 |
7 | 1. multi tracks でも json 上の annotation.text の位置は変わりません。
8 | 2. JSON validator の導入時に annotation.text を track 内から取ろうとするバグがありました。
9 | 3. 4.1.10 で alert からトーストに表示方法を変更しました
10 | 4. 5.0.0 で`Upload`ボタンの制御を有効無効から、星マークの有無に変更しました
11 |
12 | #### -- 手段 --
13 |
14 | 1. multi_tracks.json が読み込めること
15 | 2. 読み込んだ時にトーストが表示されること
16 | 3. 文面は`track annotations have been merged to root annotations.`
17 | 4. Relation に track id が表示されること
18 | 5. `Upload`ボタンに星マークがつくこと
19 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20210818_01.md:
--------------------------------------------------------------------------------
1 | ## Span の Entity をすべて削除したとき Span も一緒に削除する
2 |
3 | ### 背景
4 |
5 | 1. Entity のない Span を削除する機能があります
6 | 2. Entity を一つずつ消して行く場合は正常に動いていました
7 | 3. Entity を複数選択してまとめて消して Span の Entity がなくなったときに、Span が残るバグがありました
8 | 4. 4.1.8 で対応しました
9 | 5. 4.2.1 の開発中に、Span 削除時に unfocus するための DOM 要素が取得できずにエラーが起きました
10 |
11 | ### -- 手段 --
12 |
13 | 1. Span に複数の Entity を作る
14 | 2. Span を選択解除する
15 | 3. すべての Entity を選択し、削除
16 | 4. Span が削除されること
17 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20210819_01.md:
--------------------------------------------------------------------------------
1 | ## Relation の Type を変更する
2 |
3 | ### 背景
4 |
5 | 1. 6.5.4 で namespace プロパティを\_namespace プロパティで参照してエラーが出るようになりました
6 | 2. 6.5.7 で対応しました
7 |
8 | ### -- 手段 --
9 |
10 | 1. Editor1 を選択
11 | 2. Relation モードにする
12 | 3. Relation を選択する
13 | 4. `q`キーを押してパレットを開く
14 | 5. `locatedAt`を選択する
15 | 6. Relation のラベルが`locatedAt`に変わること
16 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20210825_01.md:
--------------------------------------------------------------------------------
1 | ## pubannotation 認証する際にポップアップブロックされる
2 |
3 | ### 背景
4 |
5 | 1. 6.1.14 から PubAnnotation の認証に対応しました
6 | 2. textae は PubAnnotation のログイン画面は新規ウインドウで開きます
7 | 3. ウインドウが閉じられた際に自動的に保存をしに行くために、ウインドウの状態を監視しています
8 | 4. ブラウザの設定よってはポップアップブロック機能によって新規ウインドウがひらけません
9 | 5. ウインドウが開けなかったときにエラーが起きていました
10 |
11 | ### 手段
12 |
13 | 1. ブラウザのポップアップブロック機能で http://localhost:8000/ を対象とする
14 | 2. アノテーション保存ダイアログを開く
15 | 3. URL に`/dev/server_auth`を入力して、Save ボタンを押す
16 | 4. ポップアップがブロックされること
17 | 5. 右上に`could not save`と赤色のトースト表示がされること
18 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20210827_02.md:
--------------------------------------------------------------------------------
1 | ## Editor の下の要素をクリックできる
2 |
3 | ### 背景
4 |
5 | 1. テキストの余白が上に大きく、下は少ないように見せています
6 | 2. 実際のテキストはパラグラフの中央にあります
7 | 3. Editor の下に透明のパラグラフがはみ出しています
8 | 4. はみ出たパラグラフの下の要素がクリックできません
9 | 5. 4.4.0 で Editor の`over-flow`スタイルに`hidden`属性を設定。はみ出たパラグラフを非表示にしました
10 | 6. 5.0.0 でコンテキストメニューを追加したときに、コンテキストメニューを Editor からはみ出させたくなりました
11 | 7. `over-flow`スタイルを設定する要素を、`.textae-editor`から、パラグラフのすぐ親の要素`.textae-editor__body__text-box`に変更しました
12 | 8. 6.0.0 でテキスト中の改行のレンダリングをパラグラフから、css の`white-space: pre-wrap;`に変更しました
13 |
14 | ### -- 手段 --
15 |
16 | 1. Editor1 の下の input をクリックする
17 | 2. input にフォーカスがうつること
18 | 3. input に文字が入力できること
19 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20210901_01.md:
--------------------------------------------------------------------------------
1 | ## annotation ファイル内の begin, end を整数に自動変換する
2 |
3 | ### 背景
4 |
5 | 1. annotation ファイル内の begin, end が文字列の場合、クロススパンの検出時にエラーが出ます
6 | 2. annotation ファイル内の begin, end が小数点を含む場合、生成する span の DOM の ID に`.`が含まれ、DOM の ID として不正な形式になります
7 | 3. 5.3.1 から、begin, end の値を自動的に整数に変換します
8 |
9 | ### -- 手段 --
10 |
11 | 1. invalid.json を読み込む
12 | 2. トーストが表示されること
13 | 3. annotation をソース表示する
14 | 4. `T3`の begin が、ダブルクォートされた文字列ではなく、数値であること
15 | 5. `T3`の end が、少数ではなく、整数であること
16 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20210902_03.md:
--------------------------------------------------------------------------------
1 | ## Relation モードの背景色
2 |
3 | 1. Relation モードにする
4 | 2. 背景が薄ピンク色になること
5 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20210902_05.md:
--------------------------------------------------------------------------------
1 | ## Relation の作成
2 |
3 | ### ctrl
4 |
5 | 1. Relation モードにする
6 | 2. ctrl(Mac の場合は Cmd)を押しながら Relation を作る
7 | 3. 選んでいた Entity と作った Relation が選択される
8 |
9 | ### shift
10 |
11 | 1. Relation モードにする
12 | 2. shift を押しながら Relation を作る
13 | 3. あとに選んだ Entity と作った Relation が選択される
14 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20210907_02.md:
--------------------------------------------------------------------------------
1 | ## editor を選択して、editor 外をクリックすると、editor が選択解除される
2 |
3 | 1. フォーカスされない要素を click しても、Editor を選択解除していませんでした
4 | 2. 4.4.2 から Editor 外を click 時に、Editor を選択解除します
5 |
6 | ### -- 手段 --
7 |
8 | 1. Editor をクリックする
9 | 2. Editor が選択されていること(背景色がベージュ)
10 | 3. 一番上の input の横の`Wellcome!`をクリックする
11 | 4. Editor が選択解除されること(背景色が白)
12 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20210914_01.md:
--------------------------------------------------------------------------------
1 | ## リサイズ後も Relation のラベルクリックで Relation を選択できる
2 |
3 | ### 背景
4 |
5 | 1. jsPlumb は、Relation を描画した直後はラベルのクリックイベントを Relation のクリックイベントとして通知します
6 | 2. リサイズなどで Relation を書き直したとき、Relation を描画する SVG 要素を作り直したときに、ラベルのクリックイベントを通知しなくなります。
7 | 3. 6.1.43 で、描画直後の状態だけで、jsPlumb が常にラベルのクリックイベントを通知すると判断して、ラベルへのイベントハンドラー設定をなくしました
8 | 4. 6.2.38 で、再度ラベルにもイベントハンドラーを設定しました
9 | 5. 6.6.0 で、jsPlumb を廃止し SVG を直接描画することにしました
10 |
11 | ### -- 手段 --
12 |
13 | 1. Relation モードにする
14 | 2. ブラウザをリサイズして、Relation を移動する
15 | 3. Relation のラベルをクリックする
16 | 4. Relation が選択されること
17 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20210914_02.md:
--------------------------------------------------------------------------------
1 | ## 親子 Span の親子とも左端が画面の左端にある親 Span を選択して、左から縮めたときに、親 Span が縮まること
2 |
3 | ### 背景
4 |
5 | 1. anchorNode が子 Span で、focusNode が親 Span のときは必ず anchorNode の Span(子 Span)を広げる処理をしていました
6 | 2. 5.3.2 で、focusNode(親 Span)が選択されているときは、親 Span を縮める処理にする判定を追加しました
7 |
8 | ### -- 手段 --
9 |
10 | 1. Editor1 を選択
11 | 2. Term モードにする
12 | 3. `T1.a.b`の Span を選択せずに、左から、子 Span を超えて、縮める
13 | 4. `E1:a:b`の Span が縮まること
14 | 5. `T1.a.b`の Span を選択して、左から、子 Span を超えて、縮める
15 | 6. `T1.a.b`の Span が縮まること
16 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20210921_02.md:
--------------------------------------------------------------------------------
1 | ## Block モードで DenotationSpan をクリックしたら選択解除する
2 |
3 | ### 背景
4 |
5 | 1. 6.2.42 で対応しました
6 |
7 | ### -- 手段 --
8 |
9 | 1. Block モードにする
10 | 2. BlockSpan を選択
11 | 3. DenotationSpan をクリック
12 | 4. BlockSpan が選択解除されること
13 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20210922_01.md:
--------------------------------------------------------------------------------
1 | ## Block モードで StyleSpan をクリックしたら選択解除する
2 |
3 | ### 背景
4 |
5 | 1. 6.2.41 で対応しました
6 |
7 | ### -- 手段 --
8 |
9 | 1. Block モードにする
10 | 2. BlockSpan を選択
11 | 3. StyleSpan をクリック
12 | 4. BlockSpan が選択解除されること
13 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20210922_02.md:
--------------------------------------------------------------------------------
1 | ## スクロールしたときにコントロールバーが Editor の表示領域上部に張り付く
2 |
3 | ### 背景
4 |
5 | 1. 5.0.0 のコンテキストメニュー追加時に、コントロールバーのみ sticky して、コンテキストメニューは sticky しないことにしました。
6 | 2. 6.6.1 で sticky の実装を JavaScript から CSS に変更しました
7 | 3. Safari で sticky が動きませんでした
8 | 4. 6.6.3 で対応しました
9 |
10 | ### -- 手段 --
11 |
12 | 1. Editor を選択する
13 | 2. ブラウザをスクロールする
14 | 3. Editor がスクロールしても、コントロールバーがスクロールアウトせず、Editor の最上部にいつづけること
15 | 4. ブラウザをもっとスクロールする
16 | 5. Editor がスクロールアウトするときに、コントロールバーも一緒にスクロールアウトすること
17 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20210922_03.md:
--------------------------------------------------------------------------------
1 | ## Block モードで StyleSpan でマウスダウンして、BlockSpan を作る
2 |
3 | ### 背景
4 |
5 | 1. 6.2.48 で対応
6 |
7 | ### -- 手段 --
8 |
9 | 1. Editor1 を選択
10 | 2. Block モードにする
11 | 3. StyleSpan でマウスダウン、テキストでマウスアップ
12 | 4. BlockSpan ができること
13 | 5. StyleSpan でマウスダウン、DenotationSpan でマウスアップ
14 | 6. BlockSpan ができること
15 | 7. StyleSpan でマウスダウン、StyleSpan でマウスアップ
16 | 8. BlockSpan ができること
17 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20210929_01.md:
--------------------------------------------------------------------------------
1 | ## Block モードでテキストでマウスダウンして、BlockSpan を作る
2 |
3 | ### 背景
4 |
5 | 1. 6.2.0 で、テキストでのマウスアップに対応
6 | 2. 6.2.43 で、StyleSpan でのマウスアップに対応
7 | 3. 6.2.44 で、DenotationSpan でのマウスアップに対応
8 |
9 | ### -- 手段 --
10 |
11 | 1. Editor1 を選択
12 | 2. Block モードにする
13 | 3. テキストでマウスダウン、テキストでマウスアップ
14 | 4. BlockSpan ができること
15 | 5. テキストでマウスダウン、DenotationSpan でマウスアップ
16 | 6. BlockSpan ができること
17 | 7. テキストでマウスダウン、StyleSpan でマウスアップ
18 | 8. BlockSpan ができること
19 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20210929_02.md:
--------------------------------------------------------------------------------
1 | ## Block モードで DenotationSpan でマウスダウンして、BlockSpan を作る
2 |
3 | ### 背景
4 |
5 | 1. 6.2.45 で、テキストでのマウスアップに対応
6 | 2. 6.2.46 で、DenotationSpan でのマウスアップに対応
7 | 3. 6.2.47 で、StyleSpan でのマウスアップに対応
8 |
9 | ### -- 手段 --
10 |
11 | 1. Editor1 を選択
12 | 2. Block モードにする
13 | 3. DenotationSpan でマウスダウン、テキストでマウスアップ
14 | 4. BlockSpan ができること
15 | 5. DenotationSpan でマウスダウン、DenotationSpan でマウスアップ
16 | 6. BlockSpan ができること
17 | 7. DenotationSpan でマウスダウン、StyleSpan でマウスアップ
18 | 8. BlockSpan ができること
19 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20210929_03.md:
--------------------------------------------------------------------------------
1 | ## BlockEntity の TypeGap 部分をクリックしたらエディタを選択する
2 |
3 | ### 背景
4 |
5 | 1. 6.2.0 からブロック機能を追加
6 | 2. Term モードにするでは対応していましたが、Block モードでは対応していませんでした。
7 | 3. 6.2.53 で対応しました。
8 |
9 | ### -- 手段 --
10 |
11 | 1. Block モードにする
12 | 2. Editor の選択を解除する(背景色が白くなること)
13 | 3. BlockEntity の TypeGap 部分(ラベルの上の空間)をクリックする
14 | 4. Editor が選択され、背景色が紫色になること
15 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20210929_04.md:
--------------------------------------------------------------------------------
1 | ## BlockEntity を選択する
2 |
3 | ### 背景
4 |
5 | 1. 6.2.0 からブロック機能を追加
6 | 2. BlockEntity を Term モードで選択できていましたが、Block モードでは選択できませんでした。
7 | 3. 6.2.54 で対応しました。
8 |
9 | ### -- 手段 --
10 |
11 | 1. Term モードにする
12 | 2. BlockEntity のラベルをクリックする
13 | 3. BlockEntity が選択されないこと
14 | 4. Block モードにする
15 | 5. BlockEntity のラベルをクリックする
16 | 6. BlockEntity が選択されること
17 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20210930_01.md:
--------------------------------------------------------------------------------
1 | ## BlockSpan を選択したときに自動的に BlockEntity を選択
2 |
3 | ### 背景
4 |
5 | 1. 6.2.0 からブロック機能を追加
6 | 2. BlockSpan は BlockEntity をただひとつ持つので、別々に選択する必要がありません
7 | 3. 6.2.59 で導入
8 |
9 | ### −− 手段 --
10 |
11 | 1. Block モードにする
12 | 2. BlockSpan を選択する
13 | 3. BlockEntity が選択されること
14 | 4. BlockEntity を選択する
15 | 5. BlockSpan が選択されること
16 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20210930_03.md:
--------------------------------------------------------------------------------
1 | ## コンフィグレーションに変更があるときは保存ボタンに星マークを表示
2 |
3 | ### 背景
4 |
5 | 1. 5.0.0 でコンフィグレーションの保存機能を追加しました
6 |
7 | ### -- 手段 --
8 |
9 | 1. editor0 を選択
10 | 2. Setting ダイアログで`Lock Edit Config`のチェックを外す
11 | 3. `Show label list editor [Q]`ボタンをクリックする
12 | 4. コンフィグレーション保存ボタンに星マークがついていること
13 | 5. Local に保存する
14 | 6. コンフィグレーション保存ボタンに星マークが消えること
15 | 7. Type 定義を変更する
16 | 8. コンフィグレーション保存ボタンに星マークがついていること
17 | 9. UNDO する
18 | 10. コンフィグレーション保存ボタンに星マークが消えること
19 | 11. REDO する
20 | 12. コンフィグレーション保存ボタンに星マークがついていること
21 | 13. Local に保存する
22 | 14. コンフィグレーション保存ボタンに星マークが消えること
23 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20210930_04.md:
--------------------------------------------------------------------------------
1 | ## コンフィグレーションを UNDO/REDO したときにトーストを表示
2 |
3 | ### 背景
4 |
5 | 1. 5.2.0 からコンフィグレーションの UNDO/REDO 実行時にトーストを表示します
6 |
7 | ### -- 手段 --
8 |
9 | 1. Type 定義を変更する
10 | 2. UNDO する
11 | 3. 緑色のトーストが表示されること
12 | 4. REDO する
13 | 5. 緑色のトーストが表示されること
14 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211028_01.md:
--------------------------------------------------------------------------------
1 | ## 実用的な annotation を開く
2 |
3 | 1.
4 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211029_01.md:
--------------------------------------------------------------------------------
1 | ## トラックをまたがって ID が重複しているときにバリデーションエラーにしないこと
2 |
3 | ### 背景
4 |
5 | 1. クロススパンの検出はトラックをまたがって判定が必要です。
6 | 2. ID の重複検出はトラックをまたがって判定する必要がありません。
7 | 3. ID の重複検出の際に、クロススパンの検出と同じ対象を使っていました。
8 | 4. 7.26.3 で修正しました。
9 |
10 | ### -- 手段 --
11 |
12 | 1. invalid_multi.json を読む
13 | 2. ID が`track1_T1`と`track2_T1`の Entity が両方表示されること
14 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211102_01.md:
--------------------------------------------------------------------------------
1 | ## Relation モードで Ctrl/Cmd を押して複数選択
2 |
3 | ### 背景
4 |
5 | 1. 5.0.5 で Entity -> Relation の順で選択した際に、Ctrl/Cmd を押していなくても、両方選択されるバグが発生
6 | 2. 6.1.28 で対応
7 |
8 | ### -- 手段 --
9 |
10 | 1. Relation モードにする
11 | 2. Entity を選択する
12 | 3. Relation をクリックする
13 | 4. Entity の選択が解除され、Relation が選択されること
14 | 5. Entity をクリックする
15 | 6. Relation の選択が解除され、Entity が選択されること
16 | 7. Ctrl/Cmd を押して Relation をクリックする
17 | 8. Entity と Relation が両方選択されること
18 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211109_02.md:
--------------------------------------------------------------------------------
1 | ## パレットを開きながらモードを変更したときに選択解除
2 |
3 | ### 背景
4 |
5 | 1. Body クリック時は選択解除するときにパレットが開いていると選択解除しません。
6 | 2. モード変更時も、パレットが開いていると選択解除していませんでした。
7 | 3. モード変更時は、パレットを閉じるのと、選択解除を両方実行するようにしました。
8 | 4. 6.1.61 で対応しました。
9 |
10 | ### -- 手段 --
11 |
12 | 1. Entity を選択する
13 | 2. パレットを開く
14 | 3. モードを変更する
15 | 4. Entity が選択解除されること
16 | 5. パレットが閉じること
17 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211109_03.md:
--------------------------------------------------------------------------------
1 | ## パレットを開いて、Editor を選択解除するとパレットが閉じる
2 |
3 | 1. Editor をクリックする
4 | 2. Editor が選択されていること(背景色がベージュ)
5 | 3. Term モードにする
6 | 4. Entity を選択する
7 | 5. `Show label list editor [Q]`ボタンをクリックする
8 | 6. パレットがボタンの近くに開くこと
9 | 7. 一番上の input をクリックする
10 | 8. Editor が選択解除されること(背景色が白)
11 | 9. パレットが閉じること
12 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211109_04.md:
--------------------------------------------------------------------------------
1 | ## ダイアログを開いているときに Editor をクリックしてもパレットを閉じない
2 |
3 | ### 背景
4 |
5 | 1. jQueryUI ダイアログを開いた時に表示されるベールをクリックすると、Editor 外を選択したと判定して Editor の選択を解除していました
6 | 2. jQueryUI ダイアログは閉じた時に、ダイアログを開いたときに選択していた要素を選択し直す機能があります。このため一見わかりません
7 | 3. パレットはエディタの選択が解除された時点で、閉じます。
8 | 4. ベールが表示されているのに、その下にあるものが操作できるように見えます。これに違和感があります
9 | 5. 5.0.0 で、jQueryUI ダイアログのベールをクリックイベントを無視する対応しました
10 |
11 | ### -- 手段 --
12 |
13 | 1. `Show label list editor [Q]`ボタンをクリックする
14 | 2. パレットが開くこと
15 | 3. アノテーション読込ダイアログを開く
16 | 4. ベールをクリックする
17 | 5. パレットが閉じないこと
18 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211109_05.md:
--------------------------------------------------------------------------------
1 | ## BlockEntity の色とラベル
2 |
3 | ### 背景
4 |
5 | 1. 6.2.0 からブロック機能を追加
6 | 2. 6.2.78 からブロックの Type 定義の色とラベルを BlockEntity に反映します
7 |
8 | ### -- 手段 --
9 |
10 | 1. Editor1 を選択
11 | 2. `block1`のラベルの背景色が赤系であること
12 | 3. `block1`のラベルの文言が`Label of block1`であること
13 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211109_06.md:
--------------------------------------------------------------------------------
1 | ## BlockEntity は TypeGap を表示しない
2 |
3 | ### 背景
4 |
5 | 1. 6.2.0 からブロック機能を追加
6 | 2. DenotationEntity の上側から Relation が出るため、上下に重なる DenotationEntity と DenotationEntity の間に TypeGap と呼ぶ隙間を空けています
7 | 3. BlockEntity は、一つの Span に複数の BlockEntity を持てません
8 | 4. 一つのヒットエリアの中に複数の BlockEntity が上下に並ぶことがなく、TypeGap は必要ありません
9 | 5. 6.2.81 で、BlockEntity の TypeGap をなくしました
10 | 6. TypeGap は Grid の`paddind-top`で実装されています
11 |
12 | ### -- 手段 --
13 |
14 | 1. Editor1 を選択
15 | 2. `block1`に TypeGap がないこと
16 | 3. `block1`に Attribute を追加する
17 | 4. `block1`に TypeGap がないこと
18 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211110_01.md:
--------------------------------------------------------------------------------
1 | ## A キーを押してエラーが起きない
2 |
3 | ### 背景
4 |
5 | 1. 6.1.5 で、Commander をオブジェクトからクラスに変更したときに、メソッド呼び出しの修正もれで、メソッドにレシバーが渡せず、エラーが起きるようになりました
6 | 2. 6.2.73 で対応しました
7 |
8 | ### -- 手段 --
9 |
10 | 1. `A`キーを押す
11 | 2. エラーが起きないこと
12 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211110_02.md:
--------------------------------------------------------------------------------
1 | ## エンティティパレットの左右キーで Attribute タブを切り替える
2 |
3 | ### Block モード
4 |
5 | #### 背景
6 |
7 | 1. 6.2.77 で Block モードに対応しました
8 |
9 | #### -- 手段 --
10 |
11 | 1. Editor1 を選択
12 | 2. Block モードにする
13 | 3. パレットを開く
14 | 4. 右キーを押す
15 | 5. Attribute タブが切り替わること
16 |
17 | ### Attribute がないとき
18 |
19 | #### 背景
20 |
21 | 1. 5.2.0 から左右キーでタブを切り替えられるようにしました
22 | 2. Attribute 定義がないときに、エンティティパレットを開いて右キーを押すとエラーが起きました
23 | 3. 6.2.70 で対応しました
24 |
25 | #### -- 手段 --
26 |
27 | 1. Editor0 を選択
28 | 2. パレットを開く
29 | 3. 右キーを押す
30 | 4. エラーが起きないこと
31 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211110_03.md:
--------------------------------------------------------------------------------
1 | ## Relation をホバーする
2 |
3 | ### 背景
4 |
5 | 1. 6.2.0 で Block モードを追加しました
6 | 2. Block モードではホバーした Relation の線が太くなっていませんでした
7 | 3. 6.5.4 で対応しました
8 | 4. 6.7.1 でホバー時に矢印を大きさを変えるのをやめました
9 |
10 | ### -- 手段 --
11 |
12 | 1. Block モードにする
13 | 2. Relation を持つ Entity をホバーする
14 | 3. Relation のラベルが濃くなること
15 | 4. Relation の線が太くなること
16 | 5. Relation モードにする
17 | 6. Relation のラベルをホバーする
18 | 7. Relation のラベルが濃くなること
19 | 8. Relation の線が太くなること
20 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211110_04.md:
--------------------------------------------------------------------------------
1 | ## BlockSpan をつくったときに TextBox の高さを調整する
2 |
3 | ### 背景
4 |
5 | 1. 6.2.0 からブロック機能を追加
6 | 2. BlockSpan をつくるとテキストが折り返されるため、テキストの高さが変わります。
7 | 3. 変わったテキストの高さに合わせて TextBox の高さを調整する必要があります。
8 | 4. 6.2.29 で対応しました。
9 |
10 | ### -- 手段 --
11 |
12 | 1. Editor4 を選択
13 | 2. Block モードにする
14 | 3. BlockSpan を追加する
15 | 4. テキストがエディタの下にはみ出ていかないこと
16 | 5. 追加した BlockSpan を削除する
17 | 6. テキストの下に余白ができないこと
18 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211117_02.md:
--------------------------------------------------------------------------------
1 | ## DenotationEntity 編集後も選択状態を保持
2 |
3 | 1. Term-Simple モードにする
4 | 2. Type を選択する
5 | 3. Type を編集する
6 | 4. Type 編集後もラベルが選択されていること
7 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211118_01.md:
--------------------------------------------------------------------------------
1 | ## エンティティを選択中かつ Shift キーを押している間に、Span をマウスクリックするとエラーが起きないこと
2 |
3 | ### 背景
4 |
5 | 1. エンティティを選択中かつ Shift キーを押している間に、Span をマウスクリックするとエラーが起きます
6 | 2. 6.0.0 で対応しました。
7 |
8 | ### -- 手段 --
9 |
10 | 1. Term モードにする
11 | 2. エンティティを選択する
12 | 3. Shift キーを押しながら、Span をマウスクリック
13 | 4. エラーが起きないこと
14 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211118_03.md:
--------------------------------------------------------------------------------
1 | ## Entity の見た目
2 |
3 | ### 背景
4 |
5 | 1. 6.2.28 で Entity のエンドポイントの表示をやめました。
6 |
7 | ### -- 手段 --
8 |
9 | 1. Entity の上に丸が表示されないこと
10 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211118_04.md:
--------------------------------------------------------------------------------
1 | ## コンフィグレーション読み込み
2 |
3 | ### 背景
4 |
5 | 1. 5.0.0 でコンフィグレーションの読込機能を追加しました
6 | 2. 6.4.149 でアノテーションとコンフィグレーションを同時に読み込んだ際に、扱うアノテーションのデータ形式をオブジェクトに変更しました。このときガード条件の追加をしなかったため、コンフィグレーションを単独で読み込むときに null 参照エラーが起きていました
7 | 3. 6.4.150 で対応しました
8 |
9 | ### -- 手段 --
10 |
11 | 1. Editor0 を選択
12 | 2. `Show label list editor [Q]`ボタンをクリックする
13 | 3. コンフィグレーション読込ダイアログを開く
14 | 4. URL 欄に`/dev/1_config.json`を入力し、`Open`ボタンを押して、サーバーから読み込む
15 | 5. パレットに`Cell`が表示されること
16 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211124_01.md:
--------------------------------------------------------------------------------
1 | ## コンフィグレーション読込ダイアログで ファイルから JSON でないファイルを読み込んだらエラーを alertify.js で表示
2 |
3 | ### 背景
4 |
5 | 1. 5.0.0 でコンフィグレーションの読込機能を追加しました
6 | 2. 5.3.0 でエラーが起きていました
7 | 3. 5.3.4 で対応
8 |
9 | #### -- 手段 --
10 |
11 | 1. Editor1 を選択
12 | 2. `Show label list editor [Q]`ボタンをクリックする
13 | 3. コンフィグレーション読込ダイアログを開く
14 | 4. URL 欄に`development.html`を入力し、`Open`ボタンを押して、サーバーから読み込む
15 | 5. 右上に`http://localhost:8000/dist/demo/development.html is not a configuration file or its format is invalid.`と赤色のトースト表示がされること
16 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211124_02.md:
--------------------------------------------------------------------------------
1 | ## コンフィグレーション読込ダイアログでテキストエリアに JSON でない文字列を入力して読み込んだらエラーを alertify.js で表示
2 |
3 | ### 背景
4 |
5 | 1. 5.0.0 でコンフィグレーションの読込機能を追加しました
6 | 2. 6.8.0 で機能を追加
7 |
8 | ### -- 手段 --
9 |
10 | 1. Editor0 を選択
11 | 2. `Show label list editor [Q]`ボタンをクリックする
12 | 3. コンフィグレーション読込ダイアログを開く
13 | 4. 適当に JSON ではない文字列をテキストエリアに記入し、`Open`ボタンを押して読み込む
14 | 5. 右上に`instant is not a configuration file or its format is invalid.`と赤色のトースト表示がされること
15 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211124_03.md:
--------------------------------------------------------------------------------
1 | ## 隣の単語と単語の一部が Span になっているときに残りを Span にする
2 |
3 | ### Boundary Detection 有効時の動作
4 |
5 | 1. Editor1 を選択
6 | 2. 隣の単語と単語の一部までが Span にする(例:`Promoter met`)
7 | 3. 単語の残りの部分を選択する(例:`hylation`)
8 | 4. Span ができないこと
9 | 5. テキストの選択が解除されること
10 |
11 | ### Boundary Detection 無効時の動作
12 |
13 | 1. Editor5 を選択
14 | 2. 隣の単語と単語の一部までが Span にする(例:`Ribonucleic a`)
15 | 3. 単語の残りの部分を選択する(例:`cid`)
16 | 4. Span ができること
17 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211124_04.md:
--------------------------------------------------------------------------------
1 | ### コンフィグレーション読込ダイアログで、URL が指定されていなければ Open ボタンを押せない
2 |
3 | ### 背景
4 |
5 | 1. 5.0.0 でコンフィグレーションの読込機能を追加しました
6 |
7 | ### -- 手段 --
8 |
9 | 1. Editor1 を選択
10 | 2. `Show label list editor [Q]`ボタンをクリックする
11 | 3. コンフィグレーション読込ダイアログを開く
12 | 4. URL が空の時は`Open`ボタンは無効
13 | 5. Local のファイルが選択されていない時は`Open`ボタンは無効
14 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211125_01.md:
--------------------------------------------------------------------------------
1 | ## コンフィグレーション読込ダイアログでテキストエリアに直接 JSON を記入し、コンフィグレーションを読み込むことができる
2 |
3 | ### 背景
4 |
5 | 1. 5.0.0 でコンフィグレーションの読込機能を追加しました
6 | 2. 6.8.0 で機能を追加
7 |
8 | ### -- 手段 --
9 |
10 | 1. Editor0 を選択
11 | 2. `Show label list editor [Q]`ボタンをクリックする
12 | 3. コンフィグレーション読込ダイアログを開く
13 | 4. `1_config.json`の内容をコピーし、`JSON`欄のテキストエリアにペーストする
14 | 5. `Open`ボタンを押して、JSON を読み込む
15 | 6. パレットに`Cell`が表示されること
16 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211125_02.md:
--------------------------------------------------------------------------------
1 | ## 読み込んだアノテーションの denotations に不正データが含まれていたら Validation Dialog に表示すること
2 |
3 | ### 背景
4 |
5 | 1. 6.2.20 ID が重複した denotations 検出機能を追加しました
6 | 2. 6.2.93 で`Dupulicated`の typo を修正
7 |
8 | ### -- 手段 --
9 |
10 | 1. invalid.json を読み込む
11 | 2. Validation Dialog を表示すること
12 | 3. `Wrong range denotations.`に `T1`と`E2`が表示されること
13 | 4. `Out of text denotations.`に`begin` が `-2` で `end` が `0` の denotation と`E1`と`T1`と`E2`が表示されること
14 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211130_01.md:
--------------------------------------------------------------------------------
1 | ## コンフィグレーション読込ダイアログで ドラッグアンドドロップでファイルを選択できる
2 |
3 | ### 背景
4 |
5 | 1. 5.0.0 でコンフィグレーションの読込機能を追加しました
6 | 2. 6.7.4 でドラッグアンドドロップでファイルを選択できる機能を追加
7 |
8 | ### -- 手段 --
9 |
10 | 1. Editor0 を選択
11 | 2. `Show label list editor [Q]`ボタンをクリックする
12 | 3. コンフィグレーション読込ダイアログを開く
13 | 4. `1_config.json`をドロップゾーン、またはダイアログ外の背景にドラッグアンドドロップする
14 | 5. `Open`ボタンを押して、ファイルを読み込む
15 | 6. パレットに`Cell`が表示されること
16 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211207_01.md:
--------------------------------------------------------------------------------
1 | ## 読み込んだアノテーションの denotations と blocks の ID 重複の検出
2 |
3 | ### 背景
4 |
5 | 1. 6.2.20 ID が重複した denotations 検出機能を追加しました
6 | 2. 6.2.21 で blocks のバリデーションを追加しました。
7 | 3. 6.2.93 で`Dupulicated`の typo を修正
8 | 4. 6.2.94 ID 重複用のテーブルを denotations と blocks で一つにまとめました
9 | 5. 6.2.95 で denotations と blocks の ID が重複している場合もチェックするようにしました。
10 |
11 | ### -- 手段 --
12 |
13 | 1. invalid.json を読み込む
14 | 2. `Duplicated IDs in Denotations and Blocks.`に`T2`がみっつと`B3`がふたつ表示されること
15 | 3. `Duplicated IDs in Denotations and Blocks.`に`EB1`がふたつ表示されること
16 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211207_03.md:
--------------------------------------------------------------------------------
1 | ## アノテーションファイル中の BlockEntity 間の Relation を読み込める
2 |
3 | ### 背景
4 |
5 | 1. 6.2.0 からブロック機能を追加
6 | 2. アノテーションファイルに BlockEntity 間の Relation を記述しても、Relation の参照先として BlockEntity が見つからにためバリデーションエラーになっていました
7 | 3. 6.2.97 で対応しました。
8 |
9 | ### -- 手段 --
10 |
11 | 1. Editor1 を選択
12 | 2. BlockEntity `B1`と`B2`の間に Relation が描画されていること
13 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211207_04.md:
--------------------------------------------------------------------------------
1 | ## アノテーションファイル中の BlockEntity 間の Attribute を読み込める
2 |
3 | ### 背景
4 |
5 | 1. 6.2.0 からブロック機能を追加
6 | 2. アノテーションファイルに BlockEntity の Attribute を記述しても、Attribute の参照先として BlockEntity が見つからにためバリデーションエラーになっていました
7 | 3. 6.2.99 で対応しました。
8 |
9 | ### -- 手段 --
10 |
11 | 1. Editor1 を選択
12 | 2. BlockEntity `B1` の Attribute が描画されていること
13 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211207_05.md:
--------------------------------------------------------------------------------
1 | ## ブロックを含むアノテーションを読み込んだあとに他のアノテーションにを読み込めること
2 |
3 | ### 背景
4 |
5 | 1. アノテーションを読み込む際に、読み込み済みのブロック情報をクリアしていませんでした。
6 | 2. 読み込んだアノテーションと矛盾が生じてエラーが起きていました。
7 | 3. 6.2.4 で対応
8 |
9 | #### -- 手段 --
10 |
11 | 1. Editor1 を選択
12 | 2. `prefix.json`を開く
13 | 3. エラーが起きないこと
14 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211207_06.md:
--------------------------------------------------------------------------------
1 | ## 選択中の BlockSpan で DenotationEntity を隠さない
2 |
3 | ### 背景
4 |
5 | 1. 6.2.0 からブロック機能を追加
6 | 2. ブロックスパンの位置を、実際の div 要素の位置より半行上に見せかけるために、背景用の div を追加しています
7 | 3. ブロックモードでは、ブロックをクリックできるように、背景用 div の z-index を加算していました
8 | 4. 背景用 div に選択中のスタイルを適用したときに DenotationEntity を隠していました
9 | 5. 6.2.37 で、背景用 div と別にマウス操作用の div を追加して、対応しました。
10 |
11 | ### -- 手段 --
12 |
13 | 1. DenotationSpan の親になる BlockSpan を作成する
14 | 2. DenotationEntity の色が変わらないこと
15 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211207_07.md:
--------------------------------------------------------------------------------
1 | ## Block 要素の div をクリックしたら選択解除する
2 |
3 | ### 背景
4 |
5 | 1. BlockSpan は div としてレンダリングしています
6 | 2. BlockSpan の表示位置を半行上に見せかけるために、BlockSpan は背景とヒットエリアを別に持っています
7 | 3. BlockSpan 自体のマウスクリックイベントをハンドリングしていなかったため、BlockSpan の背景のすぐ下をクリックしたときに選択解除していませんでした。
8 | 4. 6.2.39 で対応しました
9 |
10 | ### -- 手段 --
11 |
12 | 1. Term モードにする
13 | 2. Span を選択する
14 | 3. Block のすぐ下をクリックする
15 | 4. Span が選択解除されること
16 | 5. Block モードにする
17 | 6. BlockSpan を選択する
18 | 7. BlockSpan のすぐ下をクリックする
19 | 8. BlockSpan が選択解除されること
20 | 9. Relation モードにする
21 | 10. Relation を選択する
22 | 11. BlockSpan のすぐ下をクリックする
23 | 12. Relation が選択解除されること
24 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211208_01.md:
--------------------------------------------------------------------------------
1 | ## コンフィグレーション読込ダイアログでテキストエリアに記入した JSON を、エディタを使って編集できる
2 |
3 | ### 背景
4 |
5 | 1. 5.0.0 でコンフィグレーションの読込機能を追加しました
6 | 2. 6.8.0 で機能を追加
7 |
8 | ### -- 手段 --
9 |
10 | 1. Editor0 を選択
11 | 2. `Show label list editor [Q]`ボタンをクリックする
12 | 3. コンフィグレーション読込ダイアログを開く
13 | 4. `1_config.json`の内容をコピーし、`JSON`欄のテキストエリアにペーストする
14 | 5. `Edit`ボタンを押して、JSON エディタを展開する
15 | 6. エディタ上で`"id": "Cell"`を`"id": "cell"`に書き換える
16 | 7. `Open`ボタンを押して JSON を読み込む
17 | 8. パレットに`cell`が表示されること
18 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211208_04.md:
--------------------------------------------------------------------------------
1 | ## ファイル読み込み時の認証情報入力
2 |
3 | ### 背景
4 |
5 | 1. 4.1.19 から Basic 認証付きの anntation.json の読み込みに対応しました。
6 |
7 | ### -- 手段 --
8 |
9 | 1. アノテーション読込ダイアログを開く
10 | 2. を読み込む
11 | 3. 認証ダイアログが開くこと
12 | 4. ユーザーに`Jin-Dong Kim`、パスワードに`passpass`を設定してログインボタンを押す
13 | 5. private.json を読み込めること
14 | 6. 一度認証に成功するとブラウザがユーザーとパスワードを記憶します。もう一度試す場合はブラウザを再起動すること
15 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211208_06.md:
--------------------------------------------------------------------------------
1 | ## ホバー
2 |
3 | ### 背景
4 |
5 | 1. 6.0.0 で Modification を廃止しました
6 | 2. 6.1.49 Entity のインスタンスだけでなく、ラベルをホバーしたときも Relation を強調するようにしました
7 | 3. 6.2.28 で Entity のエンドポイントの表示をやめました
8 | 4. 6.2.85 で Term モードで、Relation が強調されなくなっていました
9 | 5. 6.2.101 で対応しました
10 | 6. 6.7.0 で Relation のラベルを Entity と同じ表示形式(以降看板と呼ぶ)に変更しました
11 |
12 | ### 連動
13 |
14 | 1. Entity のラベルをホバーすると Relation も強調する
15 | 2. Relation のラベルをホバーすると Relation も強調する
16 |
17 | ### ホバー時の見た目の変化
18 |
19 | 1. Entity のラベルの div にシャドウ
20 | 2. Relation は Relation モードでのみラベルの div にシャドウ
21 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211208_07.md:
--------------------------------------------------------------------------------
1 | ## コピー&ペースト
2 |
3 | ### 背景
4 |
5 | 1. 6.0.0 で Modification を廃止しました。
6 | 2. 6.1.1 で一つの denotation を一つのエンティティに表示することしました。
7 |
8 | ### span
9 |
10 | 1. Editor1 を選択
11 | 2. Attribute と Relation を持つ Entity のある Span を選択してコピーする
12 | 3. 他の Span を選択して貼り付ける
13 | 4. 選択した Span の全ての Entity と Attribute が、対象 Span に張り付く
14 | 5. Relation はコピーされない
15 |
16 | ### Entity
17 |
18 | 1. Editor1 を選択
19 | 2. Attribute と Relation を持つ Entity のある Entity を選択してコピーする
20 | 3. 他の Span を選択して貼り付ける
21 | 4. 選択した全ての Entity とその Attribute、対象 Span に張り付く
22 | 5. Relation はコピーされない
23 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211208_08.md:
--------------------------------------------------------------------------------
1 | ## リサイズすると Grid を移動する
2 |
3 | ### 背景
4 |
5 | 1. 4.1.10 の修正中に、リサイズしても、二段目より上の Type が横に移動するだけで縦に移動しなくなりました。
6 | 2. 4.4.3 の修正中に、Grid だけ移動して、Relation が移動しなくなりました
7 |
8 | ### -- 手段 --
9 |
10 | 1. ウインドウをリサイズする
11 | 2. Grid が Span に追従して移動すること
12 | 3. Relation が Grid に追従して移動すること
13 |
14 | ### Relation を選択してリサイズする
15 |
16 | 1. Relation モードにする
17 | 2. Relation を選択
18 | 3. リサイズして選択した Relation を移動する
19 | 4. 矢印が小さくならないこと
20 | 5. ホバーしても、線が細くならないこと
21 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211208_09.md:
--------------------------------------------------------------------------------
1 | ## タイプ変更を Undo したとき、変更対象を選択しない
2 |
3 | ### 背景
4 |
5 | 1. 6.2.0 からブロック機能を追加
6 |
7 | ### DenotationEntity
8 |
9 | 1. Term モードにする
10 | 2. DenotationEntity を選択
11 | 3. タイプを変更する
12 | 4. 戻す
13 | 5. 選択されないこと
14 |
15 | ### BlockEntity
16 |
17 | 1. Block モードにする
18 | 2. BlockEntity を選択
19 | 3. タイプを変更する
20 | 4. 戻す
21 | 5. 選択されないこと
22 |
23 | ### Relation
24 |
25 | 1. Relation モードにする
26 | 2. Relation を選択
27 | 3. タイプを変更する
28 | 4. 戻す
29 | 5. 選択されないこと
30 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211208_10.md:
--------------------------------------------------------------------------------
1 | ## 外部 JavaScript で Editor を初期フォーカスできること
2 |
3 | 1. を開く
4 | 2. Editor1 が選択されていること(背景色がベージュ)
5 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211209_01.md:
--------------------------------------------------------------------------------
1 | ## 起動直後
2 |
3 | ### 背景
4 |
5 | 1. `4.4.0`からデフォルト文字列を表示します
6 | 2. annotation がない場合も、Editor はサイズがありクリックできます
7 | 3. 起動時に一番上の Editor を選択する機能を消します
8 |
9 | ### -- 手段 --
10 |
11 | 1. Editor7 が選択されていないこと(背景色が白い)
12 | 2. Editor7 をクリック
13 | 3. Editor7 が選択されること(背景色がベージュ)
14 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211209_02.md:
--------------------------------------------------------------------------------
1 | ## Span は必ず Entity を持つ
2 |
3 | ### Entity を自動作成
4 |
5 | #### 背景
6 |
7 | 1. 4.1.8 で Entity につける id の prefix を`E`から`T`に変えました
8 | 2. 6.2.0 からブロック機能を追加
9 |
10 | #### -- 手段 --
11 |
12 | 1. Term モードにする
13 | 2. DenotationSpan を作成する
14 | 3. default の Type の Entity ができること
15 | 4. Entity の id が`T`で始まること
16 | 5. Block モードにする
17 | 6. BlockSpan を作成する
18 | 7. default の Type の Entity ができること
19 | 8. Entity の id が`T`で始まること
20 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211209_03.md:
--------------------------------------------------------------------------------
1 | ## コピーした Entity を削除してから貼付ける
2 |
3 | 1. Entity を選択する
4 | 2. コピーする
5 | 3. 削除する
6 | 4. 別の Span を選択する
7 | 5. 貼付ける
8 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211214_01.md:
--------------------------------------------------------------------------------
1 | ## 特殊な Type 文字列
2 |
3 | ### ドメインな文字列
4 |
5 | #### 背景
6 |
7 | 1. Type の Value に url を指定した場合は短縮してラベルに表示します
8 | 2. Type が`http://pubmed.org/`のときにディレクトリ名を取得しようとして空文字を取得していた
9 | 3. ラベルが空だと正しくレンダリングできません
10 | 4. 4.1.8 で対応しました
11 |
12 | #### -- 手段 --
13 |
14 | 1. Editor1 を選択
15 | 2. Type `http://pubmed.org/`の表示が`pubmed.org`になること
16 |
17 | ### ドメインが localhost
18 |
19 | 1. 既存の Entity を選択する
20 | 2. Type の Value を`http://localhost:8000/abc`に変更する
21 | 3. Type の表示が abc になること
22 |
23 | ### http で始まる URL ではない文字列
24 |
25 | 1. 既存の Entity を選択する
26 | 2. Type の Value を`http://hoge`に変更する
27 | 3. Type の表示が`http://hoge`になること
28 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211215_02.md:
--------------------------------------------------------------------------------
1 | ## 未保存変更があるときに、別のアノテーションを読み込もうとすると確認ダイアログを表示
2 |
3 | ### 背景
4 |
5 | 1. 保存していない変更があるか状態を持っています
6 | 2. 変更があるときに load しようとすると確認ダイアログを表示します
7 | 3. 一度保存すると変更状態をリセットします
8 | 4. 確認ダイアログを表示しなくなります
9 |
10 | ### -- 手段 --
11 |
12 | 1. 変更する
13 | 2. 読込む
14 | 3. 確認ダイアログが出る
15 | 4. キャンセルする
16 | 5. 保存する
17 | 6. 読込む
18 | 7. 確認ダイアログが出ない
19 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211215_03.md:
--------------------------------------------------------------------------------
1 | ## Attribute インスタスがあるアノテーション読み込んでから、Attribute 定義がないアノテーションを読み込む
2 |
3 | ### 背景
4 |
5 | 1. アノテーションを読み込むときにコンフィグレーションも読み直しています
6 | 2. コンフィグレーションを読みなおしたときにすべての Entity をレンダリングしなおしています
7 | 3. Attribute を持つ Entity をレンダリングするときに Attribute の表示名を取得しようとします
8 | 4. 6.4.90 で Attribute の表示名を取得するときに、Attribute 定義がなかったときにエラーが起きるようにしました
9 | 5. コンフィグレーションがリセット済みのため Attribute 定義が存在しないためエラーが起きます
10 | 6. 6.4.141 で対応しました
11 |
12 | ### -- 手段 --
13 |
14 | 1. Editor1 を選択
15 | 2. アノテーション読込ダイアログを開く
16 | 3. ローカルファイルから`private.json`を読み込む
17 | 4. エラーが起きないこと
18 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211215_04.md:
--------------------------------------------------------------------------------
1 | ## BlockEntity 編集ダイアログを開く
2 |
3 | ### Change Label[W]ボタン
4 |
5 | 1. Block モードにする
6 | 2. BlockEntity を選択する
7 | 3. `Change Label[W]`ボタンを押す
8 | 4. 編集ダイアログが開くこと
9 |
10 | ### W キー
11 |
12 | 1. Block モードにする
13 | 2. BlockEntity を選択する
14 | 3. `W`キーを押す
15 | 4. 編集ダイアログが開くこと
16 |
17 | ### コンテキストメニュー
18 |
19 | 1. Block モードにする
20 | 2. BlockEntity を選択する
21 | 3. 右クリックする
22 | 4. コンテキストメニューが開くこと
23 | 5. コンテキストメニューの
24 | 6. `Change Label[W]`ボタンを押す
25 | 7. 編集ダイアログが開くこと
26 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211215_05.md:
--------------------------------------------------------------------------------
1 | ## BlockSpan にはひとつの BlockEntity しか追加できない
2 |
3 | ### 背景
4 |
5 | 1. 6.2.110 で、BlockSpan にはひとつの BlockEntity しか追加できなくしました
6 |
7 | ### -- 手順 --
8 |
9 | 1. Editor1 を選択
10 | 2. Block モードにする
11 | 3. BlockSpan を選択
12 | 4. `E`キーを押す
13 | 5. BlockEntity が追加されないこと
14 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211215_07.md:
--------------------------------------------------------------------------------
1 | ## 該当 Attribute を持つアイテムを選択しているときに、パレットの Attribute 削除ボタンを有効にする
2 |
3 | ### 背景
4 |
5 | 1. 6.4.58 で無効理由を title タグで記述します
6 |
7 | ### -- 手段 --
8 |
9 | 1. Editor1 を選択
10 | 2. Term モードにする
11 | 3. Attribute のない Entity を一つ選択する
12 | 4. `q` キーを押してパレットを開く
13 | 5. `denote` タブを選ぶ
14 | 6. `remove form`ボタンが無効であること
15 | 7. title が`None of the selected items has this attribute.`であること
16 | 8. `add to`ボタンを押す
17 | 9. `remove form`ボタンが有効になること
18 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211216_01.md:
--------------------------------------------------------------------------------
1 | ## Selection Attribute 定義の Value の label、color 変更
2 |
3 | ### 背景
4 |
5 | 1. 5.2.0 から Entity パレットで Selection Attribute の Value が編集出来るようになりました。
6 |
7 | ### -- 手段 --
8 |
9 | 1. Editor1 を選択
10 | 2. Term モードにする
11 | 3. `Show label list editor [Q]`ボタンをクリックする
12 | 4. `denote`タブを選択
13 | 5. `Cell`の`Edit this value`ボタンをクリックする
14 | 6. `label`欄を変更する
15 | 7. `color`欄を変更する
16 | 8. `OK`ボタンを押す
17 | 9. パレットの Value の値が更新されるここと
18 | 10. エンティティ`E1:a:b`の Attribute のラベルと色が更新されるここと
19 | 11. すべてもどす
20 | 12. すべてやり直す
21 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20211224_03.md:
--------------------------------------------------------------------------------
1 | ## DenotationEntity を選択して編集ダイアログを開く
2 |
3 | ### Change Label[W]ボタン
4 |
5 | 1. Term モードにする
6 | 2. DenotationEntity を選択する
7 | 3. `Change Label[W]`ボタンを押す
8 | 4. 編集ダイアログが開くこと
9 |
10 | ### W キー
11 |
12 | 1. Term モードにする
13 | 2. DenotationEntity を選択する
14 | 3. `W`キーを押す
15 | 4. 編集ダイアログが開くこと
16 |
17 | ### コンテキストメニュー
18 |
19 | 1. Term モードにする
20 | 2. DenotationEntity を選択する
21 | 3. 右クリックする
22 | 4. コンテキストメニューが開くこと
23 | 5. コンテキストメニューの
24 | 6. `Change Label[W]`ボタンを押す
25 | 7. 編集ダイアログが開くこと
26 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220105_01.md:
--------------------------------------------------------------------------------
1 | ## BlockSpan のヒットエリアのタイトルに BlockSpan の ID を表示
2 |
3 | ### 背景
4 |
5 | 1. 6.4.62 で対応
6 |
7 | ### -- 手段 --
8 |
9 | 1. Editor1 を選択
10 | 2. BlockSpan のヒットエリアのタイトルに Span の ID が`begin-end`形式で入っていること
11 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220106_01.md:
--------------------------------------------------------------------------------
1 | ## 連続した BlockSpan の間に空行が挟まらない
2 |
3 | ### 背景
4 |
5 | 1. 6.2.0 で Block モードを追加しました
6 | 2. BlockSpan を div で表現しているため、div 間に改行が挟まれ、1 行余計に隙間が空いていました
7 | 3. 6.2.114 で、BlockSpan に`display: inline-block`と`width: 100px`を指定して、改行しつつ、余計な空行は挟まらないようにしました
8 |
9 | ### -- 手段 --
10 |
11 | 1. Editor1 を選択
12 | 2. `block1`と`block2`の間に隙間がないこと
13 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220106_05.md:
--------------------------------------------------------------------------------
1 | ## Relation の編集
2 |
3 | ### 背景
4 |
5 | 1. 6.0.0 で Modification を廃止しました。
6 |
7 | ### 作る、変える、消す
8 |
9 | 1. Span を2つ作る
10 | 2. Relation モードにする
11 | 3. Relation を作る
12 | 4. 作った Relation が選択される
13 | 5. Relation の type を変更する
14 | 6. Relation の線が細くならないこと
15 | 7. 作った Relation を消す
16 | 8. Entity を片方消す
17 | 9. Span が残っていたら Span を消す(Span の Entity がゼロ個になると、Span は自動的に削除されます)
18 | 10. 全て戻す
19 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220112_02.md:
--------------------------------------------------------------------------------
1 | ## Attribute 定義の順序変更
2 |
3 | ### 背景
4 |
5 | 1. 5.3.6 で、パレットの Attribute タブをドラッグアンドドロップして、Attribute 定義の順序を変更する機能を追加しました。
6 | 2. Attribute 定義の最大数を超えているときに、プラスタブを表示しません。
7 | 3. このとき同時に最後尾へのドロップができなくなっていました。
8 | 4. 6.4.88 で対応しました。
9 |
10 | ### -- 手順 --
11 |
12 | 1. Editor1 を選択
13 | 2. Term モードにする
14 | 3. `Q`キーを押してパレットを開く
15 | 4. `denote`タブを選択する
16 | 5. `denote`タブをドラッグして、`warning`タブの前の矢印の上に移動する、タブの左側に空間ができること
17 | 6. ドロップする
18 | 7. `denote`タブが、`warning`タブの前に移動すること
19 | 8. Z キーを押す
20 | 9. `denote`タブが先頭に戻ること
21 | 10. a~p までの Attribute 定義を追加する
22 | 11. o を p の後ろにドロップする
23 | 12. `o`タブが`p`タブの後ろに移動すること
24 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220112_03.md:
--------------------------------------------------------------------------------
1 | ## 別の annotatian を開いて高さが再計算されること
2 |
3 | ### 背景
4 |
5 | 1. annotation によって行数が変わるので高さを再計算しなくてはいけません。
6 |
7 | ### -- 手段 --
8 |
9 | 1. 1_annotations.json を開く
10 | 2. multi_tracks.json を開く
11 | 3. 高さが再計算されること
12 | 4. 下側の隙間が狭いこと
13 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220112_04.md:
--------------------------------------------------------------------------------
1 | ## DenotationEntity 編集ダイアログの編集キャンセル
2 |
3 | ### 閉じるボタン
4 |
5 | 1. Term モードにする
6 | 2. DenotationEntity を選択する
7 | 3. `W`キーを押す
8 | 4. 編集ダイアログが開くこと
9 | 5. 文字を変更する
10 | 6. `X`ボタンを押す
11 | 7. DenotationEntity の id が変わらないこと
12 |
13 | ### Esc キー
14 |
15 | 1. Term モードにする
16 | 2. DenotationEntity を選択する
17 | 3. `W`キーを押す
18 | 4. 編集ダイアログが開くこと
19 | 5. 文字を変更する
20 | 6. `Esc`キーを押す
21 | 7. DenotationEntity の id が変わらないこと
22 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220112_05.md:
--------------------------------------------------------------------------------
1 | ## BlockSpan のヒットエリア
2 |
3 | ### 背景
4 |
5 | 1. Block モードでは、BlockSpan のヒットエリアに背景色が着いていました
6 | 2. 6.4.63 で、Block モード以外のモードでも、背景色を薄くつける対応をしました
7 |
8 | ### -- 手段 --
9 |
10 | 1. Editor1 を選択
11 | 2. Term モードにする
12 | 3. BlockSpan のヒットエリアに背景色があること
13 | 4. Block モードにする
14 | 5. BlockSpan のヒットエリアに背景色が濃くなること
15 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220112_06.md:
--------------------------------------------------------------------------------
1 | ## 長い文字列を含むアノテーションを開く
2 |
3 | ### 背景
4 |
5 | 1. Google chrome と Safari は 65536 文字以上のテキストを複数の text node に分割します。
6 | 2. span の開始位置の offset が text node の範囲を越えることがあります。
7 | 3. text node の中に span をつくる場所が見つからずエラーになっていました。
8 | 4. 6.0.4 で対応しました。
9 |
10 | ### 手段
11 |
12 | 1. を読み込む
13 | 2. エラーが起きないこと
14 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220112_07.md:
--------------------------------------------------------------------------------
1 | ## Entity に HTML タグを含むラベルを設定したときにラベルの定義に HTML エスケープされた文字列が設定されないこと
2 |
3 | ### 背景
4 |
5 | 1. ラベルは編集ダイアログの HTML 要素に innerText を使って設定され、その値を取得するときに innerHTML を使っていたため、HTML タグを含むラベルを設定した際に、HTML エスケープされていました。
6 | 2. 6.4.18 で対応しまた。
7 |
8 | ### -- 手段 --
9 |
10 | 1. Editor1 を選択
11 | 2. Term モードにする
12 | 3. Entity を選択する
13 | 4. `w`キーを押して Entity 編集ダイアログを開く
14 | 5. `Value:`欄に`HTML`を入力する
15 | 6. 候補から`HTML tag label`を選択し、確定する
16 | 7. `q`キーを押してパレットを開く
17 | 8. `Save Configurations`ダイアログを開く
18 | 9. `entity types`に`HTML tag label`の変更がないこと
19 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220118_02.md:
--------------------------------------------------------------------------------
1 | ## line-height 変更
2 |
3 | ### 背景
4 |
5 | 1. 4.1.8 で text−box の下の隙間を小さくした
6 | 2. 4.1.16 の開発中にモジュール読み込み構文の修正漏れでエラーを起こしていました。
7 |
8 | ### -- 手段 --
9 |
10 | 1. Seting ダイアログを開く
11 | 2. line-height を変更する
12 | 3. 高さが再計算されること
13 | 4. 下側の隙間が狭いこと
14 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220119_01.md:
--------------------------------------------------------------------------------
1 | ## 先頭の Span を後ろから縮めて消したときにエラーが起きない
2 |
3 | ### 背景
4 |
5 | 1. 6.1.53 で、追加した必須パラメータのアサーションに 0 も引っかかって発生
6 | 2. 6.3.3 で対応
7 |
8 | ### -- 手段 --
9 |
10 | 1. Editor0 を選択
11 | 2. 最初の Span を後ろから縮めて消す
12 | 3. エラーが起きないこと
13 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220119_02.md:
--------------------------------------------------------------------------------
1 | ## 該当 Attribute のない Entity を選択しているときに、ショートカットキーから Attribute インスタンスを削除しようとしたら警告を表示する
2 |
3 | ### 背景
4 |
5 | 1. 6.4.58 で無効理由を title タグで記述します
6 | 2. ショートカットキーから削除できないときも、同様の情報をアラート表示します。
7 | 3. 6.4.124 で対応しました
8 |
9 | ### -- 手段 --
10 |
11 | 1. Editor1 を選択
12 | 2. Term モードにする
13 | 3. Attribute のない Entity を一つ選択する
14 | 4. `shift`キーを押しながら、`1`キーを押す
15 | 5. `None of the selected items has this attribute.`がアラート表示されること
16 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220119_03.md:
--------------------------------------------------------------------------------
1 | ## アノテーション保存時にメッセージを alertify.js で表示
2 |
3 | ### 背景
4 |
5 | 1. ステータスバーにメッセージを表示していました。
6 | 2. Editor が大きいと隠れていた
7 | 3. トーストを使って表示します
8 |
9 | ### -- 手段 --
10 |
11 | 1. annotation を保存する
12 | 2. 右上に`annotation saved`と緑色のトースト表示がされること
13 | 3. サーバを落とす
14 | 4. サーバに annotation を保存する
15 | 5. 右上に`could not save`と赤色のトースト表示がされること
16 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220119_04.md:
--------------------------------------------------------------------------------
1 | ## shift を押して Span を選択
2 |
3 | ### コピー
4 |
5 | 1. Term モードにする
6 | 2. shift で複数の Span をえらぶ
7 | 3. コピーする
8 | 4. 貼り付けする
9 | 5. 選択してる Span の全ての Entity がコピーされること
10 |
11 | ### 削除
12 |
13 | 1. Term モードにする
14 | 2. shift で複数の Span をえらぶ
15 | 3. 削除する
16 | 4. 選択してる Span が全て削除されること
17 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220119_06.md:
--------------------------------------------------------------------------------
1 | ## inline で連続した空白を含む annotation を開けること
2 |
3 | ### 背景
4 |
5 | 1. inline の annotation の text に、連続した空白が含まれていた場合、埋め込んだ時点で、1つの空白にまとめられていた
6 | 2. annotation の texte に、連続した空白が含まれていた場合、Editor 上に表示する文字列ので、1つの空白にまとめられていた
7 | 3. `textae-editor`クラスと、`textae-editor__body__text-box__paragraph-margin`クラスに、`white-space: pre`スタイルを指定が必要
8 | 4. v4.5.7 で対応
9 |
10 | ### -- 手段 --
11 |
12 | 1. editor9 を選択
13 | 2. `stomach`の Span がズレていないこと
14 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220121_02.md:
--------------------------------------------------------------------------------
1 | ## 兄弟 Span を親 Span にする
2 |
3 | ### 背景
4 |
5 | 1. 5.2.1, 5.2.2 で並んだ兄弟 Span の片方を伸ばすして、端を共有する親子 Span にする操作を便利にしました
6 | 2. 以前は、一度両側がはみ出た大きな親 Span にしてから、はみ出た部分を縮める操作が必要でした
7 | 3. 5.2.1 で、親にしたい Span を選択して、伸ばして子にしたい Span の上で mouse up して、端を共有する親 Span にできるようになりました
8 | 4. 5.2.2 で、親にしたい Span を選択して、伸ばして子にしたい Span の上にブラウザのセレクションが有る状態で、テキスト間の空白領域で mouse up して、端を共有する親 Span にできるようになりました
9 |
10 | ### -- 手段 --
11 |
12 | 1. Term モードにする
13 | 2. Span を作る
14 | 3. 兄弟になる Span を作る
15 | 4. 片方の Span をもう片方の Span を覆う範囲に広げる
16 | 5. 親子 Span になること
17 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220121_03.md:
--------------------------------------------------------------------------------
1 | ## annotation なし
2 |
3 | ### 背景
4 |
5 | 1. 開発中は annotation なしで開きません。エラーの見落としが多いです。
6 | 2. `4.4.0`から、annotation がない時はデフォルト文字列を表示します。
7 | 3. `4.5.0`から、html 属性で`mode="edit"`をつけない場合は View モードになり、View モードの場合はコントロールバーを表示しなくしました。
8 |
9 | ### Edit モード
10 |
11 | 1. Editor7 を選択
12 | 2. Editor 中に`Currently, the document is empty. Use the "import" button or press the key "i" to open a document with annotation.`が表示されること
13 | 3. エディタを選択するとコントロールバーが表示されること
14 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220125_01.md:
--------------------------------------------------------------------------------
1 | ## 連続した空白の扱い
2 |
3 | ### 背景
4 |
5 | 1. 5.0.0 アノテーションテキスト中の連続した空白をまとめずに描画しています。
6 | 2. Span をつくると、Span 内では連続した空白をまとめていました。
7 | 3. 6.1.1 で対応しました。
8 |
9 | ### -- 手段 --
10 |
11 | 1. editor9 を選択
12 | 2. `stomach ache`を Span にする
13 | 3. 単語の間の連続した空白がまとまらないこと
14 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220125_03.md:
--------------------------------------------------------------------------------
1 | ## Attribute 定義がないときにパレットが開ける
2 |
3 | ### 背景
4 |
5 | 1. 5.0.0 で Attitude を追加しました
6 | 2. 6.4.91 で、6.4.88 で Attribute 定義がないときにパレットを開くとエラーが起きていたのを直しました
7 |
8 | ### -- 手段 --
9 |
10 | 1. Editor0 を選択
11 | 2. Term モードにする
12 | 3. `q` キーを押してパレットを開く
13 | 4. エラーが起きないこと
14 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220127_02.md:
--------------------------------------------------------------------------------
1 | ## BlockSpan は親 Span を持たない
2 |
3 | ### 背景
4 |
5 | 1. BlockSpan はなんらかの Span の子になることはありません。Block モードで、他の Span の子 BlockSpan を作成できていました。
6 | 2. 6.3.7 で対応しました
7 |
8 | ### -- 手段 --
9 |
10 | 1. Term モードにする
11 | 2. 複数単語を選択して DenotationSpan を作成する
12 | 3. Block モードにする
13 | 4. 作成した DenotationSpan 中の 1 単語を選択する
14 | 5. BlockSpan が作られないこと
15 | 6. 文字列の選択が解除されること
16 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220202_01.md:
--------------------------------------------------------------------------------
1 | ## Entity パレットのタイトルを折り返さない
2 |
3 | ### 背景
4 |
5 | 1. Attribute 定義がたくさんあるとき、EntityPallet のタイトルが折り返していました。
6 | 2. 6.3.12 でタイトルに最低幅を設定しました。
7 |
8 | ### -- 手段 --
9 |
10 | 1. Editor1 を選択
11 | 2. Term モードにする
12 | 3. `Q`キーを押して、EntityPallet を開く
13 | 4. 左上のタイトル`Entity Configuration`が折り返さないこと
14 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220202_02.md:
--------------------------------------------------------------------------------
1 | ## ステータスバーの表示非表示
2 |
3 | ### 背景
4 |
5 | 1. 4.1.6 でステータスバーのデフォルト非表示になりました
6 | 2. status_bar オプションで切り替えます
7 | 3. 値は on と off の2つです
8 |
9 | ### -- 手段 --
10 |
11 | 1. 属性の status_bar に on を指定するとステータスバーが表示されること(editor1)
12 | 2. 属性の status_bar を指定しないとステータスバーが表示されないこと(editor2)
13 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220202_03.md:
--------------------------------------------------------------------------------
1 | ## スタイルで行の高さを指定できること
2 |
3 | ### 背景
4 |
5 | 1. 4.1.14 で行の高さをスタイルで上書きできるようになりました
6 | 2. 6.0.0 で padding-top と height が設定されなくなりました
7 | 3. 6.1.45 で対応
8 |
9 | ### -- 手段 --
10 |
11 | 1. Editor2 を選択する
12 | 2. `.textae-editor__body__text-box`の line-height が`14px`であること
13 | 3. `.textae-editor__body__text-box`の padding-top が`7px`であること
14 | 4. `.textae-editor__body__text-box`の height が`48px`であること
15 | 5. Setting ダイアログを開く
16 | 6. Line Height の値が 14 であること
17 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220202_05.md:
--------------------------------------------------------------------------------
1 | ## 行の高さを変更して annotation を読み直すと行が再計算されること
2 |
3 | ### 背景
4 |
5 | 1. ファイルを読み直したときに行の高さを再計算していませんでした
6 | 2. 4.4.3 で再計算することにしました
7 |
8 | ### -- 手段 --
9 |
10 | 1. Setting ダイアログで行の高さを変更する
11 | 2. 行の高さが変わること
12 | 3. Grid の位置が変わること
13 | 4. アノテーション読込ダイアログを表示
14 | 5. URL からアノテーションを読み込む
15 | 6. 行の高さが再計算されること
16 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220203_02.md:
--------------------------------------------------------------------------------
1 | ## Entity の Type 定義の label 属性
2 |
3 | ### 背景
4 |
5 | 1. 4.3.0 から config に Entity の Type に label を定義できるようになりました
6 |
7 | ### -- 手段 --
8 |
9 | 1. Edtor1 を選択
10 | 2. Term モードにする
11 | 3. Entity を選択する
12 | 4. `w`キーを押して、Type を`http://www.yahoo.co.jp`に変更します
13 | 5. Type の表示が`Regulation`になること
14 | 6. V アイコンを押して View モードに切り替える
15 | 7. Type のラベルがリンクになること
16 | 8. リンクをクリックすると`http://www.yahoo.co.jp`が開くこと
17 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220207_01.md:
--------------------------------------------------------------------------------
1 | ## Editor の自動選択
2 |
3 | ### 背景
4 |
5 | 1. 1 画面に複数のエディタを組み込めるように、エディタの選択は外部スクリプトで行っています
6 | 2. 5.2.4 までは setTimeout を使って、選択時間を遅らせて自動選択していました
7 | 3. textae の focus イベントリスナーは load イベントでバインドしています
8 | 4. html の読み込みに時間がかかった場合、textae 側が listen する前に、外部スクリプトが focus し自動選択に失敗していました
9 | 5. 5.2.5 で、外部スクリプトを load イベントで実行することで確実にエディタが自動選択されるようになりました
10 |
11 | ### -- 手段 --
12 |
13 | 1. Editor0 が自動選択されること
14 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220207_02.md:
--------------------------------------------------------------------------------
1 | ## 既存の要素を消す
2 |
3 | ### メイン
4 |
5 | 1. Relation モードにする
6 | 2. Relation を消す
7 | 3. Entity を消す
8 | 4. Term モードにする
9 | 5. Span を消す
10 | 6. Relation のある Span を消す
11 | 7. Relation のある Entity を消す
12 | 8. 全て戻す
13 | 9. 選択されないこと
14 | 10. やり直す
15 | 11. 全て戻してからやり直すのを 4 回繰り返す
16 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220207_03.md:
--------------------------------------------------------------------------------
1 | ## ラベルの定義に HTML タグが含まれているとき、HTML エスケープした文字列をオートコンプリートの候補として表示すること
2 |
3 | ### 背景
4 |
5 | 1. オートコンプリートの候補には Type 定義の`id`と`label`を表示しています。
6 | 2. HTML エスケープしていないため、`label`に HTML タグを含む Type を定義すると、オートコンプリートの候補に任意の HTML タグを挿入することが可能です。
7 | 3. 6.4.24 で対応しました。
8 |
9 | ### -- 手段 --
10 |
11 | 1. Editor1 を選択
12 | 2. Term モードにする
13 | 3. Entity を選択する
14 | 4. `w`キーを押して Entity 編集ダイアログを開く
15 | 5. `Value:`欄に`HTML`を入力する
16 | 6. 候補に赤字の`Red color HTML label`ではなく、`Red color HTML label...`が表示されること
17 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220208_01.md:
--------------------------------------------------------------------------------
1 | ## Entity と Relation を同時に選択した時の Label 編集は Relation の Label を表示
2 |
3 | ### 背景
4 |
5 | 1. SelectionModel は id だけを保持しています
6 | 2. id は外部(anntation.js)から指定されることがあります
7 | 3. id だけでは何を選択しているかわかりません
8 | 4. SelectionModel は Entity と Relation に分かれています
9 | 5. 編集モードに応じて参照する SelectionModel を切り替えます
10 | 6. 6.2.25 から SelectionModel でアノテーションモデルインスタスへの参照を保持するようになりました
11 |
12 | ### -- 手段 --
13 |
14 | 1. Relation モードにする
15 | 2. Entity を選択する
16 | 3. Ctrl を押しながら Relation を選択する
17 | 4. Label を編集する
18 | 5. `Value/Label`欄に Relation の pred の文字列が表示されること
19 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220210_02.md:
--------------------------------------------------------------------------------
1 | ## BlockEntity にパレットから Attribute を追加
2 |
3 | ### 背景
4 |
5 | 1. 6.2.71 で Block モードでパレットが開けるようになりました
6 |
7 | ### -- 手段 --
8 |
9 | 1. Editor1 を選択
10 | 2. Block モードにする
11 | 3. Attribute を持たない BlockEntity を選択する
12 | 4. パレットを開く
13 | 5. denote タブを選択する
14 | 6. `add to`ボタンを押す
15 | 7. Attribute が追加されること
16 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220215_02.md:
--------------------------------------------------------------------------------
1 | ## Term モードでテキスト上で mousedown して StyleSpan 上で mouseup してエラーが起きない
2 |
3 | ### 背景
4 |
5 | 1. 6.2.43 で発生
6 | 2. 6.3.19 で対応
7 |
8 | ### -- 手段 --
9 |
10 | 1. Editor1 を選択
11 | 2. Term モードにする
12 | 3. テキスト上で mousedown して、右方向の、StypleSpan 上で mouseup する
13 | 4. エラーが起きないこと
14 | 5. テキスト上で mousedown して、左方向の、StypleSpan 上で mouseup する
15 | 6. エラーが起きないこと
16 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220215_04.md:
--------------------------------------------------------------------------------
1 | ## アノテーションが無いときに行の高さが 41px になること
2 |
3 | ### 背景
4 |
5 | 1. 5.0.0 でアノテーションが無いときに行の高さがなくなっていました
6 | 2. 5.2.4 で対応しました
7 |
8 | ### -- 手段 --
9 |
10 | 1. Editor7 を選択する
11 | 2. `.textae-editor__body__text-box`の line-height が`41px`であること
12 | 3. `.textae-editor__body__text-box`の padding-top が`20.5px`であること
13 | 4. Setting ダイアログを開く
14 | 5. Line Height の値が 41 であること
15 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220216_02.md:
--------------------------------------------------------------------------------
1 | ## URL からアノテーション読込
2 |
3 | ### URL が指定されていなければ Open ボタンを押せない
4 |
5 | 1. アノテーション読込ダイアログを開く
6 | 2. URL 欄が空の時は`Open`ボタンは無効
7 | 3. Local のファイルが選択されていない時は`Open`ボタンは無効
8 |
9 | ### 存在しないアノテーションを読み込む
10 |
11 | #### 背景
12 |
13 | 1. 読み込み失敗時のメッセージが素っ気なかった
14 | 2. 4.1.12 から優しくなりました
15 |
16 | #### -- 手段 --
17 |
18 | 1. 存在しないファイルを読み込む
19 | 2. 赤いトーストが表示されること
20 | 3. `Could not load the file from the location you specified.:`が表示されること
21 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220216_03.md:
--------------------------------------------------------------------------------
1 | ## BlockSpan をつくったときにドキュメントの最上部までスクロールしない
2 |
3 | ### 背景
4 |
5 | 1. 6.2.0 からブロック機能を追加
6 | 2. BlockSpan を作ったとき、同時に BlockEntity を作成し両者を選択します
7 | 3. エンティティを選択する際に、ラベルにフォーカスをあてて、選択しているエンティティをブラウザの表示領域にスクロールインします
8 | 4. BlockEntity を作成する際、位置の基準となる Div の位置がブラウザ上で確定するするのが遅いため、一瞬ドキュメントの最上部に配置されます
9 | 5. このときフォーカスするとブラウザがドキュメントの最上部までスクロールします
10 | 6. 6.2.49 で、BlockEntity を選択する際に、位置が確定していなければ、確定後にフォーカスする処理をいれ、対応しました
11 |
12 | ### -- 手段 --
13 |
14 | 1. Editor4 を選択
15 | 2. Block モードにする
16 | 3. BlockSpan を追加する
17 | 4. ブラウザがドキュメントの最上部までスクロールしないこと
18 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220216_05.md:
--------------------------------------------------------------------------------
1 | ## パレットのスクロールバー
2 |
3 | ### 背景
4 |
5 | 1. パレットに、スクロールが必要ない場合も、横スクロールバーが表示されていました
6 | 2. 6.4.75 で横スクロールバーの常時表示をやめました
7 |
8 | ### -- 手段 --
9 |
10 | 1. パレットを開く
11 | 2. パレットの下部に横スクロールバーが表示されないこと
12 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220217_01.md:
--------------------------------------------------------------------------------
1 | ## Block モードで、Body クリックでパレットが閉じる
2 |
3 | ### 背景
4 |
5 | 1. 6.2.75 で Block モードに対応しました
6 | 2. BlockSpan のクリックイベントにパレットを閉じる処理がぬけていました
7 | 3. 6.4.61 で対応
8 |
9 | ### -- 手段 --
10 |
11 | 1. Block モードにする
12 | 2. `Show label list editor [Q]`ボタンをクリックする
13 | 3. パレットが開くこと
14 | 4. 行間をクリックする
15 | 5. パレットが閉じること
16 | 6. BlockSpan のすぐ上をクリックする
17 | 7. パレットが閉じること
18 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220222_01_mouse.md:
--------------------------------------------------------------------------------
1 | ## Term モードで DenotationSpan 上で mousedown して StyleSpan 上で mouseup してエラーが起きない
2 |
3 | ### 背景
4 |
5 | 1. 6.2.43 で発生
6 | 2. 6.3.20 で対応
7 |
8 | ### -- 手段 --
9 |
10 | 1. Editor1 を選択
11 | 2. Term モードにする
12 | 3. DenotationSpan 上で mousedown して、StypleSpan 上で mouseup する
13 | 4. エラーが起きないこと
14 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220222_02_mouse.md:
--------------------------------------------------------------------------------
1 | ## Term モードで BlockSpan 上で mousedown して StyleSpan 上で mouseup してエラーが起きない
2 |
3 | ### 背景
4 |
5 | 1. 6.2.0 で関数名を Typo して発生
6 | 2. 6.3.18 で対応
7 |
8 | ### -- 手段 --
9 |
10 | 1. Editor1 を選択
11 | 2. Block モードにする
12 | 3. StyleSpan の隣に BlockSpan を作成する
13 | 4. Term モードにする
14 | 5. BlockSpan 中のテキスト上で mousedown して、StypleSpan 上で mouseup する
15 | 6. エラーが起きないこと
16 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220302_01.md:
--------------------------------------------------------------------------------
1 | ## config の PushButton 設定
2 |
3 | ### 背景
4 |
5 | 1. 6.1.5 から config で自動保存、境界検出、行の高さ自動調整の ON/OFF を設定できるようになりした
6 |
7 | ### config の指定がない場合
8 |
9 | 1. Editor0 の自動保存が無効であること
10 | 2. Editor0 の行の高さ自動調整が有効であること
11 | 3. Editor0 の境界検出が有効であること
12 |
13 | ### アノテーションファイル内に cofig がある場合
14 |
15 | 1. Editor1 の自動保存が有効であること
16 | 2. Editor1 の行の高さ自動調整が無効であること
17 | 3. Editor1 の境界検出が有効であること
18 |
19 | ### config の指定があるが中身で指定がない場合
20 |
21 | 1. Editor2 の自動保存が無効であること
22 | 2. Editor2 の行の高さ自動調整が有効であること
23 | 3. Editor2 の境界検出が有効であること
24 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220302_02.md:
--------------------------------------------------------------------------------
1 | ## Entity を作成すると自動選択
2 |
3 | ### 背景
4 |
5 | 1. 新規 Entity の ID を anntotian.json の dennotation の id から連番で降っています
6 | 2. T ではじまる ID を生成した ID として扱っていました
7 | 3. annotation.json に id が T ではじまって数字以外を含む dennotation(たとえば T1.a.b)を入れると新規 ID が常に TNaN になります
8 | 4. Entity を何個作っても TNaN が振られます
9 | 5. 作成後 ID で DOM を選択する際に、最初の一個が選択されます
10 | 6. 4.1.14 で対応しました
11 | 7. 生成した ID を T 数字のみに制限しました
12 |
13 | ### -- 手段 --
14 |
15 | 1. Term モードにする
16 | 2. Span を作る
17 | 3. Entity を追加する
18 | 4. 二つの作った Entity が選択されること
19 | 5. Span を作る
20 | 6. 後に作った Span の Entity だけが選択されること(前に作った Span の Entity が選択されないこと)
21 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220302_07.md:
--------------------------------------------------------------------------------
1 | ## URL が長いときはステータスバーに...を表示する
2 |
3 | ### 背景
4 |
5 | 1. URL が長い場合に、 `Source:` の後ろで改行され、URL がフッターの範囲外に出てしまい表示されていませんでした
6 | 2. 5.0.0 からステータスバーに表示する URL が長いときは省略して表示し、改行されないようにしました
7 | 3. ブラウザの幅が 726px 以下の時に、`Source:` の後ろで改行され、URL がフッターの範囲外に出てしまい表示されていませんでした
8 | 4. 6.4.30 で対応しまた
9 |
10 | ### -- 手段 --
11 |
12 | 1. Editor0 を選択
13 | 2. ブラウザの幅を 726px 以下縮める
14 | 3. URL の末尾が切れて`...`が表示されること
15 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220302_08.md:
--------------------------------------------------------------------------------
1 | ## ステータスバーの表示
2 |
3 | ### annotations ファイルを URL で読み込んだとき
4 |
5 | 1. 絶対 URL パスで読み込んだとき、ファイルの絶対パスが表示されること(editor0)
6 | 2. 絶対 URL パスで読み込んだとき、リンクが開けること(editor0)
7 | 3. 相対 URL パスで読み込んだとき、ファイルの絶対パスが表示されること(editor1)
8 | 4. 相対 URL パスで読み込んだとき、リンクが開けること(editor1)
9 |
10 | ### annotations ファイルをローカルファイルから読み込んだとき
11 |
12 | 1. annotations ファイルのファイル名と`(local file)`が表示されること
13 |
14 | ### annotations を inline で指定したとき
15 |
16 | 1. inline で annotations ファイルを読み込んだ場合は`inline`が表示されること(editor5)
17 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220304_01.md:
--------------------------------------------------------------------------------
1 | ## パスに日本語を含む URL から annotations ファイルを読み込んだときにステータスバーにデコードした URL を表示する
2 |
3 | ### 背景
4 |
5 | 1. 5.0.0 の開発中にステータスバーにパスが表示されない URL を発見しました。
6 | 2. パスに日本語を含む URL を URL エンコードしたままステータスバーに表示すると、URL が長くなりすぎます
7 | 3. Firefox では一定長で切られ、Chrome と Safari では改行されて、見えなくなります
8 | 4. 長過ぎる URL を省略して表示するで統一してもいいのですが、人間が見たいのはデコードした URL なので、ステータスバーに表示する
9 | URL をデコードします
10 |
11 | ### -- 手段 --
12 |
13 | 1. `ゆりかごのうた.json` を読み込む
14 | 2. ステータスバーに表示される URL がデコードされていて、日本語になっていること
15 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220304_02.md:
--------------------------------------------------------------------------------
1 | ## ラベルの定義に HTML タグが含まれているとき、パレットに HTML エスケープした文字列を Entity のラベルとして表示すること
2 |
3 | ### 背景
4 |
5 | 1. Entity のラベルには Type 定義の`label`を表示しています。
6 | 2. HTML エスケープしていないため、`label`に HTML タグを含む Type を定義すると、パレット上のラベルに任意の HTML タグを挿入することが可能です。
7 | 3. 6.4.26 で対応しました。
8 |
9 | ### -- 手段 --
10 |
11 | 1. Editor1 を選択
12 | 2. Term モードにする
13 | 3. `q`を押してパレットを開く
14 | 4. `HTML tag label` のラベルが赤字の`Red color HTML label`ではなく、`Red color HTML label`であること
15 | 5. Block モードにする
16 | 6. `q`を押してパレットを開く
17 | 7. `HTML tag label` のラベルが赤字の`Red color HTML label`ではなく、`Red color HTML label`であること
18 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220308_01.md:
--------------------------------------------------------------------------------
1 | ## ラベルの定義に HTML タグが含まれているとき、HTML エスケープした文字列を Entity のラベルとして表示すること
2 |
3 | ### 背景
4 |
5 | 1. Entity のラベルには Type 定義の`label`を表示しています。
6 | 2. HTML エスケープしていないため、`label`に HTML タグを含む Type を定義すると、Entity のラベルに任意の HTML タグを挿入することが可能です。
7 | 3. 6.4.25 で対応しました。
8 |
9 | ### -- 手段 --
10 |
11 | 1. Editor1 を選択
12 | 2. DenotationEntity `E31` のラベルが赤字の`Red color HTML label`ではなく、`Red color HTML label`であること
13 | 3. BlockEntity `B1` のラベルが赤字の`Red color HTML label`ではなく、`Red color HTML label`であること
14 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220308_03.md:
--------------------------------------------------------------------------------
1 | ## オートコンプリートの候補を表示したときに Relation 編集ダイアログに横スクロールバーが表示されないこと
2 |
3 | ### 背景
4 |
5 | 1. 6.4.20 で対応しました。
6 |
7 | ### --- 手段 ---
8 |
9 | 1. Editor1 を選択
10 | 2. Relation モードにする
11 | 3. Relation を選択する
12 | 4. `Change Label[W]`ボタンを押す
13 | 5. 既存の id を消す
14 | 6. `par`を入力
15 | 7. 候補に`parent@http://dbpedia.org/ontology/parent`が表示されること
16 | 8. ダイアログに横スクロールバー表示されないこと
17 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220309_02_keyboard.md:
--------------------------------------------------------------------------------
1 | ## 外部 JavaScript で URL パラメータから属性に設定した値が反映されること
2 |
3 | ### 背景
4 |
5 | 1. 4.5.0 で URL パラメータを読むのをやめました
6 | 2. 外部の JavaScript で textae-editor に設定した属性は読みます
7 | 3. 外部の JavaScript で textae-editor に URL パラメータの値を設定するサンプルの動作確認をします
8 |
9 | ### -- 手段 --
10 |
11 | 1. を開く
12 | 2. 1_annotations が表示されること
13 | 3. Editor1 を選択
14 | 4. Edit モードであること
15 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220309_03_monuse.md:
--------------------------------------------------------------------------------
1 | ## 2 つ以上連続した空白を選択してもエラーにならないこと
2 |
3 | ### 背景
4 |
5 | 1. 2 つ以上連続した空白を選択したときに、空白を一つだけ消して、残りの空白で Span を作成していました
6 | 2. Span のレンダリング時にエラーが起きていました
7 | 3. 6.1.44 で対応
8 |
9 | ### -- 手段 --
10 |
11 | 1. Editor9 を選択
12 | 2. Term モードにする
13 | 3. `stomach ache`の間の連続した空白を選択する
14 | 4. 選択が解除されて、何もおきないこと
15 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220310_01.md:
--------------------------------------------------------------------------------
1 | ## デフォルトの Type 定義の ID を変更したときにデフォルト情報も更新する
2 |
3 | ### 背景
4 |
5 | 1. デフォルトの Type 定義の ID を変更したとき、Type 定義の情報を更新します
6 | 2. デフォルトの ID 情報を更新していません。変更前の ID のままでした
7 | 3. デフォルトの Type 定義の ID を変更したとき、デフォルト情報が消えました
8 | 4. デフォルトの Type 定義の ID を変更したあとに、Entity をつくると変更前の ID で Entity が作成されます
9 | 5. 6.4.41 で対応しました
10 |
11 | ### --- 手段 ---
12 |
13 | 1. Editor0 を選択
14 | 2. Term モードにする
15 | 3. `Show label list editor [Q]`ボタンをクリックする
16 | 4. `Protein`の`Edit this type`ボタンをクリックする
17 | 5. `Id`を変更して、`OK`ボタンをクリックする
18 | 6. パレット上の`Proetin`のデフォルトマークが消えないこと
19 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220314_01.md:
--------------------------------------------------------------------------------
1 | ## Relation 編集ダイアログでラベルを持たない Relation を開く
2 |
3 | ### 背景
4 |
5 | 1. 6.3.29 で HTML 生成用のテンプレートを Handlebars.js からテンプレートリテラルに変えたときに、ラベルを持たない Entity のラベルに null と表示されるようになりました。
6 | 2. 6.4.44 で対応
7 |
8 | ### -- 手段 --
9 |
10 | 1. Editor0 を選択
11 | 2. Relation モードにする
12 | 3. Type の定義にラベルがない Relation を選択
13 | 4. `Change Label[W]`ボタンを押す
14 | 5. 編集ダイアログが開くこと
15 | 6. `Valnue/Lable`列の下の段に何も表示されないこと
16 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220315_03_keyboard.md:
--------------------------------------------------------------------------------
1 | ## Relation 編集ダイアログ
2 |
3 | ### W キー
4 |
5 | 1. Relation モードにする
6 | 2. Relation を選択する
7 | 3. `W`キーを押す
8 | 4. 編集ダイアログが開くこと
9 | 5. タイトルバーに選択した Relation の Type の id が表示されること
10 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220318_01.md:
--------------------------------------------------------------------------------
1 | ## BlockSpan 選択時のコントロールバーの見た目の変化
2 |
3 | ### 背景
4 |
5 | 1. 6.2.0 からブロック機能を追加
6 | 2. 6.2.51 で、`Add new entity[E]`, `Copy [C]`, `Cut [X]`が有効にならないようにしました
7 | 3. 6.2.52 で、`Replicate span annotation [R]`が有効にならないようにしました
8 |
9 | ### −− 手段 --
10 |
11 | 1. Block モードにする
12 | 2. BlockSpan を選択する
13 | 3. コントロールバーの`Change label [W]`アイコンが有効になること
14 | 4. コントロールバーの`Delete [D]`アイコンが有効になること
15 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220318_03.md:
--------------------------------------------------------------------------------
1 | ## Media Attribute
2 |
3 | ### 背景
4 |
5 | 1. String Attribute の値が画像の URL のときにラベルとして画像を表示します。
6 | 2. 画像の表示サイズは String Attribute の定義の Media Height で指定できます。デフォルトは他の Attribute と同じ高さです。
7 |
8 | ### -- 手段 --
9 |
10 | 1. Editor1 を選択
11 | 2. `E19`の Attribute として画像が表示されていること
12 | 3. `q`キーを押してパレットを開く
13 | 4. `free_text_predicate`タブを開く
14 | 5. `Edit this predicate.`ボタンをクリック
15 | 6. `Max Height`の値を数値で設定する
16 | 7. `OK`ボタンを押す
17 | 8. `E19`の Attribute の画像の高さが変わること
18 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220412_01.md:
--------------------------------------------------------------------------------
1 | ## BlockEntity 編集ダイアログの編集キャンセル
2 |
3 | ### 閉じるボタン
4 |
5 | 1. Block モードにする
6 | 2. BlockEntity を選択する
7 | 3. `W`キーを押す
8 | 4. 編集ダイアログが開くこと
9 | 5. 文字を変更する
10 | 6. `X`ボタンを押す
11 | 7. BlockEntity の id が変わらないこと
12 |
13 | ### Esc キー
14 |
15 | 1. Block モードにする
16 | 2. BlockEntity を選択する
17 | 3. `W`キーを押す
18 | 4. 編集ダイアログが開くこと
19 | 5. 文字を変更する
20 | 6. `Esc`キーを押す
21 | 7. BlockEntity の id が変わらないこと
22 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220412_02.md:
--------------------------------------------------------------------------------
1 | ## 編集モードを変更したらクリップボードを空にする
2 |
3 | ### 背景
4 |
5 | 1. 6.2.0 からブロック機能を追加
6 | 2. Term モードでコピーまたはカットした DenotationEntity を BlockSpan に貼り付けられるようになりました。
7 | 3. 6.4.68 で、編集モードを変更したときに、クリップボードを空にする対応をしました。
8 |
9 | ### -- 手段 --
10 |
11 | 1. Term モードにする
12 | 2. Entity を選択する
13 | 3. `x`キーを押してカットする
14 | 4. Block モードにする
15 | 5. カットされた Entity が半透明でなくなること
16 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220413_01_mouse.md:
--------------------------------------------------------------------------------
1 | ## 親子 Span 編集
2 |
3 | ### 入れ子 Span を編集
4 |
5 | 1. 子の Span を親の範囲内でのばす
6 | 2. 親の Span を子にかぶらないように縮める
7 | 3. 戻す
8 |
9 | ### 同じサイズに
10 |
11 | 1. 親を子と同じサイズに縮める
12 | 2. 消える
13 |
14 | ### 親子 Span を入れ替える
15 |
16 | 1. 親 Span と子 Span の片側をあわせる
17 | 2. 親 Span の合っていない側を子 Span の内側に寄せる
18 | 3. 親と子の Type の位置が入れ替わること
19 |
20 | ### Type を2つ持つ Span に親を作る
21 |
22 | #### 背景
23 |
24 | 1. Grid の高さを子の Span の Type にかぶらないように上にずらしています
25 |
26 | #### -- 手段 --
27 |
28 | 1. Type を二つ持つ Span に親を作る
29 | 2. 親の Type が二つの Type の上に表示されること
30 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220415_01.md:
--------------------------------------------------------------------------------
1 | ## 行の高さ調整ボタン
2 |
3 | ### 背景
4 |
5 | 1. 4.1.12 で行の高さ調整ボタンを追加しました
6 | 2. 4.1.16 の開発中にモジュール読み込み構文の修正漏れでエラーを起こしていました
7 | 3. 6.4.80 で、行の高さの計算に、BlockEntity の高さを含めることにしました
8 |
9 | ### -- 手段 --
10 |
11 | 1. もっとも高い Grid を削除する
12 | 2. `Adjust LineHeight`ボタンをクリックする
13 | 3. 高さが調整されること
14 | 4. もっとも高い Grid より高い Grid を作る
15 | 5. `Adjust LineHeight`ボタンをクリックする
16 | 6. 高さが調整されること
17 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220415_02.md:
--------------------------------------------------------------------------------
1 | ## Line Height を px で指定
2 |
3 | ### 背景
4 |
5 | 1. 4.1.12 で Line Height の単位を px に変えました
6 | 2. 4.1.11 までは`指定値 * 16px`を行の高さに設定していました
7 | 3. 4.2.1 で、LineHeight を変更しても Grid が移動しなくなっていました
8 |
9 | ### -- 手段 --
10 |
11 | 1. Setting Dialog を開く
12 | 2. Line Height を増やす
13 | 3. 行の高さが px 単位で変更できること
14 | 4. 最大 500px まで選べること
15 | 5. 設定した値に応じて行の高さが変わること
16 | 6. 行の高さに合わせて Grid が移動すること
17 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220415_03.md:
--------------------------------------------------------------------------------
1 | ## Selection Attribute 定義の Value が唯一のときは、削除不可
2 |
3 | ### 背景
4 |
5 | 1. Selection Attribute の Value をすべて消そうとするとエラーが起きます
6 | 2. 6.1.57 で対応しました。
7 |
8 | ### -- 手段 --
9 |
10 | 1. Editor1 を選択
11 | 2. Term モードにする
12 | 3. `Show label list editor [Q]`ボタンをクリックする
13 | 4. `selection`タブを選択
14 | 5. `default`の`Remove this value.`ボタンが無効なこと
15 | 6. `Add new value`ボタンをクリックする
16 | 7. `id`欄を入力する
17 | 8. `OK`ボタンを押す
18 | 9. `default`の`Remove this value.`ボタンが有効になること
19 | 10. 追加した Value の`Remove this value.`ボタンがクリックする
20 | 11. `default`の`Remove this value.`ボタンが無効になること
21 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220419_01.md:
--------------------------------------------------------------------------------
1 | ## Setting Dialog のタイトル
2 |
3 | ### 背景
4 |
5 | 1. タイトルを変更しました。
6 |
7 | ### -- 手段 --
8 |
9 | 1. Setting Dialog を開く
10 | 2. Setting Dialog のタイトルが`Setting`であること
11 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220419_02.md:
--------------------------------------------------------------------------------
1 | ## URL からはテキストファイルのアノテーションは読み込めない
2 |
3 | ### 背景
4 |
5 | 1. 読み込み失敗時のメッセージが素っ気なかった
6 | 2. 4.1.12 から優しくなりました
7 | 3. 6.4.127 で不正なアノテーションを読み込んだ際に、不正なコンフィグレーションを読み込んだときのメッセージも表示されるようになりました
8 | 4. 6.4.142 で対応しました
9 | 5. 5.0.0 でローカルファイルからのテストファイル読み込み機能を追加しました。
10 |
11 | ### -- 手段 --
12 |
13 | 1. アノテーション読込ダイアログを表示
14 | 2. URL 欄に`http://localhost:8000/dev/target.txt`を入力し、`Open`ボタンを押して、サーバーから読み込む
15 | 3. 右上に`http://localhost:8000/dev/target.txt is not a annotation file or its format is invalid.`と赤色のトースト表示がされること
16 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220503_01_firefox.md:
--------------------------------------------------------------------------------
1 | ## オートコンプリートの候補を表示したときに Entity 編集ダイアログに横スクロールバーが表示されないこと
2 |
3 | ### 背景
4 |
5 | 1. 5.0.6 で Entity ダイアログのオートコンプリートの候補の幅を、なるべく値が省略されないように、広くしました。
6 | 2. Firefox では、Entity ダイアログに横スクロールバーが表示されていました。5.2.7 で候補の幅を 5px 短くして、対応しました。
7 |
8 | ### --- 手段 ---
9 |
10 | 1. Editor1 を選択
11 | 2. Term モードにする
12 | 3. Attribute のない Entity を選択する
13 | 4. `Change Label[W]`ボタンを押す
14 | 5. 既存の id を消す
15 | 6. `par`を入力
16 | 7. 候補に`parent@http://dbpedia.org/ontology/parent`が表示されること
17 | 8. ダイアログに横スクロールバー表示されないこと
18 |
--------------------------------------------------------------------------------
/userAcceptanceTest/20220503_02.md:
--------------------------------------------------------------------------------
1 | ## Setting Dialog の設定項目
2 |
3 | ### 背景
4 |
5 | 1. 4.1.16 で、instance/Simple モードの切り替えチェックボックスを消しました
6 | 2. 5.3.2 で、バージョン番号の表示を追加しました
7 |
8 | ### -- 手段 --
9 |
10 | 1. Setting Dialog を開く
11 | 2. Type Gap があること
12 | 3. Line Height があること
13 | 4. Lock Edit Config があること
14 | 5. Version があること
15 |
--------------------------------------------------------------------------------
/userAcceptanceTest/choice_test_devices.rb:
--------------------------------------------------------------------------------
1 | script = File.read(__FILE__).split("__END__\n").first
2 | value = DATA.gets
3 |
4 | puts value
5 |
6 | File.open(__FILE__, 'w') do
7 | _1.write script
8 | _1.write "__END__\n"
9 | _1.write DATA.read
10 | _1.write value
11 | end
12 |
13 | __END__
14 | iPad
15 | Firefox
16 | Android
17 |
--------------------------------------------------------------------------------
/userAcceptanceTest/userAcceptanceTest.md:
--------------------------------------------------------------------------------
1 | # 受け入れテスト
2 |
3 | 共通確認項目
4 |
5 | 1. `npm run dist`を実行します
6 | 2. `npm run dev:server`を実行します
7 | 3. を開きます
8 | 4. ブラウザの開発ツールを起動します。
9 | 5. 以下のテストを実行して、エラーが出ないこと
10 |
--------------------------------------------------------------------------------