diff --git a/config.js b/config.js
index 1672ce6..72bdd4e 100644
--- a/config.js
+++ b/config.js
@@ -1,5 +1,5 @@
'use strict';
module.exports = {
- examples: ['inline-nodes', 'code-editor', 'collabwriter', 'form', 'focused', 'images', 'inception', 'input', 'macros', 'nested', 'tables']
+ examples: ['code-editor', 'collabwriter', 'form', 'focused', 'images', 'inception', 'inline-nodes', 'inline-property', 'input', 'macros', 'nested', 'tables']
};
\ No newline at end of file
diff --git a/index.html b/index.html
index 1a98a5f..98a3e4b 100644
--- a/index.html
+++ b/index.html
@@ -9,6 +9,7 @@
Substance Examples
Text Macros
Code-Editor
Nested Element
+ Inline Property Editor
Inception
Collabwriter
diff --git a/inline-property/README.md b/inline-property/README.md
new file mode 100644
index 0000000..71e802c
--- /dev/null
+++ b/inline-property/README.md
@@ -0,0 +1,4 @@
+# Inline Property Node
+
+An inline node that mimicks UX of an annotation,
+i.e. its content is edited as it would belong to the text, instead of using an overlay.
diff --git a/inline-property/app.js b/inline-property/app.js
new file mode 100644
index 0000000..fd08b2e
--- /dev/null
+++ b/inline-property/app.js
@@ -0,0 +1,7 @@
+'use strict';
+
+var proseExample = require('../lib/proseExample');
+var fixture = require('./fixture');
+var config = require('./config');
+
+proseExample(fixture, config);
diff --git a/inline-property/app.scss b/inline-property/app.scss
new file mode 100644
index 0000000..2967c37
--- /dev/null
+++ b/inline-property/app.scss
@@ -0,0 +1,6 @@
+$fa-font-path: "../fonts" !default;
+@import '../node_modules/font-awesome/scss/font-awesome';
+
+body {
+ overflow: hidden;
+}
diff --git a/inline-property/config.js b/inline-property/config.js
new file mode 100644
index 0000000..91f885e
--- /dev/null
+++ b/inline-property/config.js
@@ -0,0 +1,13 @@
+'use strict';
+
+var ProseEditorPackage = require('substance/packages/prose-editor/ProseEditorPackage');
+var InlinePropertyPackage = require('./inline-property/package');
+
+module.exports = {
+ name: 'inline-property-example',
+ configure: function(config) {
+ config.import(ProseEditorPackage);
+ config.import(InlinePropertyPackage);
+ config.addStyle(__dirname+'/app.scss');
+ }
+};
diff --git a/inline-property/fixture.js b/inline-property/fixture.js
new file mode 100644
index 0000000..519ca78
--- /dev/null
+++ b/inline-property/fixture.js
@@ -0,0 +1,42 @@
+'use strict';
+/* eslint-disable indent */
+
+module.exports = function(tx) {
+ var body = tx.get('body');
+
+ tx.create({
+ id: 'title',
+ type: 'heading',
+ level: 1,
+ content: 'Inline Property Editor'
+ });
+ body.show('title');
+
+ tx.create({
+ id: 'intro',
+ type: 'paragraph',
+ content: [
+ "This shows an $, which renders a property editor",
+ "in the flow of the text, creating an interface similar to a regular annotations.",
+ "Still, in contrast to an annotation the content is owned by the inline node."
+ ].join(' ')
+ });
+ tx.create({
+ type: 'inline-property',
+ id: 'i1',
+ path: ['intro', 'content'],
+ startOffset: 14,
+ endOffset: 15,
+ content: 'inline property',
+ });
+ body.show('intro');
+
+ tx.create({
+ id: 'the-end',
+ type: 'paragraph',
+ content: [
+ "That's it."
+ ].join('')
+ });
+ body.show('the-end');
+};
diff --git a/inline-property/index.html b/inline-property/index.html
new file mode 100644
index 0000000..4b612a1
--- /dev/null
+++ b/inline-property/index.html
@@ -0,0 +1,11 @@
+
+
+
+ Inline Property Editor
+
+
+
+
+
+
+
diff --git a/inline-property/inline-property/InlineProperty.js b/inline-property/inline-property/InlineProperty.js
new file mode 100644
index 0000000..cb106ad
--- /dev/null
+++ b/inline-property/inline-property/InlineProperty.js
@@ -0,0 +1,32 @@
+'use strict';
+
+var InlineNode = require('substance/model/InlineNode');
+
+function InlineProperty() {
+ InlineProperty.super.apply(this, arguments);
+}
+
+InlineProperty.Prototype = function() {
+
+ this.getEvaluatedValue = function() {
+ var result;
+ try {
+ result = window.eval(this.value); // eslint-disable-line no-eval
+ } catch (err) {
+ console.error(err);
+ result = "ERROR";
+ }
+ return result;
+ };
+
+};
+
+InlineNode.extend(InlineProperty);
+
+InlineProperty.static.name = 'inline-property';
+
+InlineProperty.static.defineSchema({
+ content: { type: 'text', default: ' ' },
+});
+
+module.exports = InlineProperty;
diff --git a/inline-property/inline-property/InlinePropertyCommand.js b/inline-property/inline-property/InlinePropertyCommand.js
new file mode 100644
index 0000000..26089ce
--- /dev/null
+++ b/inline-property/inline-property/InlinePropertyCommand.js
@@ -0,0 +1,44 @@
+'use strict';
+
+var InlineNodeCommand = require('substance/ui/InlineNodeCommand');
+var InlineProperty = require('./InlineProperty');
+
+function InlinePropertyCommand() {
+ InlinePropertyCommand.super.apply(this, arguments);
+}
+
+InlinePropertyCommand.Prototype = function() {
+
+ this.getCommandState = function(props, context) {
+ var sel = context.documentSession.getSelection();
+ var newState = {
+ disabled: true,
+ active: false,
+ node: undefined
+ };
+ if (!sel || sel.isNull() || !sel.isPropertySelection()) {
+ return newState;
+ }
+ newState.disabled = false;
+ var doc = context.documentSession.getDocument();
+ var node = doc.get(sel.path[0]);
+ if (node && node.type === 'inline-property') {
+ newState.active = true;
+ newState.node = node;
+ } else {
+ var annos = this._getAnnotationsForSelection(props, context);
+ if (annos.length === 1 && annos[0].getSelection().equals(sel)) {
+ newState.active = true;
+ newState.node = annos[0];
+ }
+ }
+ return newState;
+ };
+
+};
+
+InlineNodeCommand.extend(InlinePropertyCommand);
+
+InlinePropertyCommand.static.name = InlineProperty.static.name;
+
+module.exports = InlinePropertyCommand;
diff --git a/inline-property/inline-property/InlinePropertyComponent.js b/inline-property/inline-property/InlinePropertyComponent.js
new file mode 100644
index 0000000..672dee8
--- /dev/null
+++ b/inline-property/inline-property/InlinePropertyComponent.js
@@ -0,0 +1,44 @@
+'use strict';
+
+var InlineNodeComponent = require('substance/ui/InlineNodeComponent');
+var TextPropertyEditor = require('substance/ui/TextPropertyEditor');
+
+function InlinePropertyComponent() {
+ InlinePropertyComponent.super.apply(this, arguments);
+}
+
+InlinePropertyComponent.Prototype = function() {
+
+ var _super = InlinePropertyComponent.super.prototype;
+
+ this.didMount = function() {
+ _super.didMount.call(this);
+ this.props.node.on('content:changed', this.rerender, this);
+ };
+
+ this.dispose = function() {
+ _super.dispose.call(this);
+ this.props.node.off(this);
+ };
+
+ this.getClassNames = function() {
+ // ATTENTION: ATM it is necessary to add .sc-inline-node
+ return 'sc-inline-property sc-inline-node';
+ };
+
+ this.renderContent = function($$) {
+ var node = this.props.node;
+ var el = $$(TextPropertyEditor, {
+ disabled: this.isDisabled(),
+ tagName: 'span',
+ path: [node.id, 'content'],
+ withoutBreak: true
+ }).ref('content');
+ return el;
+ };
+
+};
+
+InlineNodeComponent.extend(InlinePropertyComponent);
+
+module.exports = InlinePropertyComponent;
diff --git a/inline-property/inline-property/InlinePropertyTool.js b/inline-property/inline-property/InlinePropertyTool.js
new file mode 100644
index 0000000..9514d11
--- /dev/null
+++ b/inline-property/inline-property/InlinePropertyTool.js
@@ -0,0 +1,14 @@
+'use strict';
+
+var AnnotationTool = require('substance/ui/AnnotationTool');
+var InlinePropertyCommand = require('./InlinePropertyCommand');
+
+function InlinePropertyTool() {
+ InlinePropertyTool.super.apply(this, arguments);
+}
+
+AnnotationTool.extend(InlinePropertyTool);
+
+InlinePropertyTool.static.name = InlinePropertyCommand.static.name;
+
+module.exports = InlinePropertyTool;
diff --git a/inline-property/inline-property/_inline-property.scss b/inline-property/inline-property/_inline-property.scss
new file mode 100644
index 0000000..acd9093
--- /dev/null
+++ b/inline-property/inline-property/_inline-property.scss
@@ -0,0 +1,6 @@
+.sc-inline-property {
+ > .se-container {
+ padding: 2px 4px;
+ background: #eee;
+ }
+}
\ No newline at end of file
diff --git a/inline-property/inline-property/package.js b/inline-property/inline-property/package.js
new file mode 100644
index 0000000..5ad7dfc
--- /dev/null
+++ b/inline-property/inline-property/package.js
@@ -0,0 +1,18 @@
+'use strict';
+
+var InlineProperty = require('./InlineProperty');
+var InlinePropertyComponent = require('./InlinePropertyComponent');
+var InlinePropertyCommand = require('./InlinePropertyCommand');
+var InlinePropertyTool = require('./InlinePropertyTool');
+
+module.exports = {
+ name: 'hybrid-inline',
+ configure: function(config) {
+ config.addNode(InlineProperty);
+ config.addComponent(InlineProperty.static.name, InlinePropertyComponent);
+ config.addCommand(InlinePropertyCommand);
+ config.addTool(InlinePropertyTool);
+ config.addIcon(InlinePropertyCommand.static.name, { 'fontawesome': 'fa-cube' });
+ config.addStyle(__dirname+'/_inline-property.scss');
+ }
+};
diff --git a/server.js b/server.js
index 0d1f4b1..292098e 100644
--- a/server.js
+++ b/server.js
@@ -9,10 +9,9 @@ var server = require('substance/util/server');
var config = require('./config');
config.examples.forEach(function(folder) {
-
- var exampleConfigPath = path.join(__dirname, folder, 'config');
server.serveStyles(app, '/'+folder+'/app.css', {
- configPath: exampleConfigPath
+ scssPath: path.join(__dirname, folder, 'app.scss'),
+ configPath: path.join(__dirname, folder, 'config')
});
server.serveJS(app, '/'+folder+'/app.js', path.join(__dirname, folder, 'app.js'));
});