diff --git a/aio/tools/transforms/angular-base-package/rendering/truncateCode.js b/aio/tools/transforms/angular-base-package/rendering/truncateCode.js
new file mode 100644
index 0000000000..a0ea95b713
--- /dev/null
+++ b/aio/tools/transforms/angular-base-package/rendering/truncateCode.js
@@ -0,0 +1,49 @@
+module.exports = function() {
+ return {
+ name: 'truncateCode',
+ process: function(str, lines) {
+ if (lines === undefined) return str;
+
+ const parts = str && str.split && str.split(/\r?\n/);
+ if (parts && parts.length > lines) {
+ return balance(parts[0] + '...', ['{', '(', '['], ['}', ')', ']']);
+ } else {
+ return str;
+ }
+ }
+ };
+};
+
+/**
+ * Try to balance the brackets by adding closers on to the end of a string
+ * for every bracket that is left open.
+ * The chars at each index in the openers and closers should match (i.e openers = ['{', '('], closers = ['}', ')'])
+ *
+ * @param {string} str The string to balance
+ * @param {string[]} openers an array of chars that open a bracket
+ * @param {string[]} closers an array of chars that close a brack
+ * @returns the balanced string
+ */
+function balance(str, openers, closers) {
+ const stack = [];
+
+ // Add each open bracket to the stack, removing them when there is a matching closer
+ str.split('').forEach(function(char) {
+ const closerIndex = closers.indexOf(char);
+ if (closerIndex !== -1 && stack[stack.length-1] === closerIndex) {
+ stack.pop();
+ } else {
+ const openerIndex = openers.indexOf(char);
+ if (openerIndex !== -1) {
+ stack.push(openerIndex);
+ }
+ }
+ });
+
+ // Now the stack should contain all the unclosed brackets
+ while(stack.length) {
+ str += closers[stack.pop()];
+ }
+
+ return str;
+}
\ No newline at end of file
diff --git a/aio/tools/transforms/angular-base-package/rendering/truncateCode.spec.js b/aio/tools/transforms/angular-base-package/rendering/truncateCode.spec.js
new file mode 100644
index 0000000000..6e9f3b59c4
--- /dev/null
+++ b/aio/tools/transforms/angular-base-package/rendering/truncateCode.spec.js
@@ -0,0 +1,35 @@
+var factory = require('./truncateCode');
+
+describe('truncateCode filter', function() {
+ var filter;
+
+ beforeEach(function() { filter = factory(); });
+
+ it('should be called "truncateCode"',
+ function() { expect(filter.name).toEqual('truncateCode'); });
+
+ it('should return the whole string given lines is undefined', function() {
+ expect(filter.process('some text\n \nmore text\n \n'))
+ .toEqual('some text\n \nmore text\n \n');
+ });
+
+ it('should return the whole string if less than the given number of lines', function() {
+ expect(filter.process('this is a pretty long string that only exists on one line', 1))
+ .toEqual('this is a pretty long string that only exists on one line');
+
+ expect(filter.process('this is a pretty long string\nthat exists on two lines', 2))
+ .toEqual('this is a pretty long string\nthat exists on two lines');
+ });
+
+ it('should return the specified number of lines and an ellipsis if there are more lines', function() {
+ expect(filter.process('some text\n \nmore text\n \n', 1)).toEqual('some text...');
+ });
+
+ it('should add closing brackets for all the unclosed opening brackets after truncating', function() {
+ expect(filter.process('()[]{}\nsecond line', 1)).toEqual('()[]{}...');
+ expect(filter.process('([]{}\nsecond line', 1)).toEqual('([]{}...)');
+ expect(filter.process('()[{}\nsecond line', 1)).toEqual('()[{}...]');
+ expect(filter.process('()[]{\nsecond line', 1)).toEqual('()[]{...}');
+ expect(filter.process('([{\nsecond line', 1)).toEqual('([{...}])');
+ });
+});
\ No newline at end of file
diff --git a/aio/tools/transforms/angular-base-package/rendering/truncateFirstLine.js b/aio/tools/transforms/angular-base-package/rendering/truncateFirstLine.js
deleted file mode 100644
index 9070911625..0000000000
--- a/aio/tools/transforms/angular-base-package/rendering/truncateFirstLine.js
+++ /dev/null
@@ -1,13 +0,0 @@
-module.exports = function() {
- return {
- name: 'truncateFirstLine',
- process: function(str) {
- const parts = str && str.split && str.split(/\r?\n/);
- if (parts && parts.length > 1) {
- return parts[0] + '...';
- } else {
- return str;
- }
- }
- };
-};
\ No newline at end of file
diff --git a/aio/tools/transforms/angular-base-package/rendering/truncateFirstLine.spec.js b/aio/tools/transforms/angular-base-package/rendering/truncateFirstLine.spec.js
deleted file mode 100644
index c2ad68554f..0000000000
--- a/aio/tools/transforms/angular-base-package/rendering/truncateFirstLine.spec.js
+++ /dev/null
@@ -1,19 +0,0 @@
-var factory = require('./truncateFirstLine');
-
-describe('truncateFirstLine filter', function() {
- var filter;
-
- beforeEach(function() { filter = factory(); });
-
- it('should be called "truncateFirstLine"',
- function() { expect(filter.name).toEqual('truncateFirstLine'); });
-
- it('should return the whole string if only one line', function() {
- expect(filter.process('this is a pretty long string that only exists on one line'))
- .toEqual('this is a pretty long string that only exists on one line');
- });
-
- it('should return the first line and an ellipsis if there is more than one line', function() {
- expect(filter.process('some text\n \nmore text\n \n')).toEqual('some text...');
- });
-});
\ No newline at end of file
diff --git a/aio/tools/transforms/templates/api/includes/class-overview.html b/aio/tools/transforms/templates/api/includes/class-overview.html
index 24b14d468d..7a4c375e5f 100644
--- a/aio/tools/transforms/templates/api/includes/class-overview.html
+++ b/aio/tools/transforms/templates/api/includes/class-overview.html
@@ -1,13 +1,13 @@
{% import "lib/memberHelpers.html" as memberHelper -%}
- Overview
-
- {$ doc.docType $} {$ doc.name $}{$ doc.typeParams | escape $}{$ memberHelper.renderHeritage(doc) $} {
- {%- if doc.statics.length %}{% for member in doc.statics %}{% if not member.internal %}
- {$ memberHelper.renderMember(member, true) $}{% endif %}{% endfor %}{% endif %}
- {%- if doc.members.length %}{% for member in doc.members %}{% if not member.internal %}
- {$ memberHelper.renderMember(member, true) $}{% endif %}{% endfor %}{% endif %}
- }
-
+Overview
+
+{$ doc.docType $} {$ doc.name $}{$ doc.typeParams | escape $}{$ memberHelper.renderHeritage(doc) $} {
+{%- if doc.statics.length %}{% for member in doc.statics %}{% if not member.internal %}
+ {$ memberHelper.renderMember(member, 1) $}{% endif %}{% endfor %}{% endif %}
+{%- if doc.members.length %}{% for member in doc.members %}{% if not member.internal %}
+ {$ memberHelper.renderMember(member, 1) $}{% endif %}{% endfor %}{% endif %}
+}
+
diff --git a/aio/tools/transforms/templates/api/includes/decorator-overview.html b/aio/tools/transforms/templates/api/includes/decorator-overview.html
index 66537da102..8b2fe83f4d 100644
--- a/aio/tools/transforms/templates/api/includes/decorator-overview.html
+++ b/aio/tools/transforms/templates/api/includes/decorator-overview.html
@@ -2,9 +2,9 @@
Metadata Overview
-
- @{$ doc.name $}{$ doc.typeParams | escape $}({ {% if doc.members.length %}{% for member in doc.members %}{% if not member.internal %}
- {$ memberHelper.renderMember(member) $}{% endif %}{% endfor %}{% endif %}
- })
-
+
+@{$ doc.name $}{$ doc.typeParams | escape $}({ {% if doc.members.length %}{% for member in doc.members %}{% if not member.internal %}
+ {$ memberHelper.renderMember(member, 1) $}{% endif %}{% endfor %}{% endif %}
+})
+
\ No newline at end of file
diff --git a/aio/tools/transforms/templates/api/includes/interface-overview.html b/aio/tools/transforms/templates/api/includes/interface-overview.html
index 8b3199b7ac..ac4d71299c 100644
--- a/aio/tools/transforms/templates/api/includes/interface-overview.html
+++ b/aio/tools/transforms/templates/api/includes/interface-overview.html
@@ -1,10 +1,10 @@
{% import "lib/memberHelpers.html" as memberHelper -%}
- Interface Overview
-
- interface {$ doc.name $}{$ doc.typeParams | escape $}{$ memberHelper.renderHeritage(doc) $} { {% if doc.members.length %}{% for member in doc.members %}{% if not member.internal %}
- {$ memberHelper.renderMember(member, true) $}{% endif %}{% endfor %}{% endif %}
- }
-
+Interface Overview
+
+interface {$ doc.name $}{$ doc.typeParams | escape $}{$ memberHelper.renderHeritage(doc) $} { {% if doc.members.length %}{% for member in doc.members %}{% if not member.internal %}
+ {$ memberHelper.renderMember(member, 1) $}{% endif %}{% endfor %}{% endif %}
+}
+
\ No newline at end of file
diff --git a/aio/tools/transforms/templates/api/lib/memberHelpers.html b/aio/tools/transforms/templates/api/lib/memberHelpers.html
index a6887f98f5..1aa05060c5 100644
--- a/aio/tools/transforms/templates/api/lib/memberHelpers.html
+++ b/aio/tools/transforms/templates/api/lib/memberHelpers.html
@@ -9,14 +9,14 @@
{% endfor %}{% endif %}
{%- endmacro -%}
-{%- macro renderMember(member, truncate) -%}
+{%- macro renderMember(member, truncateLines) -%}
{%- if member.accessibility !== 'public' %}{$ member.accessibility $} {% endif -%}
{%- if member.isGetAccessor %}get {% endif -%}
{%- if member.isSetAccessor %}set {% endif -%}
{%- if member.isStatic %}static {% endif -%}
- {$ member.name $}{$ member.typeParameters | escape $}{$ params.paramList(member.parameters, truncate) | trim $}
+ {$ member.name $}{$ member.typeParameters | escape $}{$ params.paramList(member.parameters, truncateLines) | trim $}
{%- if member.isOptional %}?{% endif -%}
- {$ params.returnType(member.type) | trim | truncateFirstLine $}
+ {$ params.returnType(member.type) | trim | truncateCode(truncateLines) $}
{%- endmacro -%}
{%- macro renderMemberDetail(member, cssClass) -%}
diff --git a/aio/tools/transforms/templates/api/lib/paramList.html b/aio/tools/transforms/templates/api/lib/paramList.html
index d063dc2a91..3e6b721cf4 100644
--- a/aio/tools/transforms/templates/api/lib/paramList.html
+++ b/aio/tools/transforms/templates/api/lib/paramList.html
@@ -1,7 +1,7 @@
-{% macro paramList(params, truncate) -%}
+{% macro paramList(params, truncateLines) -%}
{%- if params -%}
({%- for param in params -%}
- {% if truncate %}{$ param | escape | truncateFirstLine $}{% else %}{$ param | escape $}{% endif %}{% if not loop.last %}, {% endif %}
+ {$ param | escape | truncateCode(truncateLines) $}{% if not loop.last %}, {% endif %}
{%- endfor %})
{%- endif %}
{%- endmacro -%}