smoosic 1.0.10 → 1.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -349,7 +349,7 @@ function isSmoMicrotoneParamsSer(params: Partial<SmoMicrotoneParamsSer>): params
349
349
  * @category SmoObject
350
350
  */
351
351
  export class SmoMicrotone extends SmoNoteModifierBase {
352
- tone: string;
352
+ tone: string = 'flat75sz';
353
353
  pitchIndex: number = 0;
354
354
 
355
355
  // This is how VexFlow notates them
@@ -385,10 +385,12 @@ export class SmoMicrotone extends SmoNoteModifierBase {
385
385
  get toVex(): string {
386
386
  return SmoMicrotone.smoToVex[this.tone];
387
387
  }
388
- static readonly defaults: SmoMicrotoneParams = {
389
- ctor: 'SmoMicrotone',
390
- tone: 'flat25sz',
391
- pitch: 0
388
+ static get defaults(): SmoMicrotoneParams {
389
+ return JSON.parse(JSON.stringify({
390
+ ctor: 'SmoMicrotone',
391
+ tone: 'flat25sz',
392
+ pitch: 0
393
+ }));
392
394
  }
393
395
  static get parameterArray() {
394
396
  const rv: string[] = [];
@@ -409,8 +411,8 @@ export class SmoMicrotone extends SmoNoteModifierBase {
409
411
  }
410
412
  constructor(parameters: SmoMicrotoneParams) {
411
413
  super(parameters.ctor);
412
- this.pitchIndex = parameters.pitch;
413
- this.tone = parameters.tone;
414
+ smoSerialize.serializedMerge(SmoMicrotone.parameterArray, SmoMicrotone.defaults, this);
415
+ smoSerialize.serializedMerge(SmoMicrotone.parameterArray, parameters, this);
414
416
  }
415
417
  }
416
418
 
@@ -46,6 +46,12 @@ export abstract class StaffModifierBase implements SmoModifierBase {
46
46
  const rv = SmoDynamicCtor[params.ctor](params);
47
47
  return rv;
48
48
  }
49
+ static cloneWithId(o: StaffModifierBase) {
50
+ const ser = o.serializeWithId();
51
+ const des = StaffModifierBase.deserialize(ser);
52
+ des.attrs = JSON.parse(JSON.stringify(o.attrs));
53
+ return des;
54
+ }
49
55
  serializeWithId() {
50
56
  const ser = this.serialize();
51
57
  ser.attrs = JSON.parse(JSON.stringify(this.attrs));
@@ -866,8 +872,8 @@ export class SmoTie extends StaffModifierBase {
866
872
  invert: boolean = false;
867
873
  cp1: number = 8;
868
874
  cp2: number = 12;
869
- first_x_shift: number = 0;
870
- last_x_shift: number = 0;
875
+ first_x_shift: number = -5;
876
+ last_x_shift: number = 5;
871
877
  y_shift: number = 7;
872
878
  tie_spacing: number = 0;
873
879
  lines: TieLine[] = [];
@@ -879,8 +885,8 @@ export class SmoTie extends StaffModifierBase {
879
885
  cp1: 8,
880
886
  cp2: 12,
881
887
  y_shift: 7,
882
- first_x_shift: 0,
883
- last_x_shift: 0,
888
+ first_x_shift: -5,
889
+ last_x_shift: 5,
884
890
  lines: [],
885
891
  startSelector: SmoSelector.default,
886
892
  endSelector: SmoSelector.default
@@ -777,17 +777,35 @@ export class SmoSystemStaff implements SmoObjectParams {
777
777
  */
778
778
  syncStaffModifiers(measureIndex: number, ostaff: SmoSystemStaff) {
779
779
  const mods: StaffModifierBase[] = [];
780
+ // remove any modifiers in the stored score that aren't in the view score
780
781
  this.modifiers.forEach((modifier) => {
781
782
  if (modifier.startSelector.measure !== measureIndex) {
782
783
  mods.push(modifier);
783
784
  } else {
784
785
  const omod = ostaff.modifiers.find((mm) => mm.attrs.id === modifier.attrs.id);
785
786
  if (omod) {
786
- mods.push(modifier);
787
+ mods.push(omod);
787
788
  }
788
789
  }
789
790
  });
790
791
  this.modifiers = mods;
792
+ const measureSelectors = ostaff.modifiers.filter((mm) => mm.startSelector.measure === measureIndex);
793
+ // Add any new modifiers from a copy operation
794
+ measureSelectors.forEach((modifier) => {
795
+ const dup = this.modifiers.find((mm) =>
796
+ mm.startSelector.measure === modifier.startSelector.measure &&
797
+ mm.endSelector.measure === modifier.endSelector.measure &&
798
+ mm.ctor === modifier.ctor);
799
+ if (dup ?? null === null) {
800
+ const ser = StaffModifierBase.cloneWithId(modifier);
801
+ const des = StaffModifierBase.deserialize(ser);
802
+ des.attrs = JSON.parse(JSON.stringify(ser.attrs));
803
+ des.startSelector.staff = this.staffId;
804
+ des.endSelector.staff = this.staffId;
805
+ this.modifiers.push(des);
806
+ }
807
+ });
808
+
791
809
  }
792
810
  // ### deleteMeasure
793
811
  // delete the measure, and any staff modifiers that start/end there.
@@ -144,6 +144,23 @@ export class SmoTupletTree {
144
144
  }
145
145
  }
146
146
 
147
+ /**
148
+ * Determines whether two notes are part of the same tuplet.
149
+ * @param noteOne
150
+ * @param noteTwo
151
+ */
152
+ static areNotesPartOfTheSameTuplet(noteOne: SmoNote, noteTwo: SmoNote): boolean {
153
+ if (noteOne.tupletId === noteTwo.tupletId) {
154
+ return true;
155
+ }
156
+
157
+ return false;
158
+ }
159
+
160
+ static areTupletsBothNull(noteOne: SmoNote, noteTwo: SmoNote): boolean {
161
+ return (noteOne.tupletId ?? null) === null && (noteTwo.tupletId ?? null) === null;
162
+ }
163
+
147
164
  serialize(): SmoTupletTreeParamsSer {
148
165
  const params = {
149
166
  ctor: 'SmoTupletTree',
@@ -114,7 +114,14 @@ export class XmlHelpers {
114
114
  // smo infers the stem type from the duration, but other applications don't
115
115
  static closestStemType(ticks: number) {
116
116
  const nticks = SmoMusic.closestDurationTickLtEq(ticks);
117
- return XmlHelpers.ticksToNoteTypeMap[nticks];
117
+ // closestBeamDuration returns the rounded-up beam length for dotted rhythm and tuplets,
118
+ // we want the actual stem that's used so cut it in 1/2
119
+ const beamDuration = SmoMusic.closestBeamDuration(nticks);
120
+ if (beamDuration.ticks === nticks) {
121
+ return XmlHelpers.ticksToNoteTypeMap[beamDuration.ticks];
122
+ } else {
123
+ return XmlHelpers.ticksToNoteTypeMap[beamDuration.ticks / 2];
124
+ }
118
125
  }
119
126
  static get beamStates(): Record<string, number> {
120
127
  return {
@@ -6,12 +6,14 @@ import { SmoAttrs, getId } from '../data/common';
6
6
  import { SmoMeasure, ISmoBeamGroup } from '../data/measure';
7
7
  import { TickMap } from './tickMap';
8
8
  import { smoSerialize } from '../../common/serializationHelpers';
9
+ import {SmoTuplet, SmoTupletTree} from "../data/tuplet";
9
10
 
10
11
  /**
11
12
  * @category SmoTransform
12
13
  */
13
14
  export interface SmoBeamGroupParams {
14
15
  notes: SmoNote[],
16
+ secondaryBeamBreaks: number[];
15
17
  voice: number
16
18
  }
17
19
 
@@ -21,12 +23,14 @@ export interface SmoBeamGroupParams {
21
23
  */
22
24
  export class SmoBeamGroup implements ISmoBeamGroup {
23
25
  notes: SmoNote[];
26
+ secondaryBeamBreaks: number[];
24
27
  attrs: SmoAttrs;
25
28
  voice: number = 0;
26
29
  constructor(params: SmoBeamGroupParams) {
27
30
  let i = 0;
28
31
  this.voice = params.voice;
29
32
  this.notes = params.notes;
33
+ this.secondaryBeamBreaks = params.secondaryBeamBreaks;
30
34
  smoSerialize.vexMerge(this, params);
31
35
 
32
36
  this.attrs = {
@@ -65,6 +69,7 @@ export class SmoBeamer {
65
69
  beamBeats: number;
66
70
  skipNext: number;
67
71
  currentGroup: SmoNote[];
72
+ secondaryBeamBreaks: number[];
68
73
  constructor(measure: SmoMeasure, voice: number) {
69
74
  this.measure = measure;
70
75
  this._removeVoiceBeam(measure, voice);
@@ -78,6 +83,7 @@ export class SmoBeamer {
78
83
  }
79
84
  this.skipNext = 0;
80
85
  this.currentGroup = [];
86
+ this.secondaryBeamBreaks = [];
81
87
  }
82
88
 
83
89
  get beamGroups() {
@@ -101,6 +107,7 @@ export class SmoBeamer {
101
107
  if (nrCount.length > 1) {
102
108
  this.measure.beamGroups.push(new SmoBeamGroup({
103
109
  notes: this.currentGroup,
110
+ secondaryBeamBreaks: this.secondaryBeamBreaks,
104
111
  voice
105
112
  }));
106
113
  }
@@ -108,6 +115,7 @@ export class SmoBeamer {
108
115
 
109
116
  _advanceGroup() {
110
117
  this.currentGroup = [];
118
+ this.secondaryBeamBreaks = [];
111
119
  this.duration = 0;
112
120
  }
113
121
 
@@ -151,40 +159,33 @@ export class SmoBeamer {
151
159
  return;
152
160
  }
153
161
 
162
+ if (this.currentGroup.length > 0) {
163
+ const areTupletsBothNull = SmoTupletTree.areTupletsBothNull(tickmap.notes[index - 1], tickmap.notes[index]);
164
+ const areNotesPartOfTheSameTuplet = SmoTupletTree.areNotesPartOfTheSameTuplet(tickmap.notes[index - 1], tickmap.notes[index]);
165
+
166
+ if (!areTupletsBothNull && !areNotesPartOfTheSameTuplet) {
167
+ this.secondaryBeamBreaks.push(this.currentGroup.length - 1);
168
+ }
169
+ }
170
+
154
171
  // beam tuplets
155
- // if (note.isTuplet) {
156
- // const tuplet = this.measure.getTupletForNote(note);
157
- // // The underlying notes must have been deleted.
158
- // if (!tuplet) {
159
- // return;
160
- // }
161
-
162
- // const first = tuplet.getFirstNote();
163
- // if (!first) {
164
- // return;
165
- // }
166
-
167
- // const ult = tuplet.getLastNote();
168
- // if (!ult) {
169
- // return;
170
- // }
171
-
172
- // if (first.endBeam) {
173
- // this._advanceGroup();
174
- // return;
175
- // }
176
-
177
- // // is this beamable length-wise
178
- // if (note.noteType === 'n' && note.stemTicks < 4096) {
179
- // this.currentGroup.push(note);
180
- // }
181
- // // Ultimate note in tuplet
182
- // if (ult.attrs.id === note.attrs.id && !this._isRemainingTicksBeamable(tickmap, index)) {
183
- // this._completeGroup(tickmap.voice);
184
- // this._advanceGroup();
185
- // }
186
- // return;
187
- // }
172
+ if (note.isTuplet) {
173
+ const tupletTree = SmoTupletTree.getTupletTreeForNoteIndex(this.measure.tupletTrees, tickmap.voice, index);
174
+ if (!tupletTree) {
175
+ return;
176
+ }
177
+
178
+ // is this beamable length-wise
179
+ if (note.noteType === 'n' && note.stemTicks < 4096) {
180
+ this.currentGroup.push(note);
181
+ }
182
+ // Ultimate note in tuplet
183
+ if (tupletTree.endIndex == index && !this._isRemainingTicksBeamable(tickmap, index)) {
184
+ this._completeGroup(tickmap.voice);
185
+ this._advanceGroup();
186
+ }
187
+ return;
188
+ }
188
189
 
189
190
  // don't beam > 1/4 note in 4/4 time. Don't beam rests.
190
191
  if (note.stemTicks >= 4096 || (note.isRest() && this.currentGroup.length === 0)) {
@@ -193,33 +194,32 @@ export class SmoBeamer {
193
194
  return;
194
195
  }
195
196
 
196
- //if areTupletElementsDifferent(noteOne, noteTwo)
197
- //this._completeGroup(tickmap.voice);
198
- //this._advanceGroup();
199
- if (index > 0 && !SmoBeamer.areTupletElementsTheSame(tickmap.notes[index - 1], tickmap.notes[index])) {
197
+ this.currentGroup.push(note);
198
+
199
+ if (note.endBeam) {
200
200
  this._completeGroup(tickmap.voice);
201
201
  this._advanceGroup();
202
202
  }
203
-
204
- this.currentGroup.push(note);
205
- if (note.endBeam) {
203
+ if (index == tickmap.notes.length - 1) {
204
+ //Last note in the voice. We are closing the beam with whatever has been put there
206
205
  this._completeGroup(tickmap.voice);
207
206
  this._advanceGroup();
207
+ return;
208
208
  }
209
+
209
210
  if (this.measure.timeSignature.actualBeats % 4 === 0) {
210
- if (this.duration < 8192 && this.allEighth()) {
211
- return;
212
- } else if (this.duration === 8192) {
213
- this._completeGroup(tickmap.voice);
214
- this._advanceGroup();
215
- }
211
+ if (this.duration < 8192 && this.allEighth()) {
212
+ return;
213
+ } else if (this.duration === 8192) {
214
+ this._completeGroup(tickmap.voice);
215
+ this._advanceGroup();
216
+ }
216
217
  }
217
218
  // If we are aligned to a beat on the measure, and we are in common time
218
- if (this.currentGroup.length > 1 && this.measure.timeSignature.beatDuration === 4 &&
219
- this.measureDuration % 4096 === 0) {
220
- this._completeGroup(tickmap.voice);
221
- this._advanceGroup();
222
- return;
219
+ if (this.currentGroup.length > 1 && this.measure.timeSignature.beatDuration === 4 && this.measureDuration % 4096 === 0) {
220
+ this._completeGroup(tickmap.voice);
221
+ this._advanceGroup();
222
+ return;
223
223
  }
224
224
  if (this.duration === this.beamBeats) {
225
225
  this._completeGroup(tickmap.voice);
@@ -232,19 +232,4 @@ export class SmoBeamer {
232
232
  this._advanceGroup();
233
233
  }
234
234
  }
235
-
236
- public static areTupletElementsTheSame(noteOne: SmoNote, noteTwo: SmoNote): boolean {
237
- if (typeof(noteOne.tupletId) === 'undefined' && typeof(noteTwo.tupletId) === 'undefined') {
238
- return true;
239
- }
240
- if (noteOne.tupletId === null && noteTwo.tupletId === null) {
241
- return true;
242
- }
243
- if (noteOne.isTuplet && noteTwo.isTuplet && noteOne.tupletId == noteTwo.tupletId) {
244
- return true;
245
- }
246
-
247
- return false;
248
- }
249
-
250
235
  }
@@ -105,8 +105,16 @@ export class PasteBuffer {
105
105
  _populateSelectArray(selections: SmoSelection[]) {
106
106
  let selector: SmoSelector = SmoSelector.default;
107
107
  this.modifiers = [];
108
+ let maxSelector = selections[0].selector;
109
+ let minSelector = selections[0].selector;
108
110
  selections.forEach((selection) => {
109
111
  selector = JSON.parse(JSON.stringify(selection.selector));
112
+ if (SmoSelector.gt(selector, maxSelector)) {
113
+ maxSelector = selector;
114
+ }
115
+ if (SmoSelector.lt(selector, minSelector)) {
116
+ minSelector = selector;
117
+ }
110
118
  const mod: StaffModifierBase[] = selection.staff.getModifiersAt(selector);
111
119
  if (mod.length) {
112
120
  mod.forEach((modifier: StaffModifierBase) => {
@@ -73,7 +73,10 @@ export class SmoSelector {
73
73
  (sel1.measure === sel2.measure && sel1.tick > sel2.tick);
74
74
  }
75
75
 
76
- // ## return true if sel1 > sel2.
76
+
77
+ /**
78
+ * return true if sel1 > sel2
79
+ */
77
80
  static gt(sel1: SmoSelector, sel2: SmoSelector): boolean {
78
81
  // Note: voice is not considered b/c it's more of a vertical component
79
82
  // Note further: sometimes we need to consider voice
@@ -90,13 +93,22 @@ export class SmoSelector {
90
93
  return !(SmoSelector.eq(sel1, sel2));
91
94
  }
92
95
 
96
+ /**
97
+ * return true if sel1 < sel2
98
+ */
93
99
  static lt(sel1: SmoSelector, sel2: SmoSelector): boolean {
94
100
  return SmoSelector.gt(sel2, sel1);
95
101
  }
96
102
 
103
+ /**
104
+ * return true if sel1 >= sel2
105
+ */
97
106
  static gteq(sel1: SmoSelector, sel2: SmoSelector): boolean {
98
107
  return SmoSelector.gt(sel1, sel2) || SmoSelector.eq(sel1, sel2);
99
108
  }
109
+ /**
110
+ * return true if sel1 <= sel2
111
+ */
100
112
  static lteq(sel1: SmoSelector, sel2: SmoSelector): boolean {
101
113
  return SmoSelector.lt(sel1, sel2) || SmoSelector.eq(sel1, sel2);
102
114
  }
@@ -220,53 +220,91 @@ export class SmoStretchNoteActor extends TickIteratorBase {
220
220
  this.notes = this.measure.voices[this.voice].notes;
221
221
 
222
222
  const originalNote: SmoNote = this.notes[this.startIndex];
223
- let newTicks: Ticks = { numerator: this.newStemTicks, denominator: 1, remainder: 0 };
224
223
  const multiplier = originalNote.tickCount / originalNote.stemTicks;
225
- if (originalNote.isTuplet) {
226
- const numerator = this.newStemTicks * multiplier;
227
- newTicks = { numerator: Math.floor(numerator), denominator: 1, remainder: numerator % 1 };
228
- }
224
+
225
+ const newTicks = this.calculateNewTicks(originalNote, multiplier);
229
226
 
230
227
  const replacingNote = SmoNote.cloneWithDuration(originalNote, newTicks, this.newStemTicks);
231
228
 
229
+ const {stemTicksUsed, crossedTupletBoundary} = this.determineNotesToDelete(originalNote);
230
+
231
+ // if crossing a tuplet boundary, abort stretching
232
+ if (crossedTupletBoundary) {
233
+ this.numberOfNotesToDelete = 0;
234
+ } else {
235
+ this.prepareNotesToInsert(originalNote, replacingNote, stemTicksUsed, multiplier);
236
+ }
237
+ }
238
+
239
+ private calculateNewTicks(originalNote: SmoNote, multiplier: number): Ticks {
240
+ if (originalNote.isTuplet) {
241
+ const numerator = this.newStemTicks * multiplier
242
+ return { numerator: Math.floor(numerator), denominator: 1, remainder: numerator % 1};
243
+ } else {
244
+ return { numerator: this.newStemTicks, denominator: 1, remainder: 0};
245
+ }
246
+ }
247
+
248
+ private determineNotesToDelete(originalNote: SmoNote) {
249
+ let crossedTupletBoundary = false;
232
250
  let stemTicksUsed = originalNote.stemTicks;
251
+
233
252
  for (let i = this.startIndex + 1; i < this.notes.length; ++i) {
234
- const nnote = this.notes[i];
235
- //in case notes are part of the tuplet they need to belong to the same tuplet
236
- //this check is only temporarely here, it should never come to this
237
- if (nnote.isTuplet && !this.areNotesInSameTuplet(originalNote, nnote)) {
253
+ const nextNote = this.notes[i];
254
+
255
+ const areTupletsBothNull = SmoTupletTree.areTupletsBothNull(originalNote, nextNote);
256
+ const areNotesPartOfTheSmeTuplet = SmoTupletTree.areNotesPartOfTheSameTuplet(originalNote, nextNote);
257
+
258
+ if (!areTupletsBothNull && !areNotesPartOfTheSmeTuplet) {
259
+ crossedTupletBoundary = true;
238
260
  break;
239
261
  }
240
- stemTicksUsed += nnote.stemTicks;
262
+
263
+ stemTicksUsed += nextNote.stemTicks;
241
264
  ++this.numberOfNotesToDelete;
265
+
242
266
  if (stemTicksUsed >= this.newStemTicks) {
243
267
  break;
244
268
  }
245
269
  }
246
- const remainingAmount = stemTicksUsed - this.newStemTicks;
247
- if (remainingAmount >= 0) {
270
+
271
+ return {stemTicksUsed, crossedTupletBoundary};
272
+ }
273
+
274
+ private prepareNotesToInsert(
275
+ originalNote: SmoNote,
276
+ replacingNote: SmoNote,
277
+ stemTicksUsed: number,
278
+ multiplier: number
279
+ ) {
280
+ const remainingTicks = stemTicksUsed - this.newStemTicks;
281
+
282
+ if (remainingTicks >= 0) {
248
283
  this.notesToInsert.push(replacingNote);
249
- const lmap = SmoMusic.gcdMap(remainingAmount);
250
- lmap.forEach((stemTick) => {
284
+
285
+ const tickMap = SmoMusic.gcdMap(remainingTicks);
286
+ tickMap.forEach((stemTick) => {
251
287
  const numerator = stemTick * multiplier;
252
- const nnote = SmoNote.cloneWithDuration(originalNote, {numerator: Math.floor(numerator), denominator: 1, remainder: numerator % 1}, stemTick)
253
- this.notesToInsert.push(nnote);
288
+ const newNote = SmoNote.cloneWithDuration(originalNote, {numerator: Math.floor(numerator), denominator: 1, remainder: numerator % 1}, stemTick)
289
+ this.notesToInsert.push(newNote);
254
290
  });
291
+
292
+ // Adjust tuplet indexes due to note insertion/deletion
255
293
  const noteCountDiff = (this.notesToInsert.length - this.numberOfNotesToDelete) - 1;
256
294
  SmoTupletTree.adjustTupletIndexes(this.measure.tupletTrees, this.voice, this.startIndex, noteCountDiff);
257
295
 
258
296
  //accumulate all remainders in the first note
259
- let remainder: number = 0;
297
+ let totalRemainder: number = 0;
260
298
  this.notesToInsert.forEach((note: SmoNote) => {
261
299
  if (note.ticks.remainder > 0) {
262
- remainder += note.ticks.remainder;
300
+ totalRemainder += note.ticks.remainder;
263
301
  note.ticks.remainder = 0;
264
302
  }
265
303
  });
266
- this.notesToInsert[0].ticks.numerator += Math.round(remainder);
267
-
304
+ this.notesToInsert[0].ticks.numerator += Math.round(totalRemainder);
268
305
  }
269
306
  }
307
+
270
308
  static apply(params: SmoStretchNoteParams) {
271
309
  const actor = new SmoStretchNoteActor(params);
272
310
  SmoTickIterator.iterateOverTicks(actor.measure, actor, actor.voice);
@@ -280,13 +318,6 @@ export class SmoStretchNoteActor extends TickIteratorBase {
280
318
  }
281
319
  return null;
282
320
  }
283
-
284
- private areNotesInSameTuplet(noteOne: SmoNote, noteTwo: SmoNote): boolean {
285
- if (noteOne.isTuplet && noteTwo.isTuplet && noteOne.tupletId == noteTwo.tupletId) {
286
- return true;
287
- }
288
- return false;
289
- }
290
321
  }
291
322
 
292
323
 
@@ -120,12 +120,15 @@ export class SuiRockerComponent extends SuiComponentBase {
120
120
  () => {
121
121
  val = (this as any)[this.parser]();
122
122
  if (val !== this.initialValue) {
123
+ this.initialValue = val;
124
+ if (this.dataType === 'percent') {
125
+ val = 100 * val;
126
+ }
123
127
  if (this.min != undefined && val < this.min) {
124
128
  val = this.min;
125
129
  } else if (this.max != undefined && val > this.max) {
126
130
  val = this.max;
127
131
  }
128
- this.initialValue = val;
129
132
  $(input).val(val);
130
133
  this.handleChanged();
131
134
  }
@@ -144,13 +144,6 @@ export class defaultEditorKeys {
144
144
  altKey: false,
145
145
  shiftKey: false,
146
146
  action: "makeRest"
147
- }, {
148
- event: "keydown",
149
- key: "r",
150
- ctrlKey: false,
151
- altKey: true,
152
- shiftKey: false,
153
- action: "rerender"
154
147
  }, {
155
148
  event: "keydown",
156
149
  key: "p",
package/tsconfig.json CHANGED
@@ -30,5 +30,5 @@
30
30
  "excludeNotDocumented": false,
31
31
  "entryPoints": ["./typedoc.ts"],
32
32
  },
33
- "exclude": ["node_modules/**/*"]
33
+ "exclude": ["./node_modules", "./tools", "./types", "./build", "./.github", "./git", "./release"]
34
34
  }